Danh sách bài viết

Bài 20: Tensor Là Gì? Mở Rộng Từ Vector / Ma Trận Lên N Chiều

Tensor là generalization của scalar (0D), vector (1D), ma trận (2D) lên n chiều. Bài học định nghĩa rank và shape, liệt kê các tensor thường gặp trong AI (ảnh RGB, batch ảnh, text embedding của Transformer, weight neural network, conv kernel), preview các phép toán element-wise, broadcasting, reshape, transpose, và phân biệt cách 3 framework NumPy / PyTorch / TensorFlow đặt tên đối tượng tensor.

24/05/2026
14 phút đọc
2 lượt xem
1

Mục tiêu bài học

Sau bài học, bạn sẽ:

  • Định nghĩa tensor là generalization của scalar, vector, ma trận lên n chiều.
  • Hiểu khái niệm rank (số chiều) và shape (kích thước từng chiều).
  • Đọc được shape của các tensor thường gặp trong AI: ảnh RGB, batch ảnh, text embedding, weight.
  • Nắm sơ bộ các phép toán element-wise, broadcasting, reshape, transpose.
  • Phân biệt tensor toán học và tensor trong deep learning.

Ở bài 18 chúng ta đã nói về vector và ở bài 19 là ma trận. Tensor là bước mở rộng tự nhiên của hai khái niệm đó.

2

Từ scalar lên tensor

Có thể nhìn các đối tượng số học quen thuộc theo một thang chung — số chiều của container chứa dữ liệu:

  • Scalar (0D): một số đơn lẻ. Ví dụ: nhiệt độ \( 27.5 \).
  • Vector (1D): dãy số có thứ tự. Ví dụ: \( v = [1, 2, 3] \) — embedding của một từ rút gọn xuống 3 chiều.
  • Matrix (2D): bảng số có hàng và cột. Ví dụ ma trận \( 2 \times 3 \) trong bài 19.
  • Tensor (3D, 4D, ...): mở rộng tiếp lên 3, 4, 5... chiều.

Trong deep learning, người ta thường dùng từ tensor cho tất cả — kể cả scalar, vector và ma trận — vì cùng một đối tượng ndarray / torch.Tensor có thể có 0, 1, 2 hoặc nhiều chiều.

Ví dụ ký hiệu cho một tensor 3 chiều:

\[ T \in \mathbb{R}^{d_1 \times d_2 \times d_3} \]

nghĩa là \( T \) chứa \( d_1 \cdot d_2 \cdot d_3 \) số thực, được sắp xếp theo 3 trục (axis).

3

Rank và shape

Hai thuộc tính quan trọng nhất của một tensor:

  • Rank (còn gọi là order, ndim, hoặc number of dimensions): số trục. Scalar có rank 0, vector rank 1, ma trận rank 2.
  • Shape: tuple kích thước theo từng trục.

Bảng tổng hợp:

Đối tượngRankShape ví dụSố phần tử
Scalar0()1
Vector 3 phần tử1(3,)3
Ma trận 3x42(3, 4)12
Tensor 3 chiều3(3, 4, 5)60
Tensor 4 chiều4(2, 3, 4, 5)120

Số phần tử bằng tích các kích thước trong shape:

\[ |T| = \prod_{i=1}^{n} d_i \]

Ví dụ tensor shape \( (3, 4, 5) \) có \( 3 \cdot 4 \cdot 5 = 60 \) số.

Chú ý: trong NumPy, vector 3 phần tử có shape (3,) — có dấu phẩy để phân biệt với tuple một phần tử là số nguyên. Đây không phải ma trận một hàng (shape (1, 3)) hay ma trận một cột (shape (3, 1)); ba thứ này khác nhau khi nhân ma trận và broadcasting.

4

Tensor ở đâu trong AI

Đây là phần đáng nhớ nhất của bài. Mỗi loại dữ liệu đầu vào / đầu ra của model đều có một shape chuẩn.

Ảnh RGB — 3D tensor

Một ảnh RGB có chiều cao \( H \), chiều rộng \( W \), và 3 kênh màu (Red, Green, Blue):

\[ I \in \mathbb{R}^{H \times W \times 3} \]

