9 Softmax Classifier
1 Introduction
如果直接使用之前的模型,每个输出对应相应类别的概率,那么会造成最终输出不满足分布的特点。
因此,需要对输出进行处理,使得每个类别对应的输出满足以下条件:
为解决这个问题,将最后一层Sigmoid换为Softmax层。
2 Softmax Layer
Softmax函数
使用指数操作来保证每个输出大于0,用比例来确保符合分布规律。
An example
3 Loss Function - Cross
Entropy
Cross Entropy Loss Function:
不难看出损失只对标签为一的一项有效,假设 为1,若 ,则损失无限大,反之,损失为0。这是对其合理性的简单阐释。
1 2 3 4 5 6 7 import numpy as np y = np.array([1 , 0 , 0 ]) z = np.array([0.2 , 0.1 , -0.1 ]) y_pred = np.exp(z) / np.exp(z).sum () loss = -np.sum (y * np.log(y_pred))print (loss)
注意:
如图,在PyTorch中,CrossEntropyLoss已经包含了Softmax层,因此在使用时不需要手动添加Softmax层。另外,使用One-Hot编码表示标签,需要使用LongTensor类型。
1 2 3 4 5 6 7 import torch y = torch.LongTensor([0 ]) z = torch.Tensor([[0.2 , 0.1 , -0.1 ]]) criterion = torch.nn.CrossEntropyLoss() loss = criterion(z, y)print (loss)
4 MNIST Dataset
4.1 数字图像
数字图像是指由像素点组成的二维图像,每个像素点都有一个数值来表示其颜色或灰度值。灰度图像是指每个像素点只有一个数值(单通道(channel)),而不是RGB三通道的数值。
h - 高度 | w - 宽度 | c - 通道 在PIL(Python Imaging
Library)和opencv中,图像张量是 的三维张量,分别对应高度、宽度和通道数。但在PyTorch中,图像张量是 的三维张量,分别对应通道数、高度和宽度。这是为了更高效地进行计算。(?)
MNIST数据集中的样本是28x28的灰度图像,每个像素值在 (从0~255映射到 )之间。其中,数值大的颜色深。
4.2 Import and Prepare
Dataset
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 import torchfrom torchvision import datasets, transformsfrom torch.utils.data import DataLoaderimport torch.nn.functional as Fimport torch.optim as optim batch_size = 64 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307 ,), (0.3081 ,)) ]) train_dataset = datasets.MNIST( root='../dataset/mnist' , train=True , transform=transform, download=True ) train_loader = DataLoader( train_dataset, batch_size=batch_size, shuffle=True ) test_dataset = datasets.MNIST( root='../dataset/mnist' , train=False , transform=transform, download=True ) test_loader = DataLoader( test_dataset, batch_size=batch_size, shuffle=False )
4.3 Design Model
x=x.view(-1, 28*28)中的-1表示自动计算该维度的大小,这里是将 的图像展开为 的向量。
这次使用的激活函数为更常用的relu函数。relu函数的定义为:
它的作用是将小于0的数值置为0,大于0的数值保持不变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Net (torch.nn.Module): def __init__ (self ): super (Net, self ).__init__() self .l1 = torch.nn.Linear(784 , 512 ) self .l2 = torch.nn.Linear(512 , 256 ) self .l3 = torch.nn.Linear(256 , 128 ) self .l4 = torch.nn.Linear(128 , 64 ) self .l5 = torch.nn.Linear(64 , 10 ) def forward (self, x ): x = x.view(-1 , 28 *28 ) x = F.relu(self .l1(x)) x = F.relu(self .l2(x)) x = F.relu(self .l3(x)) x = F.relu(self .l4(x)) x = self .l5(x) return x model = Net() criterion = torch.nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.01 , momentum=0.5 )
关于动(冲)量的设置 传统梯度下降: 带Momentum的梯度下降:
其中: 是当前时刻的速度 是动量系数(通常设为0.9左右)
是学习率 是当前梯度 作用:
加速收敛:在一致的方向上积累速度,加快收敛
减少震荡:平滑路径,减少在局部最小值附近的震荡
穿越鞍点:帮助模型更快地穿越梯度较小的区域
4.4 Train and Test
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 def train (epoch ): running_loss = 0.0 for batch_idx, data in enumerate (train_loader, 0 ): inputs, target = data optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, target) loss.backward() optimizer.step() running_loss += loss.item() if batch_idx % 300 == 299 : print ('[%d, %5d] loss: %.3f' % (epoch + 1 , batch_idx + 1 , running_loss / 300 )) running_loss = 0.0 def test (): correct = 0 total = 0 with torch.no_grad(): for data in test_loader: images, labels = data outputs = model(images) _, predicted = torch.max (outputs.data, dim=1 ) total += labels.size(0 ) correct += (predicted == labels).sum ().item() print ('Accuracy on test set: %d %%' % (100 * correct / total))if __name__ == '__main__' : for epoch in range (10 ): train(epoch) test()
为什么准确率不太高?
目前使用的是全连接层,而加入特征提取算法 能够提取图像的高层特征,在图像识别任务中更有效。
一些人工特征提取算法:FFT、wavelet等
自动特征提取算法:卷积神经网络(CNN)等
5 Exercise
5.1 Cross Entropy Loss vs
NLLLoss
What are the differences between CrossEntropyLoss and
NLLLoss?
Reading the document:
Try to know why:
CrossEntropyLoss <===> LogSoftmax + NLLLoss
5.2 Classifier Implementation
Try to implement a classifier for: