梯度下降所带来的问题——迭代发散

对于梯度下降算法,我们知道α值过小时,每次下降的程度非常小,导致接近最小值的过程较长,而当α值过大时,就特别容易发散。处理时可以使用数据归一化

对于α值的设置需要十分小心。我通过拟合一元线性回归时,使用梯度下降算法不断最小化损失函数

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​)=2m1​i=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​)​=m1​i=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()

上一篇:matlab画GIS地图


下一篇:2021-11-04