{ "cells": [ { "cell_type": "markdown", "id": "73bd968b-d970-4a05-94ef-4e7abf990827", "metadata": {}, "source": [ "Chapter 05\n", "\n", "# 爱因斯坦求和约定\n", "Book_4《矩阵力量》 | 鸢尾花书:从加减乘除到机器学习 (第二版)" ] }, { "cell_type": "markdown", "id": "05612796-d376-409c-bb07-3da0f851fa29", "metadata": {}, "source": [ "这段代码使用 `numpy` 库的 `einsum` 函数进行各种矩阵和向量的运算。`einsum` 函数的主要优势在于其高效的索引处理方式,使得许多复杂的矩阵和向量操作可以用简单的字符串表达式来实现。这段代码包括以下几个主要部分:\n", "\n", "1. **定义向量与矩阵**: \n", " 定义了两个列向量\n", "\n", " $$ a = \\begin{bmatrix} 1 \\\\ 2 \\\\ 3 \\end{bmatrix} $$\n", " $$ b = \\begin{bmatrix} -4 \\\\ -5 \\\\ -6 \\end{bmatrix} $$\n", "\n", " 以及它们对应的一维向量形式 \\( a_{1D} = [1, 2, 3] \\) 和 \\( b_{1D} = [-4, -5, -6] \\)。\n", "\n", "3. **向量和矩阵的求和**: \n", " 使用 `einsum('ij->', a)` 计算 \\( a \\) 中所有元素的和,即 \\( \\sum_{i,j} a_{ij} \\)。 \n", " 同样地,`einsum('i->', a_{1D})` 计算 \\( a_{1D} \\) 的元素和,即 \\( \\sum_i a_{i} \\)。\n", "\n", "4. **逐元素乘积**: \n", " 使用 `einsum('ij,ij->ij', a, b)` 计算 \\( a \\) 和 \\( b \\) 的逐元素乘积,其结果为一个矩阵,其中每个元素 \\( (i,j) \\) 对应 \\( a_{ij} \\times b_{ij} \\)。 \n", " 对一维向量 `a_1D` 和 `b_1D` 的逐元素乘积,则通过 `einsum('i,i->i', a_{1D}, b_{1D})` 实现,得到 \\( [a_1 \\times b_1, a_2 \\times b_2, a_3 \\times b_3] \\)。\n", "\n", "5. **向量的内积**: \n", " 使用 `einsum('ij,ij->', a, b)` 计算 \\( a \\) 和 \\( b \\) 的内积,即 \\( \\sum_{i,j} a_{ij} \\cdot b_{ij} \\)。 \n", " 类似地,对于一维向量的内积,通过 `einsum('i,i->', a_{1D}, b_{1D})` 计算,公式为 \\( \\sum_i a_i \\cdot b_i \\)。\n", "\n", "6. **向量的外积**: \n", " `einsum('ij,ji->ij', a, a)` 计算向量 \\( a \\) 自身的外积,生成一个矩阵,每个元素为 \\( a_{ij} \\cdot a_{ji} \\)。 \n", " 而 `einsum('i,j->ij', a_{1D}, a_{1D})` 计算 \\( a_{1D} \\) 的外积,得到一个 \\( 3 \\times 3 \\) 矩阵,其元素为 \\( a_i \\cdot a_j \\)。\n", "\n", "7. **矩阵的定义及运算**: \n", " 定义了两个 \\( 3 \\times 3 \\) 的矩阵 \\( A \\) 和 \\( B \\)。矩阵 \\( A \\) 和 \\( B \\) 之间的运算包括以下内容: \n", " \n", " - **转置**: `einsum('ji', A)` 计算 \\( A \\) 的转置。\n", " \n", " - **矩阵求和**: `einsum('ij->', A)` 计算矩阵 \\( A \\) 所有元素的和。 \n", " \n", " - **按行和按列求和**: \n", " 使用 `einsum('ij->j', A)` 计算每列的和,结果为一个一维数组,形式为 \\( \\sum_i A_{ij} \\)。 \n", " `einsum('ij->i', A)` 计算每行的和,结果形式为 \\( \\sum_j A_{ij} \\)。\n", "\n", " - **提取主对角线和计算迹**: \n", " `einsum('ii->i', A)` 提取 \\( A \\) 的主对角线元素,结果为 \\( [A_{11}, A_{22}, A_{33}] \\)。 \n", " `einsum('ii->', A)` 计算矩阵 \\( A \\) 的迹 \\( \\text{tr}(A) = \\sum_i A_{ii} \\)。\n", "\n", " - **矩阵乘法和结果求和**: \n", " `einsum('ij,jk->ik', A, B)` 计算 \\( A \\) 和 \\( B \\) 的矩阵乘积 \\( C = A \\times B \\),即 \\( C_{ik} = \\sum_j A_{ij} \\cdot B_{jk} \\)。 \n", " `einsum('ij,jk->', A, B)` 计算 \\( A \\times B \\) 的所有元素和。 \n", " `einsum('ij,jk->ki', A, B)` 先进行矩阵乘法,再对结果转置。\n", "\n", " - **逐元素乘积**: \n", " `einsum('ij,ij->ij', A, B)` 计算 \\( A \\) 和 \\( B \\) 的逐元素乘积,结果为矩阵 \\( D \\),其中 \\( D_{ij} = A_{ij} \\cdot B_{ij} \\)。" ] }, { "cell_type": "code", "execution_count": 1, "id": "97fcb029-de43-4a4b-ba5f-ad331b7a78eb", "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "id": "4a4e312b-9e45-4be6-afcc-83060d1798ee", "metadata": {}, "source": [ "## 定义矩阵和向量" ] }, { "cell_type": "code", "execution_count": 2, "id": "b8e03123-64d1-4387-8fc7-6e7464e5a529", "metadata": {}, "outputs": [], "source": [ "a = np.array([[1],\n", " [2],\n", " [3]]) # 定义列向量 a" ] }, { "cell_type": "code", "execution_count": 3, "id": "c691db9b-31d1-4661-ac0b-17f39e31bddb", "metadata": {}, "outputs": [], "source": [ "a_1D = np.array([1,2,3]) # 定义一维向量 a_1D" ] }, { "cell_type": "code", "execution_count": 4, "id": "6f95f355-f84a-4476-a424-89279c00eab2", "metadata": {}, "outputs": [], "source": [ "b = np.array([[-4],\n", " [-5],\n", " [-6]]) # 定义列向量 b" ] }, { "cell_type": "code", "execution_count": 5, "id": "9868ad35-72ff-4e73-b364-02186f82ddde", "metadata": {}, "outputs": [], "source": [ "b_1D = np.array([-4,-5,-6]) # 定义一维向量 b_1D" ] }, { "cell_type": "markdown", "id": "da290670-c5b3-45fb-90b9-d2260356cb7f", "metadata": {}, "source": [ "## 计算向量 a 的元素和" ] }, { "cell_type": "code", "execution_count": 6, "id": "ce155c35-ebdc-4fb7-9036-b64a5e7c51c5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6\n" ] } ], "source": [ "print(np.einsum('ij->',a)) # 计算矩阵 a 所有元素的和" ] }, { "cell_type": "code", "execution_count": 7, "id": "fc84a3f0-61a5-4a06-af67-dc92507acf20", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6\n" ] } ], "source": [ "print(np.einsum('i->',a_1D)) # 计算向量 a_1D 所有元素的和" ] }, { "cell_type": "markdown", "id": "3fe87ea0-03ac-4f71-8571-8ae0ed8a5269", "metadata": {}, "source": [ "## 向量 a 和 b 的逐元素乘积" ] }, { "cell_type": "code", "execution_count": 8, "id": "bc000421-7392-4603-8fe8-aa6608e1c1cb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ -4]\n", " [-10]\n", " [-18]]\n" ] } ], "source": [ "print(np.einsum('ij,ij->ij',a,b)) # 计算矩阵 a 和 b 的逐元素乘积" ] }, { "cell_type": "code", "execution_count": 9, "id": "bb28fdab-b2b0-4d28-8f62-1453d77bfbb4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ -4 -10 -18]\n" ] } ], "source": [ "print(np.einsum('i,i->i',a_1D,b_1D)) # 计算向量 a_1D 和 b_1D 的逐元素乘积" ] }, { "cell_type": "markdown", "id": "aee84a7c-d65b-440a-967b-ac45f0c28acd", "metadata": {}, "source": [ "## 向量 a 和 b 的内积" ] }, { "cell_type": "code", "execution_count": 10, "id": "34d92cbc-b818-409d-ab86-d075c27236cd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-32\n" ] } ], "source": [ "print(np.einsum('ij,ij->',a,b)) # 计算矩阵 a 和 b 的内积" ] }, { "cell_type": "code", "execution_count": 11, "id": "3142feb7-5501-49de-9576-a3c010cbb4be", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-32\n" ] } ], "source": [ "print(np.einsum('i,i->',a_1D,b_1D)) # 计算向量 a_1D 和 b_1D 的内积" ] }, { "cell_type": "markdown", "id": "f19a1dbf-204b-4d08-bb7f-89fe08a5a40f", "metadata": {}, "source": [ "## 向量 a 自身的外积" ] }, { "cell_type": "code", "execution_count": 12, "id": "e46e5895-d71d-4eed-a6ae-4c6875da71bb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [2 4 6]\n", " [3 6 9]]\n" ] } ], "source": [ "print(np.einsum('ij,ji->ij',a,a)) # 计算矩阵 a 和自身的外积" ] }, { "cell_type": "code", "execution_count": 13, "id": "1568a79b-9345-474a-aa5a-a977ef5ead8f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [2 4 6]\n", " [3 6 9]]\n" ] } ], "source": [ "print(np.einsum('i,j->ij',a_1D,a_1D)) # 计算向量 a_1D 和自身的外积" ] }, { "cell_type": "markdown", "id": "b8cf3e0c-da91-4cb8-885e-145cc69b2bb3", "metadata": {}, "source": [ "## 向量 a 和 b 的外积" ] }, { "cell_type": "code", "execution_count": null, "id": "442d8342-ac8e-4b31-8dd7-ab0c8704c3ff", "metadata": {}, "outputs": [], "source": [ "print(np.einsum('ij,ji->ij',a,b)) # 计算矩阵 a 和 b 的外积" ] }, { "cell_type": "code", "execution_count": null, "id": "81954884-d255-4524-b09b-2848891ef7e7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ -4 -5 -6]\n", " [ -8 -10 -12]\n", " [-12 -15 -18]]\n", "[[ -4 -5 -6]\n", " [ -8 -10 -12]\n", " [-12 -15 -18]]\n" ] } ], "source": [ "print(np.einsum('i,j->ij',a_1D,b_1D)) # 计算向量 a_1D 和 b_1D 的外积" ] }, { "cell_type": "markdown", "id": "9f897baa-6fca-4bf5-9613-9379363878b8", "metadata": {}, "source": [ "## 定义方阵 A 和 B" ] }, { "cell_type": "code", "execution_count": 15, "id": "31dd6b69-fc1a-4613-a3bc-f5cb51988014", "metadata": {}, "outputs": [], "source": [ "A = np.array([[1,2,3],\n", " [4,5,6],\n", " [7,8,9]]) # 定义方阵 A" ] }, { "cell_type": "code", "execution_count": 16, "id": "08d16cb0-a5cb-4b32-8f2e-fc8cf5f2a206", "metadata": {}, "outputs": [], "source": [ "B = np.array([[-1,-4,-7],\n", " [-2,-5,-8],\n", " [-3,-6,-9]]) # 定义方阵 B" ] }, { "cell_type": "markdown", "id": "ccad52d1-dc84-4b3c-a097-3380f3ec90a6", "metadata": {}, "source": [ "## A 的转置" ] }, { "cell_type": "code", "execution_count": 17, "id": "12e193cf-71e4-48b0-8cbb-cbcf3ccdbc6c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 4 7]\n", " [2 5 8]\n", " [3 6 9]]\n" ] } ], "source": [ "print(np.einsum('ji',A)) # 计算矩阵 A 的转置" ] }, { "cell_type": "markdown", "id": "1528a603-b271-4274-9f83-045fe64a99db", "metadata": {}, "source": [ "## A 的元素和" ] }, { "cell_type": "code", "execution_count": 18, "id": "2d6b2be7-e73a-46b1-9415-944930809770", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "45\n" ] } ], "source": [ "print(np.einsum('ij->',A)) # 计算矩阵 A 所有元素的和" ] }, { "cell_type": "markdown", "id": "257c86ae-4793-4f91-9bfc-6128b1c9aa01", "metadata": {}, "source": [ "## 按行求和" ] }, { "cell_type": "code", "execution_count": 19, "id": "7cef1bf8-aed8-4f0a-b97b-8758d33075da", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[12 15 18]\n" ] } ], "source": [ "print(np.einsum('ij->j',A)) # 计算矩阵 A 的每列的和" ] }, { "cell_type": "markdown", "id": "58267372-554b-4284-92c1-cee2453df11e", "metadata": {}, "source": [ "## 按列求和" ] }, { "cell_type": "code", "execution_count": 20, "id": "595287a8-6e24-408e-8552-aa7ecc6fc55f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 6 15 24]\n" ] } ], "source": [ "print(np.einsum('ij->i',A)) # 计算矩阵 A 的每行的和" ] }, { "cell_type": "markdown", "id": "d64a84cf-72a0-408d-b896-c3b88087dbf7", "metadata": {}, "source": [ "## 提取主对角线" ] }, { "cell_type": "code", "execution_count": 21, "id": "200ca6b1-c240-4d6d-a8c2-f3fd64763bea", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 5 9]\n" ] } ], "source": [ "print(np.einsum('ii->i',A)) # 提取矩阵 A 的主对角线元素" ] }, { "cell_type": "markdown", "id": "2b786c9a-5864-451f-906c-0f14253e5aad", "metadata": {}, "source": [ "## 计算矩阵 A 的迹" ] }, { "cell_type": "code", "execution_count": 22, "id": "9e3a19a5-0f54-4dfe-829c-be92fd12aa7b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "15\n" ] } ], "source": [ "print(np.einsum('ii->',A)) # 计算矩阵 A 的迹(主对角线元素的和)" ] }, { "cell_type": "markdown", "id": "05751e89-a555-438c-898a-bf925c4f66b4", "metadata": {}, "source": [ "## 矩阵 A 和 B 的乘积" ] }, { "cell_type": "code", "execution_count": 23, "id": "64413023-b87d-4a78-b275-cfd84e257fc4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ -14 -32 -50]\n", " [ -32 -77 -122]\n", " [ -50 -122 -194]]\n" ] } ], "source": [ "print(np.einsum('ij,jk->ik', A, B)) # 计算矩阵 A 和 B 的矩阵乘法" ] }, { "cell_type": "markdown", "id": "3af4c95f-aa69-49cb-a2ce-aab8772b09c4", "metadata": {}, "source": [ "## A 和 B 的矩阵乘积的所有元素和" ] }, { "cell_type": "code", "execution_count": 24, "id": "7c47a0c5-20af-4bb1-96e8-56c601115c6a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-693\n" ] } ], "source": [ "print(np.einsum('ij,jk->', A, B)) # 计算矩阵 A 和 B 的乘积矩阵的所有元素的和" ] }, { "cell_type": "markdown", "id": "a85f940b-b6bd-483e-8ddb-9cab6ee24ce0", "metadata": {}, "source": [ "## 矩阵相乘后转置" ] }, { "cell_type": "code", "execution_count": 25, "id": "56598ed4-fd7a-4f82-ab5b-573f72f966a2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ -14 -32 -50]\n", " [ -32 -77 -122]\n", " [ -50 -122 -194]]\n" ] } ], "source": [ "print(np.einsum('ij,jk->ki', A, B)) # 计算矩阵 A 和 B 的乘积后对结果转置" ] }, { "cell_type": "markdown", "id": "3ade29c2-f09c-420a-a4e4-ef3aba2aac18", "metadata": {}, "source": [ "## A 和 B 的逐元素乘积" ] }, { "cell_type": "code", "execution_count": 26, "id": "d5e5fe17-96cd-4c6d-8326-da9f6df6ac1f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ -1 -8 -21]\n", " [ -8 -25 -48]\n", " [-21 -48 -81]]\n" ] } ], "source": [ "print(np.einsum('ij,ij->ij', A, B)) # 计算矩阵 A 和 B 的逐元素乘积" ] }, { "cell_type": "code", "execution_count": null, "id": "85a80909-2aac-49ed-bb7a-f8cc6b80ee7d", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "ecd322f4-f919-4be2-adc3-69d28ef25e69", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.7" } }, "nbformat": 4, "nbformat_minor": 5 }