线性回归分析(Linear Regression Analysis)是确定两种或两种以上 变量间相互依赖的定量关系 的一种 统计分析方法 。对于一元线性回归而言,其模型主要假设为: \[y=ax+b \tag{1}\] 现在已经有了
线性回归分析(Linear Regression Analysis)是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。对于一元线性回归而言,其模型主要假设为:
\[y=ax+b \tag{1} \]现在已经有了一组数据集\(\{(x^{(i)},y^{(i)})\}_{i=1}^{N}\),想要找到一个合适的参数\(a\)和\(b\) ,使得模型对每个\(x^{(i)}\)预测出来的值\(\hat{y}^{(i)}\)与真实值\(y^{(i)}\)尽可能的非常接近。基于这个目标,可以将均方误差作为损失函数:
\[\begin{align} L(w,b) &=\frac{1}{2N}\sum_{i=1}^N(\hat{y}^{(i)}-y^{(i)})^2\\ &=\frac{1}{2N}\sum_{i=1}^N(ax^{(i)}+b-y^{(i)})^2 \end{align} \tag{2} \]对于该损失函数,可以令其最小化求出合适的参数\(a\)和\(b\) 。这种基于均方误差最小化求解线性回归参数的方法称为最小二乘法。从数据集到求出参数\(a\)和\(b\) 的过程称为学习。所用到的数据集称为知识积累。
\[\begin{align} a^*,b^* &= \arg \max_{a,b}\mathrm{L}(w,b) \end{align} \tag{3} \]对于以上优化问题,可以求相应的偏导数令其为\(0\)得到相应的解析解,也可以通过梯度下降法去求解,下面为求解过程:
\[\begin{align} \frac{\partial\mathrm{L}(w,b)}{\partial a} &=\frac{1}{N}\sum_{i=1}^N\{(ax^{(i)}+b-y^{(i)})x^{(i)}\} \\ &=\frac{1}{N}\sum_{i=1}^N\{({ax^{(i)}}^2+bx^{(i)}-y^{(i)}x^{(i)})\} \\ &=\frac{1}{N} \{ a\sum_{i=1}^N{x^{(i)}}^2+b\sum_{i=1}^Nx^{(i)}- \sum_{i=1}^Ny^{(i)}x^{(i)} \} \end{align} \tag{4} \]\[\begin{align} \frac{\partial\mathrm{L}(w,b)}{\partial b} &=\frac{1}{N}\sum_{i=1}^N(ax^{(i)}+b-y^{(i)}) \\ &=\frac{1}{N} \{ a\sum_{i=1}^N{x^{(i)}}+Nb- \sum_{i=1}^Ny^{(i)} \} \end{align} \tag{5} \]对于(4)和(5),分别令其为\(0\),可得到\(w^*\)和\(b^*\):由于求解过程不同,可能得到的表达式也会不同
\[w^*=\frac{\sum_{i=1}^N(x^{(i)}-\bar{x})(y^{(i)}-\bar{y})}{\sum_{i=1}^N(x^{(i)}-\bar{x})^2} \tag{6} \]\[b^{*}=\bar{y}-a\bar{x} \tag{7} \]通过观察可以发现,\(w^*\)的分子是自变量和因变量的协方差,分母为自变量的方差。如果对数据做中心化处理,那么可以简化以上的结果:
\[w^*=\frac{\sum_{i=1}^Nx^{(i)}y^{(i)}}{\sum_{i=1}^N{x^{(i)}}^2} \tag{8} \]\[b^*=0 \tag{9} \]下面通过代码演示基于梯度下降法来求解的过程:
def get_data(true_a,true,b):
x=np.linspace(0,2,100)
y=a*x+b+np.random.normal(size=len(x))
return(x,y)
def lin_model(x,a,b):
return a*x+b
def loss(X,Y,a,b):
return np.sum(Y-(a*X+b))/(2*len(X))
def loss_da(X,Y,a,b):
return ((a*np.sum(X**2)+b*np.sum(X)-np.sum(X*Y)))/len(X)
def loss_db(X,Y,a,b):
return (a*np.mean(X)+b-np.mean(Y))/len(X)
def SGD(X,Y,a_init,b_init,lr=0.01,error=1e-10,maxIter=100000):
a,b=(a_init,b_init)
for iter in range(0,maxIter):
da=loss_da(X,Y,a,b)
db=loss_db(X,Y,a,b)
new_a=a-lr*da
new_b=b-lr*db
if(np.abs(loss(X,Y,a,b)-loss(X,Y,a_init,b_init))<error):
return (new_a,new_b)
else:
a,b=(new_a,new_b)
return (new_a,new_b)
true_a,true_b=(2,4)
X,Y=get_data(true_a,true_b)
SGDLinerModel(X,Y,1,2)
#(1.9253542219938329, 4.022734902793057)