线性模型

问题描述

线性回归

通俗点讲,就是给一堆点,找到一条直线使所有点到直线的距离之和最小。数学描述是给定由d个属性描述的示例 ${\bf x}=(x_1,x_2,…,x_d)$,其中$x_i$表示第i个属性上的取值,线性模型试图学得一个通过属性线性组合来进行预测的函数:
$$
f(x)=w_1x_1+w_2x_2+…+w_dx_d+b
$$
写成向量形式:
$$
f(x)={\bf w^Tx}+b
$$
其中${\bf w}=(w_1,…,w_d)$与$b$ 需要由学习所得

广义线性回归:

考虑可微单调函数g(·)
$$
y=g^{-1}(w^Tx)+b
$$

一维线性回归

给定数据集$D={(x_1,y_1),(x_2,y_2),…,(x_m,y_m)}$,要使的$f(x_i)=w_i+b$能够尽量与$y_i$接近

loss:
$$
Loss=\sum_{i=1}^m(f(x_i)-y_i)^2
$$
我们需要找到:

$$
\begin{aligned}
(w^*,b^*)&=arg\min_{w,b}\sum_{i=1}^m(f(x_i)-y_i)^2\\
&=arg\min_{w,b}\sum_{i=1}^m(y_i-wx_i-b)^2
\end{aligned}
$$

令其偏导等于0:
$$
\frac{\partial Loss_{(w,b)}}{\partial w}=2(w\sum_{i=1}^mx_i^2-\sum_{i=1}^m(y_i-b)x_i)=0
$$

$$
\frac{\partial Loss_{(w,b)}}{\partial b}=2(mb-\sum_{i=1}^m(y_i-wx_i))=0
$$

可得:
$$
w=\frac{\sum_{i=1}^my_i(x_i-\bar x)}{\sum_{i=1}^mx_i^2-\frac{1}{m}(\sum_{i=1}^mx_i)^2}
$$

$$
b=\frac{1}{m}\sum_{i=1}^m(y_i-wx_i)
$$

多维线性回归

$$
f(x)={\bf w^Tx}+b
$$

将数据集表示为$m\times (d+1)$ 的矩阵形式:
$$
X=
\begin{pmatrix}
{x_{11}}&{x_{12}}&{\cdots}&{x_{1d}}&1\\
{x_{21}}&{x_{22}}&{\cdots}&{x_{2d}}&1\\
{\vdots}&{\vdots}&{\ddots}&{\vdots}&{\vdots}\\
{x_{m1}}&{x_{m2}}&{\cdots}&{x_{md}}&1
\end{pmatrix}
=\begin{pmatrix}
{x_1^T}&1\\
{x_2^T}&1\\
{\vdots}&{\vdots}\\
{x_m^T}&1
\end{pmatrix}
$$
目标y也写成向量形式$y=(y_1,y_2,…,y_m)$,则:
$$
w^*=(w_1,w_2,…,w_d,b)
$$

$$
w^*=arg\min_w(y-Xw)^T(y-Xw)
$$
矩阵求导可参考矩阵求导公式的数学推导(矩阵求导——基础篇) - 知乎 (zhihu.com)

对其求导:
$$
\frac{\partial Loss_{(w,b)}}{\partial w}=2X^T(Xw-y)=0
$$
若$X^TX$为满秩矩阵,则:
$$
w^*=(X^TX)^{-1}X^Ty
$$
此时:
$$
f(\hat x_i)=\hat x_i^T(X^TX)^{-1}X^Ty
$$

然而实际情况是,$X^TX$往往不可逆,此时可以解出多个$\hat w$, 他们都能使均方误差最小化,选择哪一个作为输出将由算法的归纳偏好决定,常见做法是引入正则化。

pytorch一维线性回归代码实现

from turtle import forward
import numpy as np
import torch
import matplotlib.pyplot as plt
from torch import nn

# 数据准备
x_train=np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.779],[6.182],[7.59],[2.167],[7.042],[10.791],[5.313],[7.997],[3.1]],dtype=np.float32)
y_train=np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],[3.366],[2.596],[2.53],[1.221],[2.827],[3.465],[1.65],[2.904],[1.3]],dtype=np.float32)
point=plt.scatter(x_train,y_train)
x_train=torch.from_numpy(x_train)
y_train=torch.from_numpy(y_train)
# 模型定义y=wx+b
class LinearRegreession(nn.Module):
def __init__(self) -> None:
super(LinearRegreession,self).__init__() #调用父类的初始化方法
self.linear=nn.Linear(1,1)#输入输出都为1维

def forward(self,x):
out=self.linear(x)
return out
if torch.cuda.is_available():
model=LinearRegreession().cuda() #如果有GPU,则加载到GPU上运行
else:
model=LinearRegreession()

#LOSS函数
criterion=nn.MSELoss()
optimizer=torch.optim.SGD(model.parameters(),lr=1e-3)#梯度下降算法

epochs=100
for epoch in range(epochs):
#判断是否使用GPU
if torch.cuda.is_available():
inputs=x_train.cuda()
target=y_train.cuda()
else:
inputs=x_train
target=y_train
#forward
out=model(inputs)
loss=criterion(out,target)
#backward
optimizer.zero_grad()

loss.backward()#求导
optimizer.step()#反向更新w与b
if (epoch+1)%20==0:
print('Epoch[{}/{}],loss:{:.6f}'.format(epoch+1,epochs,loss))
model.eval()
predict=model(x_train)
print(type(predict))
predict=predict.detach().numpy()
plt.plot(x_train.numpy(),y_train.numpy(),'ro',label='Original data')
plt.plot(x_train.numpy(),predict,label='fitting line')

plt.show()

结果.png