Tensors (เทนเซอร์)
Tensors เป็นโครงสร้างข้อมูลพื้นฐานและเป็นหัวใจสำคัญของ PyTorch โดยมีลักษณะคล้ายกับอาร์เรย์ (arrays) หรือเมทริกซ์ (matrices) มาก เราใช้เทนเซอร์เพื่อเข้ารหัสอินพุตและเอาต์พุตของโมเดล รวมถึงจัดเก็บพารามิเตอร์ของโมเดลด้วย
import torch
import numpy as np
การสร้าง Tensor (Initializing a Tensor)
เทนเซอร์สามารถสร้างขึ้นได้หลายวิธี ดังนี้:
1. สร้างจากข้อมูลโดยตรง (Directly from data)
เทนเซอร์สามารถสร้างขึ้นจากโครงสร้างข้อมูลแบบ List ของ Python ได้โดยตรง โดยชนิดข้อมูล (Data type) จะถูกประเมินโดยอัตโนมัติ
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)
print(x_data)
tensor([[1, 2],
[3, 4]])
2. สร้างจากเทนเซอร์อื่น และด้วยค่าสุ่ม
เทนเซอร์ใหม่จะคงคุณสมบัติ (shape) ของเทนเซอร์เดิมเอาไว้ หรือเราสามารถใช้ shape ที่เป็น tuple กำหนดมิติได้
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)
print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")
Random Tensor:
tensor([[0.8823, 0.9150, 0.3829],
[0.9593, 0.3904, 0.6009]])
Ones Tensor:
tensor([[1., 1., 1.],
[1., 1., 1.]])
Zeros Tensor:
tensor([[0., 0., 0.],
[0., 0., 0.]])
คุณสมบัติของ Tensor (Attributes of a Tensor)
คุณสมบัติของเทนเซอร์จะบอกรูปร่าง (shape), ชนิดข้อมูล (datatype), และอุปกรณ์ (device) ที่เทนเซอร์นั้นถูกจัดเก็บอยู่
tensor = torch.rand(3,4)
print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")
Shape of tensor: torch.Size([3, 4]) Datatype of tensor: torch.float32 Device tensor is stored on: cpu
การดำเนินการบน Tensor (Operations)
PyTorch มีฟังก์ชันการดำเนินการทางคณิตศาสตร์ พีชคณิตเชิงเส้น ฯลฯ มากกว่า 100 แบบ ซึ่งสามารถคำนวณบน GPU ได้เพื่อความเร็วที่มากขึ้น
การรวมเทนเซอร์ (Joining tensors)
คุณสามารถใช้ torch.cat เพื่อนำเทนเซอร์มาต่อกันตามมิติที่กำหนด (dimension) คล้ายกับการต่อเลโก้
tensor = torch.ones(4, 4)
tensor[:,1] = 0 # กำหนดให้คอลัมน์ที่ 1 (เริ่มนับจาก 0) มีค่าเป็น 0
# นำ tensor ขนาด 4x4 มาต่อกัน 3 อันในแกนที่ 1 (แนวนอน)
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)
tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]])
การดำเนินการทางคณิตศาสตร์ (Arithmetic operations)
ตัวอย่างการคูณแบบสมาชิกต่อสมาชิก (Element-wise product)
# z1, z2, z3 จะได้ผลลัพธ์เหมือนกัน
z1 = tensor * tensor
z2 = tensor.mul(tensor)
print(z1)
tensor([[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.]])
การทำ Indexing และ Slicing
คุณสามารถดึงข้อมูลแบบเดียวกับการใช้ NumPy (Standard numpy-like indexing and slicing) ได้เลย
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:,1] = 0
print(tensor)
First row: tensor([1., 1., 1., 1.])
First column: tensor([1., 1., 1., 1.])
Last column: tensor([1., 1., 1., 1.])
tensor([[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.]])
เทนเซอร์แบบสมาชิกเดียว (Single-element tensors)
หากคุณใช้ฟังก์ชันรวมค่าเทนเซอร์จนเหลือเพียงค่าเดียว (เช่น การหาผลรวม) คุณสามารถแปลงกลับเป็นตัวเลข Python ธรรมดาได้โดยใช้ item()
agg = tensor.sum()
agg_item = agg.item()
print(agg_item, type(agg_item))
12.0 <class 'float'>
การดำเนินการแบบ In-place
การดำเนินการใดๆ ที่บันทึกผลลัพธ์ทับตัวแปรเดิม (In-place) จะมีเครื่องหมาย _ ต่อท้าย เช่น x.copy_(y) หรือ x.t_() ฟังก์ชันเหล่านี้จะเปลี่ยนค่า x ทันที
print(f"{tensor} \n")
tensor.add_(5)
print(f"{tensor}")
tensor([[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.]])
tensor([[6., 5., 6., 6.],
[6., 5., 6., 6.],
[6., 5., 6., 6.],
[6., 5., 6., 6.]])
การเชื่อมต่อกับ NumPy (Bridge with NumPy)
เทนเซอร์ที่อยู่บน CPU และอาร์เรย์ของ NumPy สามารถ แชร์ตำแหน่งหน่วยความจำเดียวกันได้ หมายความว่าการเปลี่ยนค่าในฝั่งใดฝั่งหนึ่งจะส่งผลให้อีกฝั่งเปลี่ยนตามไปด้วย
1. แปลง Tensor เป็น NumPy array
t = torch.ones(5)
n = t.numpy()
# การเปลี่ยนแปลงที่ tensor `t` จะส่งผลไปถึงอาร์เรย์ `n` ด้วย
t.add_(1)
print(f"t: {t}") # tensor([2., 2., 2., 2., 2.])
print(f"n: {n}") # [2. 2. 2. 2. 2.]
t: tensor([2., 2., 2., 2., 2.]) n: [2. 2. 2. 2. 2.]
2. แปลง NumPy array เป็น Tensor
n = np.ones(5)
t = torch.from_numpy(n)
# การเปลี่ยนแปลงที่ NumPy array `n` จะส่งผลไปถึง tensor `t` ด้วย
np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")
t: tensor([2., 2., 2., 2., 2.], dtype=torch.float64) n: [2. 2. 2. 2. 2.]