PyTorch图形分类器

通常来说,当你处理图像,文本,语音或者视频数据时,你可以使用标准 python 包将数据加载成numpy 数组格式,然后将这个数组转换成 torch.*Tensor

  • 对于图像,可以用 Pillow,OpenCV

  • 对于语音,可以用 scipy,librosa

  • 对于文本,可以直接用 Python 或 Cython 基础数据加载模块,或者用 NLTK 和 SpaCy

特别是对于视觉,我们已经创建了一个叫做 totchvision 的包,该包含有支持加载类似Imagenet,CIFAR10,MNIST 等公共数据集的数据加载模块 torchvision.datasets 和支持加载图像数据数据转换模块torch.utils.data.DataLoader。


使用清华源conda install torchvision

第一步:在C:\Users\86188.conda 中加入channels

具体加入的内容可以打开它看一下,这里我不写了。

注:这里的channels写http不能写https,URL最后加上win-64

第二步:在power shell中运行添加channels的命令,具体添加的URL和canda文档对应

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/


或(上面和下面的命令行都可以运行一下,差不多,就算重复,它只会说已经有了,没事)

conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64 conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/win-64 conda config --set show_channel_urls yes

他报错缺什么URL,你就在conda文档加什么URL,并在PowerShell中添加conda config --add channels···,添加语句要一行一行运行,运行后重复运行,它会报错已经有了,没关系


第三步:

conda install torchvision (-c pytorch不要

注:不能加 -c pytorch它会用原来外网的连接下载

如果重复操作的话

它会警告remove or rename下面两个文件

C:\Users\86188\Anaconda3\pkgs\pytorch-1.7.0-py3.7_cuda110_cudnn8_0.zb

C:\Users\86188\Anaconda3\pkgs\pytorch-1.7.0-py3.7_cuda110_cudnn8_0\Lib\site-packages\torch\lib\cudnn_adv_infer64_8.dll

你只要直接复制地址把这两个文档删了,这样就能下载成功


最后下载完成后

我在spyder中运行还是找不到torchvison的包,jupyter依然可以,原因在于jupyter notebook是在C:\Users\86188\Desktop\DeepLearning英文文件夹中创建py,而我运行的spyder是在C:\Users\86188\Desktop\DeepLearning\PyTorch中文文档 含有中文的文件夹中

pip install torchvision -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

CIFAR-10数据集:https://www.cnblogs.com/Jerry-Dong/p/8109938.html

代码放在D盘说找不到torchvision包,放在桌面就可以运行


我感觉在jupyter notebook 里可以运行,在spyder中运行不了的原因是我的py文件放在有中文字的文件夹里了,拿出来就可以运行了。原来的运行不了,就在英文文档中再复制代码创建一个就行

!!!!!找到问题了,我把这个py文件命名成立torchvison和我要导的包torchvision重名了,它找不到包了,改个名字就好了

!!!!以后文件命名要注意不能命名成和import 包相关的名字

torchvision安装完成


代码:

# -*- coding: utf-8 -*-
"""
Created on Sun Nov 22 19:16:53 2020

@author: 86188
"""
import torch
import torchvision
import torchvision.transforms as transforms

transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))
        ])

trainset = torchvision.datasets.CIFAR10(root='./data' ,train = True,
                                        download = True,transform = transform)
trainloader = torch.utils.data.DataLoader(trainset,batch_size = 4,
                                          shuffle =True,num_workers=0)
testset =torchvision.datasets.CIFAR10(root='./data',train = False,
                                      download = True,transform = transform)
testloader = torch.utils.data.DataLoader(testset,batch_size = 4,
                                          shuffle =True,num_workers=0)
classes = ('plane', 'car', 'bird', 'cat',
 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

import matplotlib.pyplot as plt
import numpy as np

def imshow(img):
    img = img/2+0.5
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg,(1,2,0)))
    plt.show
    
'''
dataiter = iter(trainloader)
images,labels = dataiter.next()

imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
'''

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = nn.Conv2d(3,6,5)
        self.pool = nn.MaxPool2d(2,2)
        self.conv2 = nn.Conv2d(6,16,5)
        self.fc1 = nn.Linear(16*5*5,120)
        self.fc2 = nn.Linear(120,84)
        self.fc3 = nn.Linear(84,10)
        
    def forward(self,x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1,16*5*5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
net = Net()

import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)

