25 April, 2025

Dễ hiểu đến bất ngờ: RoPE, 2D-RoPE, M-RoPE

Giải thích RoPE, 2D-RoPE, M-RoPE một cách đơn giản nhất có thể.

Dễ hiểu đến bất ngờ: RoPE, 2D-RoPE, M-RoPE
Available in:
 English
 Tiếng Việt
Reading time: 22 min.
Table of content
  • Tại sao cần mã hoá vị trí (positional embedding)?
  • RoPE
  • 2D-RoPE
  • 2D-RoPE với tần số đan xen
  • M-RoPE
  • Kết luận

Bài viết này giải thích đơn giản về (1D-)RoPE, 2D-RoPE và M-RoPE, tập trung vào ý tưởng cốt lõi một cách ngắn gọn.

Lý do viết bài này ư? Mình từng rất vật lộn để hiểu các khái niệm này, chủ yếu vì não mình chỉ xử lý được qua hình ảnh chứ không phải mấy phương trình toán học kỳ quặc 😂

Với suy nghĩ đó, mình đã xây dựng bài giải thích này theo hướng trực quan và giàu hình ảnh, dịch bởi @honghanhh. Hy vọng cách tiếp cận này sẽ giúp bạn hiểu rõ hơn.

Tại sao cần mã hoá vị trí (positional embedding)?

Hãy tưởng tượng ta có 2 mô hình ngôn ngữ: một mô hình chỉ xử lý từng từ một, mô hình còn lại xử lý song song tất cả từ.

Xét câu "Chó ăn cơm":

  • Mô hình thứ nhất xử lý tuần tự "Chó" → "ăn" → "cơm". Thứ tự đầu vào quan trọng vì mô hình xử lý lần lượt, nhưng cách làm này chậm!
  • Mô hình thứ hai xử lý tất cả từ cùng lúc, thậm chí có thể nhận đầu vào lộn xộn như "ăn", "cơm", "Chó". mô hình này nhanh hơn nhưng không biết thứ tự từ.

Vấn đề ở mô hình thứ hai là nó thiếu thông tin về vị trí từ. Do đó ta cần thêm positional embedding vào input.

Giả sử ta có N vector embedding, mỗi vector kích thước n_dim. Ví dụ với 4 vector, n_dim = 8 và khởi tạo toàn 1:

11111111
22222222
33333333
44444444

Nếu thêm positional embedding 0, 1, 2, 3 bằng cách cộng thêm index vào từng vector (ví dụ minh họa):

11111111
22222222
33333333
44444444

Đương nhiên, đây chỉ là ví dụ minh hoạ. Trên thực tế, cách này không hiệu quả. Vậy giải pháp là gì?

RoPE

RoPE (Rotary Position Embedding - Mã hoá vị trí dạng xoay) là phương pháp mã hoá thông tin vị trí vào mã nhúng đầu vào của mô hình transformer.

RoPE hoạt động bằng cách xoay các vector embedding trong không gian 2D. Bỏ qua công thức toán, đây là minh hoạ đơn giản:

Vector đầu vào [x=0, y=1] được xoay ngược chiều kim đồng hồ f = 20° tại mỗi vị trí:

pos = 0
pos = 1
pos = 2
pos = 3

Trong thực tế, chúng ta không chỉ có mỗi 2 chiều mà có thể có n_dim chiều. Ví dụ, n_dim = 4:

0101
0101
0101
0101

Vậy làm thế nào mình có thể xoay một vector trong n_dim chiều?

Câu trả lời rất đơn giản: Ta chia vector thành các cặp 2D:

0101
0101
0101
0101

Mình sẽ thay mỗi cặp bằng một mũi tên để minh hoạ một cách đơn giản và dễ hiểu:

Và giờ đến phần thú vị rồi đây: Chúng ta không xoay mọi vector cùng một góc độ, vì như vậy sẽ nhanh chóng cạn kiệt các góc khả dụng.

Cách dễ hình dung nhất là nghĩ về đồng hồ 🕓, nơi kim giây quay nhiều vòng thì kim phút mới dịch chuyển một chút.

Trong RoPE, độ xoay được gọi là tần số (kí hiệu f) và được tính bằng:

fi=base(2in_dim) f_i = \text{base}^{(\dfrac{-2i}{n\_dim})}

Trong đó i là chỉ số của cặp 2D (từ 0 đến d/2 - 1), base là hằng số định trước (thường là 10000).

Để tính góc xoay (kí hiệu theta, θ) cho mỗi cặp, ta nhần chỉ số vị trí pos với tần số f:

θ=pos×f \theta = \text{pos} \times f

Ví dụ đơn giản: giả sử cặp đầu có f = 20°, cặp sau có f = 10°:

pos f = 20° f = 10°
0
1
2
3

Như các bạn thấy, cặp đầu xoay nhanh hơn cặp sau, giống kim giây chạy nhanh hơn kim phút.

Cũng như 3 kim đồng hồ có thể biểu diễn 86400 giây trong ngày, ý tưởng tương tự được dùng để biểu diễn n_dim chiều trong RoPE.

2D-RoPE

Tới thời điểm hiện tại, ta mới chỉ thảo luận về RoPE (mã hoá vị trí xoay) - phương pháp mã hoá vị trí 1D. Nó hữu ích cho chuỗi 1D như văn bản.

Nhưng nếu ta muốn dùng RoPE cho chuỗi 2D như hình ảnh thì sao?

2D-RoPE là phiên bản mở rộng đơn giản của RoPE, nơi mỗi vector đầu vào có vị trí 2D [y,x]:

[0,0][0,1][0,2][0,3]
[1,0][1,1][1,2][1,3]
[2,0][2,1][2,2][2,3]
[3,0][3,1][3,2][3,3]

Quay lại với ví dụ đồng hồ, ý tưởng đơn giản là dùng 2 đồng hồ: một cho trục y và một cho trục x.

Để minh hoạ, hãy tăng gấp đôi n_dim trong ví dụ ban đầu để có n_dim = 8:

01010101
01010101
01010101
01010101

Giờ được biểu diễn thành 4 cặp vector 2D:

Ý tưởng là chia vector thành 2 phần: một cho trục y và một cho trục x:

for Y pos for X pos

Giả sử danh sách vị trí của 4 vector này là:

  • [0, 0]
  • [0, 1]
  • [1, 2]
  • [1, 3]

Sử dụng bộ f = 40°f = 20°, ta có thể xoay các vector cho từng phần độc lập như sau:

Y f = 40° f = 20° X f = 40° f = 20°
0
0
0
1
1
2
1
3

Theo mình biết thì phương pháp 2D-RoPE này được dùng trong vision encoder của mô hình Llama 4.

2D-RoPE với tần số đan xen

Ở ví dụ trước, ta dùng chung f = 40°f = 20° cho cả hai trục. Nhưng nếu muốn dùng tần số khác nhau cho từng trục thì sao?

Ví dụ với mô hình Pixtral của Mistral:

  • Đầu tiên tạo danh sách tần số cho tất cả cặp vector 2D, ví dụ: 40°, 30°, 20°, 10°.
  • Sau đó đan xen các tần số cho từng trục, ta có 40°, 20° cho trục y30°, 10° cho trục x.
Y f = 40° f = 20° X f = 30° f = 10°
0
0
0
1
1
2
1
3

Điều thú vị là thay vì tạo một danh sách tần số (ví dụ: 40°, 30°, 20°, 10°) rồi chọn các f lẻ/chẵn, ta có thể điều chỉnh giá trị n_dim và tỷ lệ của f để đạt kết quả tương tự. Xem PR này để hiểu cách mình thực hiện.

M-RoPE

M-RoPE là viết tắt của Multimodal-RoPE (Mã hoá vị trí tương đối đa phương thức). Kỹ thuật này lần đầu được giới thiệu bởi Qwen2VL.

M-RoPE mở rộng ý tưởng từ 2D-RoPE, nhưng giờ đây chúng ta có nhiều hơn 2 chiều trên mỗi vị trí. Ví dụ: ta có thể có chiều 3D [time, y, x] hoặc thậm chí nhiều hơn.

Ý tưởng chính là thay vì chia vector mã hoá thành 2 phần, ta chia nó thành... đúng rồi đấy, n phần, với n là số chiều trên mỗi vị trí.

Nếu xem kỹ file config.json của Qwen2VL, các bạn sẽ thấy cấu hình tên mrope_section chứa 3 số. Mỗi số đại diện cho số cặp 2D trong từng phần.

  "rope_scaling": {
    "type": "mrope",
    "mrope_section": [
      16,
      24,
      24
    ]
  },

Để dễ hiểu hơn, hãy lấy ví dụ đơn giản với mã hoá có n_dim = 8, ta sẽ có 4 cặp vector 2D:

Giả sử mrope_section của chúng ta là [1, 1, 2], ta có thể chia vector mã hoá vị trí thành 3 phần:

Sau đó, RoPE được áp dụng độc lập cho từng phần bằng phương pháp tương tự như đã giải thích trong 2D-RoPE.

Kết luận

Trong bài viết này, ta đã khám phá các kỹ thuật positional embedding bằng cách tiếp cận trực quan qua hình ảnh.

Hy vọng rằng việc hình dung các phương pháp này dưới dạng phép quay và chia tách chiều sẽ giúp các khái niệm cơ bản về RoPE, 2D-RoPE và M-RoPE trở nên trực quan và dễ nắm bắt hơn, đặc biệt khi so sánh với việc tiếp cận trực tiếp bằng các công thức toán học phức tạp.

Want to receive latest articles from my blog?
Follow on
Discussion