Pytorch(一)

一、Pytorch介绍

Pytorch 是Torch在Python上的衍生物

和Tensorflow相比:

Pytorch建立的神经网络是动态的,而Tensorflow建立的神经网络是静态的

Tensorflow的高度工业化,它的底层代码很难看懂

官网:http://pytorch.org/

Pytorch主要有两个模块:

一个是torch,一个是torchvision,torch是主模块,用来搭建神经网络。torchvision是辅模块,有数据库,还有一些已经训练好的神经网络等着你直接用比如(VGG,AlexNet,ResNet)


二、基础知识

1.与Numpy交互

(1)数据转换

import torch
import numpy as np

# 创建一个np array
a = np.array([[1,2], [3,4]])
b = torch.from_numpy(a)      # 根据np array创建torch 张量
c = b.numpy()                # 根据张量, 导出np array
(2)数据运算

torch中tensor的运算与numpy array运算相似,比如

np.abs()--->torch.abs()

np.sin()---->torch.sin()等

2.变量Variable

image

(1)Variable组成

在Torch中Variable由三部分组成:data部分是Torch的Tensor,grad部分是这个变量的梯度缓存区,creator部分是这个Variable的创造节点,如果用一个Variable进行计算,那返回的也是同类型的Variable

(2)使用

导入

import torch

from torch.autograd import Variable

定义Variable的同时有一项requires_grad是关于参不参与误差反向传播,要不要计算梯度

注意Variable 和Tensor的区别:

Variable计算时,它在后台默默地搭建着一个庞大地系统,叫做计算图。computional graph将所有地计算步骤(节点)都连接起来,最后进行误差反向传递地时候,一次性将所有Variable里面地修改梯度都计算出来,而tensor只是一个数据结构。

构建计算图

y = w * x + b # y = 2 * x + 3

(3)计算梯度

# 对y求梯度
y.backward()

# 打印一下各个变量的梯度
print(x.grad)    # y对x的梯度: x.grad = 2 
print(w.grad)    # y对w的梯度: w.grad = 1 
print(b.grad)    # y对b的梯度: b.grad = 1

(4)Variable里面地数据

直接print(variable)只会输出Variable形式地数据,在很多时候是用不了地(比如想要用plt绘图),所以我们要转换一下,将它变成tensor形式

获取tensor数据:Print(variable.data),也可以将其转为numpy形式:print(variable.data.numpy())

3.Pytorch中的激活函数

导入包:import torch.nn.functional as F

平时常用的:relu、sigmoid,tanh,softplus

激活函数:激活函数的输入与输出都是variable

4.Pytorch中的数据加载器和batch

(1)生成数据生成并构建Dataset子集

import torch
import torch.utils.data as Data

torch.manual_seed(1)    

BATCH_SIZE = 5

x = torch.linspace(1, 10, 10)       # 输入数据
y = torch.linspace(10, 1, 10)       # 输出数据

# 打包成TensorDataset对象,成为标准数据集
torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y)


(2)生成batch数据

PyTorch用类torch.utils.data.DataLoader加载数据,并对数据进行采样,生成batch迭代器

# 创建数据加载器
loader = Data.DataLoader(
    dataset=torch_dataset,      # TensorDataset类型数据集
    batch_size=BATCH_SIZE,      # mini batch size
    shuffle=True,               # 设置随机洗牌
    num_workers=2,              # 加载数据的进程个数
)

for epoch in range(3):   # 训练3轮
    for step, (batch_x, batch_y) in enumerate(loader):  # 每一步
        # 在这里写训练代码...
        print('Epoch: ', epoch, '| Step: ', step, '| batch x: ', batch_x.numpy(), '| batch y: ', batch_y.numpy())


6.GPU运算

Pytorch中使用GPU计算简单,通过调用.cuda()方法,很容易实现GPU支持

torch.cuda会记录当前选择的GPU,并且分配的所有CUDA张量将在上面创建

可以使用torch.cuda.device上下文管理器更改所选设备

7.加载预训练模型

import torchvision

# 下载并加载resnet.
resnet = torchvision.models.resnet18(pretrained=True)

# 如果你只想要finetune模型最顶层的参数
for param in resnet.parameters():
    # 将resent的参数设置成不更新
    param.requires_grad = False

# 把resnet的全连接层fc 替换成自己设置的线性层nn.Linear
# 比如说,输入维度是resnet.fc.in_features, 输出是100维
resnet.fc = nn.Linear(resnet.fc.in_features, 100) 

# 测试一下
images = Variable(torch.randn(10, 3, 256, 256))
outputs = resnet(images)
print (outputs.size())   # (10, 100)

8.简单回归

import torch
from torch.autograd import Variable
import matplotlib.pyplot as plt

torch.manual_seed(1)

x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)  # 张量 x: (100, 1)
y = x.pow(2) + 0.2*torch.rand(x.size())                 # 加入噪声的张量 y: (100, 1)

# 将张量转为 Variable
x, y = Variable(x), Variable(y)

# 画一下
plt.scatter(x.data.numpy(), y.data.numpy())
plt.show()

class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # 隐层
        self.relu = torch.nn.ReLU()                          # 选择激活层
        self.predict = torch.nn.Linear(n_hidden, n_output)   # 输出层

    def forward(self, x):
        x = self.hidden(x)                                   # 计算隐层
        x = self.relu(x)                                     # 计算激活层
        x = self.predict(x)                                  # 输出层
        return x
net = Net(n_feature=1, n_hidden=10, n_output=1)              # 定义网络
print(net)
                                              #打印网络结构
# 选择损失函数和优化方法
loss_func = torch.nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.2)
plt.ion()   # hold住图
for t in range(100):
    prediction = net(x)                                      # 用网络预测一下
    loss = loss_func(prediction, y)                          # 计算损失
    optimizer.zero_grad()                                    # 清除上一步的梯度
    loss.backward()                                          # 反向传播, 计算梯度
    optimizer.step()                                         # 优化一步
    if t % 5 == 0:
        plt.cla()
        plt.scatter(x.data.numpy(), y.data.numpy())
        plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5)
        plt.text(0.5, 0, 'Loss=%.4f' % loss.data[0], fontdict={'size': 20, 'color': 'red'})
        plt.pause(1)
        print(t)
plt.ioff()
plt.show()

9.快速构建序列网络

torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中。另外 ,也可以传入一个有序模块。

# Sequential使用实例

model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

# Sequential with OrderedDict使用实例
model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

为了方便比较,我们先用普通方法搭建一个神经网络。


import torch


# 继承方式实现, 能够自定义forward
class ModuleNet(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(ModuleNet, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # 隐层
        self.relu = torch.nn.ReLU()                          # 选择激活层
        self.predict = torch.nn.Linear(n_hidden, n_output)   # 输出层

    def forward(self, x):
        x = self.hidden(x)                                   # 计算隐层
        x = self.relu(x)                                     # 计算激活层
        x = self.predict(x)                                  # 输出层
        return x

module_net = ModuleNet(1, 10, 1)

上面ModuleNet继承了一个torch.nn.Module中的神经网络结构, 然后对其进行了修改;接下来我们来使用torch.nn.Sequential来快速搭建一个神经网络。

#用序列化工具, 给予Pytorch 内部集成的网络层 快速搭建
seq_net = torch.nn.Sequential(
    torch.nn.Linear(1, 10),
    torch.nn.ReLU(),
    torch.nn.Linear(10, 1)
)

我们来打印一下2个神经网络的数据,查看区别:

print(module_net)     # 打印网络结构
"""
ModuleNet (
  (hidden): Linear (1 -> 10)
  (relu): ReLU ()
  (predict): Linear (10 -> 1)
)
"""

print(seq_net)        # 打印网络结构
"""
Sequential (
  (0): Linear (1 -> 10)
  (1): ReLU ()
  (2): Linear (10 -> 1)
)
"""



posted @ 2018-04-30 23:37  彼岸花杀是条狗  阅读(3646)  评论(1编辑  收藏  举报