使用pytorch可以更加便利的实现softmax回归模型。
读取小批量数据的方法:
由softmax回归模型的定义可知,softmax回归模型只有权重参数和偏差参数。因此可以使用神经网络子模块中的线性模块。
num_inputs = 784
num_outputs = 10
class LinearNet(nn.Module):
def __init__(self,num_inputs,num_outputs):
super(LinearNet,self).__init__()
self.linear = nn.Linear(num_inputs,num_outputs)
#定义一个输入层
#定义向前传播(在这个两层网络中,它也是输出层)
def forward(self,x):
y = self.linear(x.view(x.shape[0],-1))
#将x换形为y后,再继续向前传播
return y
net = LinearNet(num_inputs,num_outputs)
使用torch.nn中的init可以快速的初始化参数。我们令权重参数为均值为0,标准差为0.01的正态分布。偏差为0。
init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)
分开定义softmax运算和交叉熵损失函数会造成数值不稳定。因此PyTorch提供了一个具有良好数值稳定性且包括softmax运算和交叉熵计算的函数。
loss = nn.CrossEntropyLoss()
依然使用小批量随机梯度下降作为优化算法。定义学习率为0.1。
optimizer = torch.optim.SGD(net.parameters(),lr=0.01)
计算准确率的原理:
我们把预测概率最大的类别作为输出类别,如果它与真实类别y一致,说明预测正确。分类准确率就是正确预测数量与总预测数量之比
首先我们需要得到预测的结果。
从一组预测概率(变量y_hat)中找出最大的概率对应的索引(索引即代表了类别)
#argmax(f(x))函数,对f(x)求最大值所对应的点x。我们令f(x)= dim=1,即可实现求所有行上的最大值对应的索引。
A = y_hat.argmax(dim=1)
#最终输出结果为一个行数与y_hat相同的列向量
然后我们需要将得到的最大概率对应的类别与真实类别(y)比较,判断预测是否是正确的
B = (y_hat.argmax(dim=1)==y).float()
#由于y_hat.argmax(dim=1)==y得到的是ByteTensor型数据,所以我们通过.float()将其转换为浮点型Tensor()
最后我们需要计算分类准确率
我们知道y_hat的行数就对应着样本总数,所以,对B求平均值得到的就是分类准确率
(y_hat.argmax(dim=1)==y).float().mean()
上一步最终得到的数据为tensor(x)的形式,为了得到最终的pytorch number,需要对其进行下一步操作
(y_hat.argmax(dim=1)==y).float().mean().item()
#pytorch number的获取统一通过.item()实现
整理一下,得到计算分类准确率函数
def accuracy(y_hat,y):
return (y_hat.argmax(dim=1).float().mean().item())
作为推广,该函数还可以评价模型net在数据集data_iter上的准确率。
def net_accurary(data_iter,net):
right_sum,n = 0.0,0
for X,y in data_iter:
#从迭代器data_iter中获取X和y
right_sum += (net(X).argmax(dim=1)==y).float().sum().item()
#计算准确判断的数量
n +=y.shape[0]
#通过shape[0]获取y的零维度(列)的元素数量
return right_sum/n
num_epochs = 5
#一共进行五个学习周期
def train_softmax(net,train_iter,test_iter,loss,num_epochs,batch_size,optimizer,net_accurary):
for epoch in range(num_epochs):
#损失值、正确数量、总数 初始化。
train_l_sum,train_right_sum,n= 0.0,0.0,0
for X,y in train_iter:
y_hat = net(X)
l = loss(y_hat,y).sum()
#数据集损失函数的值=每个样本的损失函数值的和。
optimizer.zero_grad() #对优化函数梯度清零
l.backward() #对损失函数求梯度
optimizer(params,lr,batch_size)
train_l_sum += l.item()
train_right_sum += (y_hat.argmax(dim=1) == y).sum().item()
n += y.shape[0]
test_acc = net_accurary(test_iter, net) #测试集的准确率
print('epoch %d, loss %.4f, train right %.3f, test acc %.3f' % (epoch + 1, train_l_sum / n, train_right_sum / n, test_acc))
train_softmax(net,train_iter,test_iter,cross_entropy,num_epochs,batch_size,optimizernet_accurary,net_accurary)
训练属实是有点慢,只训练了五个周期。训练结果:
使用训练好的模型对测试集进行预测
做一个模型的最终目的当然不是训练了,所以来预测一下试试。
#将样本的类别数字转换成文本
def get_Fashion_MNIST_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
#labels是一个列表,所以有了for循环获取这个列表对应的文本列表
#显示图像
def show_fashion_mnist(images,labels):
display.set_matplotlib_formats('svg')
#绘制矢量图
_,figs = plt.subplots(1,len(images),figsize=(12,12))
#设置添加子图的数量、大小
for f,img,lbl in zip(figs,images,labels):
f.imshow(img.view(28,28).numpy())
f.set_title(lbl)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.show()
#从测试集中获得样本和标签
X, y = iter(test_iter).next()
true_labels = get_Fashion_MNIST_labels(y.numpy())
pred_labels = get_Fashion_MNIST_labels(net(X).argmax(dim=1).numpy())
#将真实标签和预测得到的标签加入到图像上
titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]
show_fashion_mnist(X[0:9], titles[0:9])
预测结果:
import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("..")
import torchvision
from IPython import display
from numpy import argmax
import torchvision.transforms as transforms
from time import time
import matplotlib.pyplot as plt
import numpy as np
batch_size =256
mnist_train = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=True,download=True,transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=False,download=True,transform=transforms.ToTensor())
#生成迭代器
train_iter = torch.utils.data.DataLoader(mnist_train,batch_size=batch_size,shuffle = True,num_workers = 4)
test_iter = torch.utils.data.DataLoader(mnist_test,batch_size = batch_size,shuffle=False,num_workers=4)
num_inputs = 784
num_outputs = 10
class LinearNet(nn.Module):
def __init__(self,num_inputs,num_outputs):
super(LinearNet,self).__init__()
self.linear = nn.Linear(num_inputs,num_outputs)
#定义一个输入层
#定义向前传播(在这个两层网络中,它也是输出层)
def forward(self,x):
y = self.linear(x.view(x.shape[0],-1))
#将x换形为y后,再继续向前传播
return y
net = LinearNet(num_inputs,num_outputs)
#初始化参数
init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)
#损失函数
loss = nn.CrossEntropyLoss()
#优化函数
optimizer = torch.optim.SGD(net.parameters(),lr=0.01)
num_epochs = 5
#一共进行五个学习周期
#计算准确率
def net_accurary(data_iter,net):
right_sum,n = 0.0,0
for X,y in data_iter:
#从迭代器data_iter中获取X和y
right_sum += (net(X).argmax(dim=1)==y).float().sum().item()
#计算准确判断的数量
n +=y.shape[0]
#通过shape[0]获取y的零维度(列)的元素数量
return right_sum/n
def get_Fashion_MNIST_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
#labels是一个列表,所以有了for循环获取这个列表对应的文本列表
def show_fashion_mnist(images,labels):
display.set_matplotlib_formats('svg')
#绘制矢量图
_,figs = plt.subplots(1,len(images),figsize=(12,12))
#设置添加子图的数量、大小
for f,img,lbl in zip(figs,images,labels):
f.imshow(img.view(28,28).numpy())
f.set_title(lbl)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.show()
def train_softmax(net,train_iter,test_iter,loss,num_epochs,batch_size,optimizer,net_accurary):
for epoch in range(num_epochs):
#损失值、正确数量、总数 初始化。
train_l_sum,train_right_sum,n= 0.0,0.0,0
for X,y in train_iter:
y_hat = net(X)
l = loss(y_hat,y).sum()
#数据集损失函数的值=每个样本的损失函数值的和。
optimizer.zero_grad() #对优化函数梯度清零
l.backward() #对损失函数求梯度
optimizer.step()
train_l_sum += l.item()
train_right_sum += (y_hat.argmax(dim=1) == y).sum().item()
n += y.shape[0]
test_acc = net_accurary(test_iter, net) #测试集的准确率
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f' % (epoch + 1, train_l_sum / n, train_right_sum / n, test_acc))
train_softmax(net,train_iter,test_iter,loss,num_epochs,batch_size,optimizer,net_accurary)
X, y = iter(test_iter).next()
true_labels = get_Fashion_MNIST_labels(y.numpy())
pred_labels = get_Fashion_MNIST_labels(net(X).argmax(dim=1).numpy())
titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]
show_fashion_mnist(X[0:9], titles[0:9])