多变量线性回归

目录

1  多元线性回归的模型形式

2  向量化

3 多元梯度下降法

2.1  特征缩放

2.2  学习率

4  特征工程


1  多元线性回归的模型形式

        在之前我们研究过的线性回归中,我们只有一个单一特征量----房屋面积x,我们希望用这个特征量来预测房价y ,假设函数是f_{w,b }(x)=wx+b

        但是现在,我们不仅有房屋面积作为预测房价的一个特征,我们还知道房间数、楼层数以及房子的年代等等,这给了我们更多的信息用来预测房价,我们用变量x1,x2,x3,x4来表示这四个特征,y表示预测的房价。

现在先引入一些概念: 

        n  --------  特征量的数目,在这个例子中,n=4

        x^{(i)}  -----  第i个训练样本的输入特征值,例如x^{(2)}表示第二个训练样本的特征向量,也就是x^{(2)}=\begin{bmatrix}1416 \\ 3 \\ 2 \\ 40 \end{bmatrix},这四个数字对应了用来预测房价的四个特征,x^{(i)}表示一个向量。

        {x_{j}}^{(i)}  ------  第i个训练样本中第j个特征量的值,例如{x_{3}}^{(2)}表示第2个训练样本中的第3个特征量的值,所以{x_{3}}^{(2)}=2

        现在我们有了多个特征,让我们来看看模型是什么样子的?

        以前,我们是这样定义模型的:f_{w,b }(x)=wx+b,其中x是一个单一特征。现在,我们增加了几个特征,模型是:f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}+w _{3}x_{3}+w _{4}x_{4}+b。举个具体的例子:在我们设置的参数中,我们可能有f_{w,b}(x)=0.1x_{1}+4x_{2}+10x_{3}-2x_{4}+80

        我们思考一下,可以怎么解释模型的参数。如果模型试图预测房价,单位为千美元,b=80可以解释为一栋房子的基础价格是8万美元;w_{1}=0.1表示每增加一平方英尺,价格增加100美元;w_{2}=4表示每增加一间浴室,价格增加4000美元;w_{3}=10,每增加一层楼层,价格增加1万美元;w_{4}=-2表示房龄每增加一年,价格减少2000美元。

        具有n个特征的模型定义为:f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}+...+w _{n}x_{n}+b

        把参数w写成一个向量形式:\mathbf{w}=\begin{bmatrix}w_{1} \\ w_{2} \\ . \\ . \\ w_{n} \end{bmatrix};特征x也写成向量形式:\mathbf{x}=\begin{bmatrix}x_{1} \\ x_{2} \\ . \\ . \\ x_{n} \end{bmatrix},因此模型可以简写成f_{w,b}=\mathbf{wx}+b  

        这种具有多个输入特征的线性回归模型称为多元线性回归,这与只有一个特征的单变量回归形成鲜明对比。

2  向量化

        当你实现学习算法时,使用向量化不仅使你的代码更简洁,还会使运行效率大大提高。

        让我们看一个向量化具体含义的例子,n=3:

        假设参数向量w=\begin{bmatrix}w_{1} \\ w_{2} \\ w_{3} \end{bmatrix};参数b=4;特征向量x\begin{bmatrix}x_{1} \\ x_{2} \\ x_{3} \end{bmatrix}

        在Python中,可以这样使用数组定义变量w,b,x:

w=np.array([1.0,2.5,-3.3])

b=4

x=np.array([10,20,30])

        在Python中, 数组的索引计数从0开始,你可以使用w[0]访问向量w的第一个值、w[1]访问第二个值、w[2]访问第三个值;相同的,访问x的各个特征值,也可以使用x[0]、x[1]、x[2]

        如果没有向量化,计算模型的预测:f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}+w _{3}x_{3}+b,在代码中,是这样的:

        f=w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+b

        你可以这样写你的代码,但如果此时n\neq 3,而是n=100或更大时,此时你的代码效率是低下的,计算效率也是低下的。

        还有另一种方式:你可以使用求和运算将w和x乘积全部相加,最后加上b ,也就是f_{w,b}(x)=\sum_{i=1}^{m}w_{j}x_{j}+b

        在代码中的表示是这样的:

f=0

for j in range(n):

        f=f+w[j]*x[j]

