第4章 基本的数学知识
第4章 基本的数学知识
[toc]
4.2.1 向量和矩阵
向量(vector)指既有大小又有方向的对象。对我们而言,向量是用来表示一系列数字的一维数组。换句话说,向量是一个由数字构成的列表。
向量通常用箭头或者粗体字表示,如下所示:
$\vec{x}$ 或 x
向量可以被拆分为更小粒度,即向量中包含的数字。我们用索引标示法表示向量中的元素,如下所示:
当$\vec{x}$ =$$
\left(
\begin{matrix}
3 \
6 \
8
\end{matrix}
\right) \tag{1}
$$时,$x_1$=3
在数学中,我们通常用索引1表示第1个元素。计算机程序则通常用索引0表示第1个元素
在Python中,我们有多种方式表示数组。例如可以用Python的列表表示前面的数组:
1 | x=[3,6,8] |
然而,我建议最好用numpy中的数组类型表示数组,因为它能提供更多的向量运算功能。
1 | import numpy as np |
不管在Python中以何种方式表示向量,向量都为我们提供了一种存储多维单一数据点或观察值的简单方法。
假设我们用0~100表示员工对每个部门的平均满意度,其中人力资源部得分57,工程部得分89,管理部得分94。
我们可以用以下向量表示这一组数据:
x=$$
\left(
\begin{matrix}
x_1 \
x_2 \
x_3
\end{matrix}
\right) \tag{1}$$=$$
\left(
\begin{matrix}
57 \
89 \
94
\end{matrix}
\right) \tag{1}$$
这个向量存储了3个不同的信息,这正是向量在数据科学中的重要用途。
理论上,你也可以将向量想象成Pandas中的Series对象。所以,我们很自然地联想到DataFrame对象。事实上,以上向量只需简单扩展,就可以由一维扩展为多维。
矩阵(matrix)是二维数组的表示形式。矩阵有两个特征需要特别关注。矩阵的维度用n×m表示,即矩阵有n行m列。矩阵通常用大写符合、加粗斜体字表示,比如大写X。例如下面这个矩阵:
$$
\left(
\begin{matrix}
3 & 4 \
8 & 55 \
5 & 9
\end{matrix}
\right)
$$
它有3行2列,所以是3×2矩阵。
如果矩阵的行数和列数相等,则称之为正方形矩阵(square matrix),简称方阵。
矩阵通常用来存储结构化数据,它是Pandas中DataFrame类型的泛化。因此,矩阵是数据科学工具箱中最重要的数学工具。
继续之前的案例,假设有3个位于不同地点的办公室,每个办公室都有人力资源部、工程部和管理部。我们可以用3个向量分别表示以上3个办公室3个部门的满意度得分,如下所示:
x=$$
\left(
\begin{matrix}
57 \
89 \
94
\end{matrix}
\right)$$,y=$$
\left(
\begin{matrix}
67 \
87 \
84
\end{matrix}
\right)$$,z=$$
\left(
\begin{matrix}
65 \
98 \
60
\end{matrix}
\right)$$
然而,这样的表示方式不但难以处理,而且不具有扩展性。如果我们有100个办公室,就需要100个不同的数组存储信息。矩阵恰好能解决这一问题。我们可以创建一个3×3矩阵,每一行代表不同的部门,每一列代表不同的办公室。
办公室1 | 办公室2 | 办公室3 | |
---|---|---|---|
人力资源部 | 57 | 67 | 65 |
工程部 | 89 | 87 | 98 |
管理部 | 94 | 84 | 60 |
这样看起来更加自然。我们去掉行标签和列标签之后,剩下的数字就组成了一个真正的矩阵。
X=$$
\begin{pmatrix}
57 & 67 & 65 \
89 & 87 & 98 \
94 & 84 & 60
\end{pmatrix}$$
快速练习
(1)如果增加第4个办公室,矩阵需要增加1行,还是增加1列?
(2)增加第4个办公室后,矩阵的维度是多少?
(3)如果在最初的矩阵X中去除“管理部”的数据,新矩阵的维度是什么?
(4)计算矩阵所含元素数量的通用公式是什么?
答案
(1)增加1列。
(2)3×4
(3)2×3
(4)n×m,其中n为矩阵行数,m为矩阵列数。
4.2.2 算术符号
点积
点积(dot product)是类似于加法和乘法的运算符,通常用来合并两个向量,如下所示:
$$
\begin{pmatrix}
3\
7
\end{pmatrix}
·
\begin{pmatrix}
9\
5
\end{pmatrix}=3×9+7×5=62
$$
点积的结果是一个单一的数值,称为标量(scalar)。
这有何用途呢?假设我们用向量表示用户对喜剧、言情剧和动作片3种不同类型电影的喜欢程度,取值范围1~5。
假设某用户喜欢喜剧,不喜欢言情剧,对动作片不喜欢也不讨厌,那么用向量表示如下:
$$
\begin{pmatrix}
5\
1\
3
\end{pmatrix}
$$
其中:
- 5表示喜欢喜剧;
- 1表示不喜欢言情剧;
- 3表示不喜欢也不讨厌动作片。
现在,假设有两部电影,一部是言情喜剧片,一部是喜剧动作片。每部电影同样有自己的特征向量,如下所示:
$$m_1$$=$$
\left(
\begin{matrix}
4 \
5 \
1
\end{matrix}
\right)$$,$$m_2$$=$$
\left(
\begin{matrix}
5 \
1 \
5
\end{matrix}
\right)$$
其中,$m_1$是言情喜剧片,$m_2$是喜剧动作片。
为了决定向用户推荐哪部电影,我们使用点积将用户的偏好向量和每部电影的特征向量相乘,乘积最高的电影将被推荐给用户。
4.2.3 图表
斜率
斜率=m=$ {y_2-y_1 \over x_2-x_1} $
斜率指两点之间的变化比率(rate of change)。变化比率在数据科学种非常重要,特别是在涉及微分方程和微积分运算时。
变化比率是表示变量如何同时变化,以及变化程度的指标。假设我们为咖啡温度和时间建模,得到的变化比率是:
$- {2℉ \over 1min} $
这个变化比率指咖啡温度每分钟下降2℉。
4.2.4 指数/对数
指数(exponent)指数字和自身相乘的次数。
$$2^4$$=2 · 2 · 2 · 2=16
2是底数,4是指数
对数(logarithm)则用于回答“以A数为底(base)得到B的指数是多少?”
$\log_2(16)$=4
2是底数,4是对数
如果你发现这两个概念非常接近,那就对了!事实上,对数和指数高度相关,对数即指数。以上两个公式是同一个事物的两种表示方式,其核心思想是2×2×2×2=16。
另外,对数和指数在计算增长率时也特别有用。大部分时候,指数和对数可以帮助我们对数量的增长趋势进行建模。
常数e约等于2.718,它在实践中具有很强的实用性。最常见的例子是计算资金的增长情况。假设银行账户有5000美元,以年化利率3%进行增长。我们使用以下公式对存款余额进行建模:
$$
A=Pe^{rt}
$$
其中:
- A为最终的存款金额;
- P为初始投资金额(5000美元);
- e为常数(2.718);
- r为年化增长率(0.03);
- t为时间(单位:年)。
我们非常好奇账户余额需要多长时间才能翻倍?用公式表示如下:
$$
10000=5000e^{0.03t}
$$
等价于求解:
$$
2=e^{0.03t}(两边都除以5000)
$$
4.2.5 集合论
集合论(set theory)指面向集合对象的数学运算,它被认为是其他数学原理和定理的根基之一。对我们而言,集合论主要用来处理包含大量元素的群体。
集合是由一组不重复对象构成的群体,仅此而已!集合可以被看作Python中的列表,但不含重复对象。事实上,在Python中甚至有专门的set对象。
1 | s=set() |
在Python中,花括号{}既可以指集合(set),也可以指字典(dictionary)。字典由键和键值成对组成,比如:
1 | dict={"dog":"human's best friend","cat":"destroyer of world"} |
字典和集合共用同样的符号,是因为它们具有同样的特性:集合不可以用重复项,正如字典不可以有重复键一样。
集合的大小(magnitude)是一个描述集合所含元素数量的值,表示方式为:|A|=A的大小
1 | s #=={1,2,3} |
集合可以为空,用符号Ø表示。空集的大小为零。
我们使用符号∈表示某个元素包含在集合中,如下所示:
$$
2∈{1,2,3}
$$
2包含在由1、2和3组成的集合中。如果一个集合包含在另一个集合中,我们称第1个集合是第2集合的子集。
$$
A={1,5,6},B={1,5,6,7,8}
\
A\subseteq B
$$
A是B的子集,B是A的超集。如果A是B的子集且A不等于B(即B中至少有一个元素不包含在A中),那么A是B的真子集。以下是集合的例子:
- 偶数集合是整数集合的子集;
- 每个集合都是自身的子集,但不是真子集;
- 由所有推文构成的集合是由所有英文推文构成集合的超集。
在数据科学中,我们用集合(或者列表)表示一系列对象,很多时候用来归纳用户的行为。事实上,这种方式非常常见。
假设一家营销公司想预测客户将购买哪个品牌的衣服。我们有客户历史上购买衣服的品牌信息,我们的目标是预测该客户会喜欢的新品牌。假设1个客户曾购买过Target、Banana Republic和Old Navy,在Python中表示如下:
1 | user1={"Target","Banana Republic","Old Navy"} |
请注意,我们在以上代码中使用{}符号创建一个集合,而不是用[]符号创建一个列表。
第2个客户购买过的品牌有:
1 | user2={"Banana Republic","Gap","Kohl's"} |
我们希望知道这两个客户的相似程度。根据目前有限的信息,我们可以将相似性定义为两个客户都购买过的品牌有哪些,这被称为交集(intersection)。
两个集合的交集指由同时出现在两个集合中的元素组成的集合,用符号$$\cap$$表示,如下所示:
$$
user1 \cap user2={Banana Republic}
\
|user1 \cap user2|=1
$$
以上两个用户的交集只有1个,看起来好像并不是特别棒。但是,考虑到每个集合仅有3个元素,1/3的相似度似乎也并不坏。
如果我们想知道两个客户总共购买过的品牌有哪些,这称之为并集(union)。
两个集合的并集指由两个集合中所有元素组成的集合,用符号$$\cup$$表示,如下所示:
$$
user1 \cup user2={Banana\ Republic,Target,Old\ Navy,Gap,Kohl’s}
\
|user1 \cup user2|=5
$$
当我们计算user1和user2的相似度时,应同时使用交集和并集。user1和user2的交集有1个元素,并集有5个元素。所以,我们可以定义两者的相似度为:
$$
{|user1 \cap user2|\over|user1 \cup user2|}={1\over5}=0.2
$$
事实上,在集合理论中它有一个正式的名字,叫杰卡德相似度(jaccard similarity)。
对于集合A和B,两者的杰卡德相似度为:
$$
JS(A,B)={|A \cap B|\over|A \cup B|}
$$
从以上公式不难发现,杰卡德相似度也可以被定义为交集的大小除以并集的大小。
杰卡德相似度为我们提供了一种量化集合相似性的方法。
根据直觉,我们推测杰卡德相似度的值介于0~1,当相似度接近0时表示几乎没有共性,当相似度接近1时表示客户相似性最高。如果我们仔细考虑一下它的定义,这个推测就显得更加合理:
$$
JS(A,B)={两个客户都买过的品牌数量\over两个客户总共买过的品牌数量}
$$
以上内容在Python中表示如下:
1 | user1={"Target","Banana Republic","Old Navy"} |
当我们开始学习概率论处理多维数据时,集合论的应用将越来越广泛。我们使用集合表示现实世界发生的各种事件。
4.3 线性代数
还记得之前的电影推荐引擎吗?如果我们要从10000部电影中选出10部推荐给用户,需要怎么办呢?我们需要将每个用户的简历和10000部电影分别计算点积。线性代数(linear algebra)为我们提供了更高效的计算工具。
线性代数是计算矩阵和向量的一个数学分支。它通过对计算对象进行分解和重构,增强了实用性。下面我们介绍几个线性代数的处理规则。
矩阵乘积
和数值乘积类似,我们也可以对矩阵进行乘积运算。本质上,矩阵乘积是同时进行大量点积运算的过程。以下面这两个矩阵乘积为例:
$$
\begin{pmatrix}
1 & 5\
5 & 8\
7 & 8
\end{pmatrix}·
\begin{pmatrix}
3 & 4\
2 & 5 \
\end{pmatrix}
$$
需要注意的是:
- 矩阵乘积不支持交换律,矩阵相乘的顺序影响着最终结果,这一点和数值乘积有所区别。
- 为了对矩阵进行乘积,矩阵的维度必须匹配。第1个矩阵的列数必须和第2个矩阵的行数一致。
矩阵如何相乘
本质上,矩阵乘积是进行一系列点积的过程。有一个简单的方法计算矩阵乘积。回到之前的例子:
$$
\begin{pmatrix}
1 & 5\
5 & 8\
7 & 8
\end{pmatrix}·
\begin{pmatrix}
3 & 4\
2 & 5 \
\end{pmatrix}
$$
我们已经知道矩阵乘积的结果是一个3×2的新矩阵,新矩阵的样子如下:
$$
\begin{pmatrix}
m_{11} & m_{12} \
m_{21} & m_{22} \
m_{31} & m_{32}
\end{pmatrix}
$$
请注意,新矩阵的每个元素都有下标,第1个数字表示行号,第2个数字表示列号。$$m_{32}$$指第3行第2列的元素。
新矩阵的每个元素都是原矩阵对应行和列的点积。比如$m_{xy}$是第1个矩阵x行和第2个矩阵y列的点积,如下所示:
$$
m_{11}=(1,5)·\begin{pmatrix}
3\
2\
\end{pmatrix}=13
\
m_{12}=(1,5)·\begin{pmatrix}
4\
5\
\end{pmatrix}=29
$$
以此类推,我们将得到乘积后的新矩阵:
$$
\begin{pmatrix}
13 & 29\
31 & 60\
37 & 68\
\end{pmatrix}
$$
回到电影推荐的案例。我们已经知道用户对喜剧、言情剧和动作片的偏好是:
$$
U=用户偏好=\begin{pmatrix}
5\
1\
3
\end{pmatrix}
$$
假设我们有10000部电影,每部电影都有喜剧、言情剧和动作片3个特征值。为了给用户推荐电影,我们需要将用户的偏好向量和10000部电影的特征向量进行乘积。我们可以用矩阵乘积表示。
我们用矩阵符号表示以上矩阵,而不是将10000个矩阵都列出来。我们已经有了表示用户偏好的向量U(可以被看作3×1矩阵),以及所有电影组成的3×10000维度的矩阵:
$$
M=3×10000维度矩阵
$$
现在,我们有两个矩阵:一个是3×1,另一个是3×10000。由于这两个矩阵维度不满足相乘条件,所以无法直接相乘。我们需要对矩阵U进行转置(transpose),即行转为列,列转为行。转置后的新矩阵如下:
$$
U^T=U的转置=(5,1,3)
$$
下面在Python中完成以上内容。
1 | import numpy as np |
我们使用numpy模块的array函数创建矩阵,user_pref和movies是我们得到的数据。我们使用numpy模块的shape方法检查矩阵的维度,如下所示:
1 | print(user_pref.shape) #(1,3) |
矩阵维度正确。下面我们继续使用numpy模块计算两个矩阵的乘积:
1 | #np.dot does both dot products and matrix multiplication |
计算结果是一个由整数组成的数组,每一个值表示对应电影的推荐指数。
下面我们对本例进行扩展,计算推荐超过10000部电影所需的时间。
1 | import time |
我在jupyter notebook上的运行结果如下
1 | 0.0 seconds to run 10000 movies |