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(2)數據運算as np # 創建一個np array a = np.array([[1,2], [3,4]]) b = torch.from_numpy(a) # 根據np array創建torch 張量 c = b.numpy() # 根據張量, 導出np array
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(一)