最小二乘法(OrdinaryLeastSquares,OLS)是常见的估计模型参数的方法。
早在19世纪,勒让德就认为按照“误差的平方和最小”这个规则估计出来的模型是最接近真实情形的。于是就有:
其中,yi是观测值或真实值,即样本数据,即采集得到的数据。f(xi)是把数据带入假设的模型中得到的理论值。即这个式子表示:真实值和理论值距离的平方和最小的时候,对假设的模型估计出来的参数是最接近真实情形的。这个准则被称为最小二乘准则。这里的“二乘”就是平方的意思。
2.公式推导
首先定义线性回归的目标函数(ObjectiveFunction)或称损失函数(LossFunction)为均方误差(MeanSquaredError,MSE),公式为误差平方和(sumofsquarederrors,SSE)除以样本数(n),其中
MSE越小越小,所以是一个最小化的问题。
3.以矩阵表示SSE:
注意:这里的wx已经包含了b*x0这一项,即wx是个大矩阵,横向拼接了特征变量矩阵wx以及偏移矩阵b,这部分可在之后的范例1中的代码X=np.hstack((X,b))这句看出。之外,矩阵计算乘法要遵循第一个矩阵的列等于第二个矩阵的行这个规则,所以(y-wx)2变换到矩阵形式为(y-wx)T(y-wx)。
(2)对w偏微分得
结合矩阵、微分,我们就能够轻松求出线性回归的系数,此原理是神经网络优化求解的基石。
3.程序代码
范例1:以普通最小二乘法建立线性回归模型,预测波士顿(Boston)房价。
(1)依据以上公式推导的结论(即最后一个公式)计算出回归系数。
#载入套件importnumpyasnpfromsklearnimportdatasets#载入sklearn内建数据集ds=datasets.load_boston()#特征变数,即用于预测房价的变量值,shape=(506,13)X=ds.data#b=b*x^0,shape=(506,1)b=np.ones((X.shape[0],1))#通过横向拼接将b并入w,shape=(506,14)X=np.hstack((X,b))#目标变数,即最终预测出来的房价,shape=(506,)y=ds.target#根据以上推导的最后一个公式求解出wW=np.linalg.inv(X.T@X)@X.T@yprint(f'W={W}')代码运行结果:
1#计算效能衡量指标2#计算误差平方和SSE(sumofsquarederrors,SSE),SSE越接近于0,说明模型选择和拟合更好,数据预测也越成功3SSE=((X@W-y)**2).sum()4#计算均方误差MSE(MeanSquaredError,MSE)5MSE=SSE/y.shape[0]6#计算均方根误差RMSE(RootMeanSquaredError,RMSE)7RMSE=MSE**(1/2)8print(f'MSE={MSE}')9print(f'RMSE={RMSE}')1011#计算判别系数(R^2),该统计量越接近1,表明变量对y的解释能力越强,即模型对数据拟合的越好12#ravel可以让多维数据变成一维13y_mean=y.ravel().mean()14SST=((y-y_mean)**2).sum()15R2=1-(SSE/SST)16print(f'R2={R2}')代码运行结果:
(3)以Sklearn库自带的求解线性回归模型的函数和衡量指标的函数验证以上推导过程。
1fromsklearn.linear_modelimportLinearRegression2fromsklearn.metricsimportr2_score,mean_squared_error34#模型训练5lr=LinearRegression()6lr.fit(X,y)78#预测9y_pred=lr.predict(X)1011#回归系数12print(f'W={lr.coef_},{lr.intercept_}\n')1314#计算效能衡量指标15print(f'MSE={mean_squared_error(y,y_pred)}')16print(f'RMSE={mean_squared_error(y,y_pred)**.5}')17print(f'R2={r2_score(y,y_pred)}')代码运行结果:
从代码运行结果可知,以上公式推导的结果和函数库计算出来的结果一致。
范例2:使用Scipy以普通最小二乘法计算函数x2+5的最小值。
先对函数绘图,再调用scipy.optimize模块的leastsq()函数进行优化求解。
1#函数绘图2importnumpyasnp3importmatplotlib.pyplotasplt4fromscipy.optimizeimportleastsq5plt.ion()67x=np.linspace(-5,5,11)8910#x^2+511deff(x):12returnx**2+5131415#绘座标轴16plt.axhline()17plt.axvline()18#绘图19plt.plot(x,f(x),'g')20plt.scatter([0],[5],color='r')2122importnumpyasnp23fromscipy.optimizeimportleastsq242526#x^2+527deff(x):28returnx**2+5293031#使用最小平方法求解32#leastsq():Minimizethesumofsquaresofasetofequations.33print(leastsq(f,5,full_output=1))#full_output=1==>显示详尽的结果代码运行结果:
在leastsq()函数中,第一个参数是求解的函数;第二个参数是起始点;leastsq()是采用逼近法,而非纯数学公式求解,nfev显示它经过22次执行周期,才找到最小值5(fvec),当时x=1.72892379e-05≈0。
leastsq()第二个参数起始点可设置为任意值,通常采用随机数或是直接给0。指定值设定不佳的话,仍然可以找到最佳解,不过,需要较多次的执行周期,也就是所谓的较慢收敛(Convergence)。
当面对较复杂的函数或较多的变量时,我们很难单纯运用数学去求解,因此,逼近法会是一个比较实用的方法,深度学习的梯度下降法就是一个典形的例子。
备注:以上2.公式推导和3.程序代码均来自《深度学习全书公式+推导+代码+TensorFlow全程案例》——洪锦魁主编清华大学出版社ISBN978-7-302-61030-4这本书。