点击【拇指笔记】,关注我的公众号。
这一部分依然使用之前的Fashion-MNIST数据集。
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 = 0)
test_iter = torch.utils.data.DataLoader(mnist_test,batch_size = batch_size,shuffle=False,num_workers=0)
Fashion-MNIST数据集中的图像为28*28像素,也就是由784个特征值。Fashion-MNIST数据集一共有十个类别。因此模型需要784个输入,10个输出。假设隐藏单元为256(超参数,可调节)。
num_inputs,num_outputs,num_hiddens = 784,10,256
#隐藏层权重参数、隐藏层偏差参数、输出层权重参数和输出层偏差参数初始化。
w1 = torch.tensor(np.random.normal(0,0.01,(num_inputs,num_hiddens)),dtype = torch.float)
b1 = torch.zeros(num_hiddens,dtype = torch.float)
w2 = torch.tensor(np.random.normal(0,0.01,(num_hiddens,num_outputs)),dtype = torch.float)
b2 = torch.zeros(num_outputs,dtype = torch.float)
params = [w1,b1,w2,b2]
#对w1,w2,b1,b2开启自动求导
for param in params:
param.requirers_grad_(requires_grad = True)
def relu(X): return torch.max(input=X,other = torch.tensor(0.0))
def net(X):
X = X.view((-1,num_inputs))
#将输入换形为列向量的形式
H = relu(torch.matmul(X,W1)+b1)
#计算出隐藏层的输出
O = torch.matmul(H,W2)+b2
#计算输出
return O
这里采用计算softmax运算和交叉熵数值稳定性更好的函数。
loss = torch.nn.CrossEntropyLoss()
使用小批量随机梯度下降算法。
def sgd(params,lr,batch_size):
#lr:学习率,params:权重参数和偏差参数
for param in params:
param.data -= lr*param.grad/batch_size
#.data是对数据备份进行操作,不改变数据本身。
计算准确率的原理:
我们把预测概率最大类别作为输出类别,如果它与真实类别一致,说明预测正确。分类准确率就是正确预测数量与总预测数量之比。
首先我们需要得到预测的结果。
从一组预测概率(变量y_hat)中找出最大的概率对应的索引(索引即代表了类别)
#argmax(f(x))函数,对f(x)求最大值所对应的点x。我们令f(x)= dim=1,即可实现求所有行上的最大值对应的索引。
A = y_hat.argmax(dim=1)
然后我们需要将得到的最大概率对应的类别与真实类别(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、隐藏层神经单元数num_hiddens和学习率lr都是可以调节的超参数,通过调节超参数的值可以获得分类更准确的模型。
num_epochs,lr = 5,100
def train_MLP(net,train_iter,test_iter,loss,num_epochs,batch_size,params,lr ,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() #对优化函数梯度清零
for param in params:
param.grad.data.zero_()
l.backward() #对损失函数求梯度
optimzer(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_accuracy(test_iter, net) #测试集的准确率
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f' % (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))
train_MLP(net,train_iter,test_iter,loss,num_epochs,batch_size,params,lr,sgd,net_accurary)
可以看出,使用了多层感知机后,神经网络的识别准确率有了提升。且运行时间有所加长(5个学习周期运行了80秒)。
单线程:运行了80s。
四线程:运行了41s。
使用训练好的模型对测试集进行预测
做一个模型的最终目的当然不是训练了,所以来识别数据集试试。
#将样本的类别数字转换成文本
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])