1. 程式人生 > >Pytorch(一)

Pytorch(一)

orf red 上下 shuffle ack 優化 sent req adding

一、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

技術分享圖片

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



Pytorch(一)