梯度下降法详解(附带实例)
梯度下降法(Gradient Descent,GD)的代价函数是误差平方和(SSE),它与 OLS 所用的代价函数相同,为:
其中,
为预测值:
OLS 回归可以理解为没有单位阶跃函数的 Adaline,这样就可以得到连续的目标值,而不是分类标签 -1 和 1。
【实例】用普通最小二乘法估计线性回归的参数,从而使样本点的垂直距离(残差或误差)之和最小化。
绘制使用梯度下降的优化算法时,以训练集迭代次数作为成本函数成本,检查算法是否收敛到了最低成本。

图 4 算法的收敛效果
通过可视化手段,观察线性回归与训练数据的拟合程度。为此,定义简单的辅助函数绘制训练样本的散点图并添加回归线:

图 5 房间数目与房价之间的关系
如图 5 所示,线性回归反映了房价随房间数目增加的基本趋势。但是数据显示,在许多情况下,房间数目并不能很好地解释房价。
在某些应用中,将预测结果变量以原始缩放进行报告也很重要。可以直接调用 StandardScaler 的 inverse_transform 方法,把对价格预测的结果恢复到以价格为 1000 美元的坐标轴上:
根据模型计算,这样的房屋价格为 10 840 美元。另外,如果处理标准化变量,从技术角度来说,不需要更新截距的权重,因为在这些情况下,y 轴的截距是 0。可以通过打印权重来快速确认这一点:



OLS 回归可以理解为没有单位阶跃函数的 Adaline,这样就可以得到连续的目标值,而不是分类标签 -1 和 1。
【实例】用普通最小二乘法估计线性回归的参数,从而使样本点的垂直距离(残差或误差)之和最小化。
from sklearn.preprocessing import StandardScaler import numpy as np import pandas as pd import matplotlib.pyplot as plt plt.rcParams['font.sans-serif']=['SimHei'] #显示中文 plt.rcParams['axes.unicode_minus']=False df=pd.read_csv('housing.data', header=None, sep='\s+') df.columns=['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'R M', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'M EDV'] print(df.head()) #显示住房数据集运行程序,输出如下:
CRIM ZN INDUS CHAS NOX R M AGE DIS RAD TAX \ 0 0.00632 18.0 2.31 0 0.538 6.575 65.2 4.0900 1 296.0 1 0.02731 0.0 7.07 0 0.469 6.421 78.9 4.9671 2 242.0 2 0.02729 0.0 7.07 0 0.469 7.185 61.1 4.9671 2 242.0 3 0.03237 0.0 2.18 0 0.458 6.998 45.8 6.0622 3 222.0 4 0.06905 0.0 2.18 0 0.458 7.147 54.2 6.0622 3 222.0 PTRATIO B LSTAT M EDV 0 15.3 396.90 4.98 24.0 1 17.8 396.90 9.14 21.6 2 17.8 392.83 4.03 34.7 3 18.7 394.63 2.94 33.4 4 18.7 396.90 5.33 36.2
#一个线性回归模型 class LinearRegressionGD(object): def__init__(self, eta=0.001, n_iter=20): self.eta=eta self.n_iter=n_iter def fit(self, X, y): self.w_=np.zeros(1+X.shape[1]) self.cost_=[] for i in range(self.n_iter): output=self.net_input(X) errors=(y-output) self.w_[1:]+= self.eta * X.T.dot(errors) self.w_[0]+=self.eta * errors.sum() cost=(errors * * 2).sum()/2.0 self.cost_.append(cost) return self def net_input(self, X): return np.dot(X, self.w_[1:])+self.w_[0] def predict(self, X): return self.net_input(X)为了观察 LinearRegressionGD 回归器的具体实现,用住房数据的 RM(房间数)变量作为解释变量,训练可以预测 MEDV(房价)的模型。此外通过标准化变量以确保梯度下降法算法具有更好的收敛性。
X=df[['R M']].values y=df['M EDV'].values sc_x=StandardScaler() sc_y=StandardScaler() X_std= sc_x.fit_transform(X) #sklearn的大多数转换器期望数据存储在二维阵列 y_std= sc_y.fit_transform(y[:, np.newaxis]).flatten() lr=LinearRegressionGD() lr.fit(X_std, y_std)
绘制使用梯度下降的优化算法时,以训练集迭代次数作为成本函数成本,检查算法是否收敛到了最低成本。
plt.plot(range(1, lr.n_iter+1), lr.cost_) plt.ylabel('SSE') plt.xlabel('Epoch') plt.show() #效果如图 4 所示

图 4 算法的收敛效果
通过可视化手段,观察线性回归与训练数据的拟合程度。为此,定义简单的辅助函数绘制训练样本的散点图并添加回归线:
#观察线性回归与训练数据的拟合程度 def lin_regplot(X, y, model): #s:指定散点图点的大小, 默认为20, 通过传入新的变量, 实现气泡图的绘制 #c:指定散点图点的颜色, 默认为蓝色 #edgecolors:设置散点边界线的颜色 plt.scatter(X, y, c='steelblue', edgecolor='white', s=70) plt.plot(X, model.predict(X), color='black', lw=2) return #用lin_regplot函数来绘制房间数目与房价之间的关系, 如图7-8所示 lin_regplot(X_std, y_std, lr) plt.xlabel('平均房间数[R M](标准化)') plt.ylabel('价格为1000美元[M EDV](标准化)') plt.show()

图 5 房间数目与房价之间的关系
如图 5 所示,线性回归反映了房价随房间数目增加的基本趋势。但是数据显示,在许多情况下,房间数目并不能很好地解释房价。
在某些应用中,将预测结果变量以原始缩放进行报告也很重要。可以直接调用 StandardScaler 的 inverse_transform 方法,把对价格预测的结果恢复到以价格为 1000 美元的坐标轴上:
#把价格的预测结果恢复到以价格为1000美元的坐标轴 num_rooms_std=sc_x.transform(np.array([[5.0]])) #有5个房间的房屋价格 price_std=lr.predict(num_rooms_std) print("价格为1000美元:%.3f"% sc_y.inverse_transform(price_std)) 价格为1000美元:10.840
根据模型计算,这样的房屋价格为 10 840 美元。另外,如果处理标准化变量,从技术角度来说,不需要更新截距的权重,因为在这些情况下,y 轴的截距是 0。可以通过打印权重来快速确认这一点:
print('Slope:%.3f'%lr.w_[1]) print('Intercept:%.3f'%lr.w_[0])运行程序,输出如下:
Slope:0.695
Intercept:-0.000