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 }
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})) }) }) })