概念
線性回歸(linear regression)意味着可以把輸入項分別乘以一些
常量,然后把結果加起來得到輸出。
這個輸出就是我們需要預測的
目標值
而這些
常量就是所謂的
回歸系數
我們把求這些回歸系數的過程叫做
回歸,這個過程是對已知數據點的
擬合過程
更一般化的解釋來自
Tom M.Mitchell的《機器學習》:回歸的含義是逼近一個實數值的目標函數
標准線性回歸
那應該怎么求回歸系數
w呢。一個常用的方法是找出使得預測值和實際值之間的誤差最小的,為了避免正負誤差之間的相互抵消,我們采用平方誤差,也就是傳說中的
最小二乘法。
平方誤差可以寫作:

用矩陣表示寫作:

現在需要對這個公式求最小,其實就變成了一個最優化問題。
對w求導,得到:

令其等於0,解出w如下:

這個公式中包含了對矩陣求逆的操作,所以需要在實際計算過程中判斷矩陣是否可逆。
到這里,線性回歸的主要思想就算完成,下面用數據集來試一下
例子中用到的數據集ex0.txt大概長成這樣:

代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# -*- coding: utf-8 -*-
# Author: Alan
# date: 2016/4/7
from
numpy
import
*
def
loadData(filename):
# 計算特征數量
numFeat
=
len
(
open
(filename).readline().split(
'\t'
))
-
1
fr
=
open
(filename)
dataMat
=
[]; labelMat
=
[]
for
line
in
fr.readlines():
lineArr
=
[]
currLine
=
line.strip().split(
'\t'
)
for
i
in
range
(numFeat):
lineArr.append(
float
(currLine[i]))
dataMat.append(lineArr)
labelMat.append(
float
(currLine[
-
1
]))
return
dataMat, labelMat
# 標准的線性回歸函數,使用最小二乘法
def
standRegres(xArr, yArr):
xMat
=
mat(xArr)
# 和transpose()一個意思
yMat
=
mat(yArr).T
xTx
=
xMat.T
*
xMat
# 計算行列式的值,如果等於零,則不可求逆
if
linalg.det(xTx)
=
=
0.0
:
print
'cannot do inverse!'
return
# 回歸系數
ws
=
xTx.I
*
(xMat.T
*
yMat)
return
ws
# 測試標准回歸,查看其求出的回歸系數
def
testStandR():
filename
=
'E:\ml\machinelearninginaction\Ch08\ex0.txt'
xArr, yArr
=
loadData(filename)
print
"查看數據集的前兩個實例的特征:"
print
xArr[
0
:
2
]
weights
=
standRegres(xArr, yArr)
print
"求出的系數為:"
print
weights
|
standRegres()函數實現了線性回歸算法,然后用過運行testStandR()函數測試之,結果如下:

得出了系數就相當於得到了回歸方程,現在通過一個輸入就可以分別乘以回歸系數得到輸出,實現了預測的目的。
圖示原始數據和擬合直線
我們可以通過直觀的展示數據分布和擬合的直線來觀察擬合的效果
繪圖代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
def
plotData():
import
matplotlib.pyplot as plt
'''下面這段代碼繪制原始數據的散點圖'''
filename
=
'E:\ml\machinelearninginaction\Ch08\ex0.txt'
xArr, yArr
=
loadData(filename)
xMat
=
mat(xArr);yMat
=
mat(yArr)
figure
=
plt.figure()
ax
=
figure.add_subplot(
111
)
# 取第二個特征繪圖
# flatten()函數轉化成一維數組
# matrix.A屬性返回矩陣變成的數組,和getA()方法一樣
ax.scatter(xMat[:,
1
].flatten().A[
0
], yMat.T[:,
0
].flatten().A[
0
])
'''下面這段代碼繪制擬合直線'''
# 返回給定數據的數組形式的拷貝
xCopy
=
xMat.copy()
xCopy.sort(
0
)
weights
=
standRegres(xArr, yArr)
print
weights.shape
yHat
=
xCopy
*
weights
# yHat 表示擬合直線的縱坐標,用回歸系數求出
ax.plot(xCopy[:,
1
], yHat, c
=
'green'
)
plt.show()
|
繪圖效果:

評價模型
這樣的一個建模過程是非常直觀也非常容易理解的。
幾乎任一數據集都可以用上述方法建立模型,那么如何判斷模型好壞呢?
這里引入一種計算
預測序列和
真實值序列匹配程度的方法,就是計算兩個序列的
相關系數
很方便的是Numpy庫提供了相關系數的計算方法:
corrcoef(yEstimate, yActual)
運行代碼:
1
2
3
4
5
6
|
# 利用相關系數評價模型的匹配程度
def
eval
():
xMat
=
mat(xArr)
yMat
=
mat(yArr)
yHat
=
xMat
*
weights
print
corrcoef(yHat.T, yMat)
|
顯示結果如下:

表示兩者的相關系數為0.98,說明兩者的相關性很大
這樣就完成了一個標准的線性回歸,但是很明顯地,被擬合的數據中還有波動的特性沒有被表達出來,
也就說事實上這樣是欠擬合的。
那么如何才能進一步增強模型的表達能力呢,下一篇筆記將會解決這個問題。
總結
- 這種簡單的最佳擬合直線把數據當做直線進行擬合,表現不錯。
- 但是從繪制的散點圖中可以看出數據還具有明顯的波動特性,而這個特性是直線擬合所不能表達的,是它的缺陷
- 回歸需要數值型數據,標稱型數據需要轉換才能使用
參考文獻
《機器學習實戰》
這里是比較好的關於矩陣求導的講解