- 记录pytorch的学习过程 – 备注多,方便查阅
- torch的基本使用方法
- 实现一个线性回归模型并测试
import torch
torch.__version__
'1.8.0+cpu'
1.torch基本的使用方法`
1.1创建一个矩阵0矩阵
x = torch.empty(5,3)
x
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
1.2创建一个随机值
x = torch.randn(5,3)
x
tensor([[ 0.9290, 0.8528, -0.4443],
[ 1.0932, -0.7507, -0.2703],
[ 0.2908, -1.6405, -0.6977],
[ 0.0574, 0.1044, 0.0233],
[ 0.0722, 0.1150, 0.3934]])
1.3构建一个全0矩阵
x = torch.zeros(5,3)
x
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
1.4直接输入数据
x = torch.tensor([5.5,3])
x
tensor([5.5000, 3.0000])
1.5 view操作可以改变矩阵的维度
x = torch.randn(4,4)
y = x.view(16)
z = x.view(-1,8)
x.shape,y.shape,z.shape
(torch.Size([4, 4]), torch.Size([16]), torch.Size([2, 8]))
1.6 Pytorch的自动求导机制
1.6.1 需要求导的,可以手动定义
# 方法1
x = torch.randn(3,4,requires_grad=True)
x
tensor([[-0.9228, 0.5714, -0.6876, 1.9532],
[-0.3574, -0.3873, -1.8445, -1.2344],
[-0.7455, -0.2275, -2.0875, -0.5985]], requires_grad=True)
# 方法2
x = torch.randn(3,4)
x.requires_grad=True
x
tensor([[-0.7503, -1.0792, -0.7416, -1.4556],
[ 1.4662, 0.0910, -0.3608, -0.0494],
[ 0.7349, 0.0184, 1.0263, 2.2171]], requires_grad=True)
b = torch.randn(3,4,requires_grad=True)
b
tensor([[-1.5929, 1.3165, -0.2407, 1.1987],
[ 1.7689, 0.7053, -0.0073, -1.4798],
[ 1.0369, 0.7267, 1.0260, -0.8435]], requires_grad=True)
1.6.2 对可求导的参数进行运算后得到的参数,也是可求导的
t = x + b
t
tensor([[-2.3433, 0.2373, -0.9824, -0.2569],
[ 3.2351, 0.7963, -0.3681, -1.5292],
[ 1.7718, 0.7452, 2.0523, 1.3736]], grad_fn=<AddBackward0>)
y = t.sum()
y
tensor(4.7316, grad_fn=<SumBackward0>)
x.requires_grad,b.requires_grad,t.requires_grad,y.requires_grad
(True, True, True, True)
1.6.3在最后一步调用一下这个反向传播,然后就可以求各个数的梯度了
y.backward()
1.6.4 b的梯度
b.grad
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aQN0CLmY-1617518437305)(attachment:image.png)]
1.6.5 梯度计算的流程
随机生成一组数进行测试
x = torch.rand(1)
b = torch.rand(1,requires_grad=True)
w = torch.rand(1,requires_grad=True)
y = w * x
z = y + b
查看下是否需要进行求导
x.requires_grad,w.requires_grad,b.requires_grad,y.requires_grad,z.requires_grad
(False, True, True, True, True)
查看各参数是否是叶子节点
x.is_leaf,w.is_leaf,y.is_leaf,b.is_leaf,z.is_leaf
(True, True, False, True, False)
反向传播
z.backward(retain_graph=True) # 梯度是会累加的,retain_graph=True将之前的清空
w.grad
tensor([0.5243])
b.grad
tensor([1.])
2. 动手写一个线性回归
- y = 2x+1
2.1 准备数据
import numpy as np
x_values = [i for i in range(11)]
x_train = np.array(x_values,dtype=np.float32) # 将数据以ndarray的方式读入
x_train = x_train.reshape(-1,1) # 将其转换为矩阵的格式,防止格式上的错误
x_train.shape,x_train
((11, 1),
array([[ 0.],
[ 1.],
[ 2.],
[ 3.],
[ 4.],
[ 5.],
[ 6.],
[ 7.],
[ 8.],
[ 9.],
[10.]], dtype=float32))
y_values = [2 * x + 1 for x in x_values]
y_train = np.array(y_values,dtype=np.float32)
y_train = y_train.reshape(-1,1)
y_train
array([[ 1.],
[ 3.],
[ 5.],
[ 7.],
[ 9.],
[11.],
[13.],
[15.],
[17.],
[19.],
[21.]], dtype=float32)
import torch.nn as nn
2.2 定义一个线性回归模型
- 线性回归其实就是一个不加激活函数的全连接层
class LinearRegressionModel(nn.Module):
# __init__()函数中写的就是要用到的哪些层,是继承自nn.Model里面的
def __init__(self,input_dim,output_dim):
super(LinearRegressionModel,self).__init__()
self.liner = nn.Linear(input_dim,output_dim) # input_dim这里就是每次数据有几个特征
def forward(self,x):
out = self.liner(x)
return out
input_dim = 1
output_dim = 1
model = LinearRegressionModel(input_dim,output_dim)
model
LinearRegressionModel(
(liner): Linear(in_features=1, out_features=1, bias=True)
)
2.3 指定好参数和损失函数
epochs = 1000
learning_rate = 0.01
optimizer = torch.optim.SGD(model.parameters(),lr=learning_rate) # 传入需要更新的参数和学习率
criterion = nn.MSELoss()
2.4 训练模型
for epoch in range(epochs):
epoch += 1
# 将ndarray格式的数据转成tensor格式
inputs = torch.from_numpy(x_train)
labels = torch.from_numpy(y_train)
# 每一次迭代时,梯度要清零,否则会叠加
optimizer.zero_grad()
# 前向传播
outputs = model(inputs)
# 计算损失
loss = criterion(outputs,labels)
# 反向传播 -- 会计算梯度,但是参数没有更新
loss.backward()
# 更新参数的权重
optimizer.step() # 这个就是参数的更新
if epoch % 50 == 0:
print('epoch {},loss {}'.format(epoch,loss))
epoch 50,loss 0.24966569244861603
epoch 100,loss 0.14240005612373352
epoch 150,loss 0.0812196210026741
epoch 200,loss 0.04632469266653061
epoch 250,loss 0.026421738788485527
epoch 300,loss 0.015069996938109398
epoch 350,loss 0.008595331571996212
epoch 400,loss 0.004902484826743603
epoch 450,loss 0.0027961786836385727
epoch 500,loss 0.0015948202926665545
epoch 550,loss 0.0009096470312215388
epoch 600,loss 0.0005188201903365552
epoch 650,loss 0.0002959173871204257
epoch 700,loss 0.0001687801122898236
epoch 750,loss 9.626944665797055e-05
epoch 800,loss 5.4907563026063144e-05
epoch 850,loss 3.131549237878062e-05
epoch 900,loss 1.786198299669195e-05
epoch 950,loss 1.0188020496570971e-05
epoch 1000,loss 5.812353720102692e-06
2.5 用数据测试模型的结果
predicted = model(torch.from_numpy(x_train).requires_grad_()).data.numpy()
predicted
array([[ 0.9955155],
[ 2.9961615],
[ 4.996807 ],
[ 6.997453 ],
[ 8.998099 ],
[10.998745 ],
[12.999392 ],
[15.000037 ],
[17.000683 ],
[19.00133 ],
[21.001974 ]], dtype=float32)
predicted = model(torch.tensor([1.,4,6]).reshape(-1,1)) # 是按照列进行传数据!
predicted
tensor([[ 2.9962],
[ 8.9981],
[12.9994]], grad_fn=<AddmmBackward>)
2.6 模型的保存与存取
torch.save(model.state_dict(),'linerModel.pkl')
model.load_state_dict(torch.load('linerModel.pkl'))
<All keys matched successfully>