人工智能大数据

人工智能00036 深度学习与图像识别书评36 PyTorch实

2024-01-17  本文已影响0人  良友知音

我们将介绍如何使用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类型

上一篇下一篇

猜你喜欢

热点阅读