NumPy的应用-4
向量
向量(vector)也叫矢量,是一个同时具有大小和方向,且满足平行四边形法则的几何对象。与向量相对的概念叫标量或数量,标量只有大小,绝大多数情况下没有方向。我们通常用带箭头的线段来表示向量,在平面直角坐标系中的向量如下图所示。需要注意的是,向量是表达大小和方向的量,并没有规定起点和终点,所以相同的向量可以画在任意位置,例如下图中 w \small{\boldsymbol{w}} w 和 u \small{\boldsymbol{u}} u 两个向量并没有什么区别。
向量有很多种代数表示法,对于二维空间的向量,下面几种写法都是可以的。
a = ⟨ a 1 , a 2 ⟩ = ( a 1 , a 2 ) = ( a 1 a 2 ) = [ a 1 a 2 ] \boldsymbol{a} = \langle a_1, a_2 \rangle = (a_1, a_2) = \begin{pmatrix} a_1 \\\\ a_2 \end{pmatrix} = \begin{bmatrix} a_1 \\\\ a_2 \end{bmatrix} a=⟨a1,a2⟩=(a1,a2)= a1a2 = a1a2
向量的大小称为向量的模,它是一个标量,对于二维空间的向量,模可以通过下面的公式计算。
∣ a ∣ = a 1 2 + a 2 2 \lvert \boldsymbol{a} \rvert = \sqrt{a_{1}^{2} + a_{2}^{2}} ∣a∣=a12+a22
注意,这里的 ∣ a ∣ \small{\lvert \boldsymbol{a} \rvert} ∣a∣ 并不是绝对值,你可以将其称为向量 a \small{\boldsymbol{a}} a 的二范数,这是数学中的符号重用现象。上面的写法和概念也可以推广到 n \small{n} n 维空间,我们通常用 R n \small{\boldsymbol{R^{n}}} Rn 表示 n \small{n} n 维空间,我们刚才说的二维空间可以记为 R 2 \small{\boldsymbol{R^{2}}} R2 ,三维空间可以记为 R 3 \small{\boldsymbol{R^{3}}} R3 。虽然生活在三维空间的我们很难想象四维空间、五维空间是什么样子,但是这并不影响我们探讨高维空间,机器学习中,我们经常把有 n \small{n} n 个特征的训练样本称为一个 n \small{n} n 维向量。
向量的加法
相同维度的向量可以相加得到一个新的向量,运算的方法是将向量的每个分量相加,如下所示。
u = [ u 1 u 2 ⋮ u n ] , v = [ v 1 v 2 ⋮ v n ] , u + v = [ u 1 + v 1 u 2 + v 2 ⋮ u n + v n ] \boldsymbol{u} = \begin{bmatrix} u_1 \\\\ u_2 \\\\ \vdots \\\\ u_n \end{bmatrix}, \quad \boldsymbol{v} = \begin{bmatrix} v_1 \\\\ v_2 \\\\ \vdots \\\\ v_n \end{bmatrix}, \quad \boldsymbol{u} + \boldsymbol{v} = \begin{bmatrix} u_1 + v_1 \\\\ u_2 + v_2 \\\\ \vdots \\\\ u_n + v_n \end{bmatrix} u= u1u2⋮un ,v= v1v2⋮vn ,u+v= u1+v1u2+v2⋮un+vn
向量的加法满足“平行四边形法则”,即两个向量 u \small{\boldsymbol{u}} u 和 v \small{\boldsymbol{v}} v 构成了平行四边形的两条邻边,相加的结果是平行四边形的对角线,如下图所示。
向量的数乘
一个向量 v \small{\boldsymbol{v}} v 可以和一个标量 k \small{k} k 相乘,运算的方法是将向量中的每个分量与该标量相乘即可,如下所示。
v = [ v 1 v 2 ⋮ v n ] , k ⋅ v = [ k ⋅ v 1 k ⋅ v 2 ⋮ k ⋅ v n ] \boldsymbol{v} = \begin{bmatrix} v_1 \\\\ v_2 \\\\ \vdots \\\\ v_n \end{bmatrix}, \quad k \cdot \boldsymbol{v} = \begin{bmatrix} k \cdot v_1 \\\\ k \cdot v_2 \\\\ \vdots \\\\ k \cdot v_n \end{bmatrix} v= v1v2⋮vn ,k⋅v= k⋅v1k⋅v2⋮k⋅vn
我们可以用 NumPy 的数组来表示向量,向量的加法可以通过两个数组的加法来实现,向量的数乘可以通过数组和标量的乘法来实现,此处不再进行赘述。
向量的点积
点积(dot product)是两个向量之间最为重要的运算之一,运算的方法是将两个向量对应分量的乘积求和,所以点积的结果是一个标量,其几何意义是两个向量的模乘以二者夹角的余弦如下所示。
u = [ u 1 u 2 ⋮ u n ] , v = [ v 1 v 2 ⋮ v n ] \boldsymbol{u} = \begin{bmatrix} u_1 \\\\ u_2 \\\\ \vdots \\\\ u_n \end{bmatrix}, \quad \boldsymbol{v} = \begin{bmatrix} v_1 \\\\ v_2 \\\\ \vdots \\\\ v_n \end{bmatrix} \quad u= u1u2⋮un ,v= v1v2⋮vn
u ⋅ v = ∑ i = 1 n u i v i = ∣ u ∣ ∣ v ∣ c o s θ \boldsymbol{u} \cdot \boldsymbol{v} = \sum_{i=1}^{n}{u_iv_i} = \lvert \boldsymbol{u} \rvert \lvert \boldsymbol{v} \rvert cos\theta u⋅v=i=1∑nuivi=∣u∣∣v∣cosθ
假如我们用三维向量来表示用户对喜剧片、言情片和动作片这三类电影的偏好,我们用 1 到 5 的数字来表示喜欢的程度,其中 5 表示非常喜欢,4 表示比较喜欢,3 表示无感,2 表示比较反感,1 表示特别反感。那么,下面的向量表示用户非常喜欢喜剧片,特别反感言情片,对动作片不喜欢也不反感。
u = ( 5 1 3 ) \boldsymbol{u} = \begin{pmatrix} 5 \\\\ 1 \\\\ 3 \end{pmatrix} u= 513
现在有两部电影上映了,一部属于言情喜剧片,一部属于喜剧动作片,我们把两部电影也通过3维向量的方式进行表示,如下所示。
m 1 = ( 4 5 1 ) , m 2 = ( 5 1 5 ) \boldsymbol{m_1} = \begin{pmatrix} 4 \\\\ 5 \\\\ 1 \end{pmatrix}, \quad \boldsymbol{m_2} = \begin{pmatrix} 5 \\\\ 1 \\\\ 5 \end{pmatrix} m1= 451 ,m2= 515
如果现在我们需要向刚才的用户推荐一部电影,我们应该给他推荐哪一部呢?我们可以将代表用户的向量 u \small{\boldsymbol{u}} u 和代表电影的向量 m 1 \small{\boldsymbol{m_{1}}} m1 和 m 2 \small{\boldsymbol{m_{2}}} m2 分别进行点积运算,再除以向量的模长,得到向量夹角的余弦值,余弦值越接近 1,说明向量的夹角越接近 0 度,也就是两个向量的相似度越高。很显然,我们应该向用户推荐跟他观影喜好相似度更高的电影。
c o s θ 1 = u ⋅ m 1 ∣ u ∣ ∣ m 1 ∣ ≈ 4 × 5 + 5 × 1 + 3 × 1 5.92 × 6.48 ≈ 0.73 cos\theta_1 = \frac{\boldsymbol{u} \cdot \boldsymbol{m1}}{|\boldsymbol{u}||\boldsymbol{m1}|} \approx \frac{4 \times 5 + 5 \times 1 + 3 \times 1}{5.92 \times 6.48} \approx 0.73 cosθ1=∣u∣∣m1∣u⋅m1≈5.92×6.484×5+5×1+3×1≈0.73
c o s θ 2 = u ⋅ m 2 ∣ u ∣ ∣ m 2 ∣ ≈ 5 × 5 + 1 × 1 + 3 × 5 5.92 × 7.14 ≈ 0.97 cos\theta_2 = \frac{\boldsymbol{u} \cdot \boldsymbol{m2}}{|\boldsymbol{u}||\boldsymbol{m2}|} \approx \frac{5 \times 5 + 1 \times 1 + 3 \times 5}{5.92 \times 7.14} \approx 0.97 cosθ2=∣u∣∣m2∣u⋅m2≈5.92×7.145×5+1×1+3×5≈0.97
大家可能会说,向量 m 2 \small{\boldsymbol{m_{2}}} m2 代表的电影肉眼可见跟用户是更加匹配的。的确,对于一个三维向量我们凭借直觉也能够给出正确的答案,但是对于一个 n \small{n} n 维向量,当 n \small{n} n 的值非常大时,你还有信心凭借肉眼的观察和本能的直觉给出准确的答案吗?向量的点积可以通过dot
函数来计算,而向量的模长可以通过 NumPy 的linalg
模块中的norm
函数来计算,代码如下所示。
u = np.array([5, 1, 3])
m1 = np.array([4, 5, 1])
m2 = np.array([5, 1, 5])
print(np.dot(u, m1) / (np.l