Chào mừng các bạn đến với bài viết thứ bảy trong loạt bài về Lập Trình Neural Network Với Pytorch. Trong bài viết này, chúng ta sẽ bắt đầu giới thiệu và tìm hiểu sâu hơn về chính PyTorch bằng cách khám phá các Tensors của nó. Bắt đầu thôi!
Giới Thiệu Tensors PyTorch
Các tensors PyTorch chính là cấu trúc dữ liệu mà chúng ta sẽ sử dụng khi lập trình mạng neural trong PyTorch.
Khi lập trình mạng neural, tiền xử lý dữ liệu thường là một trong những bước đầu tiên quan trọng nhất trong quy trình tổng thể và mục tiêu của tiền xử lý dữ liệu là chuyển đổi dữ liệu đầu vào đang ở dạng thô thành dạng tensor.
Torch.Tensor
Chúng ta có thể tạo một đối tượng torch.Tensor như sau:
> t = torch.Tensor() > type(t) torch.Tensor
Điều này tạo ra một tensor trống (tensor không có dữ liệu), nhưng chúng ta sẽ thêm dữ liệu ngay sau đây.
Thuộc Tính Của Tensor
Đầu tiên, hãy xem xét một vài thuộc tính tensor. Mỗi torch.Tensor có các thuộc tính sau:
- torch.dtype
- torch.device
- torch.layout
Nhìn vào Tensor t, chúng ta có thể thấy các giá trị thuộc tính mặc định sau:
> print(t.dtype) > print(t.device) > print(t.layout) torch.float32 cpu torch.strided
torch.dtype
Trong ví dụ trên Dtype là torch.float32 chỉ định loại dữ liệu được chứa trong tensor. Tensors chứa dữ liệu số đồng nhất (cùng loại) với một trong các loại sau:
Data type | dtype | CPU tensor | GPU tensor |
32-bit floating point | torch.float32 | torch.FloatTensor | torch.cuda.FloatTensor |
64-bit floating point | torch.float64 | torch.DoubleTensor | torch.cuda.DoubleTensor |
16-bit floating point | torch.float16 | torch.HalfTensor | torch.cuda.HalfTensor |
8-bit integer (unsigned) | torch.uint8 | torch.ByteTensor | torch.cuda.ByteTensor |
8-bit integer (signed) | torch.int8 | torch.CharTensor | torch.cuda.CharTensor |
16-bit integer (signed) | torch.int16 | torch.ShortTensor | torch.cuda.ShortTensor |
32-bit integer (signed) | torch.int32 | torch.IntTensor | torch.cuda.IntTensor |
64-bit integer (signed) | torch.int64 | torch.LongTensor | torch.cuda.LongTensor |
Mỗi loại đều có phiên bản CPU và GPU tương ứng. Một điều cần lưu ý về kiểu dữ liệu tensor là các phép toán xảy ra giữa các tensor phải có cùng kiểu dữ liệu. Tuy nhiên, điều này chỉ áp dụng cho các phiên bản PyTorch thấp hơn 1.3.
Các phép toán số học và so sánh, kể từ phiên bản PyTorch 1.3 trở lên, có thể thực hiện được cho dù chúng không cùng kiểu dữ liệu. Ví dụ dưới đây không được phép trong phiên bản 1.2. Tuy nhiên, trong phiên bản 1.3 trở lên, kết quả trả về một tensor với dtype = torch.float32.
torch.tensor([1], dtype=torch.int) + torch.tensor([1], dtype=torch.float32)
Bạn có thể xem tài liệu đầy đủ để biết thêm chi tiết.
Torch.device
Trong ví dụ trên, device là CPU tức là chỉ định thiết bị (CPU hoặc GPU) nơi dữ liệu của Tensor được phân bổ. Điều này sẽ xác định nơi tính toán cho tensor.
PyTorch hỗ trợ việc sử dụng nhiều thiết bị và chúng được chỉ định bằng cách sử dụng index như sau:
> device = torch.device('cuda:0') > device device(type='cuda', index=0)
Một điều cần lưu ý khi sử dụng nhiều thiết bị là hoạt động giữa các tensor phải xảy ra giữa các tensor tồn tại trên cùng một thiết bị.
Torch.layout
Trong ví dụ trên layout là strided tức là chỉ định cách tensor được lưu trong bộ nhớ. Bạn có thể tìm hiểu thêm stride tại đây.
Bỏ Qua Các Thuộc Tính Tensor
Là một lập trình viên mạng Neural, chúng ta cần lưu ý những điều sau:
- Dữ liệu của tensor phải thống nhất với nhau (dtype).
- Việc tính toán giữa các tensor phụ thuộc vào dtype và device
Bây giờ chúng ta hãy xem các cách phổ biến để tạo ra tensors bằng dữ liệu trong PyTorch.
Tạo Tensor Bằng Dữ Liệu
Đây là những cách chính để tạo các đối tượng tensor (các lớp thể hiện của torch.Tensor), với dữ liệu (giống mảng) trong PyTorch:
torch.Tensor(data)
torch.tensor(data)
torch.as_tensor(data)
torch.from_numpy(data)
Tất cả chúng đều chấp nhận một số dạng dữ liệu và cung cấp cho chúng ta một thể hiện của lớp torch.Tensor.
Chúng ta sẽ bắt đầu bằng cách chỉ tạo một tensor với mỗi tùy chọn và xem những gì chúng ta nhận được. Bắt đầu bằng cách tạo một số dữ liệu.
Ta có thể sử dụng một danh sách hoặc chuỗi Python, nhưng numpy.ndarrays là tùy chọn phổ biến hơn, vì vậy chúng ta sẽ sử dụng một numpy.ndarray như sau:
> data = np.array([1,2,3]) > type(data) numpy.ndarray
Điều này cung cấp cho chúng ta một chút dữ liệu đơn giản với kiểu numpy.ndarray.
Bây giờ, hãy tạo các tensor của với mỗi tùy chọn (1 – 4) và xem những gì chúng ta nhận được:
> o1 = torch.Tensor(data) > o2 = torch.tensor(data) > o3 = torch.as_tensor(data) > o4 = torch.from_numpy(data) > print(o1) > print(o2) > print(o3) > print(o4) tensor([1., 2., 3.]) tensor([1, 2, 3], dtype=torch.int32) tensor([1, 2, 3], dtype=torch.int32) tensor([1, 2, 3], dtype=torch.int32)
Tất cả các tùy chọn (o1, o2, o3, o4) dường như tạo ra cùng một tensors ngoại trừ tùy chọn đầu tiên. Tùy chọn đầu tiên (o1) có các dấu chấm đằng sau mỗi số chỉ ra rằng các số đó là kiểu float, trong khi ba tùy chọn tiếp theo có kiểu int32.
Trong bài tiếp theo, chúng ta sẽ xem sét kỹ hơn về sự khác biệt này. Bây giờ, chúng ta hãy xem một số tùy chọn có sẵn để tạo tensors từ đầu mà không cần có bất kỳ dữ liệu nào trước đó.
Các Tùy Chọn Tạo Tensor Không Cần Có Dữ Liệu
Dưới đây là một số tùy chọn có sẵn.
Chúng ta có hàm torch.eye() trả về một tensor 2-D với các giá trị nằm trên đường chéo và các số 0 nằm ở những vị trí còn lại. Tên eye() được kết nối với ý tưởng về identity matrix, là một ma trận vuông với các giá trị trên đường chéo chính và các số 0 nằm ở những vị trí còn lại.
> print(torch.eye(2)) tensor([ [1., 0.], [0., 1.] ])
Chúng ta có hàm torch.zeros() tạo ra một tensor ma trận 0:
> print(torch.zeros([2,2])) tensor([ [0., 0.], [0., 0.] ])
Tương tự như vậy, chúng ta có hàm torch.ones () để tạo ra một tensor ma trận đơn vị:
> print(torch.ones([2,2])) tensor([ [1., 1.], [1., 1.] ])
Chúng ta cũng có hàm torch.rand() tạo ra một tensor có giá trị là ngẫu nhiên.
> print(torch.rand([2,2])) tensor([ [0.0465, 0.4557], [0.6596, 0.0941] ])
Trên đây là một vài tùy chọn để tạo tensor không cần có dữ liệu, bạn có thể tham khảo PyTorch documentation để xem đầy đủ các tùy chọn khác.
Kết Luận
Hi vọng qua bài viết này các bạn đã hiểu rõ cách mà chúng ta sử dụng pytorch để tạo ra các tensor từ sử dụng dữ liệu đến các tùy chọn không cần dữ liệu. Điều đó sẽ thật đơn giản nếu sử dụng numpy.ndarrays.
Trong bài tiếp theo, chúng ta sẽ xem xét sâu hơn một chút về các tùy chọn tạo dữ liệu và chúng ta sẽ khám phá sự khác biệt giữa các tùy chọn này cũng như xem tùy chọn nào hoạt động tốt nhất.
Hẹn gặp lại các bạn trong bài viết tiếp theo!