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

【动手学深度学习笔记】之PyTorch实现softmax回归

作者头像
树枝990
发布2020-08-20 07:52:03
1.6K0
发布2020-08-20 07:52:03
举报
文章被收录于专栏:拇指笔记拇指笔记拇指笔记

1. 使用pytorch实现softmax回归模型

使用pytorch可以更加便利的实现softmax回归模型。

1.1 获取和读取数据

读取小批量数据的方法:

  1. 首先是获取数据,pytorch可以通过以下代码很方便的获取Fashion-MNIST数据集。 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()) #参数 #root : processed/training.pt 和 processed/test.pt 的主目录 #train : True = 训练集, False = 测试集 #download : True = 从互联网上下载数据集,并把数据集放在root目录下. 如果数据集之前下载过,将处理过的数据(minist.py中有相关函数)放在processed文件夹下 #transform = transforms.ToTensor():使所有数据转换为Tensor
  2. 然后是生成一个迭代器,用来读取数据 #生成迭代器 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) #参数 #dataset:Dataset类型,从其中加载数据 #batch_size:int类型,每个批量加载多少个数 #shuffle:bool类型,每个学习周期都打乱顺序 #num_workers:int类型,加载数据时使用多少子进程。默认值为0. #collate_fn:定义如何取样本,可通过定义自己的函数来实现。 #pin_memory:锁页内存处理。 #drop_last:bool类型,如果有剩余的样本,True表示丢弃;Flase表示不丢弃

1.2 定义和初始化模型

由softmax回归模型的定义可知,softmax回归模型只有权重参数和偏差参数。因此可以使用神经网络子模块中的线性模块。

  1. 首先定义网络,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)
  1. 初始化参数

使用torch.nn中的init可以快速的初始化参数。我们令权重参数为均值为0,标准差为0.01的正态分布。偏差为0。

init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)

1.3 softmax运算和交叉熵损失函数

分开定义softmax运算和交叉熵损失函数会造成数值不稳定。因此PyTorch提供了一个具有良好数值稳定性且包括softmax运算和交叉熵计算的函数。

loss = nn.CrossEntropyLoss()

1.4 定义优化算法

依然使用小批量随机梯度下降作为优化算法。定义学习率为0.1。

optimizer = torch.optim.SGD(net.parameters(),lr=0.01)

1.5 计算分类准确率

计算准确率的原理:

我们把预测概率最大的类别作为输出类别,如果它与真实类别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

1.6 训练模型

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)

训练属实是有点慢,只训练了五个周期。训练结果:

1.7 预测

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

做一个模型的最终目的当然不是训练了,所以来预测一下试试。

#将样本的类别数字转换成文本
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])
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-02,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 使用pytorch实现softmax回归模型
    • 1.1 获取和读取数据
      • 1.2 定义和初始化模型
        • 1.3 softmax运算和交叉熵损失函数
          • 1.4 定义优化算法
            • 1.5 计算分类准确率
              • 1.6 训练模型
                • 1.7 预测
                  • 完整程序
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档