一、从本文起学会快速阅读和学习
本来是想把关于快速阅读的说明写在前一节,但最后还是觉得放在这个例子里面更加妥当。
首先要明确一点:快速阅读绝不等于读得快!真正的快速阅读实际上是明确阅读的要点,把最多的精力放在最重要的地方去细读;同时果断地减少甚至舍弃对不重要的点的阅读。比如有的文档可能有2000个单词,但实际上真正有用的部分就只有200词。如果只给你10分钟的时间,你去搞明白这200词的内容实际上并不困难。但如果每个点都想看明白,估计10分钟连这2000个词都还没认全时间就已经过去了。
那么与之对应的快速学习也是同样的道理。尤其在初学的时候,一定要把精力放在主干的知识框架上,而那些细枝末节的东西有空了或者遇到了再去慢慢看。相反如果一来就想一口气把所有的细节都弄清楚,那么很有可能掌握正确学习方法的同学已经在用sklearn做项目了,而你还在纠结线性回归的实现。
废话不多说,我们直接进入正题。
二、线性回归的原理回顾及官方文档
线性回归的公式非常简单:
y
^
(
w
,
x
)
=
w
0
+
w
1
x
1
+
.
.
.
+
w
p
x
p
\hat{y}(w, x) = w_0 + w_1 x_1 + ... + w_p x_p
y^(w,x)=w0+w1x1+...+wpxp
这里
x
i
x_i
xi 代表输入向量的第
i
i
i 维,
w
i
w_i
wi则是参数的第
i
i
i维,
y
^
\hat{y}
y^ 是输出值。从原理上我们其实只关心两个问题:如何根据现有的数据算出它的参数?参数求出之后我们怎么用它来预测?
官方很直接地先给出了这样一段代码:
>>> import numpy as np
>>> from sklearn.linear_model import LinearRegression
>>> X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
>>> # y = 1 * x_0 + 2 * x_1 + 3
>>> y = np.dot(X, np.array([1, 2])) + 3
>>> reg = LinearRegression().fit(X, y)
>>> reg.coef_
array([1., 2.])
>>> reg.intercept_
3.0000...
>>> reg.predict(np.array([[3, 5]]))
array([16.])
注意,上述叙述过程其实就是我们通常的学习新模型的方式。先看看原理,再直接粘代码。这种方式其实就是最简单直接的方式。但如果只是这样去复制粘贴,很显然是不行的。因为如果没有理解代码的涵义,那么遇到变化时就完全不知所措,到时候又得回来老老实实看原理,很显然这就很浪费时间。
回顾本文开头所讲,我们是要细读那些最重要的地方,很显然,这段代码就是我们要去细读的地方。
三、官方文档的分析
这段代码中前2行的代码只是导入对应的Numpy库和LinearRegression模块,可以忽略,要用的时候照着样子照抄即可,顶多注意一下这里把numpy
取了一个别名叫np
.
接下来3-5行是在生成原始数据。这里我们仔细观察一下。首先变量X
很显然是输入变量,而注释中也很清楚地说明了输出变量的值是由公式
y
=
1
∗
x
0
+
2
∗
x
1
+
3
y = 1 * x_0 + 2 * x_1 + 3
y=1∗x0+2∗x1+3 得到的。那么这里我们仔细看一下两个变量的结构。我们将X
和 y
分别输出:
X
array([[1, 1],
[1, 2],
[2, 2],
[2, 3]])
y
array([ 6, 8, 9, 11])
这里注意到,X
是一个
5
×
2
5\times 2
5×2 的数组(和矩阵稍有不同,但形状完全一样),而y
是一个一维的数组。由此可见,我们要用来拟合的数据,其输入变量必须是列向量,而输出的这个变量则相对自由(注意,这也是sklearn相对比较坑的一点;官方的说法是为了节省内存开销,但如果熟悉Matlab、R等相对更加专业的计算类程序的人容易觉得不适应)。那么明白了这一点,我们要输入怎样的数据就完全明确了。那么如果我们想换上自己的数据不外乎也就是把X
和y
按照同样的格式输入即可。
接下来第6行就很有意思了。首先它是直接调用LinearRegression
类的方法fit(X,y)
,直接实例化了一个线性回归模型,并且用上面生成的数据进行了拟合。看到这里就能够明白了,原来只需要把数据按照格式输入,就可以完成模型的拟合。事实上这段代码也可以改成以下形式:
reg = LinearRegression()
reg.fit(X, y)
因为fit()
方法返回值其实是模型本身self
,所以在初始化reg
之后只需要直接调用fit()
,它自己对应的系数值(属性)就被成功赋值。这种写法个人更为推荐,因为它虽然看起来多出一行,但整个运行的机制则显得更加清晰。
第9,11行就是系数和偏差值的展示。上面提到,注释中已经说明了数据就是由方程
y
=
1
∗
x
0
+
2
∗
x
1
+
3
y = 1 * x_0 + 2 * x_1 + 3
y=1∗x0+2∗x1+3生成的,而这时我们看到系数值分别等于 1,2
而偏差值是3
,和理论模型完全一致。
重点在第13行,此时它调用了LinearRegression
类的predict()
方法。那么显然,这个方法就是利用拟合好的线性回归模型来计算新输入值对应的输出值。这里新输入值仍然和拟合时的格式保持一致。
那么小结一下,根据官方文档,要拟合一个线性回归模型并且预测出新值的话,其实只需要进行四个步骤:
- 格式化数据,输入为
n*d
的数组,其中n
表示数据的个数,d
是维度;输出值是一维数组。 - 初始化模型
LinearReregression()
- 拟合
fit(X,y)
- 预测
predict(X_test)
四、举一反三
注意,到这里还并没有结束。一个成功的调包侠工程师,在看懂一段代码过后一定要进一步对其进行探索,那么这里我们容易想到几个问题:
- 很显然上述的生成数据的方式太低效,我想用点随机的数据行不行?或者我想用更大一点的数据行不行?
- 模型预测虽然可以做了,但想要评估一下预测结果行不行?
- 我想把结果画出来行不行?
当然都可以。再当然,要实现这些方法就要用到其它的一些库和方法。
比如,上述例子只给了5个点,我想试一试
X
=
{
1
,
2
,
.
.
.
,
100
}
X = \left\{1,2,...,100 \right\}
X={1,2,...,100},
y
=
0.3
∗
X
+
1
y = 0.3*X+1
y=0.3∗X+1,那么这里就涉及到numpy
的应用了。比如我们可以用这种方法:
import numpy as np
X = np.reshape(np.arange(100),[-1,1])
y = 0.3*X + 1
reg.fit(X,y)
这段代码同样可以运行。但是注意到这里我们用到了另一个方法 np.reshape()
,这是为了保证X
满足fit
函数的数据结构要求。如果去掉这个方法则会报错。
另外模型评估可以直接用reg.score(X,y)
,或者再去查询其它的模型评估方法。如果要画图则需要用到matplotlib
。
当然,后面两个问题就是在已经理解和掌握了LinearRegression()
之后的扩展内容。实际上在完成了第1个问题时,我们就已经学会了如何使用这个方法了。
五、小结
本文详细讲解了sklearn中的线性回归模型LinearRegression()
的使用。相信这会你已经发现我们并没有讲太多的原理,而是直接根据模型的功能去查询方的代码。再通过代码的内容详细分析了其中的关键点,即数据的结构(我们也可以更直接地叫它shape
)。相信看完这篇文章顶多也花不了10分钟,但你已经掌握了LinearRegression
的用法。至于更深的理论,更多花哨的用法,就在你具体的项目、研究中再去查询就好。
其它的模型,我们也会用类似的方法加以讲解。有兴趣的同学也可以试试用上述的方式去看看其它的模型,说不定会有意想不到的效果。
参考内容: