[Deep Learning] Pytorch cơ bản
Cơ bản Pytorch
1. Mục lục
- Mục lục
- Cơ bản Pytorch
- Tensor
- 3.1. Khởi tạo Tensor
- 3.2. Tensor trên CPU / GPU
- 3.3. Các kiểu dữ liệu Tensor
- 3.4. Các toán tử trên Tensor
- 3.4.1. Cú pháp
- 3.4.2. Các toán tử trên phần tử (element-wise) thường dùng
- 3.4.3. Broadcast
- Tensor
- Variable
- 4.1. Khởi tạo Variable
- 4.2. Autograd
- Variable
2. Cơ bản Pytorch
Pytorch là framework Deep Learning cho phép lập trình trên Python, thực hiện các phép tính toán trên GPU. Cài đặt Pytorch dễ dàng bằng cách theo hướng dẫn trên trang chủ http://pytorch.org.
Lưu ý: Các code ví dụ trong bài thực hành này hoạt động tốt nhất trên Python 3.5.
3. Tensor
Tensor là kiểu dữ liệu chính trong Pytorch. Có thể hình dung Tensor là khối ma trận nhiều chiều.
3.1. Khởi tạo Tensor
Khởi tạo Tensor có kích thước 3 hàng, 4 cột:
import torch
x = torch.Tensor(3,4)
print(x)
Kết quả in ra Tensor:
5.0234e+24 4.5894e-41 5.0234e+24 4.5894e-41
0.0000e+00 0.0000e+00 6.7355e+24 4.5894e-41
0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00
[torch.FloatTensor of size 3x4]
Vì ta không đặc tả cách khởi tạo nên việc chạy đi chạy lại script trên sẽ in ra các kết quả khác nhau và miền giá trị của mỗi phần tử sẽ không biết trước được.
Khởi tạo Tensor theo phân phối đồng đều (uniform distribution)
import torch
x = torch.rand(3,4)
print(x)
Mỗi phần tử nằm trong miền giá trị [0,1)
0.6179 0.2847 0.2000 0.9990
0.8118 0.1532 0.6351 0.9820
0.0704 0.5383 0.8822 0.1310
[torch.FloatTensor of size 3x4]
Khởi tạo Tensor nhiều chiều:
import torch
x = torch.Tensor([[2,5],[4,3],[1,5]])
y = torch.Tensor([[[1,2,3,4], [2,6,8,1], [4,8,10,2]], [[0,2,7,6], [1,9,3,2], [1,2,3,4]]])
print(x)
print(y)
print('y.size()', y.size())
Dùng phương thức .size()
để kiểm tra kích thước Tensor. Kết quả:
2 5
4 3
1 5
[torch.FloatTensor of size 3x2]
(0 ,.,.) =
1 2 3 4
2 6 8 1
4 8 10 2
(1 ,.,.) =
0 2 7 6
1 9 3 2
1 2 3 4
[torch.FloatTensor of size 2x3x4]
y.size() torch.Size([3, 2])
Tensor cũng có thể được tạo từ kiểu dữ liệu NumPy.
import torch
import numpy as np
x = np.array([1,2,3])
y = torch.from_numpy(X)
print('x', x)
print('y', y)
y += 1
print('x*', x)
print('y*', y)
z = y.numpy()
print('z', z)
print('type(z)', type(z))
Khởi tạo numpy array x, chuyển đổi x thành Tensor y. Tensor y cộng thêm 1 đơn vị, x cũng sẽ tự động thay đổi theo. Từ Tensor ta cũng có thể chuyển đổi ngược lại về numpy.
x [1 2 3]
y
1
2
3
[torch.LongTensor of size 3]
x* [2 3 4]
y*
2
3
4
[torch.LongTensor of size 3]
z [2 3 4]
type(z) <class 'numpy.ndarray'>
3.2. Tensor trên CPU / GPU
Tính toán trên GPU nhanh gấp nhiều lần trên CPU. Tensor hỗ trợ việc tính toán trên GPU, mặc định Tensor tạo theo cách thông thường sẽ nằm trên CPU. Để đem Tensor lên GPU tính toán, ta dùng phương thức .cuda()
.
import torch
x = torch.Tensor([1,2,3])
y = torch.Tensor([4,5,6])
if torch.cuda.is_available():
x = x.cuda()
y = y.cuda()
print(x + y)
else:
print('Cuda is not available!')
Dòng lệnh torch.cuda.is_available()
kiểm tra xem máy tính có hỗ trợ CUDA. Nếu có kết quả sẽ in ra như sau:
5
7
9
[torch.cuda.FloatTensor of size 3 (GPU 0)]
Minh họa việc tính toán trên GPU nhanh hơn CPU bằng ví dụ sau:
import torch
import time
x = torch.rand(10000,10000)
y = torch.rand(10000,10000)
tic = time.time()
x + y
toc = time.time()
print('Elapsed time on CPU: %fs' % (toc-tic))
x = x.cuda()
y = y.cuda()
tic = time.time()
x + y
toc = time.time()
print('Elapsed time on GPU: %fs' % (toc-tic))
Kết quả:
Elapsed time on CPU: 0.118872s
Elapsed time on GPU: 0.000901s
3.3. Các kiểu dữ liệu Tensor
Bảng các kiểu dữ liệu Tensor (http://pytorch.org/docs/0.3.0/tensors.html#torch-tensor):
Kiểu dữ liệu | CPU Tensor | GPU Tensor |
---|---|---|
32-bit floating point | torch.FloatTensor | torch.cuda.FloatTensor |
64-bit floating point | torch.DoubleTensor | torch.cuda.DoubleTensor |
16-bit floating point | torch.HalfTensor | torch.cuda.HalfTensor |
8-bit integer (unsigned) | torch.ByteTensor | torch.cuda.ByteTensor |
8-bit integer (signed) | torch.CharTensor | torch.cuda.CharTensor |
16-bit integer (signed) | torch.ShortTensor | torch.cuda.ShortTensor |
32-bit integer (signed) | torch.IntTensor | torch.cuda.IntTensor |
64-bit integer (signed) | torch.LongTensor | torch.cuda.LongTensor |
import torch
x = torch.FloatTensor(range(5))
y = torch.cuda.FloatTensor(range(5))
print(x)
print(y)
Kết quả:
0
1
2
3
4
[torch.FloatTensor of size 5]
0
1
2
3
4
[torch.cuda.FloatTensor of size 5 (GPU 0)]
3.4. Các toán tử trên Tensor
3.4.1. Cú pháp
Có các cú pháp sau:
- Dùng toán tử nhị phân
import torch x = torch.rand(3) y = torch.rand(3) z = x + y print(z)
Kết quả:
1.6920 1.1049 1.0741 [torch.FloatTensor of size 3]
- Dùng phương thức trong class
torch
import torch x = torch.rand(3) y = torch.rand(3) z = torch.add(x, y) print(z)
- Dùng phương thức trong thực thể Tensor. Cách này sẽ trực tiếp thay đổi dữ liệu trong thực thể gọi phương thức.
import torch x = torch.rand(3) y = torch.rand(3) z = x.add_(y) print(z)
3.4.2. Các toán tử trên phần tử (element-wise) thường dùng
- Toán tử cộng: + / torch.add()
- Toán tử nhân: * / torch.mul()
import torch x = torch.FloatTensor([[2,5],[4,3],[1,5]]) y = torch.FloatTensor([[1,4],[-2,2],[3,-2]]) print(x) print(y) print(torch.mul(x,y))
Từng phần tử của ma trận x nhân tương ứng từng phần tử của ma trận y. Kết quả:
2 5 4 3 1 5 [torch.FloatTensor of size 3x2] 1 4 -2 2 3 -2 [torch.FloatTensor of size 3x2] 2 20 -8 6 3 -10 [torch.FloatTensor of size 3x2]
- Toán tử bình phương: ** / torch.pow()
import torch x = torch.FloatTensor([1,2,3]) print(torch.pow(x, 2)) print(x**2)
- Toán tử căn bậc 2: torch.sqrt()
import torch torch.sqrt(torch.randn(4))
3.4.3. Broadcast
Broadcast cho phép ta thực hiện các toán tử giữa 2 tensor của pytorch / mảng numpy không cùng số chiều. Quy tắc Broadcast:
- Thêm chiều vào phía trước tensor có chiều ngắn hơn cho đến khi số chiều 2 tensor bằng nhau
- Số phần tử của mỗi chiều của 2 tensor phải:
- bằng nhau, hoặc
- một tensor có 1 phần tử, giá trị của phần tử được nhân bản thành k phần tử (bằng với số phần tử của tensor còn lại ở chiều đang xét)
import torch
x = torch.rand(2,1,3)
y = torch.ones(3,1)
print(x)
print(y)
print(x+y)
Giải thích:
- Kích thước của x: 2x1x3
- Kích thước của y: 3x1
- Broadcast:
- Thêm chiều vào phía trước của y cho đến khi số chiều bằng x –> kích thước của y: 1x3x1
- Xét chiều thứ 0: chiều thứ 0 của y là 1, nhỏ hơn x (là 2) –> kích thước y: 2x3x1
- Xét chiều thứ 1: chiều thứ 1 của y là 3, lớn hơn x (là 1) –> kích thước x: 2x3x3
- Xét chiều thứ 2: chiều thứ 2 của y là 1, nhỏ hơn x (là 3) –> kích thước y: 2x3x3
- Kết quả kích thước tensor đầu ra sẽ là 2x3x3
(0 ,.,.) =
0.6508 0.2330 0.3965
(1 ,.,.) =
0.1472 0.8538 0.4213
[torch.FloatTensor of size 2x1x3]
1
1
1
[torch.FloatTensor of size 3x1]
(0 ,.,.) =
1.6508 1.2330 1.3965
1.6508 1.2330 1.3965
1.6508 1.2330 1.3965
(1 ,.,.) =
1.1472 1.8538 1.4213
1.1472 1.8538 1.4213
1.1472 1.8538 1.4213
[torch.FloatTensor of size 2x3x3]
Nếu vi phạm quy tắc broadcast trên thì Pytorch sẽ báo lỗi:
import torch
x=torch.FloatTensor(5,2,4,1)
y=torch.FloatTensor(3,1,1)
(x+y).size()
Hiển thị lỗi:
RuntimeError: inconsistent tensor size, expected r_ [5 x 2 x 4 x 1], t [5 x 2 x 4 x 1] and src [3 x 1 x 1] to have the same number of elements, but got 40, 40 and 3 elements respectively
4. Variable
Variable là class bao bọc (wrapper) Tensor cho phép thực hiện tính toán đạo hàm. Variable lưu trữ data (tensor) và grad (gradient).
4.1. Khởi tạo Variable
import torch
from torch.autograd import Variable
x = Variable(torch.ones(2, 2), requires_grad=True)
print(x)
Variable hỗ trợ hầu hết các toán tử của Tensor.
4.2. Autograd
Minh họa cách tính Gradient tự động trong Pytorch bằng ví dụ sau: Cho đồ thị tính toán như hình. Đầu vô [x,y,z] = [5,3,7]. Tất cả các trọng số w đều được khởi tạo là 0.5. Tính kết quả (biến result) khi ta cho [x,y,z] qua mạng (forward) và gradient của mỗi trọng số w (backward).
import torch
from torch.autograd import Variable
xy = Variable(torch.FloatTensor([5, 3]), requires_grad=True) # size: 2
z = Variable(torch.FloatTensor([7]), requires_grad=True) # size: 1
w12 = Variable(torch.FloatTensor([0.5, 0.5]), requires_grad=True) # size: 2
w3 = Variable(torch.FloatTensor([0.5]), requires_grad=True) # size: 1
w4 = Variable(torch.FloatTensor([0.5]), requires_grad=True) # size: 1
w5 = Variable(torch.FloatTensor([0.5]), requires_grad=True) # size: 1
k = xy*w12
o1 = k[0]*k[1]
o2 = o1*w4 + z*w3
result = o2*w5
print('result', result) # 2.6875
result.backward()
print('w12.grad', w12.grad) # 1.8750, 1.8750
print('w3.grad', w3.grad) # 3.5000
print('w4.grad', w4.grad) # 1.8750
print('w5.grad', w5.grad) # 5.3750
Forward
o1 = x * w1 * y * w2 = 5 * 0.5 * 3 * 0.5 = 3.75
o2 = o1 * w4 + z * w3 = 3.75 * 0.5 + 7 * 0.5 = 5.375
result = o2 * w5 = 5.375 * 0.5 = 2.6875
Backward
Cần chú ý công thức đạo hàm của hàm hợp:
f'(u(x)) = f'(u) * u'(x)
result = o2 * w5
Đạo hàm của result theo w5 = (o2 * w5)' = o2 = 5.375
Đạo hàm của result theo o2 = f'(o2) = w5 = 0.5
o2 = o1 * w4 + z * w3
Đạo hàm của result theo w3 = f'(o2) * o2'(w3) = 0.5 * z = 3.5
Đào hàm của result theo w4 = f'(o2) * o2'(w4) = 0.5 * o1 = 1.875
Đào hàm của result theo o1 = g'(o1) = f'(o2) * o2'(o1) = 0.5 * w4 = 0.25
o1 = x * w1 * y * w2
Đạo hàm của result theo w1 = g'(o1) * o1'(w1) = 0.25 * x * y * w2 = 1.875
Đạo hàm của result theo w2 = g'(o1) * o1'(w2) = 0.25 * x * w1 * y = 1.875
Link download: 2018-02-21-pytorch-co-ban.pdf
Tham khảo thêm: