Bỏ qua

Tích của các vector

Các tích vector là những phép toán cơ bản để đo độ tương đồng và tính các phép chiếu. File này bao quát tích trong, tích vô hướng, độ tương đồng cosine, tích có hướng, và tích ngoài — những phép toán cung cấp năng lượng cho các cơ chế chú ý, embedding, và lập luận hình học trong AI.

  • Chúng ta đã thấy cách cộng và co giãn các vector. Nhưng ta có thể nhân hai vector với nhau được không? Hóa ra có hơn một cách để làm điều đó, và mỗi cách trả lời một câu hỏi khác nhau.

  • Tích trong (inner product) là ý tưởng tổng quát: một hàm nhận hai vector và sinh ra một số duy nhất (một vô hướng). Nó là bản thiết kế trừu tượng cho việc "nhân" các vector.

  • Mọi tích trong phải thỏa mãn ba quy tắc:

    • Xác định dương: \(\langle \mathbf{v}, \mathbf{v} \rangle \geq 0\), và bằng không chỉ với vector không. Nhân một vector với chính nó luôn cho kết quả không âm.
    • Đối xứng: \(\langle \mathbf{u}, \mathbf{v} \rangle = \langle \mathbf{v}, \mathbf{u} \rangle\). Thứ tự không quan trọng.
    • Tuyến tính: \(\langle a\mathbf{u} + b\mathbf{v}, \mathbf{w} \rangle = a\langle \mathbf{u}, \mathbf{w} \rangle + b\langle \mathbf{v}, \mathbf{w} \rangle\). Nó phân phối qua phép cộng và co giãn.
  • Tích vô hướng (dot product) là tích trong phổ biến nhất. Đây là phiên bản cụ thể mà bạn sẽ dùng gần như ở mọi nơi. Với hai vector \(\mathbf{a} = (a_1, a_2, \ldots, a_n)\)\(\mathbf{b} = (b_1, b_2, \ldots, b_n)\):

\[\mathbf{a} \cdot \mathbf{b} = a_1 b_1 + a_2 b_2 + \cdots + a_n b_n\]
  • Nhân các thành phần tương ứng, rồi cộng tất cả lại. Chỉ đơn giản như vậy.

  • Nhưng con số này nghĩa là gì? Tích vô hướng có một diễn giải hình học tuyệt đẹp:

\[\mathbf{a} \cdot \mathbf{b} = \|\mathbf{a}\| \, \|\mathbf{b}\| \cos(\theta)\]

Tích vô hướng: vector a được chiếu lên b, với góc θ và phép chiếu được hiển thị

  • Điều này kết nối tích vô hướng trực tiếp với góc \(\theta\) giữa hai vector. Kết quả cho bạn biết hai vector "đồng thuận" về hướng đến mức nào.

  • Nếu chúng chỉ cùng hướng (\(\theta = 0°\)), \(\cos(\theta) = 1\) và tích vô hướng đạt cực đại.

  • Nếu chúng trực giao (\(\theta = 90°\)), \(\cos(\theta) = 0\) và tích vô hướng chính xác bằng không. Điều này cho ta một phép thử chính xác cho tính trực giao.

  • Nếu chúng chỉ theo hướng ngược nhau (\(\theta = 180°\)), \(\cos(\theta) = -1\) và tích vô hướng âm.

  • Một vector tự nhân với chính nó cho độ lớn bình phương của nó: \(\mathbf{a} \cdot \mathbf{a} = \|\mathbf{a}\|^2\).

  • Tích vô hướng còn cho ta phép chiếu (projection), cái bóng mà một vector đổ lên vector khác. Phép chiếu của \(\mathbf{a}\) lên \(\mathbf{b}\) là:

\[\text{proj}_{\mathbf{b}}(\mathbf{a}) = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{b}\|^2} \, \mathbf{b}\]
  • Hãy tưởng tượng chiếu một ánh sáng thẳng đứng xuống \(\mathbf{b}\). Cái bóng của \(\mathbf{a}\) trên đường thẳng đó chính là phép chiếu. Nó cho bạn biết có bao nhiêu phần của \(\mathbf{a}\) nằm theo hướng của \(\mathbf{b}\).

  • Độ tương đồng cosine (cosine similarity) chuẩn hóa tích vô hướng bằng cách chia cho cả hai độ lớn:

\[\cos(\theta) = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\| \, \|\mathbf{b}\|}\]
  • Điều này cho một giá trị nằm giữa \(-1\)\(1\) đo lường sự căn chỉnh hướng, bỏ qua độ dài các vector. Nó được dùng rộng rãi trong ML để so sánh những thứ như tài liệu, embedding, và sở thích người dùng.

  • Giờ, tích vô hướng nhận hai vector và trả về một vô hướng. Tích có hướng (cross product) làm ngược lại, nó nhận hai vector và trả về một vector mới.

  • Tích có hướng \(\mathbf{a} \times \mathbf{b}\) sinh ra một vector vuông góc với cả \(\mathbf{a}\)\(\mathbf{b}\):

