diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,11 @@
 Revision history for Haskell package learning-hmm
 ===
 
+## Version 0.3.1.0
+- Add function `baumWelch'` that performs the Baum-Welch algorithm and returns
+  a result locally maximizing its likelihood. This behaviour is different from
+  that of `baumWelch`, which returns a list of intermediate results.
+
 ## Version 0.3.0.0
 - Add `Learning.IOHMM` which represents a class of input-output HMM
 - Delete `Learning.HMM.new`
diff --git a/learning-hmm.cabal b/learning-hmm.cabal
--- a/learning-hmm.cabal
+++ b/learning-hmm.cabal
@@ -1,5 +1,5 @@
 name:                learning-hmm
-version:             0.3.0.1
+version:             0.3.1.0
 stability:           experimental
 
 synopsis:            Yet another library for hidden Markov models
diff --git a/src/Learning/HMM.hs b/src/Learning/HMM.hs
--- a/src/Learning/HMM.hs
+++ b/src/Learning/HMM.hs
@@ -5,6 +5,7 @@
   , withEmission
   , viterbi
   , baumWelch
+  , baumWelch'
   , simulate
   ) where
 
@@ -121,6 +122,21 @@
   checkModelIn "baumWelch" model `seq`
   checkDataIn "baumWelch" model xs `seq`
   map (first $ fromInternal ss os) $ I.baumWelch model' xs'
+  where
+    ss     = states model
+    os     = outputs model
+    os'    = V.fromList os
+    model' = toInternal model
+    xs'    = U.fromList $ fromJust $ mapM (`V.elemIndex` os') xs
+
+-- | @baumWelch' model xs@ performs the Baum-Welch algorithm using the
+--   observed outputs @xs@, and returns a model locally maximizing its log
+--   likelihood.
+baumWelch' :: (Eq s, Eq o) => HMM s o -> [o] -> (HMM s o, LogLikelihood)
+baumWelch' model xs =
+  checkModelIn "baumWelch" model `seq`
+  checkDataIn "baumWelch" model xs `seq`
+  first (fromInternal ss os) $ I.baumWelch' model' xs'
   where
     ss     = states model
     os     = outputs model
diff --git a/src/Learning/HMM/Internal.hs b/src/Learning/HMM/Internal.hs
--- a/src/Learning/HMM/Internal.hs
+++ b/src/Learning/HMM/Internal.hs
@@ -5,6 +5,7 @@
   , withEmission
   , viterbi
   , baumWelch
+  , baumWelch'
   -- , baumWelch1
   -- , forward
   -- , backward
@@ -162,6 +163,14 @@
     n = U.length xs
     step (m, _)     = baumWelch1 m n xs
     (models, logLs) = unzip $ iterate step (model, undefined)
+
+baumWelch' :: HMM -> U.Vector Int -> (HMM, LogLikelihood)
+baumWelch' model xs = go (undefined, -1/0) (baumWelch1 model n xs)
+  where
+    n = U.length xs
+    go (m, l) (m', l')
+      | l' - l > 1.0e-9 = go (m', l') (baumWelch1 m' n xs)
+      | otherwise       = (m, l')
 
 -- | Perform one step of the Baum-Welch algorithm and return the updated
 --   model and the likelihood of the old model.
diff --git a/src/Learning/IOHMM.hs b/src/Learning/IOHMM.hs
--- a/src/Learning/IOHMM.hs
+++ b/src/Learning/IOHMM.hs
@@ -5,6 +5,7 @@
   , withEmission
   , viterbi
   , baumWelch
+  , baumWelch'
   , simulate
   ) where
 
@@ -140,6 +141,24 @@
   checkModelIn "baumWelch" model `seq`
   checkDataIn "baumWelch" model xs ys `seq`
   map (first $ fromInternal is ss os) $ I.baumWelch model' $ U.zip xs' ys'
+  where
+    is     = inputs model
+    is'    = V.fromList is
+    ss     = states model
+    os     = outputs model
+    os'    = V.fromList os
+    model' = toInternal model
+    xs'    = U.fromList $ fromJust $ mapM (`V.elemIndex` is') xs
+    ys'    = U.fromList $ fromJust $ mapM (`V.elemIndex` os') ys
+
+-- | @baumWelch' model xs@ performs the Baum-Welch algorithm using the
+--   inputs @xs@ and outputs @ys@, and returns a model locally maximizing
+--   its log likelihood.
+baumWelch' :: (Eq i, Eq s, Eq o) => IOHMM i s o -> [i] -> [o] -> (IOHMM i s o, LogLikelihood)
+baumWelch' model xs ys =
+  checkModelIn "baumWelch" model `seq`
+  checkDataIn "baumWelch" model xs ys `seq`
+  first (fromInternal is ss os) $ I.baumWelch' model' $ U.zip xs' ys'
   where
     is     = inputs model
     is'    = V.fromList is
diff --git a/src/Learning/IOHMM/Internal.hs b/src/Learning/IOHMM/Internal.hs
--- a/src/Learning/IOHMM/Internal.hs
+++ b/src/Learning/IOHMM/Internal.hs
@@ -5,6 +5,7 @@
   , withEmission
   , viterbi
   , baumWelch
+  , baumWelch'
   -- , baumWelch1
   -- , forward
   -- , backward
@@ -168,6 +169,14 @@
     n = U.length xys
     step (m, _)     = baumWelch1 m n xys
     (models, logLs) = unzip $ iterate step (model, undefined)
+
+baumWelch' :: IOHMM -> U.Vector (Int, Int) -> (IOHMM, LogLikelihood)
+baumWelch' model xys = go (undefined, -1/0) (baumWelch1 model n xys)
+  where
+    n = U.length xys
+    go (m, l) (m', l')
+      | l' - l > 1.0e-9 = go (m', l') (baumWelch1 m' n xys)
+      | otherwise       = (m, l')
 
 -- | Perform one step of the Baum-Welch algorithm and return the updated
 --   model and the likelihood of the old model.
