module MachineLearning.TerminalProgress
(
learnWithProgressBar
, learnOneVsAllWithProgressBar
)
where
import Data.List (transpose)
import MachineLearning.Types (Vector, Matrix)
import qualified MachineLearning.Classification.Internal as MLC
import Control.Monad (foldM, mapAndUnzipM)
import Control.DeepSeq (deepseq)
import qualified System.Console.AsciiProgress as AP
import qualified Numeric.LinearAlgebra as LA
learnWithProgressBar :: (Vector -> (Vector, Matrix)) -> Vector -> Int -> IO (Vector, Matrix)
learnWithProgressBar func initialTheta nIterations = AP.displayConsoleRegions $ do
pg <- newProgressBar nIterations
(theta, optPaths) <- foldM (doLoop pg func) (initialTheta, []) [1..nIterations]
return (theta, buildOptPathMatrix $ reverse optPaths)
learnOneVsAllWithProgressBar :: (Vector -> Vector -> (Vector, Matrix)) -> Vector -> [Vector] -> Int -> IO ([Vector], [Matrix])
learnOneVsAllWithProgressBar func y initialThetaList nIterations = AP.displayConsoleRegions $ do
let numLabels = length initialThetaList
ys = MLC.processOutputOneVsAll numLabels y
pg <- newProgressBar $ nIterations * (length ys)
mapAndUnzipM (learnOneClass pg func nIterations) $ zip ys initialThetaList
newProgressBar nIterations = AP.newProgressBar AP.def {
AP.pgTotal = fromIntegral nIterations
, AP.pgFormat = "Learning :percent [:bar] (for :elapsed, :eta remaining)"
}
doLoop pg func (theta, optPaths) _ = do
let (theta', optPath) = func theta
theta' `deepseq` AP.tick pg
return (theta', (optPath : optPaths))
learnOneClass pg func nIterations (y, theta) = do
(theta, optPaths) <- foldM (doLoop pg $ func y) (theta, []) [1..nIterations]
return (theta, buildOptPathMatrix $ reverse optPaths)
buildOptPathMatrix :: [Matrix] -> Matrix
buildOptPathMatrix matrices = LA.fromBlocks $ map (\m -> [m]) matrices