小伙伴好,最近想要认真学习一波pytorch,打算通过pytorch去构建一系列的网络模型,包括CNN、LSTM、Transform等,后续都会进行搭建。一个不断学习的小菜鸡,也希望有问题小伙伴能指出。
MINST数据集是手写数字的识别,图片尺寸为(28,28,1),标签为数字的类别。
本文这次主要是对MNIST数据集进行测试。利用pytorch加载数据的方法如下:
# 利用datasets中可加载不同的数据集,本次选用MNIST数据集
from torchvision import datasets, transforms
batch_size = 128
# 加载数据
def load_data():
# 下载数据
train_data = datasets.MNIST(root='./data/',
train=True,
transform=transforms.ToTensor(),
download=True)
test_data = datasets.MNIST(root='./data/',
train=False,
transform=transforms.ToTensor())
# 返回一个数据迭代器
# shuffle:是否打乱顺序
train_loader = torch.utils.data.DataLoader(dataset=train_data,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_data,
batch_size=batch_size,
shuffle=False)
print("Loaded Data successfully!")
return train_loader, test_loader
获取数据的命令:
datasets.MNIST(root,train=True,transform=None,target_transform=None,download=False)
其中:
数据分批加载:
torch.utils.data.DataLoader(dataset=train_data,batch_size=Config.batch_size,shuffle=True)
主要实现对数据的加载,批次的数据量设置,是否打乱设置。一般训练集打乱,测试集不打乱。
如果是对自己的数据集处理,则dataset=自己的数据集,不需要使用上述加载MNIST数据集的流程。
这次主要使用BP神经网络构建,后续还会构建一些常见的CNN网络,如:LeNet、AlexNet、ResNet等进行构建。
本次构建主要包含输入层维度为28*28,输出层维度为10,隐藏层128。本次主要是对工具的使用进行介绍,小伙伴可以根据自己的需要构建网络,提高模型准确率等。
import torch
import torch.nn as nn
class BP(nn.Module):
def __init__(self):
super(BP, self).__init__()
# 构建隐藏层
self.fc1 = nn.Sequential(
nn.Linear(28*28, 128),
nn.ReLU()
)
# 构建输出层
self.fc2 = nn.Sequential(
nn.Linear(128, 10),
nn.Sigmoid()
)
def forward(self, x):
# 将照片铺平为1维向量
x = x.view(-1,784)
x = self.fc1(x)
x = self.fc2(x)
return x
data = torch.randn(1,28,28)
net = BP()
outputs = net(data)
print(outputs.shape)
构建的模型输出维度为(1,10),10代表标签的类别数目
选择合适的优化器,损失函数帮助我们的模型快速收敛,一般优化器选择Adam,SGD等效果较好,损失函数一般回归问题选择MSE,分类问题选择交叉熵损失。
# 选择损失为交叉熵损失
criterion = nn.CrossEntropyLoss()
# 选择优化器为Adam
optimizer = torch.optim.Adam()
对于一些参数的选择可以自行搜索
def train_step(self):
print("Training & Evaluating based on BP......")
file = './result/raw_train_mnist.txt'
fp = open(file,'w',encoding='utf-8')
fp.write('epoch\tbatch\tloss\taccuracy\n')
# 循环轮次
for epoch in range(Config.epoch):
# 显示当前轮
print("Epoch {:3}.".format(epoch + 1))
# 循环批次,每一批的数目当前设置128
for batch_idx,(data, label) in enumerate(self.train):
# 这里设置主要是我利用GPU训练,用cpu训练的可以忽略
data, label = Variable(data.cuda()), Variable(label.cuda())
# 优化器初始化
self.optimizer.zero_grad()
outputs = self.net(data)
# 计算损失
loss = self.criterion(outputs, label)
loss.backward()
# 进行优化计算
self.optimizer.step()
# 每100次打印一次结果
if batch_idx % Config.print_per_step == 0:
# 每100批次计算当前准确率
_, predicted = torch.max(outputs, 1)
correct = 0
for _ in predicted == label:
if _:
correct += 1
accuracy = correct / Config.batch_size
msg = "Batch: {:5}, Loss: {:6.2f}, Accuracy: {:8.2%}."
# 输出准确率
print(msg.format(batch_idx, loss, accuracy))
fp.write('{}\t{}\t{}\t{}\n'.format(epoch,batch_idx,loss,accuracy))
fp.close()
test_loss = 0.
test_correct = 0
for data, label in self.test:
data, label = Variable(data.cuda()), Variable(label.cuda())
outputs = self.net(data)
loss = self.criterion(outputs, label)
test_loss += loss * Config.batch_size
_, predicted = torch.max(outputs, 1)
correct = int(sum(predicted == label))
test_correct += correct
accuracy = test_correct / len(self.test.dataset)
loss = test_loss / len(self.test.dataset)
print("Test Loss: {:5.2f}, Accuracy: {:6.2%}".format(loss, accuracy))
torch.save(self.net.state_dict(),'./result/raw_train_mnist_model.pth')
import torch
from torchvision import datasets, transforms
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
import numpy as np
device = torch.device('cuda:0')
class Config:
batch_size = 128
epoch = 10
alpha = 1e-3
print_per_step = 100 # 控制输出
class BP(nn.Module):
def __init__(self):
super(BP, self).__init__()
self.fc1 = nn.Sequential(
nn.Linear(28*28, 128),
nn.ReLU()
)
self.fc2 = nn.Sequential(
nn.Linear(128, 10),
nn.Sigmoid()
)
def forward(self, x):
x = x.view(-1,784)
x = self.fc1(x)
x = self.fc2(x)
return x
class TrainProcess:
def __init__(self):
self.train, self.test = self.load_data()
self.net = BP().to(device)
self.criterion = nn.CrossEntropyLoss() # 定义损失函数
self.optimizer = optim.Adam(self.net.parameters(), lr=Config.alpha)
@staticmethod
def load_data():
train_data = datasets.MNIST(root='./data/',
train=True,
transform=transforms.ToTensor(),
download=True)
test_data = datasets.MNIST(root='./data/',
train=False,
transform=transforms.ToTensor())
# 返回一个数据迭代器
# shuffle:是否打乱顺序
train_loader = torch.utils.data.DataLoader(dataset=train_data,
batch_size=Config.batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_data,
batch_size=Config.batch_size,
shuffle=False)
return train_loader, test_loader
def train_step(self):
print("Training & Evaluating based on BP......")
file = './result/raw_train_mnist.txt'
fp = open(file,'w',encoding='utf-8')
fp.write('epoch\tbatch\tloss\taccuracy\n')
for epoch in range(Config.epoch):
print("Epoch {:3}.".format(epoch + 1))
for batch_idx,(data, label) in enumerate(self.train):
data, label = Variable(data.cuda()), Variable(label.cuda())
self.optimizer.zero_grad()
outputs = self.net(data)
loss = self.criterion(outputs, label)
loss.backward()
self.optimizer.step()
# 每100次打印一次结果
if batch_idx % Config.print_per_step == 0:
_, predicted = torch.max(outputs, 1)
correct = 0
for _ in predicted == label:
if _:
correct += 1
accuracy = correct / Config.batch_size
msg = "Batch: {:5}, Loss: {:6.2f}, Accuracy: {:8.2%}."
print(msg.format(batch_idx, loss, accuracy))
fp.write('{}\t{}\t{}\t{}\n'.format(epoch,batch_idx,loss,accuracy))
fp.close()
test_loss = 0.
test_correct = 0
for data, label in self.test:
data, label = Variable(data.cuda()), Variable(label.cuda())
outputs = self.net(data)
loss = self.criterion(outputs, label)
test_loss += loss * Config.batch_size
_, predicted = torch.max(outputs, 1)
correct = 0
for _ in predicted == label:
if _:
correct += 1
test_correct += correct
accuracy = test_correct / len(self.test.dataset)
loss = test_loss / len(self.test.dataset)
print("Test Loss: {:5.2f}, Accuracy: {:6.2%}".format(loss, accuracy))
torch.save(self.net.state_dict(),'./result/raw_train_mnist_model.pth')
if __name__ == "__main__":
p = TrainProcess()
p.train_step()
训练结果:
Training & Evaluating based on BP......
Epoch 1.
Batch: 0, Loss: 2.31, Accuracy: 10.16%.
Batch: 100, Loss: 1.68, Accuracy: 83.59%.
Batch: 200, Loss: 1.60, Accuracy: 89.84%.
Batch: 300, Loss: 1.60, Accuracy: 85.94%.
Batch: 400, Loss: 1.55, Accuracy: 91.41%.
Epoch 2.
Batch: 0, Loss: 1.54, Accuracy: 91.41%.
Batch: 100, Loss: 1.56, Accuracy: 89.84%.
Batch: 200, Loss: 1.53, Accuracy: 91.41%.
Batch: 300, Loss: 1.56, Accuracy: 91.41%.
Batch: 400, Loss: 1.51, Accuracy: 96.09%.
Epoch 3.
Batch: 0, Loss: 1.50, Accuracy: 97.66%.
Batch: 100, Loss: 1.54, Accuracy: 92.19%.
Batch: 200, Loss: 1.52, Accuracy: 93.75%.
Batch: 300, Loss: 1.51, Accuracy: 95.31%.
Batch: 400, Loss: 1.53, Accuracy: 93.75%.
Epoch 4.
Batch: 0, Loss: 1.51, Accuracy: 94.53%.
Batch: 100, Loss: 1.50, Accuracy: 94.53%.
Batch: 200, Loss: 1.52, Accuracy: 95.31%.
Batch: 300, Loss: 1.53, Accuracy: 93.75%.
Batch: 400, Loss: 1.50, Accuracy: 96.88%.
Epoch 5.
Batch: 0, Loss: 1.49, Accuracy: 96.88%.
Batch: 100, Loss: 1.50, Accuracy: 96.09%.
Batch: 200, Loss: 1.50, Accuracy: 97.66%.
Batch: 300, Loss: 1.50, Accuracy: 93.75%.
Batch: 400, Loss: 1.50, Accuracy: 95.31%.
Epoch 6.
Batch: 0, Loss: 1.51, Accuracy: 96.88%.
Batch: 100, Loss: 1.51, Accuracy: 94.53%.
Batch: 200, Loss: 1.54, Accuracy: 92.97%.
Batch: 300, Loss: 1.48, Accuracy: 97.66%.
Batch: 400, Loss: 1.51, Accuracy: 96.09%.
Epoch 7.
Batch: 0, Loss: 1.50, Accuracy: 96.88%.
Batch: 100, Loss: 1.51, Accuracy: 95.31%.
Batch: 200, Loss: 1.49, Accuracy: 96.88%.
Batch: 300, Loss: 1.50, Accuracy: 94.53%.
Batch: 400, Loss: 1.49, Accuracy: 94.53%.
Epoch 8.
Batch: 0, Loss: 1.49, Accuracy: 96.88%.
Batch: 100, Loss: 1.49, Accuracy: 97.66%.
Batch: 200, Loss: 1.49, Accuracy: 96.88%.
Batch: 300, Loss: 1.51, Accuracy: 96.09%.
Batch: 400, Loss: 1.51, Accuracy: 96.88%.
Epoch 9.
Batch: 0, Loss: 1.49, Accuracy: 96.88%.
Batch: 100, Loss: 1.50, Accuracy: 95.31%.
Batch: 200, Loss: 1.49, Accuracy: 96.09%.
Batch: 300, Loss: 1.49, Accuracy: 96.09%.
Batch: 400, Loss: 1.49, Accuracy: 98.44%.
Epoch 10.
Batch: 0, Loss: 1.48, Accuracy: 97.66%.
Batch: 100, Loss: 1.48, Accuracy: 98.44%.
Batch: 200, Loss: 1.50, Accuracy: 95.31%.
Batch: 300, Loss: 1.49, Accuracy: 97.66%.
Batch: 400, Loss: 1.49, Accuracy: 97.66%.
Test Loss: 1.51, Accuracy: 97.02%
这里训练了10的epoch就可以达到97%,而且是非常简单的神经网络。希望可以帮助大家可以快速上手pytorch。