Softmax回归

  • 回归和分类的区别

    回归估计一个连续值:MNIST:手写数字识别;

    • 单连续数值输出
    • 自然区间R
    • 跟真实值的区别作为损失

    分类预测一个离散类别:ImageNet:自然物体分类。

    • 通常多个输出
    • 输出i是预测为第i类的置信度
  • 概念

    Softmax是一种数学函数,通常用于将一组任意实数转换为表示概率分布的实数。

    其本质上是一种归一化函数,可以将一组任意的实数值转化为在[0, 1]之间的概率值,因为softmax将它们转换为0到1之间的值,所以它们可以被解释为概率。

    公式:
    $$
    \sigma z_i = \frac{e^{z^i}}{\sum_{j=1}^{k} e^{z^j}}
    $$

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import torch 

    # set the vector to a tensor
    z = torch.Tensor([5, 7, 10])

    # apply softmax
    softmax = torch.exp(z) / torch.sum(torch.exp(z))

    #tensor([0.0064, 0.0471, 0.9465])

损失函数

真实值y 预测值y’

均方损失 L2 Loss
$$
l(y, y’)=\frac {1}{2} (y-y’)^2
$$
L1 Loss
$$
l(y, y’)=|y-y’|
$$
Huber’ s Robust Loss
$$
l(y, y’)=\begin{cases}
|y-y’|-\frac{1}{2},\quad |y-y’| > 1\
\frac {1}{2} (y-y’)^2, \quad other
\end{cases}
$$

图片分类数据集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
from d2l import torch as d2l
import torch
import torchvision
from matplotlib_inline import backend_inline
from torch.utils import data # 方便读取数据
from torchvision import transforms # 数据操作
import matplotlib.pyplot as plt


# def use_svg_display():
# """使用svg格式在Jupyter中显示绘图"""
# backend_inline.set_matplotlib_formats('svg')
#
#
# d2l.use_svg_display()


# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0~1之间


trans = transforms.ToTensor() # 数据转为张量
mnist_train = torchvision.datasets.FashionMNIST(
root="../../data", train=True, transform=trans, download=True) # train=True指下载的是训练数据集
mnist_test = torchvision.datasets.FashionMNIST(
root="../../data", train=False, transform=trans, download=True) # train=False指测试集
"""
Fashion-MNIST由10个类别的图像组成, 每个类别由训练数据集(train dataset)
中的6000张图像 和测试数据集(test dataset)中的1000张图像组成。
因此,训练集和测试集分别包含60000和10000张图像。 测试数据集不会用于训练,只用于评估模型性能。
"""
print('mnist_train_len', len(mnist_train))
print('mnist_test_len', len(mnist_test))

"""
每个输入图像的高度和宽度均为28像素。 数据集由灰度图像组成,其通道数为1。
"""
print('数据的shape', mnist_train[0][0].shape)
"""
Fashion-MNIST中包含的10个类别,分别为t-shirt(T恤)、trouser(裤子)、
pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、
shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。
"""


# 以下函数用于在数字标签索引及其文本名称之间进行转换。
def get_fashion_mnist_labels(labels):
"""返回Fashion-MNIST数据集的文本标签"""
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]


# 可视化样本
def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): # @save
"""绘制图像列表"""
figsize = (num_cols * scale, num_rows * scale)
_, axes = 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:
# PIL图片
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))) # 一个批量有18个图片
# iter() 函数用于迭代数据集,返回一个可迭代的对象
# next() 第一个数据集
# X是图片的张量数据,Y是图片的标签
# show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y)) # 两行九列,改名
# plt.show()


batch_size = 256


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


train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers())
# shuffle=True打乱顺序,随机
# num_workers进程数

if __name__ == "__main__":
'''
李沐老师的课程展示中使用的环境是linux没有报错,但win10下在dataloader使用前需要加上:
if __name__ == "__main__":
'''
timer = d2l.Timer()
for X, y in train_iter:
continue
print(f'{timer.stop():.2f} sec')
# sec 是秒


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def load_data_fashion_mnist(batch_size, resize=None):  # 将上面的方法整合到一个函数里
"""下载Fashion-MNIST数据集,然后将其加载到内存中"""
trans = [transforms.ToTensor()]
if resize:
trans.insert(0, transforms.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()))


if __name__ == "__main__":
train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
timer = d2l.Timer()
for X, y in train_iter:
print(X.shape, X.dtype, y.shape, y.dtype)
break
print(f'{timer.stop():.2f} sec')