接下来介绍多重特征(multiple features)和向量化(vectorization)。


一、 多重特征

还记得在介绍房子的价格的时候,我们只将房子的大小作为衡量房子价格的标准。当时也声明了,现实中的房子价格会和许多其他因素相关。这里我列举出几个常见的其他因素:

影响因素 大小 距离市中心的距离 楼层 房子已开售时间
单位 平方米 1

我们这里就先列出四个相关的因素。我们知道,这些因素实际上就是我们的输入值,也就是特征
在这里,我们继续用线性回归的模型学习这些特征。我们上一节所提到的线性回归,是单一特征的线性回归,其模型与我们初中所学的一次函数形式相同:
fw,b(x)=wx+b f_{w,b}(x) = wx + b fw,b(x)=wx+b这是只有一个特征xxx(房子大小)的情况。现在,我们有了四个特征。我们分别用x1,x2,x3,x4x_1, x_2, x_3, x_4x1,x2,x3,x4分别代表房子大小、距离市中心距离、楼层、房子开售时间。显然这些变量有着不同的www,我们也用角标区分:w1,w2,w3,w4w_1,w_2,w_3,w_4w1,w2,w3,w4
如此我们的fw,b(x)f_{w,b}(x)fw,b(x)表示为:
fw1,w2,w3,w4,b(x)=w1x1+w2x2+w3x3+w4x4+b f_{w_1,w_2,w_3,w_4,b} (x)= w_1x_1+w_2x_2+w_3x_3+w_4x_4+b fw1,w2,w3,w4,b(x)=w1x1+w2x2+w3x3+w4x4+b这是有四个特征的情况。当有n个情况时,我们的模型则是:
fw1,w2,...,wn,b(x)=w1x1+w2x2+......+wnxn+b f_{w_1,w_2,...,w_n,b}(x)=w_1x_1+w_2x_2+......+w_nx_n+b fw1,w2,...,wn,b(x)=w1x1+w2x2+......+wnxn+b这里我们的处理思路是没有问题的,但是形式上看起来有些麻烦。难道我们真的要把每一项相乘然后加起来吗?如果我的n有100万呢?
于是我们采用了一种处理方法,称作向量化(vectorization)。


二、向量化

1. 引入介绍

首先说一下我对向量这个词的理解:
我们高中数学学的向量,多是二维向量 a⃗=(1,2)\vec a=(1,2)a =(1,2)
也学习了三维向量 a⃗=(1,2,3)\vec a=(1,2,3)a =(1,2,3)
它们分别在二维空间和三维空间中都代表着一个有实际方向的箭头。当一个箭头中有四个数据时,它就代表了一个四维空间的箭头。只是以我们人类的认知,无法直观感受和想象它的样子,因此线代中才会使用n维向量、n维空间这样抽象的词。
在这里,我们可以用一个n维向量x⃗\vec xx ,储存若干个特征,即:
x⃗=(x1,x2,x3,x4) \vec x = (x_1,x_2,x_3,x_4) x =(x1,x2,x3,x4)当我们特征量庞大到100万的时候,我们仍旧只要用一个向量即可表示它们的集体,而不用一个个列举。
同样,我们也应该用一个向量 w⃗\vec ww 表示它们的系数:
w⃗=(w1,w2,w3,w4) \vec w =(w_1,w_2,w_3,w_4) w =(w1,w2,w3,w4)不知是否还记得高中数学里向量的点积(dot product),它的定义是:
a⃗=(a1,a2)b⃗=(b1,b2)a⃗⋅b⃗=a1b1+a2b2 \vec a =(a_1,a_2) \\ \vec b = (b_1,b_2) \\ \vec a ·\vec b = a_1b_1+a_2b_2 a =(a1,a2)b =(b1,b2)a b =a1b1+a2b2点积得到的结果是一个数,而不再是向量。推广至多维向量,其运算也是一致的:
w⃗⋅x⃗=w1x1+w2x2+w3x3+w4x4 \vec w·\vec x = w_1x_1+w_2x_2+w_3x_3+w_4x_4 w x =w1x1+w2x2+w3x3+w4x4这样,哪怕我们的特征量有一百万,我们也可以将冗长的式子简化成上述精炼的形式。因此,我们可以将我们的模型修改为:
fw⃗,b=w⃗⋅x⃗+b f_{\vec w, b} = \vec w·\vec x + b fw ,b=w x +b 请注意不要忘记了两个向量是用点积连接的。当然,你可能想到这种写法简化:
fw,b=∑i=1nwixi+b f_{w,b} = \sum^n_{i=1} w_ix_i + b fw,b=i=1nwixi+b这也可以让我们的式子简化,但是它和向量化在机器学习领域还有很本质的区别,接下来我将讲述这两者的不同。


