当前位置:   article > 正文

《PyTorch深度学习实践》第九讲 Softmax Classifier解决多分类问题_softmax分类器改进 pytorch

softmax分类器改进 pytorch

目录

1.怎么用softmax这个分类器解决多分类问题

2.在pytorch中如何实现

实际使用

上半讲作业

回到MNIST数据集

 mnist数据集做多分类

 代码实现

1.prepare dataset

 2.design model

 3.construct loss and optimizer

 4.train and test



1.怎么用softmax这个分类器解决多分类问题

假设我们有10个分类,如何设计神经网络?

  1. 用sogmoid:原本输出属于一类的概率,现在让其输出属于10个类的概率。此时每个类别都看为一个二分类问题,用BCE算损失。但这里存在的问题是:10个类别不能相互抑制(概率和=1)
  2. 用softmax:由于1的缺点,我们希望输出的十个概率值能满足分布要求(Pi≥0,和=1),10个类得有9个参数,但希望用到并行计算的能力,所以还是希望十个类的输出的计算是一样的。

softmax层:能输出一个分布(满足 两个条件:Pi≥0,和=1

在神经网络的后面加一个softmax层

2.在pytorch中如何实现

1.神经网络算出来的结果可正可负,怎么把它变成正的?

2.和怎么等于1?       用下面这个函数公式

 例子如下:

经过softmax层后,需要算损失。借助前面的BCE损失。

因为这是多分类,其他的标签相当于都是0,所以只写当前这一项就可以。

 自己想要实现的话可以这样写,但没必须要自己写:

实际使用

 pytorch中提供NLLLoss模块,提供LogSoftmax 模块,也提供CrossEntropyLoss模块(红框内都包了,注意神经网络的最后一层不要做激活)

LongTensor[0]是指索引为0 的(就是第一个元素)为1,其余为0

 这段代码可以用来测试并理解loss的含义,loss越小预测的越准确。

  1. import torch
  2. criterion = torch.nn.CrossEntropyLoss()
  3. Y = torch.LongTensor([2,0,1])
  4. Y_pred1 = torch.Tensor([[0.1,0.2,0.9],
  5. [1.1,0.1,0.2],
  6. [0.2,2.1,0.1]])
  7. Y_pred2 = torch.Tensor([[0.8,0.2,0.3],
  8. [0.2,0.3,0.5],
  9. [0.2,0.2,0.5]])
  10. l1 = criterion(Y_pred1, Y)
  11. l2 = criterion(Y_pred2, Y)
  12. print("Batch Loss1 = ", l1.data,"\nBatch Loss2=", l2.data)

Batch Loss1 = tensor(0.4966)

Batch Loss2= tensor(1.2389)

上半讲作业

回到MNIST数据集

每张图片都是28*28的矩阵,一共有784个像素,每一个像素取值是0~255;黑色地方数值=0,越亮的地方数值越大。

将像素值线性映射到0~1后如下:

 mnist数据集做多分类

 代码实现

1.prepare dataset

PIL,全称 Python Imaging Library,是 Python 平台一个功能非常强大而且简单易用的图像处理库。但是,由于 PIL 仅支持到Python 2.7,加上年久失修,于是一群志愿者在 PIL 的基础上创建了兼容 Python 3 的版本,名字叫 Pillow ,我们可以通过安装 Pillow 来使用 PIL。

torchvision是pytorch的一个图形库,它服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。torchvision.transforms主要是用于常见的一些图形变换。这个类的主要作用是串联多个图片变换的操作。

  • 神经网络的特点:希望输入的数值比较小,范围-1~1,能遵从正态分布。这样的输入对神经网络的训练是最有帮助的。

通道 × 宽 × 高

  • ToTensor()这个对象 可以实现把单通道变成多通道,同时把值映射到(0,1) 
  •  Normalize()归一化。mnist数据集的均值和标准差 已经给出(用了很多年 大家早就算好了)。注意:说的不是取值范围,而是以0为均数,1为标准差的分布

 2.design model

  • view()函数改变张量的形状,把矩阵形的像素拉成一长条。有两个参数,是二阶张量。-1是指将来自动算它的值。

 

 3.construct loss and optimizer

冲量:深度学习中最优化方法中的动量参数,这个值影响着梯度下降 到最优值的速度,这个参数代表建议冲量配置为0.5

 4.train and test

训练集:把一轮循环封装成函数

测试集:

 

 TORCH.MAX():Returns a namedtuple (values, indices) where values is the maximum value of each row of the input tensor in the given dimension dim. And indices is the index location of each maximum value found (argmax).

  1. import torch
  2. from torchvision import transforms # 该工具包主要针对图像做处理
  3. from torchvision import datasets
  4. from torch.utils.data import DataLoader
  5. import torch.nn.functional as F # For using function relu()
  6. import torch.optim as optim # For constructing Optimizer
  7. # prepare dataset
  8. batch_size = 64
  9. transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差
  10. train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
  11. train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
  12. test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
  13. test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
  14. # design model using class
  15. class Net(torch.nn.Module):
  16. def __init__(self):
  17. super(Net, self).__init__()
  18. self.l1 = torch.nn.Linear(784, 512)
  19. self.l2 = torch.nn.Linear(512, 256)
  20. self.l3 = torch.nn.Linear(256, 128)
  21. self.l4 = torch.nn.Linear(128, 64)
  22. self.l5 = torch.nn.Linear(64, 10)
  23. def forward(self, x):
  24. x = x.view(-1, 784) # -1其实就是自动获取mini_batch
  25. x = F.relu(self.l1(x))
  26. x = F.relu(self.l2(x))
  27. x = F.relu(self.l3(x))
  28. x = F.relu(self.l4(x))
  29. return self.l5(x) # 最后一层不做激活,不进行非线性变换
  30. model = Net()
  31. # construct loss and optimizer
  32. criterion = torch.nn.CrossEntropyLoss()
  33. optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
  34. # training cycle forward, backward, update
  35. def train(epoch):
  36. running_loss = 0.0
  37. for batch_idx, data in enumerate(train_loader, 0):
  38. # 获得一个批次的数据和标签
  39. inputs, target = data
  40. optimizer.zero_grad()
  41. # 获得模型预测结果(64, 10)
  42. outputs = model(inputs)
  43. # 交叉熵代价函数outputs(64,10),target(64)
  44. loss = criterion(outputs, target)
  45. loss.backward()
  46. optimizer.step()
  47. running_loss += loss.item() # 不加会构建计算图
  48. if batch_idx % 300 == 299:
  49. print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, running_loss/300))
  50. running_loss = 0.0
  51. def test():
  52. correct = 0
  53. total = 0
  54. with torch.no_grad(): #不需要进行反向传播
  55. for data in test_loader:
  56. images, labels = data
  57. outputs = model(images)
  58. _, predicted = torch.max(outputs.data, dim=1) # dim = 1 列是第0个维度,行是第1个维度
  59. total += labels.size(0)
  60. correct += (predicted == labels).sum().item() # 拿出的索引就是多分类的类别,张量之间的比较运算
  61. print('accuracy on test set: %d %% ' % (100*correct/total))
  62. if __name__ == '__main__':
  63. for epoch in range(10):
  64. train(epoch)
  65. test()

参考:(6条消息) PyTorch 深度学习实践 第9讲_pytorch outputs_错错莫的博客-CSDN博客 

  •  到97%上不去的原因是:做图像用全连接神经网络,忽略了一些对局部信息的利用。所有元素都做了全连接,某个点和其他点都产生了一些联系。处理时权重不够多;更关心比较高抽象级别的特征(现在用的特征比较原始)。如果用某些特征提取方法后,再做分类训练,效果可能会更好

图像可以使用自动提取特征方法(CNN),不再使用人工算法如FFT傅里叶变换(转换成频域的表示),小波(wavelet)

作业:kaggle中用改数据集做多分类。Dataset: https://www.kaggle.com/c/otto-group-product-classificationchallenge/data

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/324902
推荐阅读
相关标签
  

闽ICP备14008679号