步骤:
- 数据准备
- 设计模型,计算 y ^ \hat y y^
- 构建损失函数和优化器
- 训练周期,更新参数
模型: y ^ = w ⋅ x + b \hat{y}=w\cdot x + b y^=w⋅x+b
数据集: ( x 1 , y 1 ) 、 ( x 2 , y 2 ) 、 ( x 3 , y 3 ) (x1,y1)、(x2,y2)、(x3,y3) (x1,y1)、(x2,y2)、(x3,y3)
y
1
^
=
w
x
1
+
b
\hat{y_1}=wx_1+b
y1^=wx1+b
y
2
^
=
w
x
2
+
b
\hat{y_2}=wx_2+b
y2^=wx2+b
y
3
^
=
w
x
3
+
b
\hat{y_3}=wx_3+b
y3^=wx3+b
写成矩阵形式: [ y 1 ^ y 2 ^ y 3 ^ ] = w ⋅ [ x 1 x 2 x 3 ] + b \begin{bmatrix} \hat{y_1} \\ \hat{y_2}\\ \hat{y_3} \end{bmatrix}=w\cdot \begin{bmatrix} x_1 \\ x_2\\ x_3 \end{bmatrix}+b ⎣⎡y1^y2^y3^⎦⎤=w⋅⎣⎡x1x2x3⎦⎤+b;对于 w w w 广播成3×1的矩阵
对于损失函数:
l
o
s
s
1
=
(
y
1
^
−
y
1
)
2
loss_1=(\hat{y_1}-y1)^2
loss1=(y1^−y1)2
l
o
s
s
2
=
(
y
2
^
−
y
2
)
2
loss_2=(\hat{y_2}-y2)^2
loss2=(y2^−y2)2
l
o
s
s
3
=
(
y
3
^
−
y
3
)
2
loss_3=(\hat{y_3}-y3)^2
loss3=(y3^−y3)2
同样也可写出矩阵形式。
Linear Unit:线性单元,
z
=
w
x
+
b
z=wx+b
z=wx+b
获取
x
x
x,
y
y
y 的维度,loss必须是一个标量,对于loss的矩阵对其求和或者均值
PyTorch写线性回归
将模型写成一个类,继承自torch.nn.Module
模块
类中函数必须要有
- 初始化(构造函数):
__init__
- 前馈过程中需要进行的计算(覆盖):
forward函数
调用父类的构造函数:super(LinearModel, self).__init__()
self.linear = torch.nn.Linear(1, 1)
: 构造一个Linear对象,包含权重(weight)和偏置(bias),计算wx+b输出y
- class torch.nn.Linear(in_features, out_features, bias = True)
in_features:输入特征维度
out_features:输出特征维度
bias :是否需要偏置
代码
import torch
import matplotlib.pyplot as plt
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])
# 设计模型
class LinearModel(torch.nn.Module):
def __init__(self): # 构造函数
super(LinearModel, self).__init__() # 调用父类的构造
self.linear = torch.nn.Linear(1, 1) # 构造一个Linear对象,含有权重和偏置这两个Tensor,实现wx+b;(1,1)代表输入、输出的特征维度
# 前馈过程中进行的计算,必须叫forward,实际上是覆盖
def forward(self, x): # __call__里面会调用forward函数
y_pred = self.linear(x) # 会调用__call__函数
return y_pred
model = LinearModel() # 实例化,callable
# warning信息:size_average and reduce args will be deprecated, please use reduction='sum' instead.应该是版本问题
criterion = torch.nn.MSELoss(reduction = 'sum') # 损失函数使用MSE.可求均值或者不求;构建计算图,使用torch.nn模块
# model对象的父类的parameters函数检测模型的所有需要训练权重。lr:learn rat
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01) # 优化器,不会构成计算图;
epoch_list = []
loss_list = []
for epoch in range(100):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss)
epoch_list.append(epoch)
loss_list.append(loss)
optimizer.zero_grad() # 记得清零
loss.backward() # 反向传播
optimizer.step() # 参数更新
# 打印权重和偏置
print("w = ", model.linear.weight.item())
print("b = ", model.linear.bias.item())
# 测试模型
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)
plt.plot(epoch_list, loss_list)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()
输出
0 tensor(24.8007, grad_fn=<MseLossBackward>)
1 tensor(11.1002, grad_fn=<MseLossBackward>)
2 tensor(5.0002, grad_fn=<MseLossBackward>)
3 tensor(2.2839, grad_fn=<MseLossBackward>)
4 tensor(1.0738, grad_fn=<MseLossBackward>)
5 tensor(0.5343, grad_fn=<MseLossBackward>)
6 tensor(0.2933, grad_fn=<MseLossBackward>)
7 tensor(0.1852, grad_fn=<MseLossBackward>)
8 tensor(0.1363, grad_fn=<MseLossBackward>)
9 tensor(0.1138, grad_fn=<MseLossBackward>)
10 tensor(0.1030, grad_fn=<MseLossBackward>)
11 tensor(0.0974, grad_fn=<MseLossBackward>)
... ...
86 tensor(0.0318, grad_fn=<MseLossBackward>)
87 tensor(0.0313, grad_fn=<MseLossBackward>)
88 tensor(0.0309, grad_fn=<MseLossBackward>)
89 tensor(0.0304, grad_fn=<MseLossBackward>)
90 tensor(0.0300, grad_fn=<MseLossBackward>)
91 tensor(0.0295, grad_fn=<MseLossBackward>)
92 tensor(0.0291, grad_fn=<MseLossBackward>)
93 tensor(0.0287, grad_fn=<MseLossBackward>)
94 tensor(0.0283, grad_fn=<MseLossBackward>)
95 tensor(0.0279, grad_fn=<MseLossBackward>)
96 tensor(0.0275, grad_fn=<MseLossBackward>)
97 tensor(0.0271, grad_fn=<MseLossBackward>)
98 tensor(0.0267, grad_fn=<MseLossBackward>)
99 tensor(0.0263, grad_fn=<MseLossBackward>)
w = 1.8920199871063232
b = 0.2454639971256256
y_pred = tensor([[7.8135]])
可见loss并未完全收敛,需要训练更多的次数,但是可能会导致过拟合
图像: