美文网首页人工智能大数据
人工智能00036 深度学习与图像识别书评36 PyTorch实

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

作者: 良友知音 | 来源:发表于2024-01-17 07:04 被阅读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类型

    相关文章

      网友评论

        本文标题:人工智能00036 深度学习与图像识别书评36 PyTorch实

        本文链接:https://www.haomeiwen.com/subject/onjlodtx.html