深度学习与图像识别37 PyTorch实现神经网络图像分类基础

我们将介绍如何使用PyTorch构建神经网络的一些必备元素,带你进一步了解PyTorch。

之后我们会带领大家使用之前接触过的MNIST和Cifar10两个数据集做图像分类任务,这一次我们将使用PyTorch构建神经网络算法完成实验。

要点具体如下。

·PyTorch要点概述。

·PyTorch构建神经网络处理图像的分类问题。

PyTorch的使用

PyTorch如何构建神经网络的一些必备元素。如果大家对PyTorch有更多的学习需求,则请参考PyTorch官网https://pytorch.org/,其中的文档和教学案例都很全面。

1.1 Tensor 在PyTorch中,最核心的数据结构就是Tensor了,可以认为Tensor与Numpy中的ndarrays非常类似,但是Tensor可以使用GPU加速而ndarrays不可以。

我们在PyTorch下可以使用如下命令来进行GPU运算:

if torch.cuda.is_available():

x = x.cuda()

y = y.cuda()

print(x+y)

现在我们来列举几个小例子说明下Tensor是如何使用的。

例子一,Tensor和Numpy如何互相转换。

代码首先引入torch包(import torch),之后我们定义一个Numpy的二维数组,再使用torch.from_numpy(data)这个方法将Numpy数组转为PyTorch中的Tensor结构,另外,我们还可以使用numpy()方法将Tensor重新转为Numpy结构,具体代码如下:

import torch

import numpy as np

np_data = np.arange(8).reshape((2,4))        #定义一个numpy的二维数组

torch_data = torch.from_numpy(np_data)

print(np_data)

print(torch_data)

np_data2 = torch_data.numpy()                #转回numpy

print(np_data2)  输出结果如下:

[[0 1 2 3]

[4 5 6 7]]

tensor([[0, 1, 2, 3],

       [4, 5, 6, 7]])

[[0 1 2 3]

[4 5 6 7]]  上述输出结果中,第二个就是Tensor结构了,其他的都是Numpy中的ndarrays结构。 例子二,Tensor是如何做矩阵运算的。

下面的代码演示了一个比较重要的操作即矩阵相乘,我们可以看到,在Numpy中矩阵相乘使用的是dot这个方法,而在PyTorch中使用的是mm这个方法来表示,它们的结果是一样的,具体代码如下:

import torch

import numpy as np

np_data = np.array([[1,2],[3,5]])

torch_data = torch.from_numpy(np_data)

print(np_data)

print(np_data.dot(np_data))

print(torch_data.mm(torch_data))

输出结果如下:  [[1 2]

[3 5]]

[[ 7 12]

[18 31]]

tensor([[ 7, 12],

       [18, 31]])

1.2 Variable Tensor是PyTorch中的基础组件,但是构建神经网络还远远不够,我们需要能够构建计算图的Tensor,也就是Variable(简单理解就是Variable是对Tensor的一种封装)。

其操作与Tensor是一样的,但是每个Variable都包含了三个属性(data、grad以及creator):Variable中的Tensor本身(通过.data来进行访问)、对应Tensor的梯度(通过.grad进行访问)以及创建这个Variable的Function的引用(通过.grad_fn进行访问),该引用可用于回溯整个创建链路,如果是用户自己创建Variable,则其grad_fn为None Variable 如果我们需要使用Variable,则可在代码中输入如下语句:

from torch.autograd import Variable #导入Variable我们来看一个简单的小例子,示例代码如下:

from torch.autograd import Variable

import torch

x_tensor = torch.randn(10, 5)        #从标准正态分布中返回多个样本值

#将Tensor变成Variable

x = Variable(x_tensor, requires_grad=True)

                       #默认Variable是不需要求梯度的,所以用这个方式申明需要对其进行求梯度的操作

print(x.data)

print(x.grad)

print(x.grad_fn)  

返回的结果如下(值得注意的是,我们使用的是随机数,所以读者看到的结果与下面的输出值会不一样):

tensor([[-2.0649,  0.1842,  0.5331, -1.0484,  0.0831],

       [ 1.7195, -1.0548,  2.1493,  0.0560, -1.0903],

       [-1.0321, -1.8917, -0.5778,  0.0067, -0.0236],

       [ 0.0899, -0.8397,  1.0165,  1.2902, -1.1621],

       [ 1.5001, -0.6694, -0.4219,  1.1915,  0.3660],

       [ 0.7689, -1.5318, -1.7156, -1.9283, -0.3875],

       [ 1.1318,  0.7693,  1.8216, -0.3324, -0.8397],

       [ 0.0843,  0.1739,  0.8270,  1.4916,  0.7978],

       [ 1.4329,  0.0845,  0.0045, -0.7277, -0.2752],

       [-1.3560,  0.2973,  1.8447, -0.5960,  1.8151]])

None

None

1.3 激活函数 我们来看下如何在PyTorch中加载常见的激活函数。

之前是通过

import torch.nn.functional as F来加载激活函数,随着PyTorch版本的更新,如今通过torch可以直接加载激活函数了。

下面我们通过一个示例代码段来看下如何使用PyTorch来构建激活函数,实现代码具体如下:

import torch

from torch.autograd import Variable

import matplotlib.pyplot as plt

tensor = torch.linspace(-6,6,200)

tensor = Variable(tensor)

np_data = tensor.numpy()

#定义激活函数

y_relu = torch.relu(tensor).data.numpy()

y_sigmoid =torch.sigmoid(tensor).data.numpy()

