PyTorch筆記1-PyTorch簡介
PyTorch簡介
PyTorch的安裝
PyTorch的安裝十分簡單,根據PyTorch官網,對系統選擇和安裝方式等靈活選擇即可。這裡新建一個Python3的虛擬環境後,然後在虛擬環境下用pip安裝,如下圖所示
PyTorch 會安裝兩個模組, 一個是 torch, 一個 torchvision, torch 是主模組, 用來搭建神經網路的, torchvision 是輔模組, 有資料庫, 還有一些已經訓練好的神經網路等著你直接用, 比如 (VGG, AlexNet, ResNet).
PyTorch之Tensor
pytorch是使用GPU和CPU優化的深度張量庫,torch中最重要的一個數據型別就是Tensor(張量)
Tensor是PyTorch的計算單元,可以理解為:N-dim陣列,跟Numpy類似。舉慄如下:
常數,如:a1 = 1,為0階Tensor;
向量,如:a2 = [2,1,5,1.1,2.3,1,5,1.1],為1階Tensor(也可以說一個維度);
二階矩陣為2階Tensor(2個維度),如:a3 =
3個二階矩陣為3階Tensor(3個維度),如:a4 =
- 注意:Tensor是有尺寸大小的,跟維度區分開,如a2.size()=8, a3.size()=(2,2), a4.size()=(3,2,2)
Tensor運算
下面演示其中一些操作,PyTorch的Tensor全部運算,參見這裡
import torch
import numpy as np
from torch.autograd import Variable
import torch.nn.functional as F # activation function
import matplotlib.pyplot as plt # python 的視覺化模組,畫圖用
%matplotlib inline
x1 = torch.rand(5,3) # 建立一個5*3的隨機矩陣
print(x1)
0.3658 0.7387 0.0901
0.4840 0.6414 0.1183
0.4703 0.8766 0.9165
0.7749 0.5472 0.4456
0.5532 0.4522 0.1290
[torch.FloatTensor of size 5x3]
x2 = torch.ones(5,3) # 建立 5*3 的全1矩陣
print(x2)
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
[torch.FloatTensor of size 5x3]
y1 = x1 + x2 # 兩個矩陣相加
print(y1)
1.3658 1.7387 1.0901
1.4840 1.6414 1.1183
1.4703 1.8766 1.9165
1.7749 1.5472 1.4456
1.5532 1.4522 1.1290
[torch.FloatTensor of size 5x3]
PyTorch與Numpy
Torch自稱為神經網路界的Numpy,因為它能將torch產生的Tensor放在GPU中加速運算,就像Numpy的array可以在CPU中加速運算,且numpy array和torch tensor可以相互轉換
所有numpy上關於ndarray的運算都可以運用於Tensor
從numpy到tensor的轉換:torch.from_numpy(np_data)
從tensor到numpy的轉換:np_data.numpy()
tensor與numpy的最大不同是:tensor可以在GPU上運算
np_data = np.arange(4).reshape(2,2)
torch_data = torch.from_numpy(np_data)
tensor2array = torch_data.numpy()
print(
'numpy array: \n', np_data,
'\n=================\n',
'\ntorch tensor: ', torch_data,
'\n==================\n',
'tensor to array: \n ', tensor2array
)
numpy array:
[[0 1]
[2 3]]
=================
torch tensor:
0 1
2 3
[torch.LongTensor of size 2x2]
==================
tensor to array:
[[0 1]
[2 3]]
Torch tensor的運算和Numpy array類似,詳細參考,下面演示一些
# abs 絕對值計算
data = [-1, -2, 1, 2]
tensor = torch.FloatTensor(data) # 轉換成32位浮點 tensor
print(
'numpy abs: ', np.abs(data),
'\ntorch abs: ', torch.abs(tensor)
)
# sin 三角函式
print(
'\nnumpy sin: ', np.sin(data),
'\ntorch sin: ', torch.sin(tensor)
)
# mean 均值
print(
'\nnumpy mean: ', np.mean(data),
'\ntorch mean: ', torch.mean(tensor)
)
numpy abs: [1 2 1 2]
torch abs:
1
2
1
2
[torch.FloatTensor of size 4]
numpy sin: [-0.84147098 -0.90929743 0.84147098 0.90929743]
torch sin:
-0.8415
-0.9093
0.8415
0.9093
[torch.FloatTensor of size 4]
numpy mean: 0.0
torch mean: 0.0
# matrix multiply
data = [[1,2], [3,4]]
tensor = torch.FloatTensor(data)
# correct
print(
'numpy matmul: ', np.matmul(data, data),
'\ntorch matmul: ', torch.mm(tensor, tensor)
)
numpy matmul: [[ 7 10]
[15 22]]
torch matmul:
7 10
15 22
[torch.FloatTensor of size 2x2]
Variable
在 Torch 中的 Variable 就是一個存放會變化的值的地理位置. 裡面的值會不停的變化. 就像一個裝雞蛋的籃子, 雞蛋數會不停變動. 那誰是裡面的雞蛋呢, 自然就是 Torch 的 Tensor 咯. 如果用一個 Variable 進行計算, 那返回的也是一個同類型的 Variable.
如上圖,一個Variable裡面包含著三個屬性,data,grad和creator,其中creator表示得到這個Variabel的操作,比如乘法或者加法等等,grad表示方向傳播的梯度,data表示取出這個Variabel裡面的資料
本質上 Variable 和 Variable 沒有區別,不過 Variabel 會放入一個計算圖,然後進行前向傳播,反向傳播以及自動求導, Variable 在計算同時,會把計算路徑記錄下來,在記憶體中構造一個計算圖
- 下面定義一個Variable
# 先產生雞蛋
tensor = torch.FloatTensor([[1,2], [3,4]])
# 把雞蛋放到籃子中,requires_grad 參不參與反向傳播,要不要計算梯度
variable = Variable(tensor, requires_grad=True)
print("tensor: ", tensor)
print("\n variable:", variable)
tensor:
1 2
3 4
[torch.FloatTensor of size 2x2]
variable: Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
- Variable 計算、梯度
# 對比 tensor 和 variable 的計算
t_out = torch.mean(tensor*tensor)
v_out = torch.mean(variable*variable)
print("tensor mean: ", t_out)
print("\n variable mean: ", v_out)
tensor mean: 7.5
variable mean: Variable containing:
7.5000
[torch.FloatTensor of size 1]
到目前為止, 我們看不出什麼不同, 但是時刻記住, Variable 計算時, 它在背景幕布後面一步步默默地搭建著一個龐大的系統, 叫做計算圖, computational graph.
這個圖是用來幹嘛的? 原來是將所有的計算步驟 (節點) 都連線起來, 最後進行誤差反向傳遞的時候, 一次性將所有 variable 裡面的修改幅度 (梯度) 都計算出來, 而 tensor 就沒有這個能力啦.
v_out = torch.mean(variable*variable) 就是在計算圖中新增的一個計算步驟, 計算誤差反向傳遞的時候有他一份功勞, 我們就來舉個例子:
v_out.backward() # 模擬 v_out 的誤差反向傳遞
# 下面兩步看不懂沒關係, 只要知道 Variable 是計算圖的一部分, 可以用來傳遞誤差就好.
# v_out = 1/4 * sum(variable*variable) 這是計算圖中的 v_out 計算步驟
# 針對於 v_out 的梯度就是, d(v_out)/d(variable) = 1/4*2*variable = variable/2
print(variable.grad) # 初始 variable 的梯度
Variable containing:
0.5000 1.0000
1.5000 2.0000
[torch.FloatTensor of size 2x2]
- 獲取 Variable 裡面的資料
直接print(variable)只會輸出 Variable 形式的資料,在很多時候是用不了的(如想要用 plt 畫圖),所以我們要轉換一下,將它變成 tensor 形式
print(variable) # Variable 形式
print(variable.data) # tensor 形式
print(variable.data.numpy()) # numpy 形式
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
1 2
3 4
[torch.FloatTensor of size 2x2]
[[ 1. 2.]
[ 3. 4.]]
動態圖機制
下面的動畫展示了 PyTorch 計算圖的動態生成過程
從上面的動畫,可以看出,PyTorch的計算圖是在 forward 執行過程中被定義生成的。
PyTorch 中的激勵函式
Torch 中的激勵函式(activation function)有很多,如:relu、sigmoid、tanh、softplus,
下面演示
x = torch.linspace(-5, 5, 200) # x data(tensor), shape(100,1)
x = Variable(x)
x_np = x.data.numpy() # 轉成 numpy array,出圖時用
# 幾種常用的激勵函式
y_relu = F.relu(x).data.numpy()
y_sigmoid = F.sigmoid(x).data.numpy()
y_tanh = F.tanh(x).data.numpy()
y_softplus = F.softplus(x).data.numpy()
# y_softmax = F.softmax(x).data.numpy softmax 比較特殊,不能直接顯示,用於多分類
# 畫圖
plt.figure(1, figsize=(8, 6)) # 作用新建繪畫視窗,獨立顯示繪畫的圖片
plt.subplot(221)
plt.plot(x_np, y_relu, c='red', label='relu')
plt.ylim(-1, 5) # 設定 y 軸範圍
plt.legend(loc="best") # 顯示圖例,best 為自適應
plt.subplot(222)
plt.plot(x_np, y_sigmoid, c='red', label='sigmoid')
plt.ylim(-0.2, 1.2)
plt.legend(loc="best")
plt.subplot(223)
plt.plot(x_np, y_tanh, c='red', label='tanh')
plt.ylim(-1.2, 1.2)
plt.legend(loc="best")
plt.subplot(224)
plt.plot(x_np, y_softplus, c='red', label='softplus')
plt.ylim(-0.2, 6)
plt.legend(loc="best")
plt.show()