Ví dụ ảnh 224×224 RGB có shape (224, 224, 3) — đây là input size chuẩn của ImageNet, dùng trong ResNet, VGG, EfficientNet... Một số framework như PyTorch dùng convention channel-first: shape (3, 224, 224) — số 3 đặt trước.

Batch ảnh — 4D tensor

Khi train, ta nạp nhiều ảnh cùng lúc thành một batch để GPU xử lý song song:

\[ B \in \mathbb{R}^{N \times H \times W \times C} \]

với \( N \) là batch size và \( C \) là số channel. Ví dụ 32 ảnh 224×224 RGB: shape (32, 224, 224, 3) theo channel-last, hoặc (32, 3, 224, 224) theo channel-first.

Text batch — 3D tensor cho Transformer

Đầu vào của một Transformer (sau bước embedding) thường có shape:

\[ X \in \mathbb{R}^{N \times L \times d} \]

với \( N \) là batch size, \( L \) là độ dài chuỗi token (seq_len), \( d \) là số chiều embedding (embed_dim). Ví dụ batch 8 chuỗi, mỗi chuỗi 512 token, embed_dim 768: shape (8, 512, 768) — đúng số chiều embedding của BERT-base.

Video — 4D hoặc 5D tensor

Một video clip là chuỗi frame theo thời gian:

\[ V \in \mathbb{R}^{T \times H \times W \times C} \]

với \( T \) là số frame. Batch video có thêm trục batch ở đầu, thành 5D: (N, T, H, W, C).

Weight neural network

Weight của một lớp Linear (Dense / Fully-connected) là ma trận 2D shape (out_features, in_features). Weight của một lớp Conv2d là tensor 4D shape (out_channels, in_channels, kernel_h, kernel_w) — convention của PyTorch. Ví dụ Conv2d(3, 64, kernel_size=3) có weight shape (64, 3, 3, 3).

5

Indexing tensor n-D

Với list lồng nhau trong Python thuần, để lấy một phần tử ta phải viết:

T[i][j][k]

Trong NumPy / PyTorch / TensorFlow, cú pháp gọn hơn — dùng một cặp ngoặc vuông và phân tách trục bằng dấu phẩy:

T[i, j, k]

Hai cách viết này khác nhau về cả ngữ nghĩa lẫn hiệu năng. T[i][j][k] tạo ra hai đối tượng trung gian (T[i] rồi T[i][j]), còn T[i, j, k] đi thẳng tới phần tử cần lấy. Với list thuần thì chỉ có cú pháp đầu.

Ví dụ với một ảnh RGB shape (H, W, 3):

  • img[10, 20] — pixel ở hàng 10 cột 20, kết quả là vector 3 phần tử [R, G, B].
  • img[10, 20, 0] — giá trị R của pixel đó.
  • img[:, :, 0] — kênh R toàn ảnh, shape (H, W) — chính là ảnh xám của kênh đỏ.
6

Phép toán cơ bản (preview)

Phần này chỉ giới thiệu khái niệm; chi tiết code và quy tắc sẽ ở Module 4 (NumPy).

Element-wise

Hai tensor cùng shape có thể cộng, trừ, nhân, chia theo từng vị trí tương ứng:

\[ (A + B)_{i,j,k} = A_{i,j,k} + B_{i,j,k} \]

Kết quả là một tensor mới có cùng shape với hai tensor đầu vào.

Broadcasting

Khi hai tensor khác shape, NumPy / PyTorch tự "kéo dài" tensor nhỏ hơn theo các trục thiếu để chúng cùng shape — gọi là broadcasting. Ví dụ ma trận \( A \) shape (3, 4) cộng với vector \( b \) shape (4,): \( b \) được lặp theo hàng để thành (3, 4) rồi mới cộng. Quy tắc chi tiết ở bài 33.

Reshape

Đổi shape của tensor nhưng giữ nguyên số phần tử và thứ tự lưu trong bộ nhớ. Ví dụ:

T.reshape(6, 10)   # từ (3, 4, 5) thành (6, 10) — vẫn 60 phần tử
T.reshape(60)      # thành vector 1D 60 phần tử
T.reshape(-1, 5)   # -1 có nghĩa "tự suy ra" — sẽ thành (12, 5)

