5.2 多层感知机代码实现
在 PyTorch 中实现多层感知机(MLP)可以分为以下几步:
导入所需的库和模块,包括 PyTorch 的 nn 模块,torch.optim 模块和数据加载及预处理的常用库,例如 torchvision 和 torchtext。
定义多层感知机模型。这可以通过继承 PyTorch 的 nn.Module 类并定义前向传播函数来完成。
加载数据集。这可以使用 PyTorch 提供的数据加载器或自定义加载器完成。
定义损失函数和优化器。这可以使用 PyTorch 的内置函数和优化器来完成。
开始训练模型。在训练循环中,您需要通过获取输入和标签,计算模型输出,计算损失并更新模型参数来训练模型。
在训练之后,可以使用模型进行推理或将其保存以供将来使用。
下面这个例子中,梗直哥给你演示了一个包含两个隐藏层的 MLP实现,使用 MNIST 数据集进行训练,一起来感受一下整个过程:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
# 定义 MLP 网络
class MLP(nn.Module):
def __init__(self, input_size, hidden_size, num_classes):
super(MLP, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, hidden_size)
self.fc3 = nn.Linear(hidden_size, num_classes)
def forward(self, x):
out = self.fc1(x)
out = self.relu(out)
out = self.fc2(out)
out = self.relu(out)
out = self.fc3(out)
return out
# 定义超参数
input_size = 28 * 28 # 输入大小
hidden_size = 512 # 隐藏层大小
num_classes = 10 # 输出大小(类别数)
batch_size = 100 # 批大小
learning_rate = 0.001 # 学习率
num_epochs = 10 # 训练轮数
# 加载 MNIST 数据集
train_dataset = datasets.MNIST(root='../data/mnist', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='../data/mnist', train=False, transform=transforms.ToTensor(), download=True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
# 实例化 MLP 网络
model = MLP(input_size, hidden_size, num_classes)
现在我们已经定义了 MLP 网络并加载了 MNIST 数据集,接下来使用 PyTorch 的自动求导功能和优化器进行训练。首先,定义损失函数和优化器;然后迭代训练数据并使用优化器更新网络参数。
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 训练网络
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.reshape(-1, 28 * 28)
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}')
Epoch [1/10], Step [100/600], Loss: 0.0419
Epoch [1/10], Step [200/600], Loss: 0.0931
Epoch [1/10], Step [300/600], Loss: 0.0609
Epoch [1/10], Step [400/600], Loss: 0.0482
Epoch [1/10], Step [500/600], Loss: 0.1138
Epoch [1/10], Step [600/600], Loss: 0.0533
Epoch [2/10], Step [100/600], Loss: 0.0340
Epoch [2/10], Step [200/600], Loss: 0.0619
Epoch [2/10], Step [300/600], Loss: 0.2061
Epoch [2/10], Step [400/600], Loss: 0.0695
Epoch [2/10], Step [500/600], Loss: 0.0269
Epoch [2/10], Step [600/600], Loss: 0.0330
Epoch [3/10], Step [100/600], Loss: 0.0135
Epoch [3/10], Step [200/600], Loss: 0.0710
Epoch [3/10], Step [300/600], Loss: 0.0089
Epoch [3/10], Step [400/600], Loss: 0.0139
Epoch [3/10], Step [500/600], Loss: 0.0786
Epoch [3/10], Step [600/600], Loss: 0.0331
Epoch [4/10], Step [100/600], Loss: 0.0072
Epoch [4/10], Step [200/600], Loss: 0.0183
Epoch [4/10], Step [300/600], Loss: 0.0291
Epoch [4/10], Step [400/600], Loss: 0.0399
Epoch [4/10], Step [500/600], Loss: 0.0065
Epoch [4/10], Step [600/600], Loss: 0.0306
Epoch [5/10], Step [100/600], Loss: 0.0097
Epoch [5/10], Step [200/600], Loss: 0.0073
Epoch [5/10], Step [300/600], Loss: 0.0327
Epoch [5/10], Step [400/600], Loss: 0.0027
Epoch [5/10], Step [500/600], Loss: 0.0254
Epoch [5/10], Step [600/600], Loss: 0.0136
Epoch [6/10], Step [100/600], Loss: 0.0195
Epoch [6/10], Step [200/600], Loss: 0.0124
Epoch [6/10], Step [300/600], Loss: 0.0065
Epoch [6/10], Step [400/600], Loss: 0.0975
Epoch [6/10], Step [500/600], Loss: 0.0333
Epoch [6/10], Step [600/600], Loss: 0.0346
Epoch [7/10], Step [100/600], Loss: 0.0055
Epoch [7/10], Step [200/600], Loss: 0.0003
Epoch [7/10], Step [300/600], Loss: 0.0014
Epoch [7/10], Step [400/600], Loss: 0.0052
Epoch [7/10], Step [500/600], Loss: 0.0592
Epoch [7/10], Step [600/600], Loss: 0.0139
Epoch [8/10], Step [100/600], Loss: 0.0196
Epoch [8/10], Step [200/600], Loss: 0.0122
Epoch [8/10], Step [300/600], Loss: 0.0211
Epoch [8/10], Step [400/600], Loss: 0.0009
Epoch [8/10], Step [500/600], Loss: 0.0464
Epoch [8/10], Step [600/600], Loss: 0.0207
Epoch [9/10], Step [100/600], Loss: 0.0078
Epoch [9/10], Step [200/600], Loss: 0.0047
Epoch [9/10], Step [300/600], Loss: 0.0029
Epoch [9/10], Step [400/600], Loss: 0.0047
Epoch [9/10], Step [500/600], Loss: 0.0724
Epoch [9/10], Step [600/600], Loss: 0.0219
Epoch [10/10], Step [100/600], Loss: 0.0008
Epoch [10/10], Step [200/600], Loss: 0.0054
Epoch [10/10], Step [300/600], Loss: 0.0015
Epoch [10/10], Step [400/600], Loss: 0.0029
Epoch [10/10], Step [500/600], Loss: 0.0043
Epoch [10/10], Step [600/600], Loss: 0.0025
最后,我们可以在测试数据上评估模型的准确率:
# 测试网络
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
images = images.reshape(-1, 28 * 28)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total} %')
Accuracy of the network on the 10000 test images: 97.88 %
可以看到训练效果还不错,准确率97.88%。
梗直哥建议:我们这节课言简意赅的讲解了一个例子,主要目的是突出代码实现。如果你在理解方面感觉自己有问题,可以稍微分析一下原因。如果代码看不懂是python的问题,可以考虑补充这方面知识。如果对神经网络原理还希望了解更多,可以选修哥《机器学习必修课:python实战》中神经网络相关章节内容。如果是运行或调参经验缺乏,欢迎入群讨论(微信:gengzhige99)