\[\mathbf{a} \times \mathbf{b} = (a_2 b_3 - a_3 b_2, \; a_3 b_1 - a_1 b_3, \; a_1 b_2 - a_2 b_1)\]
  • Tích có hướng chỉ hoạt động trong 3D. Trong khi tích vô hướng hoạt động ở bất kỳ số chiều nào, tích có hướng chỉ dành riêng cho không gian ba chiều.

  • Độ lớn của nó bằng diện tích hình bình hành được tạo bởi hai vector:

\[\|\mathbf{a} \times \mathbf{b}\| = \|\mathbf{a}\| \, \|\mathbf{b}\| \sin(\theta)\]
  • Hãy chú ý mẫu hình: tích vô hướng dùng \(\cos(\theta)\) và tích có hướng dùng \(\sin(\theta)\). Tích vô hướng đo mức độ hai vector căn chỉnh, tích có hướng đo mức độ chúng khác biệt về hướng.

  • Hướng của kết quả tuân theo quy tắc bàn tay phải: cuộn các ngón tay của bàn tay phải từ \(\mathbf{a}\) về phía \(\mathbf{b}\), và ngón cái chỉ về hướng của \(\mathbf{a} \times \mathbf{b}\).

  • Khác với tích vô hướng, tích có hướng không giao hoán: \(\mathbf{a} \times \mathbf{b} = -(\mathbf{b} \times \mathbf{a})\). Hoán đổi thứ tự sẽ lật hướng.

  • Nếu hai vector song song, tích có hướng của chúng là vector không (vì \(\sin(0°) = 0\)). Không có diện tích, không có hướng vuông góc.

  • Điều gì xảy ra khi bạn kết hợp ba vector dùng cả hai phép nhân? Điều này cho ta tích hỗn tạp (triple products).

  • Tích hỗn tạp vô hướng (scalar triple product) \(\mathbf{a} \cdot (\mathbf{b} \times \mathbf{c})\) trước tiên lấy tích có hướng của hai vector, rồi tự nhân kết quả với vector thứ ba. Đầu ra là một số duy nhất bằng thể tích của hình hộp xiên (một hộp 3D xiên) được tạo bởi ba vector.

  • Nếu tích hỗn tạp vô hướng bằng không, ba vector đồng phẳng (coplanar), chúng đều nằm trong cùng một mặt phẳng phẳng và không tạo thành thể tích.

  • Thứ tự có thể được xoay vòng mà không thay đổi kết quả: \(\mathbf{a} \cdot (\mathbf{b} \times \mathbf{c}) = \mathbf{b} \cdot (\mathbf{c} \times \mathbf{a}) = \mathbf{c} \cdot (\mathbf{a} \times \mathbf{b})\).

  • Tích hỗn tạp vector (vector triple product) \(\mathbf{a} \times (\mathbf{b} \times \mathbf{c})\) áp dụng tích có hướng hai lần và trả về một vector. Nó khai triển gọn gàng dùng đồng nhất thức:

\[\mathbf{a} \times (\mathbf{b} \times \mathbf{c}) = (\mathbf{a} \cdot \mathbf{c})\mathbf{b} - (\mathbf{a} \cdot \mathbf{b})\mathbf{c}\]
  • Kết quả luôn nằm trong mặt phẳng được sinh bởi \(\mathbf{b}\)\(\mathbf{c}\). Lưu ý rằng tích có hướng không kết hợp: \(\mathbf{a} \times (\mathbf{b} \times \mathbf{c}) \neq (\mathbf{a} \times \mathbf{b}) \times \mathbf{c}\).

Bài tập lập trình (dùng CoLab hoặc notebook)

  1. Tính tích vô hướng của hai vector và dùng nó để tìm góc giữa chúng. Thử làm cho chúng trực giao, song song, hoặc ngược nhau và xem góc thay đổi ra sao.

    import jax.numpy as jnp
    
    a = jnp.array([1.0, 2.0, 3.0])
    b = jnp.array([4.0, -1.0, 2.0])
    
    dot = jnp.dot(a, b)
    angle = jnp.arccos(dot / (jnp.linalg.norm(a) * jnp.linalg.norm(b)))
    
    print(f"Dot product: {dot}")
    print(f"Angle: {jnp.degrees(angle):.1f}°")
    

  2. Tính tích có hướng của hai vector 3D và xác minh kết quả vuông góc với cả hai bằng cách kiểm tra tích vô hướng của nó với mỗi vector gốc bằng không.

    import jax.numpy as jnp
    
    a = jnp.array([1.0, 0.0, 0.0])
    b = jnp.array([0.0, 1.0, 0.0])
    
    cross = jnp.cross(a, b)
    
    print(f"a x b = {cross}")
    print(f"Perpendicular to a: {jnp.dot(cross, a) == 0}")
    print(f"Perpendicular to b: {jnp.dot(cross, b) == 0}")