Skip to content

Commit 5cec660

Browse files
authored
Add files via upload
1 parent 79f58b5 commit 5cec660

16 files changed

+5703
-0
lines changed

LA_03_01_01.ipynb

+609
Large diffs are not rendered by default.

LA_03_01_02.ipynb

+320
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "407829a7-1d18-4263-8caf-d32a69660c00",
6+
"metadata": {},
7+
"source": [
8+
"Chapter 03\n",
9+
"\n",
10+
"# Python自定义函数计算矩阵乘法,内积视角\n",
11+
"《线性代数》 | 鸢尾花书:数学不难"
12+
]
13+
},
14+
{
15+
"cell_type": "markdown",
16+
"id": "48338225-feea-4d87-af1b-bb53e87d335b",
17+
"metadata": {},
18+
"source": [
19+
"这段代码实现的是**矩阵乘法**的几何解释与程序实现,特别强调了**第一视角**(即逐元素构造的视角),并通过 Python 中 `numpy` 模块中的数组操作来实现矩阵乘法的底层过程。下面从**数学角度**对这段代码进行详细解析,包含必要的数学公式,并解释各个步骤在数学中代表的含义。\n",
20+
"\n",
21+
"---\n",
22+
"\n",
23+
"### **1. 矩阵乘法的数学基础**\n",
24+
"\n",
25+
"设有两个矩阵 $A \\in \\mathbb{R}^{m \\times p}$ 和 $B \\in \\mathbb{R}^{p \\times n}$,那么它们的乘积 $C = AB$ 是一个 $m \\times n$ 的矩阵,其中第 $i$ 行第 $j$ 列元素 $C_{ij}$ 的计算方式是:\n",
26+
"\n",
27+
"$$\n",
28+
"C_{ij} = \\sum_{k=1}^{p} A_{ik} B_{kj}\n",
29+
"$$\n",
30+
"\n",
31+
"这就是矩阵乘法的核心定义。\n",
32+
"\n",
33+
"等价地,我们也可以将每个元素看作是:\n",
34+
"$$\n",
35+
"C_{ij} = \\text{dot}(A_{i,:}, B_{:,j})\n",
36+
"$$\n",
37+
"\n",
38+
"其中:\n",
39+
"- $A_{i,:}$ 是矩阵 $A$ 的第 $i$ 行(行向量)\n",
40+
"- $B_{:,j}$ 是矩阵 $B$ 的第 $j$ 列(列向量)\n",
41+
"\n",
42+
"它们的点积等价于上面的求和公式。\n",
43+
"\n",
44+
"---\n",
45+
"\n",
46+
"### **2. 代码功能解释**\n",
47+
"\n",
48+
"函数 `matrix_multiplication(A, B)` 实现了上述的数学过程:\n",
49+
"\n",
50+
"- 首先,它检查矩阵 $A$ 的列数是否等于矩阵 $B$ 的行数,即 $p_A = p_B$,这是矩阵乘法的基本条件。\n",
51+
"- 然后,它初始化一个零矩阵 $C \\in \\mathbb{R}^{m \\times n}$,用于存储结果。\n",
52+
"- 最后,通过两层循环,对每一个位置 $(i,j)$,取出 $A$ 的第 $i$ 行向量 $A_{i,:}$ 和 $B$ 的第 $j$ 列向量 $B_{:,j}$,并用 `np.dot()` 计算内积,即 $C_{ij}$。\n",
53+
"\n",
54+
"这种写法提供了“第一视角”的直观性:你可以看作每个元素 $C_{ij}$ 是通过对应的一行一列计算得来的,而不是整块矩阵乘起来的黑箱操作。\n",
55+
"\n",
56+
"---\n",
57+
"\n",
58+
"### **3. 示例分析**\n",
59+
"\n",
60+
"定义矩阵:\n",
61+
"$$\n",
62+
"A = \\begin{bmatrix}\n",
63+
"1 & 2 & 3 \\\\\n",
64+
"4 & 5 & 6\n",
65+
"\\end{bmatrix} \\in \\mathbb{R}^{2 \\times 3}\n",
66+
"$$\n",
67+
"\n",
68+
"其转置为:\n",
69+
"$$\n",
70+
"B = A^T = \\begin{bmatrix}\n",
71+
"1 & 4 \\\\\n",
72+
"2 & 5 \\\\\n",
73+
"3 & 6\n",
74+
"\\end{bmatrix} \\in \\mathbb{R}^{3 \\times 2}\n",
75+
"$$\n",
76+
"\n",
77+
"#### **计算 $AB$:**\n",
78+
"\n",
79+
"$A \\in \\mathbb{R}^{2 \\times 3}$,$B \\in \\mathbb{R}^{3 \\times 2}$,所以乘积 $C = AB \\in \\mathbb{R}^{2 \\times 2}$,每个元素计算如下:\n",
80+
"\n",
81+
"- $C_{11} = 1 \\cdot 1 + 2 \\cdot 2 + 3 \\cdot 3 = 1 + 4 + 9 = 14$\n",
82+
"- $C_{12} = 1 \\cdot 4 + 2 \\cdot 5 + 3 \\cdot 6 = 4 + 10 + 18 = 32$\n",
83+
"- $C_{21} = 4 \\cdot 1 + 5 \\cdot 2 + 6 \\cdot 3 = 4 + 10 + 18 = 32$\n",
84+
"- $C_{22} = 4 \\cdot 4 + 5 \\cdot 5 + 6 \\cdot 6 = 16 + 25 + 36 = 77$\n",
85+
"\n",
86+
"结果为:\n",
87+
"$$\n",
88+
"AB = \\begin{bmatrix}\n",
89+
"14 & 32 \\\\\n",
90+
"32 & 77\n",
91+
"\\end{bmatrix}\n",
92+
"$$\n",
93+
"\n",
94+
"#### **计算 $BA$:**\n",
95+
"\n",
96+
"$B \\in \\mathbb{R}^{3 \\times 2}$,$A \\in \\mathbb{R}^{2 \\times 3}$,所以乘积 $BA \\in \\mathbb{R}^{3 \\times 3}$,每个元素也是按内积逐一计算。\n",
97+
"\n",
98+
"比如第一个元素:\n",
99+
"- $C_{11} = 1 \\cdot 1 + 4 \\cdot 4 = 1 + 16 = 17$\n",
100+
"\n",
101+
"以此类推,可以手动验证其他元素,最终结果为:\n",
102+
"$$\n",
103+
"BA = \\begin{bmatrix}\n",
104+
"17 & 22 & 27 \\\\\n",
105+
"22 & 29 & 36 \\\\\n",
106+
"27 & 36 & 45\n",
107+
"\\end{bmatrix}\n",
108+
"$$\n",
109+
"\n",
110+
"---\n",
111+
"\n",
112+
"### **4. 总结**\n",
113+
"\n",
114+
"此函数从**线性代数中矩阵乘法的定义出发**,以编程方式逐一实现每个元素的计算。通过使用行向量和列向量的内积,本质上是在做**向量空间中的投影**操作,每个结果元素 $C_{ij}$ 都是 $A$ 的第 $i$ 行与 $B$ 的第 $j$ 列在 $p$ 维空间中的“相似度”或“相关性”。\n",
115+
"\n",
116+
"该函数虽然不如 NumPy 的 `np.matmul` 或 `@` 运算符高效,但在教学和理解上是极其直观和有价值的。"
117+
]
118+
},
119+
{
120+
"cell_type": "markdown",
121+
"id": "27df39fb-584e-478c-8cf5-380731df9bf9",
122+
"metadata": {},
123+
"source": [
124+
"## 初始化"
125+
]
126+
},
127+
{
128+
"cell_type": "code",
129+
"execution_count": 4,
130+
"id": "9280d771-240f-4618-99fc-4e302aad2fd7",
131+
"metadata": {},
132+
"outputs": [],
133+
"source": [
134+
"import numpy as np"
135+
]
136+
},
137+
{
138+
"cell_type": "markdown",
139+
"id": "48717815-46a7-46b3-b516-fa0cd8b4f67a",
140+
"metadata": {},
141+
"source": [
142+
"## 自定义函数,矩阵乘法第一视角"
143+
]
144+
},
145+
{
146+
"cell_type": "code",
147+
"execution_count": 6,
148+
"id": "8b609167-1523-4fbd-be50-50a8cffcb220",
149+
"metadata": {},
150+
"outputs": [],
151+
"source": [
152+
"def matrix_multiplication_inner(A, B):\n",
153+
" \n",
154+
" # 获取矩阵 A 和 B 的形状\n",
155+
" m, p_A = A.shape\n",
156+
" p_B, n = B.shape\n",
157+
"\n",
158+
" # 检测矩阵形状是否符合矩阵乘法规则\n",
159+
" if p_A != p_B:\n",
160+
" raise ValueError('Dimensions do not match')\n",
161+
"\n",
162+
" # 初始化结果矩阵 C,形状 (m, n),初始值设为 0\n",
163+
" C = np.zeros((m, n))\n",
164+
"\n",
165+
" # 计算每个元素\n",
166+
" for i in range(m):\n",
167+
" for j in range(n):\n",
168+
" row_i_A = A[i, :] # A 的第 i 行(行向量)\n",
169+
" col_j_B = B[:, j] # B 的第 j 列(列向量)\n",
170+
" C[i, j] = np.dot(row_i_A, col_j_B) # 计算内积\n",
171+
"\n",
172+
" return C"
173+
]
174+
},
175+
{
176+
"cell_type": "markdown",
177+
"id": "a491fe45-1b5a-465c-a0b2-86d6ea78f71a",
178+
"metadata": {},
179+
"source": [
180+
"## 矩阵乘法"
181+
]
182+
},
183+
{
184+
"cell_type": "code",
185+
"execution_count": 8,
186+
"id": "0669dd26-522c-4a22-894b-e6f5afb75159",
187+
"metadata": {},
188+
"outputs": [
189+
{
190+
"data": {
191+
"text/plain": [
192+
"array([[1, 2, 3],\n",
193+
" [4, 5, 6]])"
194+
]
195+
},
196+
"execution_count": 8,
197+
"metadata": {},
198+
"output_type": "execute_result"
199+
}
200+
],
201+
"source": [
202+
"A = np.array([[1, 2, 3],\n",
203+
" [4, 5, 6]])\n",
204+
"A"
205+
]
206+
},
207+
{
208+
"cell_type": "code",
209+
"execution_count": 9,
210+
"id": "c08b9706-5eb1-49f7-87b0-9f2eba3d9897",
211+
"metadata": {},
212+
"outputs": [
213+
{
214+
"data": {
215+
"text/plain": [
216+
"array([[1, 4],\n",
217+
" [2, 5],\n",
218+
" [3, 6]])"
219+
]
220+
},
221+
"execution_count": 9,
222+
"metadata": {},
223+
"output_type": "execute_result"
224+
}
225+
],
226+
"source": [
227+
"B = A.T\n",
228+
"B"
229+
]
230+
},
231+
{
232+
"cell_type": "markdown",
233+
"id": "50cb3105-4b7d-4388-b52e-8d5e758664f6",
234+
"metadata": {},
235+
"source": [
236+
"## 矩阵乘法"
237+
]
238+
},
239+
{
240+
"cell_type": "code",
241+
"execution_count": 11,
242+
"id": "10165623-315b-459a-9578-12bc191994e0",
243+
"metadata": {},
244+
"outputs": [
245+
{
246+
"data": {
247+
"text/plain": [
248+
"array([[14., 32.],\n",
249+
" [32., 77.]])"
250+
]
251+
},
252+
"execution_count": 11,
253+
"metadata": {},
254+
"output_type": "execute_result"
255+
}
256+
],
257+
"source": [
258+
"matrix_multiplication_inner(A, B)"
259+
]
260+
},
261+
{
262+
"cell_type": "code",
263+
"execution_count": 12,
264+
"id": "eed01818-da17-45f9-b9e7-22706d00f163",
265+
"metadata": {},
266+
"outputs": [
267+
{
268+
"data": {
269+
"text/plain": [
270+
"array([[17., 22., 27.],\n",
271+
" [22., 29., 36.],\n",
272+
" [27., 36., 45.]])"
273+
]
274+
},
275+
"execution_count": 12,
276+
"metadata": {},
277+
"output_type": "execute_result"
278+
}
279+
],
280+
"source": [
281+
"matrix_multiplication_inner(B, A)"
282+
]
283+
},
284+
{
285+
"cell_type": "markdown",
286+
"id": "b761edf5-05fd-46a0-8c46-1c849c1df004",
287+
"metadata": {},
288+
"source": [
289+
"作者\t**生姜DrGinger** \n",
290+
"脚本\t**生姜DrGinger** \n",
291+
"视频\t**崔崔CuiCui** \n",
292+
"开源资源\t[**GitHub**](https://github.com/Visualize-ML) \n",
293+
"平台\t[**油管**](https://www.youtube.com/@DrGinger_Jiang)\t\t\n",
294+
"\t\t[**iris小课堂**](https://space.bilibili.com/3546865719052873)\t\t\n",
295+
"\t\t[**生姜DrGinger**](https://space.bilibili.com/513194466) "
296+
]
297+
}
298+
],
299+
"metadata": {
300+
"kernelspec": {
301+
"display_name": "Python [conda env:base] *",
302+
"language": "python",
303+
"name": "conda-base-py"
304+
},
305+
"language_info": {
306+
"codemirror_mode": {
307+
"name": "ipython",
308+
"version": 3
309+
},
310+
"file_extension": ".py",
311+
"mimetype": "text/x-python",
312+
"name": "python",
313+
"nbconvert_exporter": "python",
314+
"pygments_lexer": "ipython3",
315+
"version": "3.12.7"
316+
}
317+
},
318+
"nbformat": 4,
319+
"nbformat_minor": 5
320+
}

LA_03_01_矩阵乘法第一视角.pdf

616 KB
Binary file not shown.

0 commit comments

Comments
 (0)