f=f+b

        以上两种效率都不高,现在我们来看看如何使用向量化来实现这一点:

        对于 f_{w,b}=\mathbf{wx}+b,可以通过点积w和x来计算这两个向量的值,最后再加上b。在代码中是这样的:

f=np.dot(w,x)+b

        向量化后的好处是:(1)代码简洁。  (2)运行速度更快。

        向量化之所以快得多,是因为点积函数利用我们计算机中的并行硬件,加速机器学习任务。

        现在,让我们更深入地了解向量化在我们的计算机背后是如何工作的:

        像这样的for循环在没有向量化的情况下运行时:

for j in range(16):

        f=f+w[j]*x[j]

        在t_{0}个时间点:计算f=f+ w[0]*x[0]

        在t_{1}个时间点:计算f=f+ w[1]*x[1]

        ...

        在t_{15}个时间点:计算f=f+ w[15]*x[15]

程序一步步地计算这些运算,一个接一个地运行。

        相比之下,Numpy中的np.dot(w,x)这个函数功能是通过计算机硬件中的矢量化实现的。计算机可以获得向量w和x的所有值,并在单一步骤中,同时并行地将每一对w和x相乘;然后,计算机会获取这些计算结果,并使用专门的硬件将它们全部相加。这意味着带有向量化的代码比没有带向量化的代码执行时间更短。

        在大型数据集中运行算法或训练大模型时,我们通常使用向量化加快运算速度。这就是为什么向量化的实现,使学习算法得以高效运行的原因。

        现在我们来看一个更新梯度下降的具体例子:假如你有一个问题,参数w=(w1,w2...w16),你要为这些参数计算导数项。参数w和导数d的值已经存储在数组np.array中。

w=np.array([0.5,1.3,...3.4])

d=np.array([0.3,0.2,...0.4])

        计算公式w_{j}=w_{j}-0.1d_{j} \: \: \: \: for\: \: i=1...16

        如果不使用向量化,你可能会这么做:

w_{1}=w_{1}-0.1d_{1}

w_{2}=w_{2}-0.1d_{2}

                ...

 w_{16}=w_{16}-0.1d_{16}

        代码是:

for j in range(16):

        w[j]=w[j]-0.1*d[j]

         如果使用向量化,就是取向量w中的16个值,并行减去向量d中的16值的0.1倍,然后将这些计算结果同时放回w:

        在代码中:

w=w-0.1*d

3 多元梯度下降法

        函数f:f_{w,b}(x)=w_{0}x_{0}+w_{1}x_{1}+w _{2}x_{2}+...+w _{n}x_{n}=\mathbf{wx}+b

        参数w视为一个向量:\mathbf{w}=\begin{bmatrix}w_{1} \\ w_{2} \\ . \\ . \\ . \\ w_{n} \end{bmatrix} ,参数b仍然是一个数字

        代价函数:J(w _{1},w _{2}...w_{n},b)=J(\mathbf{w},b)=\frac{1}{2m}\sum_{i=1}^{m}(f_{w,b}(x^{(i)})-y^{(i)})^{2}

        梯度下降:重复更新w_{j}=w_{j}-\alpha \frac{\partial }{\partial w_{j}}J(\mathbf{w},b)b=b-\alpha \frac{\partial }{\partial b}J(\mathbf{w},b)

 w_{1}=w_{1}-\alpha \frac{1}{m}\sum_{i=1}^{m}(f_{\mathbf{w},b}(x^{(i)})-y^{(i)})x_{1}^{(i)}     

w_{2}=w_{2}-\alpha \frac{1}{m}\sum_{i=1}^{m}(f_{\mathbf{w},b}(x^{(i)})-y^{(i)})x_{2}^{(i)}

......

w_{n}=w_{n}-\alpha \frac{1}{m}\sum_{i=1}^{m}(f_{\mathbf{w},b}(x^{(i)})-y^{(i)})x_{n}^{(i)}

b=b-\alpha \frac{1}{m}\sum_{i=1}^{m}(f_{\mathbf{w},b}(x^{(i)})-y^{(i)})

每次都像这样更新参数,直到找到局部最优点,使得模型收敛。

        在线性回归中,除了使用梯度下降算法更新参数外,还可以使用正规方程。 

