mltool-0.1.0.0: src/MachineLearning/Optimization.hs
{-|
Module: MachineLearning.Optimization
Description: Optimization
Copyright: (c) Alexander Ignatyev, 2016
License: BSD-3
Stability: experimental
Portability: POSIX
Optimization module.
-}
module MachineLearning.Optimization
(
MinimizeMethod(..)
, minimize
, checkGradient
)
where
import MachineLearning.Types (R, Vector, Matrix)
import MachineLearning.Model as Model
import MachineLearning.Regularization (Regularization)
import qualified MachineLearning.Optimization.GradientDescent as GD
import qualified MachineLearning.Optimization.MinibatchGradientDescent as MGD
import qualified Data.Vector.Storable as V
import qualified Numeric.LinearAlgebra as LA
import qualified Numeric.GSL.Minimization as Min
data MinimizeMethod = GradientDescent R -- ^ Gradient descent, takes alpha. Requires feature normalization.
| MinibatchGradientDescent Int Int R -- ^ Minibacth Gradietn Descent, takes seed, batch size and alpha
| ConjugateGradientFR R R -- ^ Fletcher-Reeves conjugate gradient algorithm,
-- takes size of first trial step (0.1 is fine) and tol (0.1 is fine).
| ConjugateGradientPR R R -- ^ Polak-Ribiere conjugate gradient algorithm.
-- takes size of first trial step (0.1 is fine) and tol (0.1 is fine).
| BFGS2 R R -- ^ Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm,
-- takes size of first trial step (0.1 is fine) and tol (0.1 is fine).
-- | Returns solution vector (theta) and optimization path.
-- Optimization path's row format:
-- [iter number, cost function value, theta values...]
minimize :: Model.Model a =>
MinimizeMethod
-> a -- ^ model (Least Squares, Logistic Regression etc)
-> R -- ^ epsilon, desired precision of the solution
-> Int -- ^ maximum number of iterations allowed
-> Regularization -- ^ regularization parameter
-> Matrix -- ^ X
-> Vector -- ^ y
-> Vector -- ^ initial solution, theta
-> (Vector, Matrix) -- ^ solution vector and optimization path
minimize (BFGS2 firstStepSize tol) = minimizeVD Min.VectorBFGS2 firstStepSize tol
minimize (ConjugateGradientFR firstStepSize tol) = minimizeVD Min.ConjugateFR firstStepSize tol
minimize (ConjugateGradientPR firstStepSize tol) = minimizeVD Min.ConjugatePR firstStepSize tol
minimize (GradientDescent alpha) = GD.gradientDescent alpha
minimize (MinibatchGradientDescent seed batchSize alpha) = MGD.minibatchGradientDescent seed batchSize alpha
minimizeVD method firstStepSize tol model epsilon niters reg x y initialTheta
= Min.minimizeVD method epsilon niters firstStepSize tol costf gradientf initialTheta
where costf = Model.cost model reg x y
gradientf = Model.gradient model reg x y
-- | Gradient checking function.
-- Approximates the derivates of the Model's cost function
-- and calculates derivatives using the Model's gradient functions.
-- Returns norn_2 between 2 derivatives.
-- Takes model, regularization, X, y, theta and epsilon (used to approximate derivatives, 1e-4 is a good value).
checkGradient :: Model a => a -> Regularization -> Matrix -> Vector -> Vector -> R -> R
checkGradient model reg x y theta eps = LA.norm_2 $ grad1 - grad2
where theta_m = LA.asColumn theta
eps_v = V.replicate (V.length theta) eps
eps_m = LA.diag eps_v
theta_m1 = theta_m + eps_m
theta_m2 = theta_m - eps_m
cost1 = LA.vector $ map (cost model reg x y) $ LA.toColumns theta_m1
cost2 = LA.vector $ map (cost model reg x y) $ LA.toColumns theta_m2
grad1 = (cost1 - cost2) / (LA.scalar $ 2*eps)
grad2 = gradient model reg x y theta