一、線性迴歸
用線性迴歸找到最佳擬合直線
迴歸的目的是預測數值型數據,根據輸入寫出一個目標值的計算公式,這個公式就是迴歸方程(regression equation),變量前的係數(比如一元一次方程)稱爲迴歸係數(regression weights)。求這些迴歸係數的過程就是迴歸。
假設輸入數據存放在矩陣X中,迴歸係數存放在向量w中,那麼對於數據X1的預測結果可以用Y1=XT1w得出。我們需要找到使誤差最小的w,但是如果使用誤差之間的累加的話,那麼正負誤差將會抵消,起不到效果,所以採用平方誤差。如下:
from numpy import *
def loadDataSet(fileName):
numFeat = len(open(fileName).readline().split('\t'))-1
dataMat = []; labelMat = []
fr = open(fileName)
for line in fr.readlines():
lineArr = []
curLine = line.strip().split('\t')
for i in range(numFeat):
lineArr.append(float(curLine[i]))
dataMat.append(lineArr)
labelMat.append(float(curLine[-1]))
return dataMat, labelMat
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
這部分數據是由tap分隔,並且最後一個值是目標值。接下來計算迴歸係數:
def standRegres(xArr, yArr):
xMat = mat(xArr); yMat = mat(yArr).T
xTx = xMat.T*xMat
if linalg.det(xTx) == 0.0:
print "This matrix is singular, cannot do inverse"
return
ws = xTx.I * (xMat.T*yMat)
return ws
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
該函數首先讀入x和y數組,然後將它們轉換成矩陣,之後根據公式計算平方誤差,注意,需要對XTX求逆,此時需要判斷它的行列式是否爲0,行列式等於0的矩陣無法求逆,可以直接使用linalg.det()
來計算行列式。好了,我們來看看效果,首先讀入數據:
xArr,yArr=loadDataSet('ex0.txt')
- 1
- 1
我們先看看前兩條數據:
print xArr[0:2]
[[1.0, 0.067732], [1.0, 0.42781]]
- 1
- 2
- 1
- 2
第一個值總是等於1.0,也就是x0,假定偏移量是一個常數,第二個值是x1。
現在看看計算迴歸係數函數效果:
ws = standRegres(xArr,yArr)
print ws
[[ 3.00774324]
[ 1.69532264]]
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
現在得到了迴歸係數,那麼我們可以通過迴歸方程進行預測yHat:
xMat = mat(xArr)
yMat = mat(yArr)
yHat = xMat*ws
- 1
- 2
- 3
- 1
- 2
- 3
爲方便觀察,我們畫出數據集散點圖:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xMat[:,1].flatten().A[0], yMat.T[:,0].flatten().A[0])
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
現在繪製最佳擬合直線,那麼需要畫出預測值yHat,如果直線上數據點次序混亂,繪圖時將會出現問題,所以要將點按照升序排序:
xCopy = xMat.copy()
xCopy.sort(0)
yHat=xCopy*ws
ax.plot(xCopy[:,1], yHat)
plt.show()
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
我們來看看效果:
最佳擬合直線方法將數據視爲直線進行建模,但圖中的數據集似乎還有更好的擬合方式。
二、局部線性迴歸
主要看k的選擇,因爲每個k值下算出的迴歸係數值已滿足最小均方誤差了。
線性迴歸可能出現欠擬合的現象,如上圖所示,因爲它求的是具有最小均方誤差的無偏差估計。所以有些方法允許在估計中引入一些偏差,從而降低預測的均方誤差。其中一個方法就是使用局部加權線性迴歸(Locally Weighted Linear Regression,LWLR),我們給待測點附近的每個點賦予一定的權重,是用此方法解出的迴歸係數如下:
theta
=(XTWX)−1XTWy
LWLR使用“核”來對附近的點賦予更高的權重,核的類型可以自由選擇,最常用的核就是高斯核,高斯覈對應的權重如下:
import numpy as np
import matplotlib.pyplot as plt
def loadDataSet(fileName): #general function to parse tab -delimited floats
numFeat = len(open(fileName).readline().split('\t')) - 1 #get number of fields
dataMat = []; labelMat = []
fr = open(fileName)
for line in fr.readlines():
lineArr =[]
curLine = line.strip().split('\t')
for i in range(numFeat):
lineArr.append(float(curLine[i]))
dataMat.append(lineArr)#xij,i爲特徵,j爲樣本
labelMat.append(float(curLine[-1]))
return dataMat,labelMat
#局部加權迴歸
def lwlr(testPoint,xArr,yArr,k=1.0):#
xMat = np.mat(xArr); yMat = np.mat(yArr).T
m = np.shape(xMat)[0]
weights = np.mat(np.eye((m)))#創建對角矩陣:eye()返回一個對角線元素爲1,其他元素爲0的二維數組。 以給每個數據點賦予權重
for j in range(m): #next 2 lines create weights matrix
diffMat = testPoint - xMat[j,:] #
weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2))
xTx = xMat.T * (weights * xMat)
if np.linalg.det(xTx) == 0.0:
print("This matrix is singular, cannot do inverse")
return
ws = xTx.I * (xMat.T * (weights * yMat))
return testPoint * ws
def lwlrTest(testArr,xArr,yArr,k=1.0): #測試lwlr函數:loops over all the data points and applies lwlr to each one
m = np.shape(testArr)[0]
yHat = np.zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i],xArr,yArr,k)
return yHat
def lwlrTestPlot(xArr,yArr,k=1.0): #same thing as lwlrTest except it sorts X first
yHat = np.zeros(np.shape(yArr)) #easier for plotting
xCopy = np.mat(xArr)
xCopy.sort(0)
for i in range(np.shape(xArr)[0]):
yHat[i] = lwlr(xCopy[i],xArr,yArr,k)
return yHat,xCopy
def rssError(yArr,yHatArr): #yArr and yHatArr both need to be arrays
return ((yArr-yHatArr)**2).sum()
xArr,yArr=loadDataSet(r'C:\Users\qingmu\Desktop\數據組\收藏資料\machinelearninginaction\Ch08\新建文本文檔.txt')
yHat=lwlrTest(xArr,xArr,yArr,0.1)
xMat=np.mat(xArr)
rssError=
strInd=xMat[:,1].argsort(0)
xSort=xMat[strInd][:,0,:]
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(xSort[:,1],yHat[strInd])
ax.scatter(xMat[:,1].flatten().A[0], np.mat(yArr).T.flatten().A[0], s = 2, c = 'red')
plt.show()
k=0.1
k=0.01
k=0.003
練習:
擬合交易指數和支付金額。
第一種情況:
xArr,yArr=loadDataSet(r'C:\Users\qingmu\Desktop\數據組\收藏資料\machinelearninginaction\Ch08\新建文本文檔.txt')
yHat=lwlrTest(xArr,xArr,yArr,0.1)
xMat=np.mat(xArr)
strInd=xMat[:,0].argsort(0)
xSort=xMat[strInd][:,0,:]
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(xSort[:,0],yHat[strInd])
ax.scatter(xMat[:,0].flatten().A[0], np.mat(yArr).T.flatten().A[0], s = 2, c = 'red')
plt.show()
其餘代碼均相同。k=0.1
k=0.01
k=0.003