
线性代数
从两个坐标,重新理解一个向量
看到一个向量的坐标 ,大家现在应该能够想到:从原点出发,向右移动
个单位,再向下移动
个单位。那么,这两个数字还能怎样理解?
这一篇,我们把坐标看成缩放两个基础向量的系数 。沿着这个想法继续往下,就能把线性组合、张成的空间、线性相关与无关,以及基联系起来。
前面在《向量究竟是什么》中,我们已经讲解了向量加法和数乘。接下来用到的操作,仍然是这两种,只是我们开始关心:改变数乘的系数之后,到底能够得到哪些向量?
文中的具体计算、Python 示例与配图为配套补充;本篇的向量分量和组合系数都取实数。
坐标,也是在告诉我们怎样缩放基向量
先看最熟悉的两个方向
我们先回到二维直角坐标系。这里有两个特别方便的向量:一个向右,长度为 ;另一个向上,长度也为
。
把它们分别记为:
它们合起来构成二维空间的标准基 。课程中也会使用 、
来表示这两个方向的单位向量。
现在,我们重新看向量 。数字
可以看成一个标量,把
伸长到原来的三倍;数字
则把
反向,并伸长到原来的两倍。
最后,把这两段位移相加:
这时候,坐标就不只是"横着走多少、竖着走多少",还可以理解成:第一个数缩放第一个基向量,第二个数缩放第二个基向量,然后把结果相加。
我们先把这个过程写成代码。新建 span_basis_demo.py,如果还没有安装依赖,先执行:
python
python3 -m pip install numpy
导入 NumPy,再创建标准基向量:
python
import numpy as np
e1 = np.array([1.0, 0.0])
e2 = np.array([0.0, 1.0])
p = 3 * e1 - 2 * e2
print("水平方向的位移:", 3 * e1)
print("竖直方向的位移:", -2 * e2)
print("相加得到的向量:", p)
运行代码,输出结果如下:
python
水平方向的位移: [3. 0.]
竖直方向的位移: [-0. -2.]
相加得到的向量: [ 3. -2.]
这里的 -0. 是浮点数运算中可能出现的负零,数值上仍然等于零,不表示额外的位移。
到这里,前面学习的坐标表示、向量数乘和向量加法,就组合成了同一个过程。
换一组基向量,坐标还一样吗?
接下来,我们不再只使用水平和竖直的两个单位向量,而是选择:
这两个向量同样可以作为二维空间的一组基。为什么它们符合要求,后面讲完张成和线性无关之后,我们再回来解释。
现在先观察,同一个 也可以写成:

图中左右两边使用相同的画图尺度,蓝色箭头的终点都在 。变化的是我们用来组合它的两个基础向量,以及相应的系数。
按照顺序,把新基记为 ,那么:
这里的 表示"向量
在基
下的坐标"。两个坐标列不同,但它们在各自的基下,描述的是同一个几何向量。
坐标依赖于选用的基,也依赖于基向量的排列顺序。 如果交换 和
,对应系数的顺序也需要交换。
我们继续在前面的程序中添加:
python
b1 = np.array([1.0, 1.0])
b2 = np.array([1.0, -1.0])
a, b = 0.5, 2.5
combined = a * b1 + b * b2
print("第一项:", a * b1)
print("第二项:", b * b2)
print("组合结果:", combined)
print("是否等于原向量:", np.allclose(combined, p))
输出结果:
python
第一项: [0.5 0.5]
第二项: [ 2.5 -2.5]
组合结果: [ 3. -2.]
是否等于原向量: True
这里 b1、b2 仍然存储它们在标准坐标系中的分量。代码先分别完成数乘,再把两个数组对应位置相加,所以 combined 得到的也是标准坐标。
np.allclose() 用来检查两个数值数组是否在给定容差内接近。当前系数恰好能够精确表示,后面遇到更一般的浮点数计算时,也适合用这种方式核对重建结果。
线性组合:分别缩放,然后相加
先把前面的操作写成一般形式
前面我们已经做了两次相同类型的事情:选择几个标量,分别缩放给定向量,再把结果相加。这个过程,就叫作这些向量的线性组合。
对于两个向量,写成:
这里 和
称为组合系数。它们可以是正数、负数,也可以是零,并不要求加起来等于
。
如果有更多向量,写法也一样:
大家先注意这个顺序:给定向量保持不变,改变的是它们前面的系数。 每选定一组系数,就得到一个具体的线性组合结果。
固定一个系数,会看到什么?
我们暂时固定 ,只改变
。这时候得到:
随着 在所有实数中变化,终点沿着一条与
平行的直线移动。在这个例子中,这条直线满足
。