dataiter = iter(testloader)
images, labels = dataiter.next()


#训练
for epoch in range(5): # loop over the dataset multiple times
    running_loss = 0.0
    for i,data in enumerate(trainloader,0):
        inputs,labels = data
        
        optimizer.zero_grad()
        
        outputs = net(inputs)
        loss = criterion(outputs,labels)
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item()
        if i%2000 == 1999:
            print('[%d,%5d] loss:%.3f' %(epoch+1,i+1,running_loss/2000))
            running_loss = 0.0
print('Finished Training')


# 输出图片
imshow(torchvision.utils.make_grid(images))
#print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

outputs = net(images)

_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4))) 

 

一些函数的用法解释:

torchvision.transforms.Compose()

compose组合

可以看出Compose里面的参数实际上就是个列表,而这个列表里面的元素就是你想要执行的transform操作。

torchvision.transforms的函数:

ToTensor类是实现:Convert a PIL Image or numpy.ndarray to tensor的过程,在PyTorch中常用PIL库来读取图像数据,因此这个方法相当于搭建了PILImage和Tensor的桥梁。另外要强调的是在做数据归一化之前必须要把PILImage转成Tensor,而其他resize或crop操作则不需要。

ToPILImage顾名思义是从Tensor到PILImage的过程,和前面ToTensor类的相反的操作。

Normalize类是做数据归一化的,一般都会对输入数据做这样的操作,公式也在注释中给出了,比较容易理解。前面提到在调用Normalize的时候,输入得是Tensor,这个从__call__方法的输入也可以看出来了。

出处:https://www.jianshu.com/p/1ae863c1e66d

pytorch数据集相关操作(torchvision.datasets、torch.utils.data.DataLoader、torchvision.transforms

torch.utils.data.Dataset

参数选项:

  • root:存放数据集的位置

  • train:训练集还是测试集

  • transform:数据预处理

  • target_transform:标注的预处理

  • download:是否下载,如果已经在root存在,可以不下载 比如以CIFAR10为例:

cifar = torchvision.datasets.CIFAR10(root = "../data/", train= True, download = True)

torch.utils.data.DataLoader

数据加载器。组合数据集和采样器,并在数据集上提供单进程或多进程迭代器。API定义如下:

class torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=<function default_collate>, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None)

有以下常用参数:

  • dataset: 需要加载的数据集

  • batch_size :batch大小

  • shuffle :是否打乱顺序

  • num_workers:多进程

trainloader的batch(批量)大小为4且shuffle=True。 batch 大小:每次循环我们加载图片的数目。每次循环(运行一次网络)被称为一个batchshuffle=True:每次加载数据,都会对数据进行打乱操作,这样有助于增加鲁棒性。

更过参数详见:https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader

出处:https://www.jianshu.com/p/32087b1d9260

numpy.transpose

矩阵转置

三维:

transpose((1,2,0) 初始的位置是(0,1,2),将三条轴线位置重新编排(1,2,0)

iter(),next()

可以被next函数不断调用返回下一个值的对象称为迭代器(Iterator)

我们先将训练数据加载到trainloader,并设置一个迭代器iter(trainloader),随后我们用这个迭代器来遍历训练数据,这个过程有点类似于,

for image, label in trainloader:
## do things with images and labels

torchvision.utils.make_grid()

make_grid的作用是将若干幅图像拼成一幅图像。其中padding的作用就是子图像与子图像之间的pad有多宽。nrow是一行放入八个图片。


torchvision.utils.make_grid(tensor, nrow=8, padding=2, normalize=False, range=None, scale_each=False, pad_value=0)[source]

Make a grid of images.

Parameters: tensor (Tensor or list) – 4D mini-batch Tensor of shape (B x C x H x W) or a list of images all of the same size. nrow (int, optional) – 每一行显示的图像数. 最终图标尺寸为(B / nrow, nrow). 默认为8. padding (int, optional) –填充. Default is 2. normalize (bool, optional) – If True, 归一化图像到(0, 1)区间, by subtracting the minimum and dividing by the maximum pixel value. range (tuple, optional) – tuple (min, max) where min and max are numbers, then these numbers are used to normalize the image. By default, min and max are computed from the tensor. scale_each (bool, optional) – If True, scale each image in the batch of images separately rather than the (min, max) over all images. pad_value (float, optional) – Value for the padded pixels.

出处:https://www.pianshen.com/article/6658934192/

报错:BrokenPipeError: [Errno 32] Broken pipe

该问题的产生是由于windows下多线程的问题,和DataLoader类有关

该参数是指在进行数据集加载时,启用的线程数目。截止当前2018年5月9日11:15:52,如官方未解决该BUG,则可以通过修改num_works参数为 0 ,只启用一个主进程加载数据集,避免在windows使用多线程即可。

出处:https://blog.csdn.net/qq_33666011/article/details/81873217

torch.nn

1)卷积层

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

