1 前言

在前两节中,我们介绍了线性回归并对其进行了实现1-1线性神经网络——线性回归的从零开始实现1-2线性神经网络——线性回归的简洁实现,利用线性回归我们可以预测数量问题,如房屋出售价格。我们同样对分类问题十分关心,比如哪一封电子邮件是垃圾邮件、图片上描绘的是哪一种动物等等。
在本章节,我们将介绍softmax回归以解决分类问题。值得注意的是,尽管softmax回归带有“回归”二字,但它本质上是用于分类的。我们还会介绍MNIST数据集,这是在图像分类中广泛使用的数据集之一,有了它我们便可以在后续实现softmax回归。

2 softmax回归

2.1 分类问题和回归问题

回归:是在自然区间 R R R 上,单数值的连续输出,和真实值的区别作为损失。
分类:通常有多个输出,独热编码(对类别进行一位有效编码,即对应类别设置为1,其他设置为0)。
y = [ y 1 , y 2 , . . . , y n ] T y = [y_1,y_2,...,y_n]^T y=[y1,y2,...,yn]T y i = { 1 if i=y 0 otherwise y_i = \left\{\begin{array}{ll} 1 & \text{if i=y} \\ 0 & \text{otherwise} \end{array} \right. yi={10if i=yotherwise

2.2 softmax运算

1、为每个输入计算n个未规范化的预测,这一步是通过线性回归实现的。用向量形式表示为: o = X w + b o = Xw + b o=Xw+b
2、softmax运算,将未规范化的 o o o变为非负数,并且总和为1,使得其在概率论上行得通: y ^ = softmax ( o ) \hat{y} = \text{softmax}(o) y^=softmax(o) ,其中: y ^ j = exp ( o j ) ∑ k exp ( o k ) \hat{y}_j = \frac{\text{exp}(o_j)}{\sum\limits_k \text{exp}(o_k)} y^j=kexp(ok)exp(oj)
3、最大值预测,选择最可能的类别: y ^ = softmax ( o ) \hat{y} = \text{softmax}(o) y^=softmax(o)

2.3 损失函数

1、利用极大似然估计,得到softmax回归的损失函数,在这里就不进行推导了。 L ( y , y ^ ) = − ∑ i y i log ⁡ y i ^ = − log ⁡ y y ^ L(y,\hat{y}) = - \sum\limits_{i} y_i \log{\hat{y_i}} = - \log{\hat{y_y}} L(y,y^)=iyilogyi^=logyy^ 。这个损失又称为交叉熵损失,常用来衡量两个概率的区别。
2、损失函数的梯度:损失函数对预测 o j o_j oj求偏导数得到其梯度,是真实概率和预测概率的区别: ∂ o j L ( y , y ^ ) = softmax ( o ) j − y j \partial_{o_j} L(y,\hat{y}) = \text{softmax}(o)_j - y_j ojL(y,y^)=softmax(o)jyj

2.4 模型预测和评估

1、在训练softmax回归模型后,给出任何样本特征,我们可以预测每个输出类别的概率,通常预测概率最高的类别作为输出类别。
2、我们用精度来评估模型的性能,精度等于正确预测数与预测总数的比率。

3 图像分类数据集

3.1 导入所需的函数模块

%matplotlib inline
import torch
import torchvision #这是PyTorch对于计算机视觉模型实现的库
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l

d2l.use_svg_display() #用svg显示图片,清晰度更高

3.2 读取数据集

3.2.1 下载Fashion-MNIST数据集

通过框架中的内置函数将Fashion-MNIST数据集下载并读取到内存中。

trans = transforms.ToTensor() 
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)

len(mnist_train), len(mnist_test)
(60000, 10000)

注:
1、使用ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,并除以255使得所有像素均值在0到1之间。
2、download=True会在线下载,也可以事先在网站上下载好,参数改为download=False。数据集存储在上一级目录下的data文件夹中。
3、训练集和测试集分别包含60 000和10 000张图像。

mnist_train[0][0].shape
torch.Size([1, 28, 28])

4、数据集由灰度图像构成,其通道数为1,像素高度h=28、宽度w=28。

3.2.2 两个可视化数据集的函数

get_fashion_mnist_labels可以返回Fashion-MNIST数据集的文本标签。

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]

show_images可以绘制图像列表,可视化这些样本。

def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): #绘制图像列表
    figsize = (num_cols * scale, num_rows * scale)
    _,axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
    axes = axes.flatten()
    for i, (ax, img) in enumerate(zip(axes, imgs)):
        if torch.is_tensor(img):
            ax.imshow(img.numpy())
        else:
            ax.imshow(img)
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        if titles:
            ax.set_title(titles[i])
    return axes

使用迭代器加载几个样本的图像及其相应的标签。

X, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
show_images(X.reshape(18,28,28), 2, 9, titles=get_fashion_mnist_labels(y));

3.3 读取小批量

我们还是使用数据迭代器读取数据。这里定义了一个get_dataloader_workers,使用四个进程来读取,速度更快。

batch_size = 256

def get_dataloader_workers(): #使用四个进程来读取数据
    return 4

train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers())

创建一个计时器,返回读取所有数据所需要的时间。一般读取数据的时间应该比训练模型的时间快很多。

timer = d2l.Timer() #读取所有训练数据所需的时间
for X, y in train_iter:
    continue
f'{timer.stop():2f} sec'
'2.431182 sec'

3.4 整合所有组件

将上述代码进行整合,定义一个load_data_fashion_mnist函数,用于获取和读取Fashion-MNIST数据集,返回训练集和验证集的数据迭代器。

def load_data_fashion_mnist(batch_size, resize=None):
    trans = [transforms.ToTensor()]
    if resize: #用于改变图片大小
        trans.insert(0, transform.Resize(resize))
    trans = transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)
    mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)
    
    return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),
            data.DataLoader(mnist_test, batch_size, shuffle=False, num_workers=get_dataloader_workers()))

注:
1、resize参数用于改变图片大小,默认值为None。
2、trans是一个用于存储图像变换操作的列表。如果要改变图像大小,就将resize的操作加入到trans列表中。
3、transforms.Compose(trans)将变换列表组合成一个单一的变换,这样所有的变换操作可以依次应用于图像。
4、最终函数返回两个数据加载器,一个用于训练集,一个用于测试集。

4 小结

在本节中,我们比较了回归与分类问题,并学习了softmax回归以解决分类问题。softmax运算可以输出预测类别的概率分布,通常预测概率最高的类别作为输出类别。我们用精度来评估模型的性能,精度等于正确预测数与预测总数的比率。
我们还准备了Fashion-MNIST数据集,它是一个由10个类别的图像组成的用于图像分类的数据集。构建了load_data_fashion_mnist,可以用于获取和读取Fashion-MNIST数据集,返回训练集和验证集的数据迭代器。有了Fashion-MNIST数据集,我们就可以在接下来实现softmax回归模型,评估分类算法了。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