回归和分类
回归估计一个连续值
分类预测一个离散类别
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 axesdef get_dataloader_workers():'''使用4个进程来读取数据'''return 4def 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是Falsemnist_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 = 256train_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:continueprint(f'{timer.stop():.2f} seconds')