刘二大人《Pytorch深度学习实践》第九讲多分类问题

多分类问题

在这里插入图片描述
 把原来只有一个输出,加到10个 每个输出对应一个数字,这样可以得到每个数字对应的概率值,这里每个输出做的都是sigmoid二分类(即是非1即0),所以只要有一项输出为1时,其他非1的输出都规定为0,以此来判断。
 但是这种情况下出现一个问题,每个sigmoid的输出都是独立的,当一个类别的输出概率较高时,其他类别的概率仍然会高,也就是说在输出了1的概率后,2输出的概率不会因为1的出现而受影响,这点说明了所有输出的概率值之和大于1。
&emsp’所以我们希望输出的概括要满足分布性质的要求:
在这里插入图片描述

 如何来实现上面的两个要求呢,这就用到了Softmax:
在这里插入图片描述
 根据公式可以看出来:softmax层接受上一层的输出,分母为上一层每个神经元输出的指数再求和,计算每一个概率分子则为该类的输出指数;指数确保了P(y=i)≥0的条件,该公式能够满足概率和为1

损失函数

 使用Cross Entropy Loss Function(交叉熵损失函数):
在这里插入图片描述

课上代码

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
batch_size = 64
transform = transforms.Compose(
    [
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ]
)

train_dataset = datasets.MNIST('./dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader (train_dataset, shuffle = True, batch_size = batch_size)
test_dataset = datasets.MNIST ('./dataset/mnist/', train=True, download=True, transform=transform)
test_loader = DataLoader (test_dataset, shuffle = False, batch_size = batch_size)


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, 784)
    x = F.relu (self.l1(x))
    x = F.relu (self.l2(x))
    x = F.relu (self.l3(x))
    x = F.relu (self.l4(x))
    return self.l5(x)

model = Net()

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

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()

transforms的使用方法

 采用transforms.Compose(),将一系列的transforms有序组合,实现时按照这些方法依次对图像操作。

train_transform = transforms.Compose([
    transforms.Resize((32, 32)),  # 缩放
    transforms.RandomCrop(32, padding=4),  # 随机裁剪
    transforms.ToTensor(),  # 图片转张量,同时归一化0-255 ---》 0-1
    transforms.Normalize(norm_mean, norm_std),  # 标准化均值为0标准差为1
])

还有很多其他的transforms处理方法,总结有四大类:

  1. 裁剪-Crop
中心裁剪:transforms.CenterCrop

随机裁剪:transforms.RandomCrop

随机长宽比裁剪:transforms.RandomResizedCrop

上下左右中心裁剪:transforms.FiveCrop

上下左右中心裁剪后翻转,transforms.TenCrop
  1. 翻转和旋转——Flip and Rotation
依概率p水平翻转:transforms.RandomHorizontalFlip(p=0.5)

依概率p垂直翻转:transforms.RandomVerticalFlip(p=0.5)

随机旋转:transforms.RandomRotation
  1. 图像变换
resize:transforms.Resize
标准化:transforms.Normalize
转为tensor,并归一化至[0-1]:transforms.ToTensor
填充:transforms.Pad
修改亮度、对比度和饱和度:transforms.ColorJitter
转灰度图:transforms.Grayscale
线性变换:transforms.LinearTransformation()
仿射变换:transforms.RandomAffine
依概率p转为灰度图:transforms.RandomGrayscale
将数据转换为PILImage:transforms.ToPILImage
transforms.Lambda:Apply a user-defined lambda as a transform.
  1. 对transforms操作,使数据增强更灵活
transforms.RandomChoice(transforms), 从给定的一系列transforms中选一个进行操作

transforms.RandomApply(transforms, p=0.5),给一个transform加上概率,依概率进行操作

transforms.RandomOrder,将transforms中的操作随机打乱

view()函数

 view()的作用相当于numpy中的reshape,重新定义矩阵的形状。
1.普通用法

#其中v1为1*16大小的张量,包含16个元素。v2为4*4大小的张量,同样包含16个元素。
import torch
v1 = torch.range(1, 16) 
v2 = v1.view(-1, 4)  
#-1的意思是这个维度的数量是不确定的,对于确定的第二维度4,整个元素一共有16个,因此最后的v4是4*4大小的张量
#如果4换成8的话,第一维度会调整为2
v3 = torch.range(1, 16) 
v4 = v1.view(-1, 4)  

dim维度的理解

 维度为0时,即tensor(张量)为标量。
 维度为1时,即tensor(张量)为一维向量。
 维度为2时,即tensor(张量)为二维矩阵。
 维度为3时,即tensor(张量)为三维空间矩阵。
pytorch中的tensor维度可以通过第一个数前面的中括号数量来判断,有几个中括号维度就是多少。拿到一个维度很高的向量,将最外层的中括号去掉,数最外层逗号的个数,逗号个数加一就是最高维度的维数,如此循环,直到全部解析完毕。
dim的使用:只有dim指定的维度是可变的,其他都是固定不变的

  1. torch.argmax(): 得到最大值的序号索引
a = torch.rand((3,4))
print(a)
b = torch.argmax(a, dim=1) ##指定列,也就是行不变,列之间的比较
print(b)
>>tensor([[0.8338, 0.6953, 0.7558, 0.5803],
        [0.2105, 0.7638, 0.0912, 0.3341],
        [0.5585, 0.8019, 0.6590, 0.2268]])
>>tensor([0, 1, 1])

说明:dim=1,指定列,也就是行不变,列之间的比较,所以原来的a有三行,最后argmax()出来的应该也是三个值,第一行的时候,同一列之间比较,最大值是0.8338,索引是0,同理,第二行,最大值的索引是1……
2. sum(): 求和

a = t.arange(0,6).view(2,3)
a
>>tensor([[0, 1, 2],
        [3, 4, 5]])
a.sum()
a.sum(dim=0) #指定行,行是可变的,列是不变的
a.sum(dim=1)
>>tensor(15.)
>>tensor([3., 5., 7.])
>>tensor([ 3., 12.])

说明:dim=0,指定行,行是可变的,列是不变,所以就是同一列中,每一个行的比较,所以a.sum(dim = 0),第一列的和就是3,第二列的和就是5,第三列的和就是7.
同理,a.sum(dim=1),指定列,列是可变的,行是不变的,所以就是同一列之间的比较或者操作,所以第一行的求和是3,第二行的求和是12

为什么要使用item()

 item()的作用是取出单元素张量的元素值并返回该值,保持该元素类型不变。在训练时统计loss变化时,直接将loss加起来,系统会认为这里也是计算图的一部分,也就是说网络会一直延伸变大,那么消耗的显存也就越来越大,loss.item()能够防止tensor无线叠加导致的显存爆炸

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值