1
0
mirror of https://github.com/sjwhitworth/golearn.git synced 2025-04-26 13:49:14 +08:00
golearn/optimisation/gradient_descent.go
2014-05-05 02:39:00 +01:00

70 lines
2.1 KiB
Go

package optimisation
import "github.com/gonum/matrix/mat64"
// Batch gradient descent finds the local minimum of a function.
// See http://en.wikipedia.org/wiki/Gradient_descent for more details.
func BatchGradientDescent(x, y, theta *mat64.Dense, alpha float64, epoch int) *mat64.Dense {
m, _ := y.Dims()
for i := 0; i < epoch; i++ {
xFlat := mat64.DenseCopyOf(x)
xFlat.TCopy(xFlat)
temp := mat64.DenseCopyOf(x)
temp.Mul(temp, theta)
temp.Sub(temp, y)
xFlat.Mul(xFlat, temp)
// Horrible hack to get around the fact there is no scalar division in mat64
xFlatRow, _ := xFlat.Dims()
gradient := make([]float64, 0)
for i := 0; i < xFlatRow; i++ {
row := xFlat.RowView(i)
for i := range row {
divd := row[i] / float64(m) * alpha
gradient = append(gradient, divd)
}
}
grows := len(gradient)
grad := mat64.NewDense(grows, 1, gradient)
theta.Sub(theta, grad)
}
return theta
}
// Stochastic Gradient Descent updates the parameters of theta on a random selection from X,Y.
// It is faster as it does not compute the cost function over the entire dataset every time.
// In return, there is a trade off for accuracy.
// @todo: use goroutines to parallelise training.
func StochasticGradientDescent(x, y, theta *mat64.Dense, alpha float64, epoch int) *mat64.Dense {
m, _ := y.Dims()
for i := 0; i < epoch; i++ {
for k := 0; k < m; k++ {
datXtemp := x.RowView(k)
datYtemp := y.RowView(k)
datX := mat64.NewDense(1, len(datXtemp), datXtemp)
datY := mat64.NewDense(1, 1, datYtemp)
datXFlat := mat64.DenseCopyOf(datX)
datXFlat.TCopy(datXFlat)
datX.Mul(datX, theta)
datX.Sub(datX, datY)
datXFlat.Mul(datXFlat, datX)
// Horrible hack to get around the fact there is no scalar division in mat64
xFlatRow, _ := datXFlat.Dims()
gradient := make([]float64, 0)
for i := 0; i < xFlatRow; i++ {
row := datXFlat.RowView(i)
for i := range row {
divd := row[i] / float64(m) * alpha
gradient = append(gradient, divd)
}
}
grows := len(gradient)
grad := mat64.NewDense(grows, 1, gradient)
theta.Sub(theta, grad)
}
}
return theta
}