极限速成pytorch

最近在准备搞搞这个自己的毕业设计,复现两篇论文什么的,于是要重新捡起好久不写的pytorch,于是决定简单写一个速成教程。首先,我得讲一下我的速成思想:对比学习+调整,还有速成不等于质量差,仅仅代表高效。

img

焚电子高香,敲电子木鱼

炼赛博丹药,成赛博神仙

数据操作

这里我们以numpy作为原本的模板,只指出差异,不处理相同部分,减少学习成本

很好,我们通过看文档发现貌似没什么不一样的,只是把原来的np改为torch

下面不解释的罗列:

1
2
3
4
5
6
7
import torch
torch.arrange(n) # 生成从0到n的整数
torch.shape # 查看形状
torch.reshape(Size) # 改变形状
torch.zeros(Size) # 全0矩阵
torch.ones(Size) # 全1矩阵
torch.randn(Size) # 正态分布随机数,对应的np.random.randn()

同样的,torch中也有numpy中类似的初始化方法,其使用方式与numpy一致:

1
2
3
import numpy as np
np.array()
torch.tensor()

两者具有完全一致的基本运算、广播机制、索引和切片,所以这块直接可以不学。

转换语法:

1
2
X.numpy()
torch.tensor(ndarray)

pandas转换为tensor格式

1
2
3
a = pd.read_csv("you.csv")
my_array = np.array(a)
my_tensor = torch.tensor(my_array)

线性代数

其实各种运算和numpy还是基本一样的,除了两个特定的乘法:

1
2
3
4
# 矩阵对向量乘法
torch.mv(A,x)
# 矩阵对矩阵乘法,非dot,非hadamard
torch.mm(A,B)

然后我们研究一点一点不一样的东西,也是会对写网络有帮助的,不同于我们在使用numpy手搓时,pytorch是以批为单位进网络训练,所以对轴的操作非常频繁,我以前理解轴,表示非常难记住,然后我查资料发现:轴实际上就是Shape这个list的下标

自动微分

y1s1,这应该是pytorch中最重要的功能了,自动微分提供了一个很大的便利,那就是不在需要人手去写backward函数,我们也不去纠结什么计算图什么玩意,我们直接上例子:

1
2
3
4
5
6
7
8
9
10
11
12
from torch.autograd import Variable
# 设置一个变量x,实际上呢这句话已经可以简化了
x=Variable(torch.ones(2,2),requires_grad=True)
# x=torch。ones(2,2,requires_grad=True)
y=x+2
# 这句就是在查看梯度函数的入口
y.grad_fn
z=y*y*3
out=z.mean()
# 这就是自动微分的神奇之处了
out.backward()
x.grad

原理什么的我们不去细究,甚至连参数列表我们也不去细究,就先了解到这儿,知道他很神奇就够了(毕竟一时半会儿也不用)

神经网络

看到这儿除了对自动微分可能有点懵,肯定觉得,pytorch就这?其实pytorch是出了名的接口简单,but重头戏才刚开始。这里呢,我么使用我们的传统艺能,拟合sin曲线,来走一个全部的流程,然后就能理解如何操作了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import torch
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable

# 先来一个我抄我自己,生成数据集
# 创建数据
x = torch.linspace(0, 1, 100)
y = torch.sin(2 * np.pi * x)

# 添加随机噪声
np.random.seed(20)
y_noisy = y + 0.05 * torch.randn(size=x.shape)

plt.figure()
plt.plot(x, y, label='True function', color='g')
plt.scatter(x, y_noisy, edgecolor='b', s=20, label='Noisy samples')
plt.legend()
plt.tight_layout()
plt.show()
image-20240221223054399
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.fc=nn.Linear(100,5)

def forward(self,x):
output=F.tanh(x)
output=self.fc(output)
output= output[0]+output[1]*x+output[2]*x**2+output[3]*x**3+output[4]*x**4
return output

net=Net()
criterion = nn.MSELoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
1
2
3
4
5
6
7
8
9
for i in range(30000):
y_pred=net(x)

loss=criterion(y_pred,y)
if i % 2000 == 1999:
print("epoch:{},mse:{}".format(i+1,loss.item()))
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch:2000,mse:0.10116397589445114
epoch:4000,mse:0.05751330405473709
epoch:6000,mse:0.034589387476444244
epoch:8000,mse:0.02254333905875683
epoch:10000,mse:0.016206299886107445
epoch:12000,mse:0.012865572236478329
epoch:14000,mse:0.011097476817667484
epoch:16000,mse:0.010154816322028637
epoch:18000,mse:0.009645464830100536
epoch:20000,mse:0.009363631717860699
epoch:22000,mse:0.009201298467814922
epoch:24000,mse:0.0091018071398139
epoch:26000,mse:0.009035366587340832
epoch:28000,mse:0.008986384607851505
epoch:30000,mse:0.008946665562689304
1
2
3
4
5
6
7
8
9
x_test=torch.linspace(0, 1, 100)
y_pred=net(x_test)
plt.figure()
plt.plot(x_test.detach().numpy(), y_pred.detach().numpy(), label='Regressor', color='#FFA628')
plt.plot(x, y, label='True function', color='g')
plt.scatter(x, y_noisy, edgecolor='b', s=20, label='Noisy samples')
plt.legend()
plt.tight_layout()
plt.show()

image-20240221223015717

再要加强的话,就要去学习一些dataloarder等一些包,目前来说就足够了

参考资料

zh-v2.d2l.ai/d2l-zh-pytorch.pdf

PyTorch的自动微分(autograd)_pytorch 自动微分-CSDN博客