func GradientDescent( initialGuess []float64, learningRate, precision float64, maxIterations int, gradient func([]float64) ([]float64, error), ) ([]float64, error) { if len(initialGuess) == 0 { return nil, errors.New("initialGuess cannot be empty") } oldResult := make([]float64, len(initialGuess)) newResult := make([]float64, len(initialGuess)) copy(oldResult, initialGuess) for i := 0; i < maxIterations; i++ { gradientAtOldResult, err := gradient(oldResult) if err != nil { return nil, err } newResult = vectorutilities.Add(oldResult, vectorutilities.Scale(-learningRate, gradientAtOldResult)) if (knnutilities.Euclidean(newResult, oldResult, precision)) < precision*precision { return newResult, nil } else { oldResult = newResult } } return newResult, nil }
func (gdpe *gradientDescentParameterEstimator) Estimate(initialParameters []float64) ([]float64, error) { if gdpe.trainingSet == nil { return nil, gdeErrors.NewUntrainedEstimatorError() } if len(initialParameters) == 0 { return nil, gdeErrors.NewEmptyInitialParametersError() } gradient := func(guess []float64) ([]float64, error) { sumLossGradient := make([]float64, len(initialParameters)) for i := 0; i < gdpe.trainingSet.NumRows(); i++ { row, _ := gdpe.trainingSet.Row(i) features, _ := row.Features().(slice.FloatSlice) target, _ := row.Target().(slice.FloatSlice) x := features.Values() y := target.Values()[0] lossGradient, err := gdpe.plgf(guess, x, y) if err != nil { return nil, err } sumLossGradient = vectorutilities.Add(sumLossGradient, lossGradient) } return sumLossGradient, nil } return gradientdescent.GradientDescent(initialParameters, gdpe.learningRate, gdpe.precision, gdpe.maxIterations, gradient) }
package vectorutilities_test import ( "github.com/amitkgupta/goodlearn/vectorutilities" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Vector Utilities", func() { Describe("Add", func() { It("Adds", func() { x := []float64{1.01, 2, 3, 4} y := []float64{3.14, -1, 0, 0} Ω(vectorutilities.Add(x, y)).Should(Equal([]float64{4.15, 1, 3, 4})) }) }) Describe("Scale", func() { It("Scales", func() { x := []float64{1, 2, 3, 4} a := -2.33 Ω(vectorutilities.Scale(a, x)).Should(Equal([]float64{-2.33, -4.66, -6.99, -9.32})) }) }) })