2. 向量化的作用

向量化的作用主要体现在程序上:
以Python语言为例,我们应该用数组来表示数据,同时,涉及到计算的时候,首先应引入numpy库:

import numpy as np

我们将数据用向量化表示,应该为:

w_vec = np.array([w_1, w_2, w_3, w_4])
x_vec = np.array([x_1, x_2, x_3, x_4])

在这里要注意,array先用一个“()”后,又用了一个“[ ]”括号;同时,这里要注意计算机的数组的索引是从0开始的,也就是说w_1用数组表示时,应该是w_vec[0]。
若我们的代码逻辑是下列计算公式的话:fw,b(x)=(∑n=1nwixi)+b f_{w,b} (x) = (\sum ^n_{n=1} w_ix_i) + b fw,b(x)=(n=1nwixi)+b则代码应该写成:

f = 0
for i in range(0,n)
	f += w_vec[i] * x_vec[i]
f += b

但是这样的话,我们的程序就要在循环中,依次进行n遍的计算。可如果我们改写成下列形式:

f = np.dot(w_vec, x_vec) + b

numpy的点积运算实际上执行的是下列过程:
在这里插入图片描述
也就是说,上述16个数据的运算,程序通过一步就完成了。这样能够大大减少运算所消耗的时间,尤其是当我们的特征量n是一个庞大的数字的时候,向量化节省时间的效果更加显著。


三、利用向量化实现多重特征的梯度下降运算

我们这里回顾单变量梯度下降的算法:
w=w−α∂∂wj(w,b)b=b−α∂∂bj(w,b) w = w - \alpha \frac{\partial}{\partial w}j(w,b) \\ b = b - \alpha \frac{\partial}{\partial b}j(w,b) w=wαwj(w,b)b=bαbj(w,b)选取一个较小的学习率α\alphaα,执行上述任务若干次,我们能从函数3D图的任何一个地方精准地到达谷底。
同样,成本函数也相对简单:
j(w,b)=12m∑i=1m(fw,b(x(i))−y(i))2 j(w,b) = \frac{1}{2m}\sum^m_{i=1} (f_{w,b}(x^{(i)})- y^{(i)})^2 j(w,b)=2m1i=1m(fw,b(x(i))y(i))2当特征量n≥2n \geq 2n2时,www 不再是单一的数字,而是一个向量w⃗\vec ww ,里面储存了多个www。然而,我们观察上述单变量梯度下降算法时,可发现上述算式实际上是个二元的算法,而不同的变量wwwbbb式子的区别,也仅仅是某些位置换了个变量而已。
同理可推出,当我们将www推广至w⃗\vec ww 时,我们将二维提升至多维,但是算法的结构没有改变,应该是如下表达:
w1=w1−α∂∂w1j(w⃗,b)w2=w2−α∂∂w2j(w⃗,b)......wn=wn−α∂∂wnj(w⃗,b)b=b−α∂∂bj(w⃗,b) w_1 = w_1 - \alpha \frac{\partial}{\partial w_1}j(\vec w,b) \\ w_2 = w_2 - \alpha \frac{\partial}{\partial w_2}j(\vec w,b) \\ ...... \\ w _n = w_n - \alpha \frac{\partial}{\partial w_n}j(\vec w,b) \\ b = b - \alpha \frac{\partial}{\partial b}j(\vec w,b) w1=w1αw1j(w ,b)w2=w2αw2j(w ,b)......wn=wnαwnj(w ,b)b=bαbj(w ,b)当然,用程序实现算法时,也要注意同时更新(simultaneously update)原则。即:

w_tmps = [] #初始化一个空数组
for i in range (0,n):
	w_tmp = w_vec[i] - a * partial(i, w_vec, x_vec,b) 
	w_tmps.append(w_tmp) # 将第i项计算结果加入到数组中
b_tmp = b - a * partial(-1, w_vec, x_vec,b) 
for i in range (0,n):
	w_vec[i] = w_tmp[i]
b = b_tmp
	# partial四个参数,i表示对w的第i项求偏导,w_vec和x_vec,b表示计算要用到的向量或数
	# i = -1表示对b求偏导

这样就可以实现多特征情况下的梯度下降

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