Sequential:是torch.nn自带的功能函数,实乃相见恨晚,它相当于把神经网络的各层装进一个容器,层与层之间通道数的变化也更加清晰。以基于线性降维的全连接对手写数字识别为例:
代码:
import torch
import torch.nn as nn
from torchvision import datasets
from torchvision import transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import sys
# 雷同的代码相应注释可查 “从梦到西洲” 早期博客
# 模型加载和进行数据运算可以选择GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# ---------------准备数据集--------------------
batch_size = 100
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_dataset = datasets.MNIST(root="../Hello/dataset/mnist", train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root="../Hello/dataset/mnist", train=False, download=True, transform=transform)
print(len(train_dataset))
print(len(test_dataset))
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
# -----------
# -----------struct model--------------
# Net是torch.nn.Module的子类
class Net(nn.Module):
# __init__初始类中数据成员
def __init__(self, *args):
# super()函数的常见的用途是通过构建子类来扩展先前构造的类的功能,从而节省重写子类的这些方法的时间
super(Net, self).__init__()
# Sequential可以将多层整合到一起被调用
self.model = nn.Sequential(
nn.Linear(784, 512),
nn.ReLU(),
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10)
)
# forward是定义在每次调用时执行的计算
def forward(self, x):
x = x.view(-1, 784)
x = self.model(x)
return x
model = Net()
model.to(device)
# ------------------------------------
# -----------loss optimizer--------------
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# ------------------------------------
# -----------train test--------------
train_loss = []
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader):
# inputs,target=data
inputs, target = data[0].to(device), data[1].to(device)
optimizer.zero_grad() # 梯度清零
outputs = model(inputs) # 加载模型
loss = criterion(outputs, target) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 梯度更新
running_loss += loss # 损失叠加
if batch_idx % 600 == 599:
train_loss.append((running_loss / 600).item()) # 计算每一轮的损失
print("%d loss: %.3f" % (epoch + 1, running_loss/ 600))
running_loss = 0.0
acc = []
def test(epoch):
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
# images,labels=data
images, labels = data[0].to(device), data[1].to(device)
ouputs = model(images)
_, predicted = torch.max(ouputs.data, dim=1)
correct += (predicted == labels).sum().item()
total += labels.size(0)
print("accurancy: %.3f %%" % (correct / total * 100))
acc.append((correct / total) * 100)
if __name__ == '__main__':
for epoch in range(150):
train(epoch)
test(epoch)
# sys.exit(0)
epochs = []
for i in range(0, 150):
epochs.append(i)
# 刻画测试数据集准确率和轮数的关系
plt.xlabel('epochs')
plt.xlabel('acc')
plt.plot(epochs, acc)
plt.show()
# 刻画训练损失和轮数的关系
plt.xlabel('epochs')
plt.xlabel('train_loss')
plt.plot(epochs, train_loss)
plt.show()
# ------------------------------------
刻画训练损失和轮数的关系
刻画测试数据集准确率和轮数的关系