Điều kiện: tích các kích thước mới phải bằng số phần tử cũ.

Transpose / permute axes

Đảo thứ tự các trục. Với ma trận, A.T đổi (m, n) thành (n, m). Với tensor nhiều chiều, dùng permute (PyTorch) hoặc transpose (NumPy) để chỉ định thứ tự mới của các trục. Ví dụ ảnh từ channel-last sang channel-first:

img.shape           # (224, 224, 3) — channel-last
img.transpose(2, 0, 1).shape   # (3, 224, 224) — channel-first
7

Tensor trong NumPy / PyTorch / TensorFlow

Ba framework chính cùng biểu diễn tensor nhưng đặt tên khác nhau:

FrameworkClassThiết bịAutograd
NumPynumpy.ndarrayCPUKhông
PyTorchtorch.TensorCPU + GPU (CUDA, MPS, ROCm)Có (requires_grad)
TensorFlowtf.TensorCPU + GPU + TPUCó (qua tf.GradientTape)

API rất gần nhau — phần lớn thao tác chỉ khác tên hàm. Ví dụ tạo một tensor zeros shape (2, 3):

import numpy as np
np.zeros((2, 3))

import torch
torch.zeros(2, 3)

import tensorflow as tf
tf.zeros((2, 3))

NumPy chạy thuần CPU và không hỗ trợ autograd, nên chỉ dùng cho tiền xử lý dữ liệu và toán phụ trợ. PyTorch và TensorFlow là 2 framework chính để train neural network — autograd và GPU là điểm khác biệt cốt lõi với NumPy.

8

Tensor toán học vs tensor trong DL

Từ tensor có hai nghĩa khác nhau, dễ gây nhầm:

  • Tensor trong toán / vật lý (tensor algebra, tensor calculus): object đa tuyến tính có quy tắc biến đổi tọa độ cụ thể khi đổi hệ cơ sở (ví dụ tensor stress-energy trong thuyết tương đối). Ở đây "tensor" gắn với quy tắc biến đổi.
  • Tensor trong deep learning: chỉ đơn giản là một mảng đa chiều (multi-dimensional array). Không có ràng buộc biến đổi tọa độ.

Trong toàn series này, mỗi khi nói "tensor" mặc định là nghĩa thứ hai. Khi đọc paper toán hoặc vật lý, cần để ý ngữ cảnh.

9

Code Python: mô phỏng tensor bằng list lồng

Bài này chưa dùng NumPy. Ta dùng list lồng nhau để hình dung cấu trúc; thực tế khi code AI, luôn dùng NumPy / PyTorch / TensorFlow vì nhanh hơn nhiều lần.

Ảnh xám 2×3 (shape (2, 3)):

gray = [
    [10, 20, 30],
    [40, 50, 60],
]

print(len(gray))         # 2 — số hàng
print(len(gray[0]))      # 3 — số cột
print(gray[1][2])        # 60 — phần tử hàng 1 cột 2

Ảnh RGB 2×2 (shape (2, 2, 3)) — mỗi pixel là một list 3 phần tử [R, G, B]:

rgb = [
    [[255,   0,   0], [  0, 255,   0]],   # hàng 0: pixel đỏ, pixel xanh lá
    [[  0,   0, 255], [255, 255,   0]],   # hàng 1: pixel xanh dương, pixel vàng
]

print(len(rgb))           # 2 — height
print(len(rgb[0]))        # 2 — width
print(len(rgb[0][0]))     # 3 — channel
print(rgb[0][1])          # [0, 255, 0] — pixel xanh lá
print(rgb[1][1][2])       # 0 — kênh B của pixel vàng

Hàm tự viết để tính shape:

def shape(t):
    s = []
    cur = t
    while isinstance(cur, list):
        s.append(len(cur))
        cur = cur[0] if cur else None
    return tuple(s)

print(shape(gray))   # (2, 3)
print(shape(rgb))    # (2, 2, 3)

