阅读本文大概需要 3 分钟。

 


之前说过会陆续写一些基本的机器学习算法的原理、推导和应用的文章,今天开始连载啦。

每篇文章的思路是这样的:

  • 通过实例引入这个算法的使用场景

  • 公式详细推导这个算法的实现原理

  • 借助 Python 类库来进行具体实践

如果大家觉得有哪些可以优化的地方可以留言给我,我会慢慢完善的。再后面会陆续放送各个机器学习算法、深度学习模型及相关的实例实践,希望对大家有帮助。

今天首先讲解最基本的机器学习算法,线性回归。

线性回归是机器学习中最基本的算法了,一般要学习机器学习都要从线性回归开始讲起,本节就对线性回归做一个详细的解释。

实例引入

在讲解线性回归之前,我们首先引入一个实例,张三、李四、王五、赵六都要贷款了,贷款时银行调查了他们的月薪和住房面积等因素,月薪越高,住房面积越大,可贷款金额越多,下面列出来了他们四个人的工资情况、住房面积和可贷款金额的具体情况:

姓名工资(元)房屋面积(平方)可贷款金额(元)
张三60005830000
李四90007755010
王五110008973542
赵六150005463201

看到了这样的数据,又来了一位孙七,他工资是 12000 元,房屋面积是 60 平,那他大约能贷款多少呢?

思路探索

那这时候应该往哪方面考虑呢?如果我们假定可贷款金额和工资、房屋面积都是线性相关的,要解决这个问题,首先我们想到的应该就是初高中所学的一次函数吧,它的一般表达方式是 , 就是自变量, 就是因变量, 是自变量的系数, 是偏移量,这个式子表明  和  是线性相关的, 会随着  的变化而呈现线性变化。

现在回到我们的问题中,情况稍微不太一样,这个例子中是可贷款金额会随着工资和房屋面积而呈现线性变化,此时如果我们将工资定义为 ,房屋面积定义为 ,可贷款金额定义为 ,那么它们三者的关系就可以表示为: ,这里的自变量就不再是一个了,而是两个,分别是  和 ,自变量系数就表示为了  和 ,我们将其转化为表达的形式,同时将变量的名字换一下,就成了这个样子:

这里只不过是将原表达式转为函数形式,换了个表示名字,另外参数名称从  换成了 , 换成了 ,为什么要换?因为在机器学习算法中  用的更广泛一些,约定俗成。

然后这个问题怎么解?我们只需要求得一组近似的  参数使得我们的函数可以拟合已有的数据,然后整个函数表达式就可以表示出来了,然后再将孙七的工资和房屋面积代入进去,就求出来他可以贷款的金额了。

思路拓展

那假如此时情景变一变,变得更复杂一些,可贷款金额不仅仅和工资、房屋面积有关,还有当前存款数、年龄等等因素有关,那我们的表达式应该怎么写?不用担心,我们有几个影响因素,就写定义几个变量,比如我们可以将存款数定义为 ,年龄定义为 ,如果还有其他影响因素我们可以继续接着定义,如果一共有  个影响因素,我们就定义到 ,这时候函数表达式就可以变成这样子了:


这个式子看起来挺长的不好写的吧,我们可以使用求和公式写成如下形式:

如果要使得这个公式成立,这里需要满足一个条件就是 ,其实在实际场景中  是不存在的,因为第一个影响因素我们用  来表示了,第二个影响因素我们用  来表示了,依次类推。所以这里我们直接指定  即可。

后来我们又将公式简化为线性代数的向量表示,这里  是  向量转置的结果,而  向量又表示为 ,同样地, 向量可以表示为 ,总之,表达成后面的式子,看起来更简洁明了。

好了,这就是最基本的线性判别解析函数的写法,是不是很简单。

实际求解

那接下来我们怎样实际求解这个问题呢?比如拿张三的数据代入到这个函数表达式中,这里还是假设有两个影响因素,张三的数据我们可以表示为 ,注意这里我们在数据的右上角加了一个小括号,里面带有数字,如果我们把张三的数据看成一个条目,那么这个数字就代表了这个条目的序号,1 就代表第一条数据,2 就代表第二条数据,为啥这么写?也是约定俗成,以后也会经常采用这样的写法,记住就好了。

所以,我们的愿景是要使得我们的函数能够拟合当前的这条数据,所以我们希望是这样的情况:


其中  是真实值,但我们知道,哪有那么容易十全十美,丝毫不差的拟合函数,所以上面的式子一般来说是不成立的,函数计算值和真实值还是多少还是有一定的误差的吧,如果我们想知道函数真实拟合的结果的话,我们需要把  变量代入函数,会得到一个函数本身拟合的结果,是这样的:


这里的  就是我们函数得到的结果了。一般来说,二者是会存在一定的误差的,所以误差我们一般可以写成他们的差的绝对值或平方的形式,使用绝对值或平方的目的是消去正负号的影响,比如写成平方的形式就是这样子:

这个式子就是我们函数真实拟合值和真实值之间的差距,没问题吧。

相应的,如果是李四的数据,误差就可以写为:

依次类推,如果是第  条数据,误差就可以写成:

