线性代数是处理向量空间的数学分支,在这里我会详细讲解在本章节中使用到的线性代数知识,它会始终贯穿到章节中。
Vectors(向量)
vectors可以与另外的vectors相加形成新的vectors,同时vectors也可以与某个常值相乘形成另外的vectors。
具体来讲,vectors是在有限维度空间里聚集的一些点,它们是一个很好的方法表示数值型数据。
例如,如果你有一些人的身高、体重和年龄的数据,你可以把你的数据看成是三维向量(身高,体重,年龄);如果你正在教一门课程,你可以把你的学生的成绩分成4个等级,形成4个维度的向量(exam1,exam2,exam3,exam4)。
在python中向量是怎么表示的呢?最简单的方法把list容器里的数字看成vectors,3个数字的list对应于3个维度空间的vector:
height_weight_age = [70, # inches,
170, # pounds,
40 ] # years
这种表示方法有个问题就是Python的list容器没有关于vectors的算数运算,所以我们自己建立了算数工具,现在让我们开始做这个。
首先是两个vectors相加,前提条件是vectors v 和vectors w 有相同的长度,相加的意思就是他们的第一个元素v[0]+w[0],他们第二个元素是v[1]+w[1],等等。(如果他们没有相同的长度是不被允许相加的。)
例如,vectors [1,2]和vectors[2,1]相加,结果是[3,3],如下图所示:
我们可以通过zip把2个vectors结合在一起,使用list容器的for理解功能把对应的元素相加:
def vector_add(v, w):
"""adds corresponding elements"""
return [v_i + w_i
for v_i, w_i in zip(v, w)]
类似的,两个vectors相减就是对应的元素相减:
def vector_subtract(v, w):
"""subtracts corresponding elements"""
return [v_i - w_i
for v_i, w_i in zip(v, w)]
我们有的时候需要把若干个vectors相加,即创建一个vector,它的第一个元素是所有vectors的第一个元素的和,它的第二元素是所有vectors的第二个元素的和,等等。最简单的做法就是在同一时刻只对2个vectors进行相加:
def vector_sum(vectors):
"""sums all corresponding elements"""
result = vectors[0]
for vector in vectors[1:]:
result = vector_add(result, vector)
return result
如果你仔细思考一下,你就会发现我们其实是在使用vector_add函数减少vectors的数量,这个就意味着我们可以使用高阶函数更加简洁的重写这个功能:
def vector_sum(vectors):
return reduce(vector_add, vectors)
或者使用偏函数(属于函数式编程的思维):
vector_sum = partial(reduce, vector_add)
我们需要vector乘以一个常值,我们可以简单的把vector里的每个元素乘以常值:
def scalar_multiply(c, v):
"""c is a number, v is a vector"""
return [c * v_i for v_i in v]
这个允许我们计算具有相同大小vectors集合的均值:
def vector_mean(vectors):
"""compute the vector whose ith element is the mean of the
ith elements of the input vectors"""
n = len(vectors)
return scalar_multiply(1/n, vector_sum(vectors))
很显然还缺少点乘,就是2个vectors对应元素相乘后再相加得到一个常值:
def dot(v, w):
"""v_1 * w_1 + ... + v_n * w_n"""
return sum(v_i * w_i
for v_i, w_i in zip(v, w))
点乘测量的是vector v与vector w的相似程度,如果w与v在一条直线上那么是最相似的,其点值最大,垂直时点值最小,最不相似。
使用下面代码很容易计算vector的平方和:
def sum_of_squares(v):
"""v_1 * v_1 + ... + v_n * v_n"""
return dot(v, v)
我们能使用上面公式计算vector的幅度(或者长度):
import math
def magnitude(v):
return math.sqrt(sum_of_squares(v)) # math.sqrt is square root function
我们现在要计算2个vectors的距离,定义如下:
def squared_distance(v, w):
"""(v_1 - w_1) ** 2 + ... + (v_n - w_n) ** 2"""
return sum_of_squares(vector_subtract(v, w))
def distance(v, w):
return math.sqrt(squared_distance(v, w))
我们还有一种更加聪明的写法(与上面等价):
def distance(v, w):
return magnitude(vector_subtract(v, w))
下面一节我将要介绍线性代数的矩阵操作。