2.1  特征缩放

        假设你有一个机器学习问题,这个问题有多个特征,如果你能确保不同特征的取值在相近的范围内,那么梯度下降法就能更快的收敛。

        以房价为例,假设我们使用两个特征x_{1}x_{2}\hat{price}=w_{1}x_{1}+w_{2}x_{2}+bx_{1}是房屋面积大小,取值在300-2000平方英尺之间;x_{2}是房间数,取值在0-5之间。

        现在让我们以一个面积为2000平方英尺,5间卧室,价格为500k美元的房子为例。对于这个训练示例,你认为参数w_{1},w_{2}的合理值是多少。让我们看几组参数:

        假设w_{1}=50,w_{2}=0.1,b=50,在这种情况下,以千美元为单位的估计价格\hat{price}=50*2000+0.1*5+50=100050.5,因此这不是一组好的参数选择。

        假设w_{1}=0.1w_{2}=50b=50\hat{price}=0.1*2000+50*5+50=500,这组模型参数恰好和房屋的真实价格相同。

        基于以上参数选择的例子,我想说的是:当一个特征的可能取值范围很大时(比如房子面积的取值最高可达2000平方英尺),一个好的模型更有可能学会选择一个相对较小的参数值,比如0.1;同样地,当特征的可能值较小时(比如卧室的数量),那么它的参数的合理值将相对较大,比如50

        我们来看看特征的散点图:其中横轴表示房子面积x_{1},纵轴表示房间数x_{2} ,如果你在此绘制训练数据,你会发现水平轴的数值比垂直轴的要大很多。我们再看看代价函数在等高线图中呈现的样子:水平轴的范围要比垂直轴的窄很多,所以轮廓是椭圆形。这是因为对w_{1}非常小的改变,可能会对预测价格产生非常大的影响,从而对代价函数产生非常大的影响,因为w_{1}往往会乘一个非常大的数;相比之下,需要w_{2}发生更大的变化才能显著改变预测结果,对w_{2}的小幅度调整几乎不会对代价函数产生太大影响。

        在这种情况下,由于等高线又高又瘦,梯度下降可能会来回反弹很长时间,最终才找到通往全局最小值的路径。

        在这样的情况下,一种有效的方法就是进行特征缩放,使得特征的范围在0-1之间,让数据看起来分布均匀。代价函数的等高线图看起来更圆。梯度下将可以找到一条更直接的路径到达全局最小值。

        那么我们该如何实现特征缩放?

        x_{1}的范围是300\leq x_{1}\leq 2000,一种方法是x_{1}=\frac{x_{1}}{2000},即除以范围的最大值,x_{1}的范围将缩放至0.15\leq x_{1}\leq 1;同样地,由于x_{2}的范围是0\leq x_{2}\leq 5,每个x_{2}除以范围的最大值,x_{2}=\frac{x_{2}}{5}x_{2}的范围将缩放至0\leq x_{2}\leq 1。如果你将缩放后的数据绘制在表上,它看起来可能是这样的:

         除了除以范围的最大值以外,我们还可以进行均值归一化:重新调整原始特征,使数据围绕零中心化。

        要计算x_{1}的均值归一化,首先找到训练集x_{1}的平均值\mu _{1}x_{1}=\frac{x_{1}-\mu _{1}}{max-min}=\frac{x_{1}-\mu _{1}}{2000-300}

x_{2}=\frac{x_{2}-\mu _{2}}{max-min}=\frac{x_{2}-\mu _{2}}{5-0} 

        还有一种常见的特征缩放方法----Z-score归一化。你需要计算每个特征的标准差。你需要先计算均值\mu和标准差\sigmax_{1}=\frac{x_{1}-\mu _{1}}{\sigma _{1}}x_{2}=\frac{x_{2}-\mu _{2}}{\sigma _{2}}

