地點(diǎn):鑒主
時(shí)間:2017-1130
本文主要記錄學(xué)習(xí) Pytorch Tutorials 過(guò)程中的筆記及相關(guān)問(wèn)題。
PyTorch 的相關(guān)背景就不做介紹了,網(wǎng)上很多。
在實(shí)際的使用過(guò)程中來(lái)看,對(duì)比之前用過(guò)的 TensorFlow 和 Keras 而言,使用 PyTorch 就像是在寫(xiě)一個(gè)普通的 Python 程序,而不是像 TF 和 Keras 一樣限制頗多,因此在使用的過(guò)程中,相比于其他框架能夠很清楚自己做的是什么,非常的新手友好。
PyTorch 基本概念
機(jī)器學(xué)習(xí)方面的幾個(gè)重要概念在 PyTorch 主要通過(guò) Tensors, Autograd, nn module 進(jìn)行體現(xiàn)。
Tensors
Numpy 是一個(gè)很好的計(jì)算工具,但是它無(wú)法使用 GPUs 加速數(shù)值計(jì)算,因此性能不能滿(mǎn)足要求。
首先引入最基本的 PyTorch 概念: Tensor. Tensor 是一個(gè) n 維數(shù)組,同時(shí) PyTorch 提供了多種函數(shù)對(duì)它進(jìn)行操作。與 Numpy.array 相同的是, PyTorch 的 Tensors 不包含任何 深度學(xué)習(xí),計(jì)算圖或者梯度 這些科學(xué)計(jì)算的工具。
然而不同于 numpy 的是,PyTorch 的 Tensors 能夠利用 GPUs 來(lái)進(jìn)行加速數(shù)值計(jì)算。在 GPU 上運(yùn)行 PyTorch 的 Tensor, 我們需要將它簡(jiǎn)單轉(zhuǎn)換一下數(shù)據(jù)格式。
# -*- coding: utf-8 -*-
import torch
dtype = torch.FloatTensor
# dtype = torch.cuda.FloatTensor # 在 GPU 上運(yùn)行調(diào)用的函數(shù)
# N is 批數(shù)目; D_in is 輸入維數(shù);
# H is 隱藏層維數(shù); D_out is 輸出層維數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建隨機(jī)輸入輸出數(shù)據(jù)
x = torch.randn(N, D_in).type(dtype)
y = torch.randn(N, D_out).type(dtype)
# 隨機(jī)初始化權(quán)重文件
w1 = torch.randn(D_in, H).type(dtype)
w2 = torch.randn(H, D_out).type(dtype)
# 設(shè)置學(xué)習(xí)率
learning_rate = 1e-6
for t in range(500):
# 前向傳播,計(jì)算預(yù)測(cè)的 y 值
h = x.mm(w1)
h_relu = h.clamp(min=0)
y_pred = h_relu.mm(w2)
# 計(jì)算并且輸出 loss 值
loss = (y_pred - y).pow(2).sum()
print(t, loss)
# 基于 loss 值 反向傳播計(jì)算 w1 和 w2 的梯度
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
# 使用梯度下降更新權(quán)值
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
可以看出,在實(shí)際的操作上面,其使用方法和 numpy 非常相似。
Autograd
上面的例子實(shí)現(xiàn)了前向傳播和反向傳播,這是神經(jīng)網(wǎng)絡(luò)的基礎(chǔ)。在實(shí)際的過(guò)程中,我們可以使用 Automatic Differentiation 來(lái)自動(dòng)計(jì)算神經(jīng)網(wǎng)絡(luò)的反向傳播值。PyTorch 中的 autograd 包就是用于提供這個(gè)功能。
When using autograd, the forward pass of your network will define a computational graph; nodes in the graph will be Tensors, and edges will be functions that produce output Tensors from input Tensors. Backpropagating through this graph then allows you to easily compute gradients.
當(dāng)使用 autograd 時(shí),你網(wǎng)絡(luò)中的前向傳播將會(huì)定義一個(gè)計(jì)算圖,在這個(gè)圖中的每個(gè)節(jié)點(diǎn)都是張量,邊可以提供從輸入張量到輸出張量的處理功能。隨后圖中的反向傳播過(guò)程能夠讓你簡(jiǎn)單計(jì)算梯度。
在實(shí)際的使用中非常簡(jiǎn)單。我們將 PyTorch 的 Tensors 包裝進(jìn) Variable ; 一個(gè) Varible 展示了計(jì)算圖中的一個(gè)節(jié)點(diǎn)。如果 x 是一個(gè) Variable ,x.data 既是張量,x.grad 是另一個(gè) Variable,其中包含了通過(guò)變換值求出的 x 梯度。
PyTorch Variable 的操作基本和 PyTorch Tensors 一樣。區(qū)別在于使用 Variable 定義的是一個(gè)計(jì)算圖,允許網(wǎng)絡(luò)自動(dòng)求梯度。
隨后使用 Variables 和 autograd 來(lái)實(shí)現(xiàn)上文的神經(jīng)網(wǎng)絡(luò), 現(xiàn)在我們不需要再實(shí)現(xiàn)上文的 backward pass 過(guò)程。
import torch
from torch.autograd import Variable
dtype = torch.FloatTensor
# dtype = torch.cuda.FloatTensor # gpu 運(yùn)行時(shí)的代碼
# N is 批數(shù)目; D_in is 輸入維數(shù);
# H is 隱藏層維數(shù); D_out is 輸出層維數(shù).
N, D_in, H, D_out = 64, 1000, 100, 10
# 創(chuàng)建隨機(jī) Tensors 來(lái)保存 輸入和輸出, 隨后將它們包進(jìn) Variables
# 設(shè)置 requires_grad = False 來(lái)表示我們無(wú)需計(jì)算梯度
# with respect to these Variables during the backward pass.
x = Variable(torch.randn(N, D_in).type(dtype), requires_grad=False)
y = Variable(torch.randn(N, D_out).type(dtype), requires_grad=False)
# 為權(quán)值創(chuàng)建隨機(jī) Tensor, 并且將它們包進(jìn) Variables
# 設(shè)置 requires_grad = True 表示我們需要計(jì)算梯度
# respect to these Variables during the backward pass.
w1 = Variable(torch.randn(D_in, H).type(dtype), requires_grad=True)
w2 = Variable(torch.randn(H, D_out).type(dtype), requires_grad=True)
learning_rate = 1e-6
for t in range(500):
# Forward pass: 使用 Variables 中的值計(jì)算 y;這個(gè)操作和我們使用 Tensors 計(jì)算
# 時(shí)一樣, 但是我們不需要保持對(duì)中間值的引用,因?yàn)槲覀儫o(wú)需動(dòng)手實(shí)現(xiàn) backward pass .
y_pred = x.mm(w1).clamp(min=0).mm(w2)
# 使用 Variable 中的函數(shù)計(jì)算并且輸出 loss 值
# 此時(shí) loss 值是一個(gè) shape (1, ) 的 Variable,并且 loss.data 是一個(gè)形狀為 (1, ) 的 Tensor。
# loss.data[0] 是一個(gè)保存 loss 值的標(biāo)量
loss = (y_pred - y).pow(2).sum()
print(t, loss.data[0])
# 使用 autograd 計(jì)算 backward pass. 這個(gè)調(diào)用將會(huì)計(jì)算 loss 值的梯度,依據(jù)的是
# 所有 requires_grad = True 的 Variable。
# After this call w1.grad and w2.grad will be Variables holding the gradient
# of the loss with respect to w1 and w2 respectively.
loss.backward()
# 使用 梯度下降更新權(quán)值;w1.data 和 w2.data 是 Tensors。
# w1.grad 和 w2.grad 是 Variable; w1.grad.data 和 w2.grad.data 是 Tensors
w1.data -= learning_rate * w1.grad.data
w2.data -= learning_rate * w2.grad.data
# 更新權(quán)值之后將梯度歸 0
w1.grad.data.zero_()
w2.grad.data.zero_()
PyTorch : Variables and autograd
nn module
PyTorch CNN
為了進(jìn)行實(shí)際操作,用 PyTorch 構(gòu)建一個(gè) CNN 是很常見(jiàn)的方法。
首先需要導(dǎo)入基本的包。
參考
http://pytorch.org/tutorials/beginner/pytorch_with_examples.html