回归和分类
回归估计一个连续值
分类预测一个离散类别
Softmax回归实际是一个分类问题
从回归到多类分类
对类别进行一位有效编码
y = [ y 1 , y 2 , ⋯ , y n ] T y=[y_1,y_2,\cdots,y_n]^T y=[y1,y2,⋯,yn]T,如果是第i类,则值为1,否则为0
使用均方损失训练,最大值预测为(即softmax函数)
y
^
=
a
r
g
m
a
x
i
o
i
\hat y = argmax_i\ o_i
y^=argmaxi oi
需要更置信的识别正确类(大余量):
o y − o i ≥ Δ ( y , i ) o_y -o_i\ge \Delta(y,i) oy−oi≥Δ(y,i)
校验比例
输出匹配概率(非负,和为1)
y
^
=
s
o
f
t
m
a
x
(
o
)
y
^
i
=
e
x
p
(
o
i
)
∑
k
e
x
p
(
o
k
)
\hat y = softmax(o)\\ \hat y_i =\frac{exp(o_i)}{\sum_k exp(o_k)}
y^=softmax(o)y^i=∑kexp(ok)exp(oi)
概率
y
y
y和
y
^
\hat y
y^的区别作为损失
交叉熵损失
交叉熵用来衡量两个概率的区别 H ( p , q ) = ∑ i − p i l o g ( q i ) H(p,q)=\sum_i - p_ilog(q_i) H(p,q)=∑i−pilog(qi)
将它作为损失函数:
l
(
y
,
y
^
)
=
−
∑
i
y
i
l
o
g
y
^
i
=
−
l
o
g
y
^
y
(假设是第
y
类)
l(y,\hat y)=-\sum_i y_ilog\hat y_i = -log \hat y_y (假设是第y类)
l(y,y^)=−i∑yilogy^i=−logy^y(假设是第y类)
关心正确类的预测值
其梯度是真实概率和预测概率的区别
∂
o
i
l
(
y
,
y
^
)
=
s
o
f
t
m
a
x
(
o
)
i
−
y
i
\partial_{o_i}l(y,\hat y) =softmax(o)_i -y_i
∂oil(y,y^)=softmax(o)i−yi
损失函数
均方损失(L2 Loss)
l
(
y
,
y
′
)
=
1
2
(
y
−
y
′
)
2
l(y,y')=\frac 12 (y-y')^2
l(y,y′)=21(y−y′)2
在梯度下降时,预测值与真实值相差较远时,梯度会较大,但在离原点比较远时,可能并不希望有较大的梯度,这种情况下可以使用L1 Loss。
绝对值损失(L1 Loss)
l ( y , y ′ ) = ∣ y − y ′ ∣ l(y,y')=|y-y'| l(y,y′)=∣y−y′∣
好处就是,无论离原点多远,梯度下降时的导数都是正负1,但在比较接近时,可能就出现振荡了
Huber’s Robust Loss
结合两种的好处
KaTeX parse error: Unknown column alignment: * at position 32: … \begin{array}{*̲*lr**} |y-y'|-\…
读取多类分类的数据集
图像分类数据集
使用Fashion-MNIST数据集
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l
# 看一下图片的形状
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):
"画图"
figsize = (num_cols * scale, num_rows * scale)
fig, 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:
# 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])
d2l.plt.show() # 加上show图片才会显示
return axes
def get_dataloader_workers():
'''使用4个进程来读取数据'''
return 4
def load_data_fashion_mnist(batch_size, resize=None): #resize可以改变图片的大小
"""下载Fashion-MNIST数据集,然后将其加载到内存中"""
trans = [transforms.ToTensor()]# 将图片转换成tensor
# 将图片下载,train表示是训练数集,transform表示是tensor而不是图片,download表示从网上下载
if resize:
trans.insert(0, transforms.Resize(resize))
trans = transforms.Compose(trans)
# 将图片下载,train表示是训练数集,transform表示是tensor而不是图片,download表示从网上下载
mnist_train = torchvision.datasets.FashionMNIST(
root="./data", train=True, transform=trans, download=True)
# 训练数据集的下载,则train是False
mnist_test = torchvision.datasets.FashionMNIST(
root="./data", train=False, transform=trans, download=True)
print(len(mnist_train))
print(len(mnist_test))
print(mnist_train[0][0].shape) # 黑白图片,所以channel为1,train[0]表示取第一个元素,第二个[0]表示是取图片,[1]表示取标签
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()))
d2l.use_svg_display() # 使用svg来显示图片
# 通过ToTenseor实例将图像数据从PIL类型变换成32位浮点数格式
# 并除以255使得所有像素的值均在0到1之间
# 将数据集放进dataloader里面,指定一个batch_size,我们就可以得到一个批次的数据
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))
batch_size = 256
train_iter = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=get_dataloader_workers())
timer = d2l.Timer()
for X, y in train_iter:
continue
print(f'{timer.stop():.2f} seconds')