二维卷积层, 输入的尺度是(N, Cin,H,W),输出尺度(N,Cout,Hout,Wout)的计算方式:

2)标准化层

class torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True)

对小批量(mini-batch)3d数据组成的4d输入进行批标准化(Batch Normalization)操作

3)池化层

class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

对于输入信号的输入通道,提供2维最大池化(max pooling)操作

如果输入的大小是(N,C,H,W),那么输出的大小是(N,C,H_out,W_out)

4)损失函数 nn.CrossEntropyLoss()

出处:https://www.cnblogs.com/wanghui-garcia/p/10775859.html

nn.Linear()

  • nn.Linear():用于设置网络中的全连接层,需要注意的是全连接层的输入与输出都是二维张量

  • 一般形状为[batch_size, size],不同于卷积层要求输入输出是四维张量。其用法与形参说明如下:

  • in_features指的是输入的二维张量的大小,即输入的[batch_size, size]中的size。

  • out_features指的是输出的二维张量的大小,即输出的二维张量的形状为[batch_size,output_size],当然,它也代表了该全连接层的神经元个数。

  • 从输入输出的张量的shape角度来理解,相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。

出处:https://www.cnblogs.com/douzujun/p/13366939.html

torch.optim

torch.optim是一个实现了多种优化算法的包,大多数通用的方法都已支持,提供了丰富的接口调用,未来更多精炼的优化算法也将整合进来。 为了使用torch.optim,需先构造一个优化器对象Optimizer,用来保存当前的状态,并能够根据计算得到的梯度来更新参数。 要构建一个优化器optimizer,你必须给它一个可进行迭代优化的包含了所有参数(所有的参数必须是变量s)的列表。 然后,您可以指定程序优化特定的选项,例如学习速率,权重衰减等。

optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)
self.optimizer_D_B = torch.optim.Adam(self.netD_B.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))

enumerate(sequence, [start=0])

enumerate英文翻译为枚举的意思。 可以将一个可遍历的数据对象组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

  • 参数

  1. sequence # 一个序列、迭代器或其他支持迭代对象。

  2. start # 下标起始位置、默认为0

optimizer.zero_grad()

optimizer.zero_grad()意思是把梯度置零,也就是把loss关于weight的导数变成0.

另外Pytorch 为什么每一轮batch需要设置optimizer.zero_grad:

根据pytorch中的backward()函数的计算,当网络参量进行反馈时,梯度是被积累的而不是被替换掉;但是在每一个batch时毫无疑问并不需要将两个batch的梯度混合起来累积,因此这里就需要每个batch设置一遍zero_grad 了。

出处:https://blog.csdn.net/scut_salmon/article/details/82414730

torch.max()

torch.max(a,1) 返回每一行中最大值的那个元素,且返回其索引(返回最大元素在这一行的列索引)

输出是预测与十个类的近似程度,与某一个类的近似程度越高,网络就越认为图像是属于这一类 别。所以让我们打印其中最相似类别类标.

torch.max)(a,0) 返回每一列中最大值的那个元素,且返回索引(返回最大元素在这一列的行索引)

_,predicted=torch.max(output.data,dim=1)

要在前面加_的原因:

torch.max(output.data,dim=1)返回的是两个值:每一行中最大值的那个元素和其索引;而我们需要的是它的索引下标,来确定是那个类[0,1,2,3,4,5,6,7,9]

_,predicted表示接收两个值,_得到是我们不需要的元素值

 

posted @ 2021-01-29 13:42  向阳而生w  阅读(326)  评论(0)    收藏  举报