图中只标出了几个终点作为示例,真实的系数可以连续变化,并不局限于整数。我们也可以运行下面的代码,先观察几个结果:
python
for coefficient in [-1, 0, 1, 2]:
endpoint = coefficient * b1 + b2
print(f"a = {coefficient:2d},终点:", endpoint)
输出结果:
python
a = -1,终点: [ 0. -2.]
a = 0,终点: [ 1. -1.]
a = 1,终点: [2. 0.]
a = 2,终点: [3. 1.]
这里还有一个区别需要提前说明:固定了一个系数得到的这条直线,不一定经过原点。 它只是全部线性组合中的一部分;后面所说的张成空间,需要让所有组合系数都自由变化。
张成的空间:所有可能结果组成的集合
从一个结果,变成一整组结果
如果每次只选择一组系数,我们得到的是一个向量。现在把所有可能的系数组合都考虑进去,就得到一个向量集合,也就是给定向量张成的空间 ,英文叫作 span。
对于前面的两个向量,定义为:
公式中的竖线可以读作"其中"。整句话就是:所有能够写成 ,且系数
都是实数的向量,组成的集合。
更一般地,张成空间包含给定向量的所有线性组合。这个定义也可以对照教材 Interactive Linear Algebra:Vector Equations and Spans 阅读。
所以,当我们问两个向量张成什么空间,其实是在问:只使用这两个向量,允许反复数乘和相加,最终能够到达哪些位置?
二维平面里,有三种情况
先看前面的 和
。它们不共线,改变两个系数,就能够得到平面中的任意向量。
这件事可以直接计算。假设我们想得到任意一个 ,那么需要:
只要选择:
就一定能够到达目标。因此,它们张成整个 。这里
表示所有实数二维向量组成的空间。
接下来,如果我们把第二个向量换成 ,会怎么样?
无论怎样选择 ,结果都只是
的倍数。两个向量的箭头共线,最终只能到达一条过原点的直线,无法离开这条线。
最后,如果给定的两个向量都是零向量,数乘和相加的结果也只能是零向量。

图中使用终点来代表从原点出发的向量,省去了大量重叠的箭头。左图的点只是有限采样,真实的张成空间包含点与点之间的所有位置,并向画面外无限延伸。
大家可以把这三种情况放在一起看:
| 给定的两个二维向量 | 张成的空间 | 空间的维数 |
|---|---|---|
| 不共线 | 整个二维平面 | 2 |
| 共线,且至少一个非零 | 一条过原点的直线 | 1 |
| 都是零向量 | 只有零向量 | 0 |
这里的维数,可以先理解为独立方向的个数,后面会用基给出正式解释。向量有几个分量、给定了几个向量、张成空间是几维,是三个不同的问题。
还可以检查一个始终成立的特点:把全部系数取为零,一定得到零向量。因此,张成空间一定包含原点。前面固定 得到的
,就不能直接当成这两个向量的张成空间。
三维空间里,增加一个向量能走得更远吗?
两个不共线的向量,先确定一个平面
我们把前面的想法放到三维空间中。选择两个三维向量:
它们的任意线性组合可以写成:
从结果可以看到,第三个分量始终等于前两个分量之和。也就是说,所有结果都落在平面 上。
反过来,这个平面中的任意一点,都能通过取 、
得到。因此,
和
张成的空间,就是这个过原点的平面。
它们都是三维向量,但它们张成的空间只有二维。 三个坐标分量是在描述向量所处的环境,并不意味着这两个向量已经提供了三个独立方向。
第三个向量在平面内,空间不变
现在增加一个向量:
它已经能够由前两个向量组合出来。于是,加入它之后,任意线性组合都可以重新整理成:
右边依然只是 和
的线性组合,结果仍然在原来的平面中。
所以,增加了第三个向量,并没有增加新的可达位置。它对于张成这个平面来说,是可以去掉的。
第三个向量在平面外,才能补上新的方向
我们换成另一个向量:
它不满足 ,所以不在前面的平面内。加入这个向量后:
现在,对于任意目标 ,只要取
、
、
,就能够得到它。
这一次,三个向量确实张成了整个 。

