Python 梯度下降正在潜水岭

Python 梯度下降正在潜水岭,python,machine-learning,linear-regression,gradient-descent,Python,Machine Learning,Linear Regression,Gradient Descent,我正在学习Andrew Ng的Coursera课程,并试图使用他在幻灯片中使用的住房数据(可以找到)编写一个梯度下降的基本python实现。我没有使用numpy或scikit学习或任何东西,我只是试图让代码使用1D输入和输出,并使用一行theta0+theta1*x(2个变量)。我的代码非常简单,但即使我提高或降低学习率,或者让它运行更多的迭代,它仍然会设法发散。我已经看过并尝试过多个其他公式,但仍然存在分歧。我已确保数据正确加载。代码如下: dataset_f = open("housing_

我正在学习Andrew Ng的Coursera课程,并试图使用他在幻灯片中使用的住房数据(可以找到)编写一个梯度下降的基本python实现。我没有使用numpy或scikit学习或任何东西,我只是试图让代码使用1D输入和输出,并使用一行
theta0+theta1*x
(2个变量)。我的代码非常简单,但即使我提高或降低学习率,或者让它运行更多的迭代,它仍然会设法发散。我已经看过并尝试过多个其他公式,但仍然存在分歧。我已确保数据正确加载。代码如下:

dataset_f = open("housing_prices.csv", "r")

dataset = dataset_f.read().split("\n")

xs = []
ys = []

for line in dataset:
    split = line.split(",")
    xs.append(int(split[0]))
    ys.append(int(split[2]))

m = float(len(xs))

learning_rate = 1e-5

theta0 = 0
theta1 = 0

n_steps = 1


def converged():
    return n_steps > 1000


while not converged():
    print("Step #" + str(n_steps))
    print("θ Naught: {}".format(theta0))
    print("θ One: {}".format(theta1))

    theta0_gradient = (1.0 / m) * sum([(theta0 + theta1 * xs[i] - ys[i]) for i in range(int(m))])
    theta1_gradient = (1.0 / m) * sum([(theta0 + theta1 * xs[i] - ys[i]) * xs[i] for i in range(int(m))])

    theta0_temp = theta0 - learning_rate * theta0_gradient
    theta1_temp = theta1 - learning_rate * theta1_gradient

    theta0 = theta0_temp
    theta1 = theta1_temp

    n_steps += 1

print(theta0)
print(theta1)
θ0和θ1很快变成
nan
,因为它们趋于无穷大。我注意到的是,θ0和θ1都在正负之间振荡,并且变得越来越大。例如:

Step #1
θ Naught: 0
θ One: 0

Step #2
θ Naught: 3.4041265957446813
θ One: 7642.091281914894

Step #3
θ Naught: -146.0856377478662
θ One: -337844.5760108272

Step #4
θ Naught: 6616.511688310662
θ One: 15281052.424862152

Step #5
θ Naught: -299105.2400554526
θ One: -690824180.132845

Step #6
θ Naught: 13522088.241560074
θ One: 31231058614.54401

Step #7
θ Naught: -611311852.8608981
θ One: -1411905961438.4395

Step #8
θ Naught: 27636426469.18927
θ One: 63829999475126.086

Step #9
θ Naught: -1249398426624.6619
θ One: -2885651696197370.0

Step #10
θ Naught: 56483294981582.41
θ One: 1.304556757051869e+17

Step #11
θ Naught: -2553518992810967.5
θ One: -5.89769144561785e+18

Step #12
θ Naught: 1.1544048994968486e+17
θ One: 2.6662515218056607e+20

Step #13
θ Naught: -5.218879028251596e+18
θ One: -1.2053694641507752e+22

我对你的代码做了一些小改动。忽略我的导入,这纯粹是为了我自己的绘图目的。这个应该使用您的新数据集。主要的变化是简单地调整学习率和删除一些不必要的类型转换

import matplotlib.pyplot as plt
import numpy as np

dataset_f = open("actual_housing_prices.csv", "r")

dataset = dataset_f.read().split("\n")

xs = []
ys = []

for line in dataset:
    split = line.split(",")
    xs.append(int(split[0]))
    ys.append(int(split[2]))

m = len(xs)

learning_rate1 = 1e-7
learning_rate2 = 1e-3

theta0 = 0
theta1 = 0

n_steps = 1


def converged():
    return n_steps > 100000


while not converged():
    print("Step #" + str(n_steps))
    print("Theta Naught: {}".format(theta0))
    print("Theta One: {}".format(theta1))

    theta0_gradient = (1.0 / m) * sum([theta0 + theta1*xs[i] - ys[i] for i in range(m)])
    theta1_gradient = (1.0 / m) * sum([(theta0 + theta1*xs[i] - ys[i])* xs[i] for i in range(m)])

    theta0_temp = theta0 - learning_rate2 * theta0_gradient
    theta1_temp = theta1 - learning_rate1 * theta1_gradient

    theta0 = theta0_temp
    theta1 = theta1_temp

    n_steps += 1

print(theta0)
print(theta1)

print("Error: {}".format(sum([ys[i]-theta0+theta1*xs[i] for i in range(m)])))
plt.plot(xs, ys, 'ro')
plt.axis([0, max(xs), 0, max(ys)])
my_vals = list(np.arange(0, max(xs), 0.02))
plt.plot(my_vals, map(lambda q: theta0+theta1*q, my_vals), '-bo')
plt.show()

下面是使用两个优化权重得到的结果行:

您是否对照有限差分实现检查了梯度计算?@Julien否。我最大的困惑是,我多次检查代码,发现它与公式(在线和课程中给出)完全匹配还有他们在互联网上发布的其他代码(作为教程,而不是问题),所以我想知道为什么我的代码不起作用,那么你先这样做怎么样?此外,如果不共享您使用的损失函数,也很难提供帮助,也许您也应该在每次迭代时输出该损失:没有绝对理由认为θ不应发散(如果损失的SGD=1/x,x将发散),如果损失减少,则SGD工作,问题可能在于数据和/或你对损失函数的选择。我会加上损失,看看它是否减少,但我预计它会增加,因为θ变得如此之大。哦,我想这可能与累积舍入有关。非常感谢当我测试代码时,它仍然以同样的方式发散。此外,当您加载数据时,您会执行
ys.append(split[1])
操作,但除非您修改.csv文件,否则它应该是
split[2]
,因为我试图预测价格(csv上的第三列)。这是我用你的代码得到的输出:Step#1θNout:0θOne:0 Step#2θNout:3.1702127657447E-05θOne:0.06674021276595746…Step#18θNout:8.606923562890784e+21θOne:1.9878833724324306437E+25 Step#19θNout:-3.8910518224336254e+23θOne:-8.6901258E。然后使用m将其发送到nan数据位于您提供的链接位置(只有两列)。这不是正确的数据吗?您应该设置IPython,并确保所有输入和中间数据都是正确的。我把嵌入语句放在你的while循环之前。我只是编辑它来处理新链接上的数据。TLDR是你的学习率太高了。将其放到1e-7解决了所有问题。我还必须再次将初始转换更改为int。获取当前在那里的代码(我在30分钟前编辑了它)。它确实有效。上面的图像现在是您发布的新数据集的图像(请参见y轴)。我把你的新文件命名为actual_housing_prices.csv,所以你可以把它改回去,但是是的。