刘二大人《PyTorch深度学习实践》第九讲 多分类问题 Softmax Classifer
二分类问题通常使用sigmoid函数进行分类,多分类问题同通常使用softmax函数进行分类,它可以预测每个类别的概率。对于阿拉伯数字预测问题,选择预测值最高的类别作为结果即可。
以MNIST手写数字识别为例,MNIST数据集图片为28*28=784。
首先需要引入包。
import torch
from torchvision import transforms,datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
再利用dataset引入数据集。
transform=transforms.Compose([
transforms.ToTensor(), #转变为图像张量,变为多通道 1*28*28
transforms.Normalize((0.1307,),(0.3081,))]) #归一化 0-1分布
train_dataset=datasets.MNIST(root="../dataset/mnist/",train=True,download=True,transform=transform)
train_loader=DataLoader(dataset=train_dataset,shuffle=True,batch_size=batch_size)
test_dataset=datasets.MNIST(root="../dataset/mnist",train=False,download=True,transform=transform)
test_loader=DataLoader(dataset=test_dataset,shuffle=True,batch_size=batch_size)
构建神经网络,该网络有5个线性层,5个激活层,采用relu函数作为激活函数。
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
self.l1=torch.nn.Linear(784,512)
self.l2=torch.nn.Linear(512,256)
self.l3=torch.nn.Linear(256,128)
self.l4=torch.nn.Linear(128,64)
self.l5=torch.nn.Linear(64,10)
def forward(self,x):
x=x.view(-1,784)
x=F.relu(self.l1(x))
x=F.relu(self.l2(x))
x=F.relu(self.l3(x))
x=F.relu(self.l4(x))
x=F.relu(self.l5(x))
return x
定义优化和损失函数,这里损失采用交叉熵损失,优化方法为SGD。
criterion=torch.nn.CrossEntropyLoss()
optimizer=optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
定义训练函数。
def train(epoch):
running_loss=0.0
for batch_idx,data in enumerate(train_loader,0):
inputs,labels=data
optimizer.zero_grad()
outputs=model(inputs)
loss=criterion(outputs,labels)
loss.backward()
optimizer.step()
running_loss+=loss.item()
if batch_idx%300==299: #300次迭代输出一次
print('[%d,%5d] loss:%.3f' %(epoch+1,batch_idx+1,running_loss/300))
running_loss=0.0
再定义测试函数,求出测试精度。
def test():
correct=0
total=0
with torch.no_grad(): #无梯度
for data in test_loader:
images,labels=data
outputs=model(images)
_,predicted=torch.max(outputs.data,dim=1) # _为每行最大值 predicted为最大值下标
total+=labels.size(0)
correct+=(predicted==labels).sum().item()
print("Accuracy on test set:%s %%"%(100*correct/total))
完整代码为:
#MNIST手写数字识别28*28=784
import torch
from torchvision import transforms,datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
batch_size=64
transform=transforms.Compose([
transforms.ToTensor(), #转变为图像张量,变为多通道 1*28*28
transforms.Normalize((0.1307,),(0.3081,))]) #归一化 0-1分布
train_dataset=datasets.MNIST(root="../dataset/mnist/",train=True,download=True,transform=transform)
train_loader=DataLoader(dataset=train_dataset,shuffle=True,batch_size=batch_size)
test_dataset=datasets.MNIST(root="../dataset/mnist",train=False,download=True,transform=transform)
test_loader=DataLoader(dataset=test_dataset,shuffle=True,batch_size=batch_size)
#激活层relu
#输入维度为4 (样本数,1,28,28) 转化为二维 (N,784)
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
self.l1=torch.nn.Linear(784,512)
self.l2=torch.nn.Linear(512,256)
self.l3=torch.nn.Linear(256,128)
self.l4=torch.nn.Linear(128,64)
self.l5=torch.nn.Linear(64,10)
def forward(self,x):
x=x.view(-1,784)
x=F.relu(self.l1(x))
x=F.relu(self.l2(x))
x=F.relu(self.l3(x))
x=F.relu(self.l4(x))
x=F.relu(self.l5(x))
return x
model=Model()
criterion=torch.nn.CrossEntropyLoss()
optimizer=optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
def train(epoch):
running_loss=0.0
for batch_idx,data in enumerate(train_loader,0):
inputs,labels=data
optimizer.zero_grad()
outputs=model(inputs)
loss=criterion(outputs,labels)
loss.backward()
optimizer.step()
running_loss+=loss.item()
if batch_idx%300==299: #300次迭代输出一次
print('[%d,%5d] loss:%.3f' %(epoch+1,batch_idx+1,running_loss/300))
running_loss=0.0
def test():
correct=0
total=0
with torch.no_grad(): #无梯度
for data in test_loader:
images,labels=data
outputs=model(images)
_,predicted=torch.max(outputs.data,dim=1) # _为每行最大值 predicted为最大值下标
total+=labels.size(0)
correct+=(predicted==labels).sum().item()
print("Accuracy on test set:%s %%"%(100*correct/total))
if __name__=='__main__':
for epoch in range(10):
train(epoch)
test()