y_tanh = torch.tanh(tensor).data.numpy()

plt.figure(1, figsize=(8, 6))

plt.subplot(221)

plt.plot(np_data, y_relu, c='red', label='relu')

plt.legend(loc='best')

plt.subplot(222)

plt.plot(np_data, y_sigmoid, c='red', label='sigmoid')

plt.legend(loc='best')

plt.subplot(223)

plt.plot(np_data, y_tanh, c='red', label='tanh')

plt.legend(loc='best')

plt.show()  

上述代码非常直观且易于理解,关于其解释就不多赘述了。代码的运行效果如图7-2所示。

1.4 损失函数 在之前我们已经对常用的损失函数做了一些讲解,本节中就不再赘述了。

PyTorch已经对这些常用的损失函数做好了封装,不必再向之前那样自己写代码来实现了。我们在本节中将主要介绍两个损失函数:

均方误差损失(MeanSquareErrorLoss)函数和交叉熵损失(CrossEntropyLoss)函数。

1.均方误差损失函数 PyTorch中均方差损失函数被封装成MSELoss函数,其调用方法如下:

torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')  调用方法中的参数及说明具体如下。 ·size_average(bool,optional):基本弃用(参见reduction)。

默认情况下,损失是批次(batch)中每个损失元素的平均值。请注意,对于某些损失,每个样本均有多个元 素。如果将字段size_average设置为False,则需要将每个batch的损失相加。

当reduce设置为False时忽略。默认值为True。 ·reduce(bool,optional):基本弃用(参见reduction)。

默认情况下,根据size_average,对每个batch中结果的损失进行平均或求和。当reduce为False时,返回batch中每个元素的损失并忽略size_average。默认值为True。

·reduction(string,optional):输出元素包含3种操作方式,即none、mean和sum。'none':不做处理。'mean':输出的总和除以输出中元素的数量。'sum':输出的和。

注意:size_average和reduce基本已被弃用,而且指定这两个args中的任何一个都将覆盖reduce。默认值为mean。 在PyTorch 0.4之后,参数size_average和reduce已被舍弃,最新版本是推荐使用re duction参数控制损失函数的输出行为,如果读者需要了解更具体的使用情况,则请参阅https://pytorch.org/docs/stable/nn.html#torch.nn.MSELoss。

2.交叉熵损失函数 PyTorch中的交叉熵损失函数将nn.LogSoftmax()和nn.NLLLoss()合并在一个类中,函数名为CrossEntropyLoss()。

CrossEntropyLoss是多分类任务中常用的损失函数,在PyTorch中其调用方法如下:  torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')  调用方法中的参数及其说明具体如下。

·weight(Tensor,optional):多分类任务中,手动给出每个类别权重的缩放量。如果给出,则其是一个大小等于类别个数的张量。

·size_average(bool,optional):已基本弃用(参见reduction)。

默认情况下,损失是batch中每个损失元素的平均值。请注意,对于某些损失,每个样本都包含了多个元素。

如果将字段size_average设置为False,则将每个小批量的损失相加。当reduce为False时则忽略。默认值为True。

·ignore_index(int,optional):指定被忽略且不对输入梯度做贡献的目标值。当size_average为True时,损失 则是未被忽略目标的平均。

·reduce(bool,optional):已基本弃用(参见reduction)。默认情况下,根据size_average,对每个batch中结果的损失进行平均或求和。当reduce为False时,返回batch中每个元素的损失并忽略size_average。默认值为True。

·reduction(string,optional):输出元素有3种操作方式,即none、mean和sum。'none':不做处理。'mean':输出的总和除以输出中的元素数量。'sum':输出的和。

注意:size_average和reduce正在被弃用,而且指定这两个args中的任何一个都将覆盖reduce。默认值为mean。 官方的示例代码如下:

>>> loss = nn.CrossEntropyLoss()

>>> input = torch.randn(3, 5, requires_grad=True)

>>> target = torch.empty(3, dtype=torch.long).random_(5)

>>> output = loss(input, target)

>>> output.backward()  

值得注意的是,PyTorch是不支持one-hot编码类型的,输入的都是真实的target,所以如果输入的真实分类是one-hot编码的话则需要自行转换,即将target one_hot的编码格式转换为每个样本的类别,再传给CrossEntropyLoss。

完整的代码实现具体如下:


import torch

from torch import nn

import numpy as np

#编码one_hot

def one_hot(y):

   '''

   y: (N)的一维Tensor,值为每个样本的类别

   out:

       y_onehot:转换为one_hot编码格式

   '''

   y = y.view(-1, 1)

   y_onehot = torch.FloatTen

sor(3, 5)

   # In your for loop

   y_onehot.zero_()

   y_onehot.scatter_(1, y, 1)

   return y_onehot

def cross_entropy_one_hot(target):

   #解码

   _, labels = target.max(dim=1)

   return labels

   #如果需要调用cross_entropy,则还需要传入一个in-put_

   #return F.cross_entropy(input_, labels)

x = np.array([1,2,3])

x_tensor =torch.from_numpy(x)

print(one_hot(x_tensor))

x2 = np.array([[0,1,0,0,0]])

x2_tensor = torch.from_numpy(x2)

print(cross_entropy_one_hot(x2_tensor))  输出结果具体如下:


tensor([[0., 1., 0., 0., 0.],

       [0., 0., 1., 0., 0.],

       [0., 0., 0., 1., 0.]]) #one-hot编码类型

tensor([1]) #truelabel类型

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容