Hàm shape trên giả định mọi list con cùng độ dài — một tensor "vuông vắn". NumPy thì cưỡng chế ràng buộc này khi bạn tạo array; nếu list con lệch nhau sẽ tạo ra object array hoặc raise ValueError.

10

Vì sao tensor quan trọng

  • Toàn bộ deep learning là chuỗi biến đổi tensor. Forward pass của một model = áp dụng liên tiếp các phép tensor (nhân ma trận, convolution, activation, normalization, attention) lên input tensor.
  • Backprop cũng là phép tensor. Gradient của loss theo từng weight là một tensor cùng shape với weight đó.
  • GPU tăng tốc tensor. GPU có hàng nghìn core nhỏ, mỗi core làm một phép tính số học. Phép element-wise trên tensor lớn được chia đều cho các core, chạy song song — đây là lý do GPU train DL nhanh hơn CPU vài chục đến vài trăm lần.
  • Mọi dữ liệu đều quy về tensor. Ảnh, âm thanh, text, bảng số — đều được encode thành tensor trước khi đưa vào model. Hiểu shape của tensor là bước đầu tiên để đọc được code DL.
11

Bài tập

  1. Cho một ảnh RGB 4×4, biểu diễn nó bằng list 3D shape (4, 4, 3) trong Python. Chọn màu tuỳ ý (gợi ý: vẽ một dải gradient từ đỏ sang xanh theo hàng).
  2. Một batch gồm 32 ảnh 224×224 RGB có shape là gì theo convention channel-last? Theo channel-first? Tổng số phần tử là bao nhiêu?
  3. Input của BERT-base ở dạng embedding có shape (N, 512, 768). Hỏi rank, các trục lần lượt là gì, và số phần tử khi \( N = 4 \).
  4. Một tensor có shape (3, 4, 5). Liệt kê 3 cách reshape hợp lệ thành tensor 2D.
Đáp án
  1. Một cách:
    img = [
        [[255, 0, 0], [191, 0, 64], [128, 0, 128], [64, 0, 191]],
        [[255, 0, 0], [191, 0, 64], [128, 0, 128], [64, 0, 191]],
        [[255, 0, 0], [191, 0, 64], [128, 0, 128], [64, 0, 191]],
        [[255, 0, 0], [191, 0, 64], [128, 0, 128], [64, 0, 191]],
    ]
    Có 4 hàng, mỗi hàng 4 pixel, mỗi pixel 3 channel — shape (4, 4, 3).
  2. Channel-last: (32, 224, 224, 3). Channel-first: (32, 3, 224, 224). Số phần tử: \( 32 \cdot 224 \cdot 224 \cdot 3 = 4\,816\,896 \).
  3. Rank 3. Trục 0 là batch, trục 1 là seq_len (512 token), trục 2 là embed_dim (768). Với \( N = 4 \): \( 4 \cdot 512 \cdot 768 = 1\,572\,864 \) số.
  4. Tensor có \( 3 \cdot 4 \cdot 5 = 60 \) phần tử. Ba shape 2D hợp lệ ví dụ: (6, 10), (12, 5), (60, 1). Còn nhiều shape khác miễn tích bằng 60.
12

Tổng kết và bài tiếp theo

  • Tensor là mảng đa chiều — generalization của scalar (0D), vector (1D), ma trận (2D) lên n chiều.
  • Hai thuộc tính cốt lõi: rank (số trục) và shape (tuple kích thước). Số phần tử = tích các kích thước.
  • Trong AI: ảnh RGB là 3D, batch ảnh là 4D, text embedding của Transformer là 3D, conv kernel là 4D, video batch là 5D.
  • Phép toán chính: element-wise, broadcasting, reshape, transpose / permute — chi tiết ở Module 4 (NumPy).
  • 3 framework dùng tensor: NumPy ndarray, PyTorch torch.Tensor, TensorFlow tf.Tensor. PyTorch và TensorFlow thêm autograd và GPU.
  • Tensor trong DL là multi-dimensional array, không phải tensor toán có quy tắc biến đổi tọa độ.

Sang nhóm thống kê. Bài 21 bắt đầu với 3 đại lượng đo lường xu hướng trung tâm: mean, median, mode.