PyTorch是一个基于Python的开源机器学习库,广泛用于深度学习任务。它由Facebook的人工智能研究团队于2016年开发并发布。以下是对PyTorch的详细介绍:
1. 动态计算图(Dynamic Computational Graph):
PyTorch采用了动态计算图的方式来构建模型。与静态计算图的框架(如TensorFlow)相比,动态计算图允许你在运行时使用Python控制流语句(如if,for循环等),并根据需要改变计算图的结构。这使得PyTorch更灵活,并且更适合用于研究和实验。
2. 张量(Tensor):
PyTorch中的核心数据结构是张量。张量类似于NumPy的多维数组,可以在GPU上加速计算。PyTorch的张量支持自动求导功能,并且自动求导过程是通过跟踪计算图来实现的。
3. 自动求导(Autograd):
PyTorch的自动求导机制使得对模型的梯度计算变得非常简单。通过将`requires_grad=True`设置为张量的属性,PyTorch会自动跟踪这个张量在计算中的操作,并构建计算图。然后,通过调用`backward()`函数,就可以自动计算模型的梯度。
4. 模型构建:
使用PyTorch可以非常灵活地构建深度学习模型。你可以使用`torch.nn`模块中的各种层来构建模型,也可以自定义模型的结构。类似于其他深度学习框架,你需要定义模型的前向传播函数,并根据需要使用各种层来定义模型的网络结构。
5. 训练模型:
PyTorch提供了一系列优化器(如SGD、Adam等)来优化模型的参数。你可以通过计算损失函数来指导优化器的更新过程。通常,训练模型的过程包括以下几个步骤:准备数据、定义模型、定义损失函数、选择优化器、迭代训练过程。
6. GPU加速:
PyTorch提供了简单而有效的方式在GPU上进行加速计算。通过将张量移动到GPU上,可以利用GPU的并行计算能力来加速模型的训练和推理。此外,PyTorch还提供了一些辅助函数,用于在CPU和GPU之间无缝切换。
如果之前有参考过我的博文的话应该会有所了解,我基本上90%的项目都是基于keras+Tensorflow构建的,而基于PyTorch的相关项目开发实践会偏少一下,因为最初入坑深度学习的时候就是接触的Tensorflow,本文的核心目的就是想要对标Keras来系统性地总结记录下PyTorch框架开发构建模型的几种主流方式,本质上来讲对于这些高级的框架来说,搭建开发模型的思想都是相似的,总结对比学习有助于系统理解消化。
基于PyTroch主要有三种构建模型的方式:
1、nn.Sequential按层顺序构建模型
使用nn.Sequential是一种简单而方便的方式来构建模型,它允许顺序地将模块组合在一起。nn.Sequential是 nn.Module 的子类,可以包含一个或多个模块,并按照顺序依次应用这些模块。每个模块的输出作为下一个模块的输入,形成一个顺序的网络结构。
demo代码实现如下所示:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
model = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
这种方式是我觉得跟Keras的函数模型构建方式最为相似的方法了。
2、继承nn.Module基类构建自定义模型
首先,我们定义一个继承自nn.Module类的自定义模型类,可以根据需求定义模型的结构和前向传播逻辑。
demo代码实现如下所示:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.flatten = nn.Flatten()
self.linear1 = nn.Linear(784, 256)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(256, 10)
def forward(self, x):
x = self.flatten(x)
x = self.linear1(x)
x = self.relu(x)
x = self.linear2(x)
return x
这种方式应该是我们耳熟能详的最为经典的PyTroch构建模型的方式了,也是最为主流的方式了。
3、继承nn.Module基类构建模型并辅助应用模型容器来封装
当模型的结构比较复杂时,我们可以应用模型容器(nn.Sequential,nn.ModuleList,nn.ModuleDict)对模型的部分结构进行封装。这样做会让模型整体更加有层次感,有时候也能减少代码量。
demo代码实现如下所示:
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.layers = nn.ModuleList([
nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
])
def forward(self, x):
for layer in self.layers:
x = layer(x)
return x
model = MyModel()
这里仅仅是示意代码,可以用作模型容器的有好几种对象,如下所示:
nn.Sequential
nn.ModuleList
nn.ModuleDict
这里分别给出来了三种模型构建的方式,之后同样以mnist数据集为例,给出代码实现:
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST('data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
def train(model, train_loader, criterion, optimizer, epochs):
model.train()
for epoch in range(epochs):
running_loss = 0.0
for inputs, labels in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print('Epoch {} - Training loss: {:.4f}'.format(epoch+1, running_loss/len(train_loader)))
train(model, train_loader, criterion, optimizer, epochs=5)
def evaluate(model, test_loader):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in test_loader:
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on test set: {:.2f}%'.format(100 * correct / total))
evaluate(model, test_loader)
在后面的实际项目中可以基于上面三种不同的模型构建方式来开发构建模型,根据特定的需求场景来选取对应的方式。