【深度学习8】Pytorch使用及使用小案例

八、PyTorch

8.1 相关定义

1 张量Tensor

优点:可以使用GPU加速

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

2)矩阵运算

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))
2 Variable

Tensor是PyTorch中的基础组件,但是构建神经网络还远远不够,我们需要能够构建计算图的Tensor,也就是Variable(简单理解就是Variable是对Tensor的一种封装)。
其操作与Tensor是一样的,但是每个Variable都包含了三个属性

  • .dataVariable中的Tensor本身
  • .grad对应Tensor的梯度
  • .grad_fn创建这个Variable的Function的引用(该引用可用于回溯整个创建链路,如果是用户自己创建Variable,则其grad_fn为None)

image-20220504081841335

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)

8.2 激活函数

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

8.3 损失函数

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已被舍弃。

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。

8.4 PyTorch实战

1 MNIST手写数字识别

PyTorch实战之MNIST分类第一个案例我们使用MNIST数据集来进行手写数字的识别。

1)数据准备

import torch
from torch.utils.data import DataLoader
import torchvision.datasets as dsets
import torchvision.transforms as transforms
batch_size = 100
# MNIST dataset
train_dataset = dsets.MNIST(root = '/pymnist', #选择数据的根目录
                           train = True, # 选择训练集
                           transform = transforms.ToTensor(), #转换成tensor变量
                           download = True) # 从网络上download图片
test_dataset = dsets.MNIST(root = '/pymnist', #选择数据的根目录
                           train = False, # 选择测试集
                           transform = transforms.ToTensor(), #转换成tensor变量
                           download = True) # 从网络上download图片
#加载数据
train_loader = torch.utils.data.DataLoader(dataset = train_dataset, 
                                           batch_size = batch_size, #使用批次数据
                                           shuffle = True)  # 将数据打乱
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
                                          batch_size = batch_size,
                                          shuffle = True)

2)创建神经网络模型

import torch.nn as nn
import torch

input_size = 784 #mnist的像素为28*28
hidden_size = 500
num_classes = 10 #输出为10个类别分别对应0-9

# 创建神经网络模型
class Neural_net(nn.Module):
#初始化函数,接受自定义输入特征的维数,隐含层特征维数以及输出层特征维数。
    def __init__(self, input_num,hidden_size, out_put):
        super(Neural_net, self).__init__()
        self.layer1 = nn.Linear(input_num, hidden_size)#从输入到隐藏层的线性处理
        self.layer2 = nn.Linear(hidden_size, out_put)#从隐层到输出层的线性处理

    def forward(self, x):
        out = self.layer1(x) #输入层到隐藏层的线性计算
        out = torch.relu(out) #隐藏层激活
        out = self.layer2(out) #输出层,注意,输出层直接接loss
        return out

net = Neural_net(input_size, hidden_size, num_classes)
print(net)

3)训练

# optimization
from torch.autograd import Variable
import numpy as np
learning_rate = 1e-1 #学习率
num_epoches = 5
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr = learning_rate)#使用随机梯度下降
for epoch in range(num_epoches):
    print('current epoch = %d' % epoch)
    for i, (images, labels) in enumerate(train_loader): #利用enumerate取出一个可迭代对象的内容
        images = Variable(images.view(-1, 28 * 28))
        labels = Variable(labels)
        
        outputs = net(images) #将数据集传入网络做前向计算
        loss = criterion(outputs, labels) #计算loss
        optimizer.zero_grad() #在做反向传播之前先清除下网络状态
        loss.backward() #loss反向传播
        optimizer.step() #更新参数
        
        if i % 100 == 0:
            print('current loss = %.5f' % loss.item())
            
print('finished training')

4)评估

#做prediction
total = 0
correct = 0
for images, labels in test_loader:
    images = Variable(images.view(-1, 28 * 28))
    outputs = net(images)
    print(outputs)
    _, predicts = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicts == labels).sum()
print('Accuracy = %.2f' % (100 * correct / total))

全部代码

import torch
from torch.utils.data import DataLoader
import torchvision.datasets as dsets
import torchvision.transforms as transforms
batch_size = 100
# MNIST dataset
train_dataset = dsets.MNIST(root = '/pymnist', #选择数据的根目录
                           train = True, # 选择训练集
                           transform = transforms.ToTensor(), #转换成tensor变量
                           download = True) # 从网络上download图片
test_dataset = dsets.MNIST(root = '/pymnist', #选择数据的根目录
                           train = False, # 选择测试集
                           transform = transforms.ToTensor(), #转换成tensor变量
                           download = True) # 从网络上download图片
#加载数据
train_loader = torch.utils.data.DataLoader(dataset = train_dataset, 
                                           batch_size = batch_size, #使用批次数据
                                           shuffle = True)  # 将数据打乱
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
                                          batch_size = batch_size,
                                          shuffle = True)


import torch.nn as nn
import torch

input_size = 784 #mnist的像素为28*28
hidden_size = 500
num_classes = 10 #输出为10个类别分别对应0-9

