前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【动手学深度学习笔记】之多层感知机实现

【动手学深度学习笔记】之多层感知机实现

作者头像
树枝990
发布2020-08-19 22:39:59
6070
发布2020-08-19 22:39:59
举报
文章被收录于专栏:拇指笔记

点击【拇指笔记】,关注我的公众号。


1.1 获取和读取数据

这一部分依然使用之前的Fashion-MNIST数据集。

代码语言:javascript
复制
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)

1.2 定义并初始化模型参数

Fashion-MNIST数据集中的图像为28*28像素,也就是由784个特征值。Fashion-MNIST数据集一共有十个类别。因此模型需要784个输入,10个输出。假设隐藏单元为256(超参数,可调节)。

代码语言:javascript
复制
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)

代码语言:javascript
复制
def relu(X):	return torch.max(input=X,other = torch.tensor(0.0))

1.4 定义模型

代码语言:javascript
复制
def net(X):
	X = X.view((-1,num_inputs))
    #将输入换形为列向量的形式
    H = relu(torch.matmul(X,W1)+b1)
    #计算出隐藏层的输出
    O = torch.matmul(H,W2)+b2
    #计算输出
    return O

1.5 定义损失函数

这里采用计算softmax运算和交叉熵数值稳定性更好的函数。

代码语言:javascript
复制
loss = torch.nn.CrossEntropyLoss()

1.6 优化函数

使用小批量随机梯度下降算法。

代码语言:javascript
复制
def sgd(params,lr,batch_size):
    #lr:学习率,params:权重参数和偏差参数
    for param in params:
        param.data -= lr*param.grad/batch_size
        #.data是对数据备份进行操作,不改变数据本身。

1.7 计算分类准确率

计算准确率的原理:

我们把预测概率最大类别作为输出类别,如果它与真实类别一致,说明预测正确。分类准确率就是正确预测数量与总预测数量之比。

首先我们需要得到预测的结果。

从一组预测概率(变量y_hat)中找出最大的概率对应的索引(索引即代表了类别)

代码语言:javascript
复制
#argmax(f(x))函数,对f(x)求最大值所对应的点x。我们令f(x)= dim=1,即可实现求所有行上的最大值对应的索引。
A = y_hat.argmax(dim=1)  

然后我们需要将得到的最大概率对应的类别与真实类别(y)比较,判断预测是否是正确的

代码语言:javascript
复制
B = (y_hat.argmax(dim=1)==y).float()
#由于y_hat.argmax(dim=1)==y得到的是ByteTensor型数据,所以我们通过.float()将其转换为浮点型Tensor()

最后我们需要计算分类准确率

我们知道y_hat的行数就对应着样本总数,所以,对B求平均值得到的就是分类准确率

代码语言:javascript
复制
(y_hat.argmax(dim=1)==y).float().mean()

上一步最终得到的数据为tensor(x)的形式,为了得到最终的pytorch number,需要对其进行下一步操作

代码语言:javascript
复制
(y_hat.argmax(dim=1)==y).float().mean().item()#pytorch number的获取统一通过.item()实现

整理一下,得到计算分类准确率函数

代码语言:javascript
复制
def accuracy(y_hat,y):    return (y_hat.argmax(dim=1).float().mean().item())

作为推广,该函数还可以评价模型net在数据集data_iter上的准确率。

代码语言:javascript
复制

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

1.8 训练模型

在训练模型时,迭代周期数num_epochs、隐藏层神经单元数num_hiddens和学习率lr都是可以调节的超参数,通过调节超参数的值可以获得分类更准确的模型。

代码语言:javascript
复制

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)

1.9 训练结果

可以看出,使用了多层感知机后,神经网络的识别准确率有了提升。且运行时间有所加长(5个学习周期运行了80秒)。

1.9.1 单线程与多线程

单线程:运行了80s。

四线程:运行了41s。

1.10 识别测试集

使用训练好的模型对测试集进行预测

做一个模型的最终目的当然不是训练了,所以来识别数据集试试。

代码语言:javascript
复制

#将样本的类别数字转换成文本
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])

识别结果

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 拇指笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 获取和读取数据
  • 1.2 定义并初始化模型参数
  • 1.4 定义模型
  • 1.5 定义损失函数
  • 1.6 优化函数
  • 1.7 计算分类准确率
  • 1.8 训练模型
  • 1.9 训练结果
    • 1.9.1 单线程与多线程
    • 1.10 识别测试集
      • 识别结果
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档