python - 梯度下降的实现爆炸到无穷大?
问题描述
这就是我为线性回归生成训练数据的方式。
!pip install grapher, numpy
from grapher import Grapher
import matplotlib.pyplot as plt
import numpy as np
# Secret: y = 3x + 4
# x, y = [float(row[0]) for row in rows], [float(row[5]) for row in rows]
x, y = [a for a in range(-20, 20)], [3*a + 4 for a in range(-20, 20)]
g = Grapher(['3*x + 4'], title="y = 3x+4")
plt.scatter(x, y)
g.plot()
然后,我在一个简单的二次函数 (x - 7)^2 上尝试了梯度下降
def n(x):
return (x-7)**2
cur_x = 0
lr = 0.001
ittr = 10000
n = 0
prev_x = -1
max_precision = 0.0000001
precision = 1
while n < ittr and precision > max_precision:
prev_x = cur_x
cur_x = cur_x - lr * (2*(cur_x - 7))
precision = abs(prev_x - cur_x)
n+=1
if n%100 == 0:
print(n, ':')
print(cur_x)
print()
print(cur_x)
这非常有效。
然后我做了一个线性回归类来做同样的事情。
class LinearRegression:
def __init__(self, X, Y):
self.X = X
self.Y = Y
self.m = 1
self.c = 0
self.learning_rate = 0.01
self.max_precision = 0.000001
self.itter = 10000
def h(self, x, m, c):
return m * x + c
def J(self, m, c):
loss = 0
for x in self.X:
loss += (self.h(x, m, c) - self.Y[self.X.index(x)])**2
return loss/2
def calc_loss(self):
return self.J(self.m, self.c)
def guess_answer(self, step=1):
losses = []
mcvalues = []
for m in np.arange(-10, 10, step):
for c in np.arange(-10, 10, step):
mcvalues.append((m, c))
losses.append(self.J(m, c))
minloss = sorted(losses)[0]
return mcvalues[losses.index(minloss)]
def gradient_decent(self):
print('Orignal: ', self.m, self.c)
nm = 0
nc = 0
prev_m = 0
perv_c = -1
mprecision = 1
cprecision = 1
while nm < self.itter and mprecision > self.max_precision:
prev_m = self.m
nm += 1
self.m = self.m - self.learning_rate * sum([(self.h(x, self.m, self.c) - self.Y[self.X.index(x)])*x for x in self.X])
mprecision = abs(self.m - prev_m)
return self.m, self.c
def graph_loss(self):
plt.scatter(0, self.J(0))
print(self.J(0))
plt.plot(self.X, [self.J(x) for x in self.X])
def check_loss(self):
plt.plot([m for m in range(-20, 20)], [self.J(m, 0) for m in range(-20, 20)])
x1 = 10
y1 = self.J(x1, 0)
l = sum([(self.h(x, x1, self.c) - self.Y[self.X.index(x)])*x for x in self.X])
print(l)
plt.plot([m for m in range(-20, 20)], [(l*(m - x1)) + y1 for m in range(-20, 20)])
plt.scatter([x1], [y1])
LinearRegression(x, y).gradient_decent()
输出是
Orignal: 1 0
(nan, 0)
然后我尝试绘制我的损失函数 (J(m, c)) 并尝试使用它的导数来查看它是否真的给出了斜率。我怀疑我搞砸了我的 d(J(m, c))/dm
运行后LinearRegression(x, y).check_loss()
我得到这张图
在我想要的任何一点上,它都是一个斜坡。为什么它在我的代码中不起作用?
解决方案
推荐阅读
- swift - MusicItemCollection 被错误解码
- python - pip 卸载不会完全删除包
- java - 如何跟踪整个安卓屏幕上的所有手势?
- java - 杰克逊:序列化地图
- c# - 通过 Socket 发送数据流的最佳方式是什么?
- python - 在 python 中的列表上键入转换错误。确保返回为 integer[] 而不是 str 列表的正确方法是什么?
- javascript - Typescript:如何为对象类型的键值对定义接口
- css - 如何让子块与父块大小相同
- python - 我的代码没有从单词列表中返回任何内容
- css - 如何将两个按钮元素对齐到移动视图的标题右侧