要使得我们的函数对所有的数据都能尽量很好地拟合,我们可以把这些误差加起来求个平均,假设一共  条数据,那么所有数据的误差可以写成如下形式:

注意这里  指的是第几条数据,是从 1 开始的,一直到  为止,然后使用了求和公式对每一条数据的误差进行累加和,最后除以了 ,我们的最终目的就是找出合适的 ,使得这个  的值最小,即误差最小,在机器学习中,我们就把  称为损失函数(Loss Function),即我们要使得损失值最小。

有的小伙伴可能好奇损失函数前面为什么是 ,而不是 ?因为我们后面要用到这个算式的导数,所以这里多了个 2 是为了便于求导计算。况且一个表达式要求最小值,前面乘一个常数是对结果没影响的。

求解过程

由于我们求解的是线性回归问题,所以整个损失函数的图像非常简单清晰,如果只有  和  两个参数,我们甚至可以直接画出其图像,整个损失函数大小随  和  的变化实际上类似于这样子:

可以看到这是一个凸函数,竖轴代表损失函数的大小,横纵两轴代表  和  的变化,可见在中间的最低谷损失函数取得最小值,这时候损失函数在  和  上的导数都是 0,因此我们可以一步到位,直接用偏导置零的方式来求解损失函数取得最小值时的  值的大小。

所以我们可以先对每个  求解其偏导结果,这里  表示为 ,代表  中的某一维:

直接将偏导置零即可直接求解    

这里将所有数据代入,即可通过求解方程组的形式直接解出  的值,但这些方程组里面其实  之间存在彼此依赖关系,需要联立求解出来。

如果不用这种求解方式,我们可以使用梯度下降的方式来进行求解,在这里  只需要逐步更新即可:

这里  就是学习率, 每经过一步都会进行一次更新,得到新的结果,经过梯度下降过程, 都会更新为使得梯度最小化的数值,最后就完成了  的求解。

以上便是线性回归的整个推导和求解过程。

实战操作

现在呢,我们想要根据前面的数据来求解这个真实的问题,为了解决这个问题,我们在这里用 Python 的 Sklearn 库来实现。

对于线性回归来说,Sklearn 已经做好了封装,直接使用 LinearRegression 即可。

它的 API 如下:

class sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=None)

参数解释如下:

  • fit_intercept : 布尔值,是否使用偏置项,默认是 True。

  • normalize : 布尔值,是否启用归一化,默认是 False。当 fit_intercept 被置为 False 的时候,这个参数会被忽略。当该参数为 True 时,数据会被归一化处理。

  • copy_X : 布尔值,默认是 True,如果为 True,x 参数会被拷贝不会影响原来的值,否则会被复写。

  • n_jobs:数值或者布尔,如果设置了,则多核并行处理。

属性如下:

  • coef_:x 的权重系数大小

  • intercept_:偏置项大小

代码实现如下:

from sklearn.linear_model import LinearRegression

x_data = [
    [600058],
    [900077],
    [1100089],
    [1500054]
]
y_data = [
    30000550107354263201
]

lr = LinearRegression()
lr.fit(x_data, y_data)
print('方程为:y={w1}x1+{w2}x2+{b}'.format(w1=round(lr.coef_[0], 2),
                                       w2=round(lr.coef_[1], 2),
                                       b=lr.intercept_))
x_test = [[1200060]]
print('住房面积为:', lr.predict(x_test)[0])

运行结果:

方程为:y=4.06x1+743.15x2+-37831.862532707615
住房面积为:55484.33779181102

在这里我们首先声明了 LinearRegression 对象,然后将数据整合成 x_data 和 y_data 的形式,然后通过调用 fit() 方法来对数据进行拟合。

拟合完毕之后,LinearRegression 的 coef_ 对象就是各个 x 变量的权重大小,即对应着 ,intercept_ 则是偏移量,对应着 ,这样我们就可以得到一个线性回归表达式了。

然后我们再调用 predict() 方法,将新的测试数据传入,便可以得到其预测结果,最终结果为 55484.34,即孙七的可贷款额度为 55484.34 元。


©著作权归作者所有:来自51CTO博客作者mb5fe159f193922的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. Python 如何爬取实时变化的 WebSocket 数据
  2. Python排序算法[二]:测试数据的迷雾散去
  3. 学习C的第三天-函数
  4. Python常用的数据存储方式有哪些?五种!
  5. NBA球员投篮数据可视化。
  6. 手把手教你用Bokeh进行可视化数据分析(附源码)
  7. 5个原因告诉你:为什么在成为数据科学家之前,“逻辑回归”是第一个
  8. 金州勇士4年3冠的成功秘诀!数据可视化分析告诉你答案
  9. 数据科学大佬的简历上都有哪些技能?

随机推荐

  1. Android常用布局之LinearLayout(线性布局
  2. Android窗口治理机制
  3. 关于android的animation的xml定义中的and
  4. Android Studio开发环境的搭建
  5. Android嵌入式系统程序开发
  6. android的布局属性(转)
  7. android emulator( android模拟器)
  8. Android中的相对布局
  9. Android Handler机制8之消息的取出与消息
  10. android 全屏显示