使用梯度下降实现线性回归

时间:2019-11-22 14:42:54

标签: machine-learning linear-regression gradient-descent

我正在尝试实现具有梯度下降的线性回归,如本文(https://towardsdatascience.com/linear-regression-using-gradient-descent-97a6c8700931)所述。 我遵循了实现的原则,但是经过几次迭代,结果却溢出了。 我正尝试大致获得此结果:y = -0.02x + 8499.6。

代码:

package main

import (
    "encoding/csv"
    "fmt"
    "strconv"
    "strings"
)

const (
    iterations = 1000
    learningRate = 0.0001
)

func computePrice(m, x, c float64) float64 {
    return m * x + c
}

func computeThetas(data [][]float64, m, c float64) (float64, float64) {
    N := float64(len(data))
    dm, dc := 0.0, 0.0
    for _, dataField := range data {
        x := dataField[0]
        y := dataField[1]
        yPred := computePrice(m, x, c)
        dm += (y - yPred) * x
        dc += y - yPred
    }

    dm *= -2/N
    dc *= -2/N
    return m - learningRate * dm, c - learningRate * dc
}

func main() {
    data := readXY()
    m, c := 0.0, 0.0
    for k := 0; k < iterations; k++ {
        m, c = computeThetas(data, m, c)
    }
    fmt.Printf("%.4fx + %.4f\n", m, c)
}

func readXY() ([][]float64) {
    file := strings.NewReader(data)

    reader := csv.NewReader(file)
    records, err := reader.ReadAll()
    if err != nil {
        panic(err)
    }
    records = records[1:]
    size := len(records)
    data := make([][]float64, size)
    for i, v := range records {
        val1, err := strconv.ParseFloat(v[0], 64)
        if err != nil {
            panic(err)
        }
        val2, err := strconv.ParseFloat(v[1], 64)
        if err != nil {
            panic(err)
        }
        data[i] = []float64{val1, val2}
    }
    return data
}

var data = `km,price
240000,3650
139800,3800
150500,4400
185530,4450
176000,5250
114800,5350
166800,5800
89000,5990
144500,5999
84000,6200
82029,6390
63060,6390
74000,6600
97500,6800
67000,6800
76025,6900
48235,6900
93000,6990
60949,7490
65674,7555
54000,7990
68500,7990
22899,7990
61789,8290`

在这里它可以在GO操场上进行: https://play.golang.org/p/2CdNbk9_WeY

我需要解决什么才能获得正确的结果?

1 个答案:

答案 0 :(得分:0)

  

为什么公式对一个数据集起作用而不对另一个数据集起作用?

除了sascha的评论外,这是查看梯度下降应用问题的另一种方法:该算法无法保证迭代产生的结果要比前一个更好,因此不一定会收敛到结果,因为:

  • dmdc上的梯度mc彼此独立地处理; m根据dm沿下降方向更新,而c同时根据dc沿下降方向更新-但具有一定的曲面z = f(m,c),则mc之间的梯度在轴mc之间可以具有相反的符号,因此,在更新mc中的任何一个会收敛时,更新两个动作都偏离了最佳状态。
  • 但是,在线性回归到点云的情况下,失败原因更有可能是mc的更新的完全任意大小,由不确定的学习率和梯度。这样的更新很有可能超出目标函数的最小值,即使每次迭代都以更高的幅度重复进行此更新。