2.2  学习率

        梯度下降算法就是找到参数w和b,并且希望他能够最小化代价函数J(w,b )。在梯度下降算法运行时,绘出代价函数J(w,b )的图。这里的x轴表示梯度下降算法的迭代次数,随着梯度下降算法的运行,可能会得到这样一条曲线,这条曲线显示的是:在运行梯度下降算法迭代后,得到的w和b值所对应的代价函数J的值。如果梯度下降算法正常工作的话,每一步迭代之后,J(w,b )的值都应该下降。通过这条曲线,可以帮助判断梯度下降算法是否已经收敛。

        对于每一个特定问题,梯度下降算法所需要的迭代次数可能会相差很大。对于这个问题,梯度下降算法可能只需要30步迭代就可以达到收敛;换个问题,也许梯度下降算法需要3000步迭代;对于另一个问题,可能有需要三百万步迭代。我们很难提前判断梯度下降算法需要多少步才能收敛,我们通常要画出代价函数随迭代步数增加的变化曲线,通过曲线来判断梯度下降算法是否已经收敛。

        另外也可以进行一些自动的收敛测试,也就是说让一种算法来告诉你梯度下降算法是否已经收敛。比如:代价函数一步迭代后的下降小于一个很小的值\varepsilon=10^{-3},这个测试就判断函数已经收敛。但通常选择一个合适的阈值\varepsilon是很困难的。所以为了检查梯度下降算法是否已经收敛,还是更通过看上面这样的图比较好。

        看这种曲线图还可以告诉你或提前警告你算法没有正常工作。

        如果你看到代价函数随迭代步数的变化曲线是下图这样的,这就表明梯度下降算法没有正常工作。这意味着你应该使用较小的学习率\alpha 

  

        如果你看到代价函数随迭代步数的变化曲线是下图这样的,可能是由于学习率太大导致的,需要选择较小的学习率来解决。

        如果学习率太小的话,收敛速度慢;如果学习率太大,代价函数可能不会在每次迭代都下降,甚至可能不收敛。为了调试所有的情况,通常绘制代价函数随迭代步数变化的曲线。

        一个正确实现梯度下降的调试技巧是:当使用足够小的学习率时,代价函数在每次迭代中都下降。如果梯度下降法不起作用,可以将学习率设成一个很小的值,看看是否会在每次迭代后,代价下降;如果将学习率设置成一个很小的值,代价函数的值在每次迭代后并不总是减少,反而有时会增加,这意味着代码中某处存在错误。

        我们通常会尝试一系列的\alpha值,比如0.001  ,0.003, 0.01,0.03, 0.1,0.3,1 ,然后对于这些不同的\alpha值绘制代价函数随迭代步数变化的曲线,选择使得代价函数J(w,b )值快速下降的一个\alpha值。

4  特征工程

        特征的选择会对学习算法性能产生巨大影响。选择或输入正确的特征是使算法良好运行的关键步骤。我们来看看如何为学习算法选择或设计最合适的特征。

        我们重新审视预测房价的例子来看看特征工程:假设每栋房子有两个特征,x_{1}是房屋所建地块的宽度,x_{2}是地块的深度。

根据这两个特征x_{1}x_{2},你可能会构建 一个这样的模型,其中f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}+b,这个模型可能不错。你可能注意到房子的面积area=frontage*depth,或许用面积会比单独用宽度和深度更能预测价格。这是你可能会定义一个新特征x_{3}=x_{1}*x_{2}x_{3}表示地块的面积。因此可以定义一个新模型f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}+w_{3}x_{3}+b ,这个模型可能会比之前定义的模型更好。

        刚才所做的创建新特征,就是特征工程的例子。特征工程:通过转换或组合问题的原始特征,根据直觉或已有的知识去设计新的特征,以便使学习算法更容易做出精确的预测。

        特征工程不仅允许你拟合直线,还可以拟合非线性函数到你的数据上。

        采用多元线性回归和特征方程提出一个新的算法,称为多项式回归,它可以拟合曲线或非线性函数。

        假设你有一个住房数据集,看起来是这样的,其中特征x表示房子的面积,直线似乎不太适合拟合数据,你可以用曲线来拟合数据,这个模型可能是:f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}^{2}+b ;但是随后你又考虑到二次函数会在某一个x点开始下落,而随着房子面积x的增加,房价是要上升的,这时你会选择三次函数f_{w,b}(x)=w_{1}x_{1}+w_{2}x_{2}^{2}+w_{3}x_{3}^{3}+b

        如果你创建的是多次方的函数模型,那么特征缩放就很重要了。如果房子的范围在1-1000平方英尺,那么x_{1}^{2}范围就是一到一百万,x_{1}^{3}的范围就是一到十亿。它们之间的范围相差太多,要使用特征缩放把它们的特征值调整到合适的范围。

        另一种方案:你可以使用\sqrt{x},此时模型就是:f_{w,b}(x)=w_{1}x_{1}+w_{2}\sqrt{x}+b,这也是另一个可能对此数据集也有效的特征选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值