对于梯度下降算法,我们知道α值过小时,每次下降的程度非常小,导致接近最小值的过程较长,而当α值过大时,就特别容易发散。处理时可以使用数据归一化
对于α值的设置需要十分小心。我通过拟合一元线性回归时,使用梯度下降算法不断最小化损失函数
J
(
θ
0
,
θ
1
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J(θ_0,θ_1)=\frac{1}{2m}\sum_{i=1}^m(h_θ(x^{(i)})−y^{(i)})^2
J(θ0,θ1)=2m1i=1∑m(hθ(x(i))−y(i))2
其中的偏导项是
∂
J
(
θ
0
,
θ
1
)
∂
θ
j
=
1
m
∑
i
=
0
m
(
h
θ
(
x
i
)
−
y
i
)
x
j
i
\begin{aligned} \frac{\partial J(θ_0,θ_1)}{\partial\theta_j} = \frac1m\sum_{i=0}^m(h_\theta(x^i)-y^i)x^i_j \end{aligned}
∂θj∂J(θ0,θ1)=m1i=0∑m(hθ(xi)−yi)xji
最开始数据通过标准化方程直接求解得到的数据
Y
=
0.047
x
+
7.03
Y = 0.047x+7.03
Y=0.047x+7.03
之后尝试使用梯度下降算法求损失函数最小值,系数初值为0
α值设置为0.0001
所得到的最终值直接发散,函数走势如图
尝试减小α值为0.00001
此时并未发散,a = 0.082 b=0.17与期望值相差特别多,其走势如图
可见下降速度十分慢,迭代10000效果并不理想
将α值设为0.0006时结果为 a=0.078 b=0.99,走势如图
也许你会想,再加大一点α值,会收敛的更快,但是只加了0.00001
也就是α值为0.00007时,迭代发散了……
当试着减少0.000001时,也就是α值为0.000069时,迭代并没有发散,但所带来的结果仅为 a = 0.07 b=1.12 与期望值0.04与7.03相差实在太多,而最小值下降的速度实在是太慢,10000次仅下降至最小值的一半(PS:α=0.0000699 同样会发散 >_<)
只有将初值设置为[7,0]期望值附近时所得到的迭代速度才会更加迅速
尝试了多种解决方案后终于找到一个方式,将原始数据归一化
将数据归一化后得到的期望值为
Y
=
4.071
X
+
14.022
Y = 4.071X+14.022
Y=4.071X+14.022
而使用梯度下降算法时,最开始也是尝试比较小的α值,比如0.00006,0.00007,发现并为再次出现发散的情况,但收敛速度也是极慢,之后经过尝试直接将α值增大至0.01此时依旧没有发散,而且收敛效果非常好,结果为
Y
=
4.070
X
+
14.021
Y=4.070X+14.021
Y=4.070X+14.021
基本吻合期望值,函数下降趋势如图,下降效果十分明显
代码如下:
# coding=utf-8
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
df = pd.read_csv('adver.csv')
Y = df.iloc[:,3]
X = df.iloc[:,0]
# plt.scatter(x=X,y=Y)
# plt.show()
my = np.mean(Y)
mx = np.mean(X)
dx = (X-mx)/np.std(X)
dy=(Y-my)/np.std(Y)
ymat=np.mat(Y).T
bias= np.ones((X.size))
xmat= np.mat(dx).T
xmat=np.insert(xmat,0,values=bias,axis=1)
# 标准方程解法
xtx = xmat.T*xmat
w=[]
w=xtx.I*(xmat.T*ymat)
print(w)
# model=linear_model.LinearRegression()
# model.fit(xmat,ymat)
# print(model.coef_)
# print(model.intercept_)
def cossfun(x,y,theta):
m = x.shape[0]
hx = x*theta
sqerrors = np.multiply((hx-y),(hx-y))
J = 1/(2*m)*np.sum(sqerrors)
return J
def gradientDescent(x,y,theta,alpha):
m = y.shape[0]
temp=[]
j_his = []
max_iters = 1000
# epsion = 1e-6
for i in range(max_iters):
hx = x * theta
# hx=x.dot(theta)
cost = (hx-y)
theta = theta - (alpha/m)*x.T.dot(cost)
temp.append(theta)
J=cossfun(x, y, theta)
# if abs(j_his[-1:] - J) <= epsion:
# break
j_his.append(J)
return theta,j_his,temp
theta=np.mat([0,0]).T
theta, j_history, temp = gradientDescent(xmat,ymat,theta,0.01)
print(theta)
plt.plot(range(len(j_history)),j_history)
plt.show()