.. _sec_geometry-linear-algebraic-ops:
Hình học và các hoạt động đại số tuyến tính
===========================================
Trong :numref:`sec_linear-algebra`, chúng tôi gặp phải những điều cơ
bản về đại số tuyến tính và thấy nó có thể được sử dụng như thế nào để
thể hiện các hoạt động phổ biến để chuyển đổi dữ liệu của chúng tôi. Đại
số tuyến tính là một trong những trụ cột toán học quan trọng dựa trên
phần lớn công việc mà chúng ta làm trong học sâu và trong học máy rộng
hơn. Trong khi :numref:`sec_linear-algebra` chứa đủ máy móc để truyền
đạt cơ học của các mô hình học sâu hiện đại, có rất nhiều hơn cho chủ đề
này. Trong phần này, chúng ta sẽ đi sâu hơn, làm nổi bật một số diễn
giải hình học của các phép toán đại số tuyến tính, và giới thiệu một vài
khái niệm cơ bản, bao gồm eigenvalues và eigenvectors.
Hình học của Vectơ Trước tiên, chúng ta cần thảo luận về hai cách giải thích hình học phổ biến của vectơ, như một trong hai điểm hoặc hướng trong không gian. Về cơ bản, một vectơ là danh sách các số như danh sách Python bên dưới.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.. code:: python
v = [1, 7, 0, 1]
Các nhà toán học thường viết điều này dưới dạng vectơ \* cột\* hoặc \*
hàng\*, đó là để nói là
.. math::
\mathbf{x} = \begin{bmatrix}1\\7\\0\\1\end{bmatrix},
hoặc là
.. math::
\mathbf{x}^\top = \begin{bmatrix}1 & 7 & 0 & 1\end{bmatrix}.
Chúng thường có các diễn giải khác nhau, trong đó các ví dụ dữ liệu là
vectơ cột và trọng lượng được sử dụng để tạo thành các tổng trọng số là
vectơ hàng. Tuy nhiên, nó có thể có lợi để linh hoạt. Như chúng ta đã mô
tả trong :numref:`sec_linear-algebra`, mặc dù định hướng mặc định của
một vectơ duy nhất là một vectơ cột, đối với bất kỳ ma trận nào đại diện
cho một tập dữ liệu dạng bảng, coi mỗi ví dụ dữ liệu như một vectơ hàng
trong ma trận là thông thường hơn.
Với một vector, cách giải thích đầu tiên mà chúng ta nên đưa ra nó là
một điểm trong không gian. Trong hai hoặc ba chiều, ta có thể hình dung
các điểm này bằng cách sử dụng các thành phần của các vectơ để xác định
vị trí của các điểm trong không gian so với một tham chiếu cố định gọi
là *origin*. Điều này có thể được nhìn thấy trong :numref:`fig_grid`.
.. _fig_grid:
.. figure:: ../img/grid-points.svg
An illustration of visualizing vectors as points in the plane. The
first component of the vector gives the :math:`x`-coordinate, the
second component gives the :math:`y`-coordinate. Higher dimensions
are analogous, although much harder to visualize.
Quan điểm hình học này cho phép chúng ta xem xét vấn đề ở mức độ trừu
tượng hơn. Không còn phải đối mặt với một số vấn đề dường như không thể
vượt qua như phân loại hình ảnh là mèo hoặc chó, chúng ta có thể bắt đầu
xem xét các nhiệm vụ trừu tượng như tập hợp các điểm trong không gian và
hình dung nhiệm vụ khám phá cách tách hai cụm điểm riêng biệt.
Song song, có quan điểm thứ hai mà mọi người thường lấy vectơ: như hướng
trong không gian. Chúng ta không chỉ có thể nghĩ về vector
:math:`\mathbf{v} = [3,2]^\top` là vị trí :math:`3` đơn vị ở bên phải và
:math:`2` các đơn vị lên từ nguồn gốc, chúng ta cũng có thể nghĩ về nó
như là hướng để thực hiện :math:`3` bước sang phải và :math:`2` bước
lên. Bằng cách này, chúng tôi xem xét tất cả các vectơ trong hình
:numref:`fig_arrow` giống nhau.
.. _fig_arrow:
.. figure:: ../img/par-vec.svg
Any vector can be visualized as an arrow in the plane. In this case,
every vector drawn is a representation of the vector
:math:`(3,2)^\top`.
Một trong những lợi ích của sự thay đổi này là chúng ta có thể hiểu rõ
về hành động bổ sung vector. Đặc biệt, chúng ta làm theo các hướng dẫn
được đưa ra bởi một vectơ, và sau đó làm theo các hướng dẫn được đưa ra
bởi người kia, như được thấy trong :numref:`fig_add-vec`.
.. _fig_add-vec:
.. figure:: ../img/vec-add.svg
We can visualize vector addition by first following one vector, and
then another.
Phép trừ vector có cách giải thích tương tự. Bằng cách xem xét danh tính
mà :math:`\mathbf{u} = \mathbf{v} + (\mathbf{u}-\mathbf{v})`, chúng ta
thấy rằng vector :math:`\mathbf{u}-\mathbf{v}` là hướng đưa chúng ta từ
điểm :math:`\mathbf{v}` đến điểm :math:`\mathbf{u}`.
Dot Sản phẩm và Angles Như chúng ta đã thấy trong :numref:`sec_linear-algebra`, nếu chúng ta lấy hai vectơ cột :math:`\mathbf{u}` và :math:`\mathbf{v}`, chúng ta có thể tạo thành sản phẩm chấm của chúng bằng cách tính toán:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.. math:: \mathbf{u}^\top\mathbf{v} = \sum_i u_i\cdot v_i.
:label: eq_dot_def
Bởi vì :eq:`eq_dot_def` là đối xứng, chúng ta sẽ phản ánh ký hiệu
của phép nhân cổ điển và viết
.. math::
\mathbf{u}\cdot\mathbf{v} = \mathbf{u}^\top\mathbf{v} = \mathbf{v}^\top\mathbf{u},
để làm nổi bật thực tế là trao đổi thứ tự của các vectơ sẽ mang lại câu
trả lời tương tự.
Sản phẩm dot :eq:`eq_dot_def` cũng thừa nhận một giải thích hình
học: it is closely related to the angle between two vectors. Consider
the angle shown in :numref:`fig_angle`.
.. _fig_angle:
.. figure:: ../img/vec-angle.svg
Between any two vectors in the plane there is a well defined angle
:math:`\theta`. We will see this angle is intimately tied to the dot
product.
Để bắt đầu, chúng ta hãy xem xét hai vectơ cụ thể:
.. math::
\mathbf{v} = (r,0) \; \text{and} \; \mathbf{w} = (s\cos(\theta), s \sin(\theta)).
Vector :math:`\mathbf{v}` có chiều dài :math:`r` và chạy song song với
trục :math:`x`, và vector :math:`\mathbf{w}` có chiều dài :math:`s` và ở
góc :math:`\theta` với trục :math:`x`. Nếu chúng ta tính toán sản phẩm
chấm của hai vectơ này, chúng ta thấy rằng
.. math::
\mathbf{v}\cdot\mathbf{w} = rs\cos(\theta) = \|\mathbf{v}\|\|\mathbf{w}\|\cos(\theta).
Với một số thao tác đại số đơn giản, chúng ta có thể sắp xếp lại các
thuật ngữ để có được
.. math::
\theta = \arccos\left(\frac{\mathbf{v}\cdot\mathbf{w}}{\|\mathbf{v}\|\|\mathbf{w}\|}\right).
Nói tóm lại, đối với hai vectơ cụ thể này, tích chấm kết hợp với các
định mức cho chúng ta biết góc giữa hai vectơ. Thực tế tương tự này là
đúng nói chung. Tuy nhiên, chúng tôi sẽ không lấy được biểu thức ở đây,
nếu chúng ta xem xét viết :math:`\|\mathbf{v} - \mathbf{w}\|^2` theo hai
cách: một với sản phẩm chấm và một hình học khác sử dụng định luật
cosin, chúng ta có thể có được mối quan hệ đầy đủ. Thật vậy, đối với bất
kỳ hai vectơ :math:`\mathbf{v}` và :math:`\mathbf{w}`, góc giữa hai
vectơ là
.. math:: \theta = \arccos\left(\frac{\mathbf{v}\cdot\mathbf{w}}{\|\mathbf{v}\|\|\mathbf{w}\|}\right).
:label: eq_angle_forumla
Đây là một kết quả tốt đẹp vì không có gì trong các tài liệu tham khảo
tính toán hai chiều. Thật vậy, chúng ta có thể sử dụng điều này trong ba
hoặc ba triệu chiều mà không gặp vấn đề gì.
Như một ví dụ đơn giản, chúng ta hãy xem làm thế nào để tính toán góc
giữa một cặp vectơ:
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
from IPython import display
from mxnet import gluon, np, npx
from d2l import mxnet as d2l
npx.set_np()
def angle(v, w):
return np.arccos(v.dot(w) / (np.linalg.norm(v) * np.linalg.norm(w)))
angle(np.array([0, 1, 2]), np.array([2, 3, 4]))
.. parsed-literal::
:class: output
array(0.41899002)
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
import torch
import torchvision
from IPython import display
from torchvision import transforms
from d2l import torch as d2l
def angle(v, w):
return torch.acos(v.dot(w) / (torch.norm(v) * torch.norm(w)))
angle(torch.tensor([0, 1, 2], dtype=torch.float32), torch.tensor([2.0, 3, 4]))
.. parsed-literal::
:class: output
tensor(0.4190)
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
import tensorflow as tf
from IPython import display
from d2l import tensorflow as d2l
def angle(v, w):
return tf.acos(tf.tensordot(v, w, axes=1) / (tf.norm(v) * tf.norm(w)))
angle(tf.constant([0, 1, 2], dtype=tf.float32), tf.constant([2.0, 3, 4]))
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Chúng tôi sẽ không sử dụng nó ngay bây giờ, nhưng rất hữu ích khi biết
rằng chúng ta sẽ đề cập đến các vectơ mà góc là :math:`\pi/2` (hoặc
tương đương :math:`90^{\circ}`) là \* trực tho\*. Bằng cách kiểm tra
phương trình trên, chúng ta thấy rằng điều này xảy ra khi
:math:`\theta = \pi/2`, đó là điều tương tự như
:math:`\cos(\theta) = 0`. Cách duy nhất điều này có thể xảy ra là nếu
bản thân sản phẩm chấm bằng 0, và hai vectơ là trực giao nếu và chỉ khi
:math:`\mathbf{v}\cdot\mathbf{w} = 0`. Điều này sẽ chứng minh là một
công thức hữu ích khi hiểu các đối tượng về mặt hình học.
It is reasonable to ask: why is computing the angle useful? The answer
comes in the kind of invariance we expect data to have. Consider an
image, and a duplicate image, where every pixel value is the same but
:math:`10\%` the brightness. The values of the individual pixels are in
general far from the original values. Thus, if one computed the distance
between the original image and the darker one, the distance can be
large. However, for most ML applications, the *content* is the same---it
is still an image of a cat as far as a cat/dog classifier is concerned.
However, if we consider the angle, it is not hard to see that for any
vector :math:`\mathbf{v}`, the angle between :math:`\mathbf{v}` and
:math:`0.1\cdot\mathbf{v}` is zero. This corresponds to the fact that
scaling vectors keeps the same direction and just changes the length.
The angle considers the darker image identical.
Ví dụ như thế này ở khắp mọi nơi. Trong văn bản, chúng ta có thể muốn
chủ đề được thảo luận không thay đổi nếu chúng ta viết dài gấp đôi tài
liệu nói cùng một điều. Đối với một số mã hóa (chẳng hạn như đếm số lần
xuất hiện của các từ trong một số từ vựng), điều này tương ứng với việc
tăng gấp đôi vector mã hóa tài liệu, vì vậy một lần nữa chúng ta có thể
sử dụng góc.
Cosine Similarity
~~~~~~~~~~~~~~~~~
In ML contexts where the angle is employed to measure the closeness of
two vectors, practitioners adopt the term *cosine similarity* to refer
to the portion
.. math::
\cos(\theta) = \frac{\mathbf{v}\cdot\mathbf{w}}{\|\mathbf{v}\|\|\mathbf{w}\|}.
Cosin có giá trị lớn nhất là :math:`1` khi hai vectơ trỏ theo cùng một
hướng, giá trị tối thiểu là :math:`-1` khi chúng chỉ theo hướng ngược
lại, và giá trị :math:`0` khi hai vectơ là trực giao. Lưu ý rằng nếu các
thành phần của vectơ chiều cao được lấy mẫu ngẫu nhiên với trung bình
:math:`0`, cosin của chúng gần như sẽ luôn gần với :math:`0`.
Siêu máy bay
------------
Ngoài việc làm việc với các vectơ, một đối tượng chính khác mà bạn phải
hiểu để đi xa trong đại số tuyến tính là \* hyperplane\*, một khái quát
hóa cho các kích thước cao hơn của một đường thẳng (hai chiều) hoặc của
một mặt phẳng (ba chiều). Trong một không gian vectơ :math:`d` chiều,
một siêu phẳng có :math:`d-1` kích thước và chia không gian thành hai
nửa không gian.
Hãy để chúng tôi bắt đầu với một ví dụ. Giả sử rằng chúng ta có một
vector cột :math:`\mathbf{w}=[2,1]^\top`. Chúng tôi muốn biết, “những
điểm :math:`\mathbf{v}` với :math:`\mathbf{w}\cdot\mathbf{v} = 1` là
gì?” Bằng cách nhớ lại kết nối giữa các sản phẩm chấm và góc trên
:eq:`eq_angle_forumla`, chúng ta có thể thấy rằng điều này tương
đương với
.. math::
\|\mathbf{v}\|\|\mathbf{w}\|\cos(\theta) = 1 \; \iff \; \|\mathbf{v}\|\cos(\theta) = \frac{1}{\|\mathbf{w}\|} = \frac{1}{\sqrt{5}}.
.. _fig_vector-project:
.. figure:: ../img/proj-vec.svg
Recalling trigonometry, we see the formula
:math:`\|\mathbf{v}\|\cos(\theta)` is the length of the projection of
the vector :math:`\mathbf{v}` onto the direction of
:math:`\mathbf{w}`
Nếu chúng ta xem xét ý nghĩa hình học của biểu thức này, chúng ta thấy
rằng điều này tương đương với việc nói rằng độ dài của phép chiếu
:math:`\mathbf{v}` theo hướng :math:`\mathbf{w}` chính xác là
:math:`1/\|\mathbf{w}\|`, như được thể hiện trong
:numref:`fig_vector-project`. Tập hợp tất cả các điểm mà điều này là
đúng là một đường thẳng ở góc phải với vector :math:`\mathbf{w}`. Nếu
chúng ta muốn, chúng ta có thể tìm thấy phương trình cho dòng này và
thấy rằng nó là :math:`2x + y = 1` hoặc tương đương :math:`y = 1 - 2x`.
Nếu bây giờ chúng ta nhìn vào những gì xảy ra khi chúng ta hỏi về tập
hợp các điểm với :math:`\mathbf{w}\cdot\mathbf{v} > 1` hoặc
:math:`\mathbf{w}\cdot\mathbf{v} < 1`, chúng ta có thể thấy rằng đây là
những trường hợp các dự báo dài hơn hoặc ngắn hơn
:math:`1/\|\mathbf{w}\|`, tương ứng. Do đó, hai bất bình đẳng đó xác
định hai bên của dòng. Bằng cách này, chúng tôi đã tìm ra cách cắt không
gian của chúng tôi thành hai nửa, trong đó tất cả các điểm ở một bên đều
có sản phẩm chấm dưới ngưỡng và phía bên kia ở trên như chúng ta thấy
trong :numref:`fig_space-division`.
.. _fig_space-division:
.. figure:: ../img/space-division.svg
If we now consider the inequality version of the expression, we see
that our hyperplane (in this case: just a line) separates the space
into two halves.
Câu chuyện trong chiều cao hơn là nhiều như nhau. Nếu bây giờ chúng ta
lấy :math:`\mathbf{w} = [1,2,3]^\top` và hỏi về các điểm trong ba chiều
với :math:`\mathbf{w}\cdot\mathbf{v} = 1`, chúng ta có được một mặt
phẳng ở góc phải với vector :math:`\mathbf{w}` đã cho. Hai bất đẳng thức
lại xác định hai mặt của mặt phẳng như được thể hiện trong
:numref:`fig_higher-division`.
.. _fig_higher-division:
.. figure:: ../img/space-division-3d.svg
Hyperplanes in any dimension separate the space into two halves.
Trong khi khả năng hình dung của chúng ta hết vào thời điểm này, không
có gì ngăn cản chúng ta làm điều này trong hàng chục, hàng trăm hoặc
hàng tỷ chiều. Điều này xảy ra thường xuyên khi nghĩ về các mô hình học
máy. Ví dụ, chúng ta có thể hiểu các mô hình phân loại tuyến tính như
các mô hình từ :numref:`sec_softmax`, như các phương pháp để tìm các
siêu phẳng tách biệt các lớp mục tiêu khác nhau. Trong bối cảnh này, các
siêu máy bay như vậy thường được gọi là *kế hoạch quyết định*. Phần lớn
các mô hình phân loại học sâu kết thúc bằng một lớp tuyến tính được đưa
vào một softmax, do đó người ta có thể diễn giải vai trò của mạng nơ-ron
sâu là tìm một nhúng phi tuyến tính sao cho các lớp mục tiêu có thể được
tách sạch bằng các siêu phẳng.
Để đưa ra một ví dụ được xây dựng bằng tay, hãy chú ý rằng chúng ta có
thể tạo ra một mô hình hợp lý để phân loại hình ảnh nhỏ của áo phông và
quần dài từ tập dữ liệu thời trang MNIST (thấy trong
:numref:`sec_fashion_mnist`) bằng cách chỉ lấy vectơ giữa phương tiện
của chúng để xác định mặt phẳng quyết định và nhãn cầu một ngưỡng thô.
Đầu tiên chúng ta sẽ tải dữ liệu và tính toán trung bình.
.. raw:: html
.. raw:: html
.. code:: python
# Load in the dataset
train = gluon.data.vision.FashionMNIST(train=True)
test = gluon.data.vision.FashionMNIST(train=False)
X_train_0 = np.stack([x[0] for x in train if x[1] == 0]).astype(float)
X_train_1 = np.stack([x[0] for x in train if x[1] == 1]).astype(float)
X_test = np.stack(
[x[0] for x in test if x[1] == 0 or x[1] == 1]).astype(float)
y_test = np.stack(
[x[1] for x in test if x[1] == 0 or x[1] == 1]).astype(float)
# Compute averages
ave_0 = np.mean(X_train_0, axis=0)
ave_1 = np.mean(X_train_1, axis=0)
.. raw:: html
.. raw:: html
.. code:: python
# Load in the dataset
trans = []
trans.append(transforms.ToTensor())
trans = transforms.Compose(trans)
train = torchvision.datasets.FashionMNIST(root="../data", transform=trans,
train=True, download=True)
test = torchvision.datasets.FashionMNIST(root="../data", transform=trans,
train=False, download=True)
X_train_0 = torch.stack(
[x[0] * 256 for x in train if x[1] == 0]).type(torch.float32)
X_train_1 = torch.stack(
[x[0] * 256 for x in train if x[1] == 1]).type(torch.float32)
X_test = torch.stack(
[x[0] * 256 for x in test if x[1] == 0 or x[1] == 1]).type(torch.float32)
y_test = torch.stack([torch.tensor(x[1]) for x in test
if x[1] == 0 or x[1] == 1]).type(torch.float32)
# Compute averages
ave_0 = torch.mean(X_train_0, axis=0)
ave_1 = torch.mean(X_train_1, axis=0)
.. raw:: html
.. raw:: html
.. code:: python
# Load in the dataset
((train_images, train_labels), (
test_images, test_labels)) = tf.keras.datasets.fashion_mnist.load_data()
X_train_0 = tf.cast(tf.stack(train_images[[i for i, label in enumerate(
train_labels) if label == 0]] * 256), dtype=tf.float32)
X_train_1 = tf.cast(tf.stack(train_images[[i for i, label in enumerate(
train_labels) if label == 1]] * 256), dtype=tf.float32)
X_test = tf.cast(tf.stack(test_images[[i for i, label in enumerate(
test_labels) if label == 0]] * 256), dtype=tf.float32)
y_test = tf.cast(tf.stack(test_images[[i for i, label in enumerate(
test_labels) if label == 1]] * 256), dtype=tf.float32)
# Compute averages
ave_0 = tf.reduce_mean(X_train_0, axis=0)
ave_1 = tf.reduce_mean(X_train_1, axis=0)
.. raw:: html
.. raw:: html
Nó có thể là thông tin để kiểm tra các trung bình này một cách chi tiết,
vì vậy hãy để chúng tôi vẽ những gì họ trông như thế nào. Trong trường
hợp này, chúng ta thấy rằng trung bình thực sự giống như một hình ảnh mờ
của một chiếc áo phông.
.. raw:: html
.. raw:: html
.. code:: python
# Plot average t-shirt
d2l.set_figsize()
d2l.plt.imshow(ave_0.reshape(28, 28).tolist(), cmap='Greys')
d2l.plt.show()
.. figure:: output_geometry-linear-algebraic-ops_80b1c3_29_0.svg
.. raw:: html
.. raw:: html
.. code:: python
# Plot average t-shirt
d2l.set_figsize()
d2l.plt.imshow(ave_0.reshape(28, 28).tolist(), cmap='Greys')
d2l.plt.show()
.. figure:: output_geometry-linear-algebraic-ops_80b1c3_32_0.svg
.. raw:: html
.. raw:: html
.. code:: python
# Plot average t-shirt
d2l.set_figsize()
d2l.plt.imshow(tf.reshape(ave_0, (28, 28)), cmap='Greys')
d2l.plt.show()
.. figure:: output_geometry-linear-algebraic-ops_80b1c3_35_0.svg
.. raw:: html
.. raw:: html
Trong trường hợp thứ hai, chúng ta lại thấy rằng trung bình giống như
một hình ảnh mờ của quần.
.. raw:: html
.. raw:: html
.. code:: python
# Plot average trousers
d2l.plt.imshow(ave_1.reshape(28, 28).tolist(), cmap='Greys')
d2l.plt.show()
.. figure:: output_geometry-linear-algebraic-ops_80b1c3_41_0.svg
.. raw:: html
.. raw:: html
.. code:: python
# Plot average trousers
d2l.plt.imshow(ave_1.reshape(28, 28).tolist(), cmap='Greys')
d2l.plt.show()
.. figure:: output_geometry-linear-algebraic-ops_80b1c3_44_0.svg
.. raw:: html
.. raw:: html
.. code:: python
# Plot average trousers
d2l.plt.imshow(tf.reshape(ave_1, (28, 28)), cmap='Greys')
d2l.plt.show()
.. figure:: output_geometry-linear-algebraic-ops_80b1c3_47_0.svg
.. raw:: html
.. raw:: html
Trong một giải pháp hoàn toàn máy học, chúng ta sẽ tìm hiểu ngưỡng từ
tập dữ liệu. Trong trường hợp này, tôi chỉ đơn giản là mắt một ngưỡng
trông tốt trên dữ liệu đào tạo bằng tay.
.. raw:: html
.. raw:: html
.. code:: python
# Print test set accuracy with eyeballed threshold
w = (ave_1 - ave_0).T
predictions = X_test.reshape(2000, -1).dot(w.flatten()) > -1500000
# Accuracy
np.mean(predictions.astype(y_test.dtype) == y_test, dtype=np.float64)
.. parsed-literal::
:class: output
array(0.801, dtype=float64)
.. raw:: html
.. raw:: html
.. code:: python
# Print test set accuracy with eyeballed threshold
w = (ave_1 - ave_0).T
# '@' is Matrix Multiplication operator in pytorch.
predictions = X_test.reshape(2000, -1) @ (w.flatten()) > -1500000
# Accuracy
torch.mean((predictions.type(y_test.dtype) == y_test).float(), dtype=torch.float64)
.. parsed-literal::
:class: output
/tmp/ipykernel_118305/3819644537.py:2: UserWarning: The use of `x.T` on tensors of dimension other than 2 to reverse their shape is deprecated and it will throw an error in a future release. Consider `x.mT` to transpose batches of matricesor `x.permute(*torch.arange(x.ndim - 1, -1, -1))` to reverse the dimensions of a tensor. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:2318.)
w = (ave_1 - ave_0).T
.. parsed-literal::
:class: output
tensor(0.7870, dtype=torch.float64)
.. raw:: html
.. raw:: html
.. code:: python
# Print test set accuracy with eyeballed threshold
w = tf.transpose(ave_1 - ave_0)
predictions = tf.reduce_sum(X_test * tf.nest.flatten(w), axis=0) > -1500000
# Accuracy
tf.reduce_mean(
tf.cast(tf.cast(predictions, y_test.dtype) == y_test, tf.float32))
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Hình học của biến đổi tuyến tính
--------------------------------
Thông qua :numref:`sec_linear-algebra` và các cuộc thảo luận trên,
chúng ta có một sự hiểu biết vững chắc về hình học của vectơ, độ dài và
góc. Tuy nhiên, có một đối tượng quan trọng mà chúng ta đã bỏ qua thảo
luận, và đó là một sự hiểu biết hình học về các biến đổi tuyến tính được
thể hiện bằng ma trận. Nội bộ hoàn toàn những gì ma trận có thể làm để
chuyển đổi dữ liệu giữa hai không gian chiều cao có khả năng khác nhau
cần thực hành đáng kể, và vượt quá phạm vi của phụ lục này. Tuy nhiên,
chúng ta có thể bắt đầu xây dựng trực giác theo hai chiều.
Giả sử rằng chúng ta có một số ma trận:
.. math::
\mathbf{A} = \begin{bmatrix}
a & b \\ c & d
\end{bmatrix}.
If we want to apply this to an arbitrary vector
:math:`\mathbf{v} = [x, y]^\top`, we multiply and see that
.. math::
\begin{aligned}
\mathbf{A}\mathbf{v} & = \begin{bmatrix}a & b \\ c & d\end{bmatrix}\begin{bmatrix}x \\ y\end{bmatrix} \\
& = \begin{bmatrix}ax+by\\ cx+dy\end{bmatrix} \\
& = x\begin{bmatrix}a \\ c\end{bmatrix} + y\begin{bmatrix}b \\d\end{bmatrix} \\
& = x\left\{\mathbf{A}\begin{bmatrix}1\\0\end{bmatrix}\right\} + y\left\{\mathbf{A}\begin{bmatrix}0\\1\end{bmatrix}\right\}.
\end{aligned}
Điều này có vẻ giống như một tính toán kỳ lạ, nơi một cái gì đó rõ ràng
trở nên hơi bất khả xâm phạm. Tuy nhiên, nó cho chúng ta biết rằng chúng
ta có thể viết cách mà ma trận biến đổi vectơ *any* về cách nó biến đổi
\* hai vectơ cụ thể\ *: :math:`[1,0]^\top` và :math:`[0,1]^\top`. Điều
này đáng để xem xét trong một khoảnh khắc. Về cơ bản chúng ta đã giảm
một bài toán vô hạn (những gì xảy ra với bất kỳ cặp số thực nào) thành
một vấn đề hữu hạn (những gì xảy ra với các vectơ cụ thể này). Các vectơ
này là một ví dụ a *\ basis\ *, nơi chúng ta có thể viết bất kỳ vectơ
nào trong không gian của chúng ta dưới dạng tổng trọng số của các vectơ
cơ bản* này\*.
Hãy để chúng tôi vẽ những gì xảy ra khi chúng ta sử dụng ma trận cụ thể
.. math::
\mathbf{A} = \begin{bmatrix}
1 & 2 \\
-1 & 3
\end{bmatrix}.
Nếu chúng ta nhìn vào vector cụ thể :math:`\mathbf{v} = [2, -1]^\top`,
chúng ta thấy đây là :math:`2\cdot[1,0]^\top + -1\cdot[0,1]^\top` và do
đó chúng ta biết rằng ma trận :math:`A` sẽ gửi điều này đến
:math:`2(\mathbf{A}[1,0]^\top) + -1(\mathbf{A}[0,1])^\top = 2[1, -1]^\top - [2,3]^\top = [0, -5]^\top`.
Nếu chúng ta làm theo logic này thông qua một cách cẩn thận, nói bằng
cách xem xét lưới của tất cả các cặp số nguyên của điểm, chúng ta thấy
rằng những gì xảy ra là phép nhân ma trận có thể nghiêng, xoay, và quy
mô lưới điện, nhưng cấu trúc lưới phải vẫn như bạn thấy trong
:numref:`fig_grid-transform`.
.. _fig_grid-transform:
.. figure:: ../img/grid-transform.svg
The matrix :math:`\mathbf{A}` acting on the given basis vectors.
Notice how the entire grid is transported along with it.
Đây là điểm trực quan quan trọng nhất để nội tâm hóa về các biến đổi
tuyến tính được thể hiện bằng ma trận. Ma trận không có khả năng làm
biến dạng một số phần của không gian khác với những phần khác. Tất cả
những gì họ có thể làm là lấy tọa độ ban đầu trên không gian của chúng
ta và nghiêng, xoay và quy mô chúng.
Một số biến dạng có thể nghiêm trọng. For instance ví dụ the matrix ma
trận
.. math::
\mathbf{B} = \begin{bmatrix}
2 & -1 \\ 4 & -2
\end{bmatrix},
nén toàn bộ mặt phẳng hai chiều xuống một dòng duy nhất. Xác định và làm
việc với các biến đổi như vậy là chủ đề của một phần sau, nhưng về mặt
hình học chúng ta có thể thấy rằng điều này về cơ bản khác với các loại
biến đổi mà chúng ta đã thấy ở trên. Ví dụ, kết quả từ ma trận
:math:`\mathbf{A}` có thể là “uốn cong trở lại” vào lưới gốc. Kết quả từ
ma trận :math:`\mathbf{B}` không thể vì chúng ta sẽ không bao giờ biết
vector :math:`[1,2]^\top` đến từ đâu - nó là :math:`[1,1]^\top` hay
:math:`[0, -1]^\top`?
Trong khi bức ảnh này dành cho ma trận :math:`2\times2`, không có gì
ngăn cản chúng ta tham gia các bài học đã học vào các chiều cao hơn. Nếu
chúng ta lấy vectơ cơ bản tương tự như :math:`[1,0, \ldots,0]` và xem ma
trận của chúng ta gửi chúng ở đâu, chúng ta có thể bắt đầu có cảm giác
về cách nhân ma trận biến dạng toàn bộ không gian trong bất kỳ không
gian chiều nào chúng ta đang xử lý.
Sự phụ thuộc tuyến tính
-----------------------
Xem xét lại ma trận
.. math::
\mathbf{B} = \begin{bmatrix}
2 & -1 \\ 4 & -2
\end{bmatrix}.
Điều này nén toàn bộ mặt phẳng xuống để sống trên dòng đơn
:math:`y = 2x`. Câu hỏi bây giờ đặt ra: có cách nào đó chúng ta có thể
phát hiện ra điều này chỉ nhìn vào chính ma trận? Câu trả lời là thực sự
chúng ta có thể. Chúng ta hãy lấy :math:`\mathbf{b}_1 = [2,4]^\top` và
:math:`\mathbf{b}_2 = [-1, -2]^\top` là hai cột của :math:`\mathbf{B}`.
Hãy nhớ rằng chúng ta có thể viết mọi thứ được chuyển đổi bởi ma trận
:math:`\mathbf{B}` như một tổng trọng số của các cột của ma trận: như
:math:`a_1\mathbf{b}_1 + a_2\mathbf{b}_2`. Chúng tôi gọi đây là một kết
hợp tuyến tính\*. Thực tế là :math:`\mathbf{b}_1 = -2\cdot\mathbf{b}_2`
có nghĩa là chúng ta có thể viết bất kỳ sự kết hợp tuyến tính nào của
hai cột đó hoàn toàn về nói :math:`\mathbf{b}_2` kể từ
.. math::
a_1\mathbf{b}_1 + a_2\mathbf{b}_2 = -2a_1\mathbf{b}_2 + a_2\mathbf{b}_2 = (a_2-2a_1)\mathbf{b}_2.
Điều này có nghĩa là một trong các cột, theo một nghĩa nào đó, dư thừa
vì nó không xác định một hướng duy nhất trong không gian. Điều này không
nên làm chúng ta ngạc nhiên quá nhiều vì chúng ta đã thấy rằng ma trận
này sụp đổ toàn bộ mặt phẳng xuống thành một dòng duy nhất. Hơn nữa,
chúng ta thấy rằng sự phụ thuộc tuyến tính
:math:`\mathbf{b}_1 = -2\cdot\mathbf{b}_2` nắm bắt điều này. Để làm cho
điều này đối xứng hơn giữa hai vectơ, chúng ta sẽ viết cái này là
.. math::
\mathbf{b}_1 + 2\cdot\mathbf{b}_2 = 0.
Nói chung, chúng ta sẽ nói rằng một tập hợp các vectơ
:math:`\mathbf{v}_1, \ldots, \mathbf{v}_k` là \* phụ thuộc tuyến tính\*
nếu có hệ số tồn tại :math:`a_1, \ldots, a_k` \* không bằng 0\* để
.. math::
\sum_{i=1}^k a_i\mathbf{v_i} = 0.
Trong trường hợp này, chúng ta có thể giải quyết cho một trong các vectơ
về một số sự kết hợp của những người khác, và hiệu quả làm cho nó dư
thừa. Do đó, sự phụ thuộc tuyến tính trong các cột của ma trận là một
nhân chứng cho thực tế là ma trận của chúng ta đang nén không gian xuống
một số chiều thấp hơn. Nếu không có sự phụ thuộc tuyến tính, chúng tôi
nói rằng các vectơ là \* độc lập tuyến tính\*. Nếu các cột của ma trận
độc lập tuyến tính, không xảy ra nén và thao tác có thể được hoàn tác.
thứ hạng
--------
Nếu chúng ta có một ma trận :math:`n\times m` chung, nó là hợp lý để hỏi
không gian kích thước mà ma trận ánh xạ vào. Một khái niệm được gọi là
*rank* sẽ là câu trả lời của chúng tôi. Trong phần trước, chúng tôi lưu
ý rằng một sự phụ thuộc tuyến tính làm chứng cho việc nén không gian vào
một chiều thấp hơn và vì vậy chúng tôi sẽ có thể sử dụng điều này để xác
định khái niệm về cấp bậc. Đặc biệt, cấp bậc của một ma trận
:math:`\mathbf{A}` là số lượng lớn nhất các cột độc lập tuyến tính giữa
tất cả các tập con của cột. Ví dụ, ma trận
.. math::
\mathbf{B} = \begin{bmatrix}
2 & 4 \\ -1 & -2
\end{bmatrix},
có :math:`\mathrm{rank}(B)=1`, vì hai cột phụ thuộc tuyến tính, nhưng
bản thân một trong hai cột không phụ thuộc tuyến tính. Đối với một ví dụ
khó khăn hơn, chúng ta có thể xem xét
.. math::
\mathbf{C} = \begin{bmatrix}
1& 3 & 0 & -1 & 0 \\
-1 & 0 & 1 & 1 & -1 \\
0 & 3 & 1 & 0 & -1 \\
2 & 3 & -1 & -2 & 1
\end{bmatrix},
và cho thấy :math:`\mathbf{C}` đã xếp hạng hai vì, ví dụ, hai cột đầu
tiên độc lập tuyến tính, tuy nhiên bất kỳ bộ sưu tập nào trong bốn cột
phụ thuộc.
Thủ tục này, như mô tả, rất không hiệu quả. Nó đòi hỏi phải xem xét mọi
tập hợp con của các cột của ma trận nhất định của chúng ta, và do đó có
khả năng hàm mũ trong số cột. Sau đó chúng ta sẽ thấy một cách hiệu quả
hơn về tính toán để tính toán thứ hạng của ma trận, nhưng hiện tại, điều
này là đủ để thấy rằng khái niệm này được xác định rõ và hiểu ý nghĩa.
Khả năng đảo ngược
------------------
Chúng ta đã thấy ở trên rằng phép nhân của một ma trận với các cột phụ
thuộc tuyến tính không thể hoàn tác, tức là, không có hoạt động nghịch
đảo nào luôn có thể khôi phục đầu vào. Tuy nhiên, nhân với ma trận cấp
bậc đầy đủ (tức là, một số :math:`\mathbf{A}` là ma trận
:math:`n \times n` với thứ hạng :math:`n`), chúng ta nên luôn luôn có
thể hoàn tác nó. Xem xét ma trận
.. math::
\mathbf{I} = \begin{bmatrix}
1 & 0 & \cdots & 0 \\
0 & 1 & \cdots & 0 \\
\vdots & \vdots & \ddots & \vdots \\
0 & 0 & \cdots & 1
\end{bmatrix}.
mà là ma trận với những người dọc theo đường chéo, và số không ở nơi
khác. Chúng tôi gọi đây là ma trận *identity*. Đó là ma trận khiến dữ
liệu của chúng tôi không thay đổi khi áp dụng. Để tìm một ma trận hoàn
tác những gì ma trận của chúng tôi :math:`\mathbf{A}` đã làm, chúng tôi
muốn tìm một ma trận :math:`\mathbf{A}^{-1}` sao cho
.. math::
\mathbf{A}^{-1}\mathbf{A} = \mathbf{A}\mathbf{A}^{-1} = \mathbf{I}.
Nếu chúng ta xem xét điều này như một hệ thống, chúng ta có
:math:`n \times n` ẩn số (các mục của :math:`\mathbf{A}^{-1}`) và
:math:`n \times n` phương trình (bình đẳng cần giữ giữa mọi mục nhập của
sản phẩm :math:`\mathbf{A}^{-1}\mathbf{A}` và mọi mục nhập của
:math:`\mathbf{I}`) vì vậy chúng ta nên khái quát mong đợi một giải pháp
tồn tại. Thật vậy, trong phần tiếp theo chúng ta sẽ thấy một đại lượng
được gọi là *determinant*, có thuộc tính miễn là yếu tố quyết định không
phải bằng 0, chúng ta có thể tìm ra giải pháp. Chúng tôi gọi ma trận
:math:`\mathbf{A}^{-1}` như ma trận *inverse*. Ví dụ, nếu
:math:`\mathbf{A}` là ma trận :math:`2 \times 2` chung
.. math::
\mathbf{A} = \begin{bmatrix}
a & b \\
c & d
\end{bmatrix},
sau đó chúng ta có thể thấy rằng nghịch đảo là
.. math::
\frac{1}{ad-bc} \begin{bmatrix}
d & -b \\
-c & a
\end{bmatrix}.
Chúng ta có thể kiểm tra để xem điều này bằng cách thấy rằng nhân với
nghịch đảo được đưa ra bởi công thức trên hoạt động trong thực tế.
.. raw:: html
.. raw:: html
.. code:: python
M = np.array([[1, 2], [1, 4]])
M_inv = np.array([[2, -1], [-0.5, 0.5]])
M_inv.dot(M)
.. parsed-literal::
:class: output
array([[1., 0.],
[0., 1.]])
.. raw:: html
.. raw:: html
.. code:: python
M = torch.tensor([[1, 2], [1, 4]], dtype=torch.float32)
M_inv = torch.tensor([[2, -1], [-0.5, 0.5]])
M_inv @ M
.. parsed-literal::
:class: output
tensor([[1., 0.],
[0., 1.]])
.. raw:: html
.. raw:: html
.. code:: python
M = tf.constant([[1, 2], [1, 4]], dtype=tf.float32)
M_inv = tf.constant([[2, -1], [-0.5, 0.5]])
tf.matmul(M_inv, M)
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Các vấn đề số Trong khi nghịch đảo của ma trận rất hữu ích về lý thuyết, chúng ta phải nói rằng hầu hết thời gian chúng ta không muốn *sử dụng* ma trận nghịch đảo để giải quyết một vấn đề trong thực tế. Nói chung, có nhiều thuật toán ổn định số hơn để giải các phương trình tuyến tính như
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. math::
\mathbf{A}\mathbf{x} = \mathbf{b},
hơn là tính toán nghịch đảo và nhân lên để có được
.. math::
\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}.
Cũng giống như phân chia bởi một số nhỏ có thể dẫn đến sự bất ổn số, vì
vậy có thể đảo ngược của một ma trận gần với có thứ hạng thấp.
Hơn nữa, thông thường ma trận :math:`\mathbf{A}` là \* thưa thớt \*, có
nghĩa là nó chỉ chứa một số lượng nhỏ các giá trị không phải bằng không.
Nếu chúng ta khám phá các ví dụ, chúng ta sẽ thấy rằng điều này không có
nghĩa là nghịch đảo thưa thớt. Ngay cả khi :math:`\mathbf{A}` là một
:math:`1` triệu bởi :math:`1` triệu ma trận với chỉ :math:`5` triệu mục
không phải bằng không (và do đó chúng tôi chỉ cần lưu trữ những
:math:`5` triệu), nghịch đảo thường sẽ có hầu hết mọi mục không âm, yêu
cầu chúng tôi lưu trữ tất cả :math:`1\text{M}^2` mục đó là :math:`1`
nghìn tỷ mục!
Mặc dù chúng ta không có thời gian để lặn tất cả các cách vào các vấn đề
số gai góc thường gặp khi làm việc với đại số tuyến tính, chúng tôi muốn
cung cấp cho bạn một số trực giác về khi nào cần tiến hành thận trọng,
và nói chung tránh đảo ngược trong thực tế là một nguyên tắc tốt.
Xác định Quan điểm hình học của đại số tuyến tính đưa ra một cách trực quan để diễn giải một đại lượng cơ bản được gọi là *quyết định*. Hãy xem xét hình ảnh lưới từ trước, nhưng bây giờ với một khu vực được tô sáng (:numref:`fig_grid-filled`).
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.. _fig_grid-filled:
.. figure:: ../img/grid-transform-filled.svg
The matrix :math:`\mathbf{A}` again distorting the grid. This time, I
want to draw particular attention to what happens to the highlighted
square.
Nhìn vào hình vuông được tô sáng. Đây là một hình vuông với các cạnh
được đưa ra bởi :math:`(0, 1)` và :math:`(1, 0)` và do đó nó có diện
tích một. Sau :math:`\mathbf{A}` biến hình vuông này, chúng ta thấy rằng
nó trở thành một hình bình hành. Không có lý do gì hình bình hành này
nên có cùng một khu vực mà chúng ta bắt đầu, và thực sự trong trường hợp
cụ thể được hiển thị ở đây
.. math::
\mathbf{A} = \begin{bmatrix}
1 & 2 \\
-1 & 3
\end{bmatrix},
nó là một bài tập trong hình học tọa độ để tính toán diện tích của hình
bình hành này và có được rằng khu vực này là :math:`5`.
Nói chung, nếu chúng ta có một ma trận
.. math::
\mathbf{A} = \begin{bmatrix}
a & b \\
c & d
\end{bmatrix},
chúng ta có thể thấy với một số tính toán rằng diện tích của hình bình
hành kết quả là :math:`ad-bc`. Khu vực này được gọi là *quyết định*.
Hãy để chúng tôi kiểm tra điều này một cách nhanh chóng với một số mã ví
dụ.
.. raw:: html
.. raw:: html
.. code:: python
import numpy as np
np.linalg.det(np.array([[1, -1], [2, 3]]))
.. parsed-literal::
:class: output
5.000000000000001
.. raw:: html
.. raw:: html
.. code:: python
torch.det(torch.tensor([[1, -1], [2, 3]], dtype=torch.float32))
.. parsed-literal::
:class: output
tensor(5.)
.. raw:: html
.. raw:: html
.. code:: python
tf.linalg.det(tf.constant([[1, -1], [2, 3]], dtype=tf.float32))
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Mắt đại bàng giữa chúng ta sẽ nhận thấy rằng biểu thức này có thể bằng 0
hoặc thậm chí tiêu cực. Đối với thuật ngữ tiêu cực, đây là vấn đề quy
ước được thực hiện chung trong toán học: nếu ma trận lật hình, chúng ta
nói khu vực này bị phủ định. Chúng ta hãy xem bây giờ rằng khi yếu tố
quyết định bằng không, chúng ta tìm hiểu thêm.
Hãy để chúng tôi xem xét
.. math::
\mathbf{B} = \begin{bmatrix}
2 & 4 \\ -1 & -2
\end{bmatrix}.
Nếu chúng ta tính toán yếu tố quyết định của ma trận này, chúng ta nhận
được :math:`2\cdot(-2 ) - 4\cdot(-1) = 0`. Với sự hiểu biết của chúng
tôi ở trên, điều này có ý nghĩa. :math:`\mathbf{B}` nén hình vuông từ
hình ảnh gốc xuống một đoạn đường, có diện tích bằng không. Và quả thực,
bị nén thành một không gian chiều thấp hơn là cách duy nhất để có diện
tích bằng 0 sau khi biến đổi. Như vậy chúng ta thấy kết quả sau là đúng:
một ma trận :math:`A` có thể đảo ngược nếu và chỉ khi yếu tố quyết định
không bằng 0.
Như một nhận xét cuối cùng, hãy tưởng tượng rằng chúng ta có bất kỳ con
số nào được vẽ trên mặt phẳng. Suy nghĩ giống như các nhà khoa học máy
tính, chúng ta có thể phân hủy con số đó thành một tập hợp các ô vuông
nhỏ để diện tích của hình là về bản chất chỉ là số lượng hình vuông
trong phân hủy. Nếu bây giờ chúng ta biến đổi con số đó bằng một ma
trận, chúng ta sẽ gửi từng ô vuông này thành hình bình hành, mỗi ô có
diện tích được đưa ra bởi yếu tố quyết định. Chúng ta thấy rằng đối với
bất kỳ con số nào, yếu tố quyết định cho số (ký) mà ma trận quy mô diện
tích của bất kỳ hình nào.
Các yếu tố quyết định tính toán cho ma trận lớn hơn có thể tốn nhiều
công sức, nhưng trực giác là như nhau. Yếu tố quyết định vẫn là yếu tố
mà :math:`n\times n` ma trận quy mô :math:`n`-khối lượng chiều.
Tensors và hoạt động đại số tuyến tính phổ biến
-----------------------------------------------
Năm :numref:`sec_linear-algebra` khái niệm về hàng chục đã được giới
thiệu. Trong phần này, chúng ta sẽ đi sâu hơn vào các cơn co thắt tensor
(tensor tương đương với phép nhân ma trận), và xem làm thế nào nó có thể
cung cấp một cái nhìn thống nhất về một số hoạt động ma trận và vector.
Với ma trận và vectơ, chúng ta biết cách nhân chúng để chuyển đổi dữ
liệu. Chúng ta cần phải có một định nghĩa tương tự cho hàng chục nếu
chúng hữu ích cho chúng ta. Hãy suy nghĩ về phép nhân ma trận:
.. math::
\mathbf{C} = \mathbf{A}\mathbf{B},
hoặc tương đương
.. math:: c_{i, j} = \sum_{k} a_{i, k}b_{k, j}.
Mô hình này là một trong những chúng ta có thể lặp lại cho hàng chục.
Đối với hàng chục, không có một trường hợp nào để tổng hợp những gì có
thể được lựa chọn phổ biến, vì vậy chúng ta cần xác định chính xác những
chỉ số chúng ta muốn tổng hợp lại. For instance ví dụ we could consider
xem xét
.. math::
y_{il} = \sum_{jk} x_{ijkl}a_{jk}.
Một sự chuyển đổi như vậy được gọi là co lại *tensor*. Nó có thể đại
diện cho một gia đình biến đổi linh hoạt hơn nhiều mà phép nhân ma trận
một mình.
Là một đơn giản hóa ký hiệu thường được sử dụng, chúng ta có thể nhận
thấy rằng tổng là trên chính xác những chỉ số xảy ra nhiều hơn một lần
trong biểu thức, do đó mọi người thường làm việc với ký hiệu \*
Einstein\*, trong đó tổng kết được thực hiện trong tất cả các chỉ số lặp
đi lặp lại. Điều này cho phép biểu thức nhỏ gọn:
.. math::
y_{il} = x_{ijkl}a_{jk}.
Ví dụ phổ biến từ đại số tuyến tính
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Chúng ta hãy xem có bao nhiêu định nghĩa đại số tuyến tính mà chúng ta
đã thấy trước đây có thể được thể hiện trong ký hiệu tensor nén này:
- :math:`\mathbf{v} \cdot \mathbf{w} = \sum_i v_iw_i`
- :math:`\|\mathbf{v}\|_2^{2} = \sum_i v_iv_i`
- :math:`(\mathbf{A}\mathbf{v})_i = \sum_j a_{ij}v_j`
- :math:`(\mathbf{A}\mathbf{B})_{ik} = \sum_j a_{ij}b_{jk}`
- :math:`\mathrm{tr}(\mathbf{A}) = \sum_i a_{ii}`
Bằng cách này, chúng ta có thể thay thế vô số ký hiệu chuyên biệt bằng
các biểu thức tensor ngắn.
Expressing in Code Tensors cũng có thể được vận hành linh hoạt trong mã. Như đã thấy trong :numref:`sec_linear-algebra`, chúng ta có thể tạo ra hàng chục như được hiển thị dưới đây.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. raw:: html
.. raw:: html
.. code:: python
# Define tensors
B = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
A = np.array([[1, 2], [3, 4]])
v = np.array([1, 2])
# Print out the shapes
A.shape, B.shape, v.shape
.. parsed-literal::
:class: output
((2, 2), (2, 2, 3), (2,))
.. raw:: html
.. raw:: html
.. code:: python
# Define tensors
B = torch.tensor([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
A = torch.tensor([[1, 2], [3, 4]])
v = torch.tensor([1, 2])
# Print out the shapes
A.shape, B.shape, v.shape
.. parsed-literal::
:class: output
(torch.Size([2, 2]), torch.Size([2, 2, 3]), torch.Size([2]))
.. raw:: html
.. raw:: html
.. code:: python
# Define tensors
B = tf.constant([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
A = tf.constant([[1, 2], [3, 4]])
v = tf.constant([1, 2])
# Print out the shapes
A.shape, B.shape, v.shape
.. parsed-literal::
:class: output
(TensorShape([2, 2]), TensorShape([2, 2, 3]), TensorShape([2]))
.. raw:: html
.. raw:: html
Tổng kết Einstein đã được thực hiện trực tiếp. Các chỉ số xảy ra trong
tổng kết Einstein có thể được truyền như một chuỗi, tiếp theo là các
hàng chục đang được hành động. Ví dụ, để thực hiện phép nhân ma trận,
chúng ta có thể xem xét tổng kết Einstein thấy ở trên
(:math:`\mathbf{A}\mathbf{v} = a_{ij}v_j`) và tự loại bỏ các chỉ số để
thực hiện:
.. raw:: html
.. raw:: html
.. code:: python
# Reimplement matrix multiplication
np.einsum("ij, j -> i", A, v), A.dot(v)
.. parsed-literal::
:class: output
(array([ 5, 11]), array([ 5, 11]))
.. raw:: html
.. raw:: html
.. code:: python
# Reimplement matrix multiplication
torch.einsum("ij, j -> i", A, v), A@v
.. parsed-literal::
:class: output
(tensor([ 5, 11]), tensor([ 5, 11]))
.. raw:: html
.. raw:: html
.. code:: python
# Reimplement matrix multiplication
tf.einsum("ij, j -> i", A, v), tf.matmul(A, tf.reshape(v, (2, 1)))
.. parsed-literal::
:class: output
(,
)
.. raw:: html
.. raw:: html
Đây là một ký hiệu rất linh hoạt. Ví dụ nếu chúng ta muốn tính toán
những gì sẽ được viết theo truyền thống như
.. math::
c_{kl} = \sum_{ij} \mathbf{b}_{ijk}\mathbf{a}_{il}v_j.
nó có thể được thực hiện thông qua tổng kết Einstein như:
.. raw:: html
.. raw:: html
.. code:: python
np.einsum("ijk, il, j -> kl", B, A, v)
.. parsed-literal::
:class: output
array([[ 90, 126],
[102, 144],
[114, 162]])
.. raw:: html
.. raw:: html
.. code:: python
torch.einsum("ijk, il, j -> kl", B, A, v)
.. parsed-literal::
:class: output
tensor([[ 90, 126],
[102, 144],
[114, 162]])
.. raw:: html
.. raw:: html
.. code:: python
tf.einsum("ijk, il, j -> kl", B, A, v)
.. parsed-literal::
:class: output
.. raw:: html
.. raw:: html
Ký hiệu này có thể đọc được và hiệu quả đối với con người, tuy nhiên
cồng kềnh nếu vì bất kỳ lý do gì chúng ta cần tạo ra sự co lại căng
thẳng theo chương trình. Vì lý do này, ``einsum`` cung cấp một ký hiệu
thay thế bằng cách cung cấp các chỉ số nguyên cho mỗi tensor. Ví dụ,
cùng một sự co lại tensor cũng có thể được viết là:
.. raw:: html
.. raw:: html
.. code:: python
np.einsum(B, [0, 1, 2], A, [0, 3], v, [1], [2, 3])
.. parsed-literal::
:class: output
array([[ 90, 126],
[102, 144],
[114, 162]])
.. raw:: html
.. raw:: html
.. code:: python
# PyTorch doesn't support this type of notation.
.. raw:: html
.. raw:: html
.. code:: python
# TensorFlow doesn't support this type of notation.
.. raw:: html
.. raw:: html
Một trong hai ký hiệu cho phép đại diện ngắn gọn và hiệu quả các cơn co
thắt tensor trong mã.
Tóm tắt \* Vectơ có thể được giải thích về mặt hình học như một trong hai điểm hoặc hướng trong không gian \* Các sản phẩm chấm xác định khái niệm góc đến không gian chiều cao tùy ý. Chúng có thể được sử dụng để xác định các mặt phẳng quyết định thường được sử dụng như là bước cuối cùng trong một nhiệm vụ phân loại. \* Phép nhân ma trận có thể được giải thích về mặt hình học là biến dạng thống nhất của tọa độ bên dưới. Chúng đại diện cho một cách rất hạn chế, nhưng về mặt toán học sạch, để biến đổi vectơ. \* Phụ thuộc tuyến tính là một cách để biết khi một tập hợp các vectơ nằm trong một không gian chiều thấp hơn chúng ta mong đợi (giả sử bạn có :math:`3` vectơ sống trong một không gian :math:`2` chiều). Thứ hạng của ma trận là kích thước của tập hợp con lớn nhất của các cột của nó độc lập tuyến tính \* Khi nghịch đảo của ma trận được xác định, đảo ngược ma trận cho phép chúng ta tìm một ma trận khác hoàn tác hành động của đầu tiên. Ma trận đảo ngược là hữu ích trong lý thuyết, nhưng đòi hỏi sự chăm sóc trong thực tế do sự bất ổn số.\* yếu tố quyết định cho phép chúng ta đo lường bao nhiêu ma trận mở rộng hoặc ký hợp đồng một không gian. Một yếu tố quyết định nonzero ngụ ý một ma trận đảo ngược (không số ít) và một yếu tố xác định có giá trị không có nghĩa là ma trận không thể đảo ngược (số ít). \* co thắt tensor và tổng kết Einstein cung cấp cho một ký hiệu gọn gàng và sạch sẽ để thể hiện nhiều tính toán được nhìn thấy trong học máy.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Exercises
---------
1. What is the angle between
.. math::
\vec v_1 = \begin{bmatrix}
1 \\ 0 \\ -1 \\ 2
\end{bmatrix}, \qquad \vec v_2 = \begin{bmatrix}
3 \\ 1 \\ 0 \\ 1
\end{bmatrix}?
2. True or false: :math:`\begin{bmatrix}1 & 2\\0&1\end{bmatrix}` and
:math:`\begin{bmatrix}1 & -2\\0&1\end{bmatrix}` are inverses of one
another?
3. Suppose that we draw a shape in the plane with area
:math:`100\mathrm{m}^2`. What is the area after transforming the
figure by the matrix
.. math::
\begin{bmatrix}
2 & 3\\
1 & 2
\end{bmatrix}.
4. Which of the following sets of vectors are linearly independent?
- :math:`\left\{\begin{pmatrix}1\\0\\-1\end{pmatrix}, \begin{pmatrix}2\\1\\-1\end{pmatrix}, \begin{pmatrix}3\\1\\1\end{pmatrix}\right\}`
- :math:`\left\{\begin{pmatrix}3\\1\\1\end{pmatrix}, \begin{pmatrix}1\\1\\1\end{pmatrix}, \begin{pmatrix}0\\0\\0\end{pmatrix}\right\}`
- :math:`\left\{\begin{pmatrix}1\\1\\0\end{pmatrix}, \begin{pmatrix}0\\1\\-1\end{pmatrix}, \begin{pmatrix}1\\0\\1\end{pmatrix}\right\}`
5. Suppose that you have a matrix written as
:math:`A = \begin{bmatrix}c\\d\end{bmatrix}\cdot\begin{bmatrix}a & b\end{bmatrix}`
for some choice of values :math:`a, b, c`, and :math:`d`. True or
false: the determinant of such a matrix is always :math:`0`?
6. The vectors :math:`e_1 = \begin{bmatrix}1\\0\end{bmatrix}` and
:math:`e_2 = \begin{bmatrix}0\\1\end{bmatrix}` are orthogonal. What
is the condition on a matrix :math:`A` so that :math:`Ae_1` and
:math:`Ae_2` are orthogonal?
7. How can you write :math:`\mathrm{tr}(\mathbf{A}^4)` in Einstein
notation for an arbitrary matrix :math:`A`?
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html