# 创建神经网络模型
class Neural_net(nn.Module):
#初始化函数,接受自定义输入特征的维数,隐含层特征维数以及输出层特征维数。
    def __init__(self, input_num,hidden_size, out_put):
        super(Neural_net, self).__init__()
        self.layer1 = nn.Linear(input_num, hidden_size)#从输入到隐藏层的线性处理
        self.layer2 = nn.Linear(hidden_size, out_put)#从隐层到输出层的线性处理

    def forward(self, x):
        out = self.layer1(x) #输入层到隐藏层的线性计算
        out = torch.relu(out) #隐藏层激活
        out = self.layer2(out) #输出层,注意,输出层直接接loss
        return out

net = Neural_net(input_size, hidden_size, num_classes)
print(net)


# optimization
from torch.autograd import Variable
import numpy as np
learning_rate = 1e-1 #学习率
num_epoches = 5
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr = learning_rate)#使用随机梯度下降
for epoch in range(num_epoches):
    print('current epoch = %d' % epoch)
    for i, (images, labels) in enumerate(train_loader): #利用enumerate取出一个可迭代对象的内容
        images = Variable(images.view(-1, 28 * 28))
        labels = Variable(labels)
        
        outputs = net(images) #将数据集传入网络做前向计算
        loss = criterion(outputs, labels) #计算loss
        optimizer.zero_grad() #在做反向传播之前先清除下网络状态
        loss.backward() #loss反向传播
        optimizer.step() #更新参数
        
        if i % 100 == 0:
            print('current loss = %.5f' % loss.item())
            
print('finished training')


#做prediction
total = 0
correct = 0
for images, labels in test_loader:
    images = Variable(images.view(-1, 28 * 28))
    outputs = net(images)
    print(outputs)
    _, predicts = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicts == labels).sum()
print('Accuracy = %.2f' % (100 * correct / total))
2 Cifar10分类

1)数据准备

import torch
from torch.utils.data import DataLoader
import torchvision.datasets as dsets
import torchvision.transforms as transforms
batch_size = 100

# MNIST dataset
train_dataset = dsets.CIFAR10(root = '/ml/pycifar', #选择数据的根目录
                           train = True, # 选择训练集
                           transform = transforms.ToTensor(), #转换成tensor变量
                           download = True) # 从网络上download图片
test_dataset = dsets.CIFAR10(root = '/ml/pycifar', #选择数据的根目录
                           train = False, # 选择测试集
                           transform = transforms.ToTensor(), #转换成tensor变量
                           download = True) # 从网络上download图片
#加载数据

train_loader = torch.utils.data.DataLoader(dataset = train_dataset, 
                                           batch_size = batch_size, 
                                           shuffle = True)  # 将数据打乱
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
                                          batch_size = batch_size,
                                          shuffle = True)

2)创建神经网络模型

from torch.autograd import Variable
import torch.nn as nn
import torch
# input_size = 3072
# hidden_size = 500
input_size = 784
hidden_size = 100
hidden_size2 = 200
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001


#定义两层神经网络
class Net(nn.Module):
    def __init__(self,input_size,hidden_size,hidden_size2,num_classes):
        super(Net,self).__init__()
        self.layer1 = nn.Linear(input_size,hidden_size)
        self.layer2 = nn.Linear(hidden_size,hidden_size2)
        self.layer3 = nn.Linear(hidden_size2,num_classes)
    
    def forward(self,x):
        out = torch.relu(self.layer1(x))
        out = torch.relu(self.layer2(out))
        out = self.layer3(out)
        return out

net = Net(input_size,hidden_size,hidden_size2,num_classes)
print(net)



3)训练

# optimization
from torch.autograd import Variable
import numpy as np
learning_rate = 1e-1 #学习率
num_epoches = 5
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr =
learning_rate)#使用随机梯度下降
for epoch in range(num_epoches):
    print('current epoch = %d' % epoch)
    for i, (images, labels) in enumerate(train_loader): #利 用enumerate取出一个可迭代对象的内容
        images = Variable(images.view(-1, 28 * 28))
        labels = Variable(labels)
        outputs = net(images) #将数据集传入网络做前向计算
        loss = criterion(outputs, labels) #计算Loss
        optimizer.zero_grad() #在做反向传播之前先清除下网络状态
        loss.backward() #Loss反向传播
        optimizer.step() #更新参数
        if i % 100 == 0:
            print('current loss = %.5f' % loss.item())
print('finished training')

4)评估

#做prediction total = 0
correct = 0
for images, labels in test_loader:
    images = Variable(images.view(images.size(0), -1))
    outputs = net(images)
    _, predicts = torch.max(outputs.data, 1) 
    total += labels.size(0)
    correct += (predicts == labels).sum()
print('Accuracy = %.2f' % (100 * correct / total))

最后我跑出来的结果是MINIST数据集的准确度为97.41%

而另一个复杂一些的彩色Cifar10数据集效果却不好,准确度只有48.35%。所以,浅层的神经网络keyi解决一部分简单的问题。深层的还是得看卷积神经网络。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值