图中平面的边缘只是绘图范围,实际平面会无限延伸。右图中的几层平面,表示固定不同的 时,原平面沿
方向平移后的位置;让
连续取遍实数,才会扫过整个空间。
大家要注意,这里说的"新方向",是指不在已有向量张成的空间中 。只看箭头的朝向是否不同,还不够。前面的 ,
,
两两都不是倍数关系,但第三个仍然没有扩大张成空间。
线性相关与线性无关:有没有可以去掉的向量?
线性相关,表示组合中存在冗余
前面的 可以写成
,去掉它也不影响张成空间。我们就说,这一组向量线性相关。
对于有限个向量,线性相关意味着:至少有一个向量能够由其余向量线性组合出来。换句话说,至少可以移除一个向量,而不缩小它们张成的空间。
这里说的是"至少一个",不是任意一个都能去掉。比如 线性相关,但如果去掉
,原本的整个平面就会缩小为一条直线。
我们再用二维例子看一个更直接的影响。令:
那么,同一个向量 ,可以有两种写法:

这说明,把 都留下来,虽然仍然能张成平面,但表示同一个向量时,系数不再唯一。它们适合用来举例说明冗余,不能直接作为二维空间的一组基。
我们继续运行下面的代码:
python
r = b1 + b2
first = 1 * b1 + 1 * b2 + 0 * r
second = 0 * b1 + 0 * b2 + 1 * r
print("系数为 (1, 1, 0):", first)
print("系数为 (0, 0, 1):", second)
print("两种写法是否相同:", np.allclose(first, second))
输出结果:
python
系数为 (1, 1, 0): [2. 0.]
系数为 (0, 0, 1): [2. 0.]
两种写法是否相同: True
线性无关,表示每个向量都不可缺少
如果没有任何一个向量可以由其余向量线性组合出来,这组向量就称为线性无关。去掉其中任意一个,张成空间都会缩小。
把这个几何理解写成正式条件,就是考察:
如果只有 才能成立,这组向量线性无关。如果存在不全为零的系数,使结果等于零向量,就线性相关。
比如 ,系数为
,这就给出了前面那组向量线性相关的明确证据。
这里"不全为零"的意思是至少一个系数非零,不要求每个系数都非零。任何包含零向量的向量组,也一定线性相关:给零向量一个非零系数,其余系数取零,就满足了条件。
几何上的"存在冗余",与公式中的"存在非零系数关系",描述的是同一件事。正式定义和等价条件可以参考 Interactive Linear Algebra:Linear Independence。
使用代码,核对张成空间的维数
前面我们通过公式,已经说明了各组向量能张成什么空间。接下来,再用程序核对这些结果。
这里先借用一个后面会展开的概念:矩阵的秩。把给定向量分别放到矩阵的各列中,矩阵的秩就等于这些列向量张成空间的维数。
python
u = np.array([1.0, 0.0, 1.0])
v = np.array([0.0, 1.0, 1.0])
w = u + v
q = np.array([0.0, 0.0, 1.0])
groups = {
"二维:不共线": np.column_stack((b1, b2)),
"二维:共线": np.column_stack((b1, 2 * b1)),
"二维:全为零": np.zeros((2, 2)),
"三维:只有 u、v": np.column_stack((u, v)),
"三维:加入平面内的 w": np.column_stack((u, v, w)),
"三维:加入平面外的 q": np.column_stack((u, v, q)),
}
for name, matrix in groups.items():
print(f"{name},张成空间的维数:{np.linalg.matrix_rank(matrix)}")
输出结果:
python
二维:不共线,张成空间的维数:2
二维:共线,张成空间的维数:1
二维:全为零,张成空间的维数:0
三维:只有 u、v,张成空间的维数:2
三维:加入平面内的 w,张成空间的维数:2
三维:加入平面外的 q,张成空间的维数:3
np.column_stack() 把这些一维数组按列拼在一起。比如三个三维向量会得到一个形状为 (3, 3) 的矩阵;两个三维向量则得到 (3, 2)。
从结果可以看到,加入 后,向量个数变成了三个,秩仍然是
;换成平面外的
,秩才增加到
。
如果秩等于列数,说明这些列向量线性无关;如果小于列数,就存在冗余。秩与环境空间维数相等时,这些列向量才能张成整个环境空间。比如两个三维向量可以线性无关,但仍然无法张成整个三维空间。
对于浮点数组,matrix_rank() 通过奇异值与容差判断数值秩。接近线性相关的实际测量数据,结果可能受误差和容差影响,具体说明见 NumPy 官方文档。当前例子的关系已经在前面用公式明确给出,代码用来核对这些关系,不需要现在就掌握奇异值分解。
基:既能覆盖整个空间,又没有冗余
现在回到基的定义
前面我们先使用了"基"这个词,现在可以把正式定义补齐了:一个向量空间的一组基,是这个空间中一组线性无关、并且能够张成该空间的向量。 教材中的定义可以对照 Basis and Dimension 阅读。
这个定义包含两个条件:
| 条件 | 它解决什么问题? |
|---|---|
| 张成整个目标空间 | 空间中的每个向量,都能够表示出来 |
| 线性无关 | 表示同一个向量时,组合系数唯一 |
如果只有第一个条件,就可能像前面的 一样,虽然覆盖了平面,却保留了冗余。如果只有第二个条件,也不一定够,例如单独一个非零向量线性无关,但只能张成一条直线。
所以,判断一组向量是不是基,要先明确:我们准备描述的,到底是哪一个空间?
前面的 是平面
的一组基,因为它们能够覆盖这个平面,而且彼此独立。但它们不是整个
的基。它们虽然都有三个分量,描述这个平面中的向量时,却只需要两个组合系数。
一组基 中向量的个数,就称为该空间的维数。同一个有限维空间可以有不同的基,但每组基包含的向量个数相同。因此,平面的基包含两个向量,整个三维空间的基包含三个向量。
为什么坐标能够唯一确定?
我们用前面的二维基说明。假设同一个向量能用两组系数表示:
把两种表示相减,得到:
因为 线性无关,只有两个系数都为零才成立。因此
、
,两组系数其实完全相同。
张成保证能表示,线性无关保证只有一种表示。 给基向量固定顺序后,我们才得到一套既完整又明确的坐标系统。
基向量也不要求一定是单位长度,或者一定两两垂直。正交单位基计算起来很方便,但这并不是基的定义要求。例如 和
并不垂直,仍然可以构成二维空间的一组基。
已知向量,怎样求它在新基下的坐标?
前面我们直接给出了 和
两个系数。现在,我们反过来,让程序求出这组坐标。
按照顺序把两个基向量放在矩阵的列中:
如果新坐标记为 ,那么我们要解决的就是:
这里的矩阵乘法,正是在把矩阵各列按照 缩放后相加。暂时先把它和线性组合联系起来,下一篇再详细讲矩阵与空间变换。
继续在程序中添加:
python
B = np.column_stack((b1, b2))
coordinates = np.linalg.solve(B, p)
rebuilt = B @ coordinates
print("基向量按列组成的矩阵:")
print(B)
print("在新基下的坐标:", coordinates)
print("重建后的标准坐标:", rebuilt)
print("是否重建成功:", np.allclose(rebuilt, p))
输出结果:
python
基向量按列组成的矩阵:
[[ 1. 1.]
[ 1. -1.]]
在新基下的坐标: [0.5 2.5]
重建后的标准坐标: [ 3. -2.]
是否重建成功: True
这里 coordinates 存储的是新基下的组合系数;B @ coordinates 才是把这些系数与基向量组合起来,重新得到标准坐标。两种数组表示的意义不同,需要根据使用的基进行区分。
按照 NumPy 官方 solve 文档,这个接口用于求解方阵系数矩阵的线性方程组,矩阵需要非奇异。当前 的两列构成二维空间的一组基,符合要求。如果两列共线,就不能继续把它当成一组基,也不能指望
solve() 给出唯一坐标。
先检查能否张成,再检查有没有冗余
到这里,我们再遇到一组向量,就可以按这样的顺序去理解:先看它们的所有线性组合能到达哪里,再看有没有向量可以去掉。能够张成目标空间,又没有冗余,才是这个空间的一组基。
大家可以先做三个练习,再运行程序核对:
- 仍然使用
、
。向量
在这组有序基下的坐标是多少?
- 对于前面的
,判断
与
,哪一个在它们张成的空间里?
能否构成二维空间的一组基?去掉哪个向量后,剩下的两个仍然是一组基?
第一题的系数是 和
,也就是
。第二题可以检查
:前者在平面内,后者不在。第三题的三个向量线性相关,不能一起作为基;例如去掉
,保留
即可。
安装 NumPy 后,执行:
python3 examples/span_basis_demo.py
看结果时,试着把每组数字重新读成一句话:它们在缩放哪些向量?所有系数变化之后,能够覆盖哪一个空间?如果换一组基,同一个几何向量的坐标会怎样改变?
下一篇,我们继续学习线性变换与矩阵,看看这些基向量发生变化时,怎样决定整个空间的变化。
参考资料与配套内容
- 上一篇:线性代数 向量究竟是什么 。
- 系列开篇:线性代数 序言 。
- 教材补充:张成空间、线性无关、基与维数。
- 代码接口:NumPy matrix_rank、NumPy solve。