Chapter8 - regression
線性迴歸
找到一個迴歸係數向量w,用y = xw來計算預測結果,問題就是如何運用現有的數據集找到最合適的w,一個常用的方法就是找出誤差最小的w,如果簡單地將誤差加減,則正值和負值會抵消,因此選用平方誤差。
即
用矩陣替換掉求和符號即爲
對w求導並令其爲0,得到
兩邊同時乘以
代碼實現
def standRegres(xArr,yArr):
xMat = mat(xArr); yMat = mat(yArr).T
xTx = xMat.T*xMat
print xMat.T.shape,xMat.shape
print xTx.shape
# 計算行列式,行列式爲0,則逆矩陣不存在
if linalg.det(xTx) == 0.0:
print "This matrix is singular, cannot do inverse"
return
ws = xTx.I * (xMat.T*yMat)
return ws
局部加權線性迴歸
http://blog.csdn.net/hujingshuang/article/details/46274723
目前計算x的預測值,用的是全局的數據,且每個數據的權值一樣,但實際是與x越接近的數據參考價值越大,所以有了局部加權,體現在誤差公式上就是對訓練集中的每個點都乘上一個權值係數,然後求和。權值係數用一個m*m的矩陣來表示,對角線上不爲0.
誤差公式爲
用矩陣表示爲
對
流程:
1.計算每個訓練點的m*m權值矩陣(只有對角線上不爲0),常用的權值計算公式有高斯核,離點越近的點權值越大,高斯核如下:
2.對每個需要預測的點都用上述的求
# 對單個點的預測
def lwlr(testPoint,xArr,yArr,k=1.0):
xMat = mat(xArr); yMat = mat(yArr).T
m = shape(xMat)[0]
weights = mat(eye((m)))
for j in range(m):
diffMat = testPoint - xMat[j,:]
weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))
xTx = xMat.T * (weights * xMat)
if 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):
m = shape(testArr)[0]
yHat = zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i],xArr,yArr,k)
return yHat
最小二乘法( OLS,ordinary least square)有解的條件是X列滿秩。
https://www.zhihu.com/question/28221429
(其實有時候會看到是不滿足列滿秩或者特徵的相關比較強時,不適合用最小二乘法,不滿足列滿秩就是逆矩陣不存在,那爲什麼相關性較強也不適用呢?相關性較強意味着
爲什麼?
假設X的大小爲m*n
有解也就是X^TX有逆矩陣,也就是X^TX滿秩,X^TX的大小爲n*n,如果滿秩的話就是秩爲n。
有以下定理:
正定矩陣爲什麼可逆:正定陣的特徵值全大於0,而行列式等於特徵值的乘積,因此行列式大於0,可逆。
-
n階方陣A可逆 <=> A非奇異 <=> |A|≠0 <=> A可表示成初等矩陣的乘積 <=> A等價於n階單位矩陣 <=> r(A) = n <=> A的列(行)向量組線性無關 <=> 齊次線性方程組AX=0 僅有零解 <=> 非 齊次線性方程組AX=b 有唯一解 <=> 任一n維向量可由A的列(或行)向量組線性表示 <=> A的特徵值都不爲0
矩陣的列秩和行秩總是相等的,因此它們可以簡單地稱作矩陣A的秩。通常表示爲r(A).
- 行(列)滿秩矩陣的一些性質及應用
嶺迴歸
用最小二乘法最誤差有什麼問題?在計算
- 因此從計算的角度可以加上一個
λI 使w=(XTX+λI)−1XTY 可以計算。 - 上面是從運算的角度,有沒有更自然的理解方式呢?
知乎上有個回答介紹了三種理解方式
1.從上述計算的角度回答
2. 從優化問題的角度。
誤差的公式爲
通過確定
方差指的是模型之間的差異,而偏差指的是模型預測值和數據之間的差異。我們需要找到方差和偏差的折中。方差,是形容數據分散程度的,算是“無監督的”,客觀的指標,偏差,形容數據跟我們期望的中心差得有多遠,算是“有監督的”,有人的知識參與的指標。
3.從多變量回歸的變量選擇來說,普通的多元線性迴歸要做的是變量的剔除和篩選,而嶺迴歸是一種shrinkage的方法,就是收縮。
嶺迴歸的迴歸參數有先驗分佈,而最小二乘對參數沒有限制。對參數進行先驗分佈限制,會使得得到的迴歸參數取值不會很病態.
求w的代碼實現:
def ridgeRegres(xMat,yMat,lam=0.2):
xTx = xMat.T*xMat
denom = xTx + eye(shape(xMat)[1])*lam
if linalg.det(denom) == 0.0:
print "This matrix is singular, cannot do inverse"
return
ws = denom.I * (xMat.T*yMat)
return ws
#### 在預處理數據的時候要對數據集進行標準化
def ridgeTest(xArr,yArr):
xMat = mat(xArr); yMat=mat(yArr).T
yMean = mean(yMat,0)
yMat = yMat - yMean
xMeans = mean(xMat,0) # 均值,對每一列求均值
xVar = var(xMat,0) # 方差
xMat = (xMat - xMeans)/xVar # 隨機變量標準化
numTestPts = 30
wMat = zeros((numTestPts,shape(xMat)[1]))
for i in range(numTestPts):
ws = ridgeRegres(xMat,yMat,exp(i-10))
wMat[i,:]=ws.T
return wMat
ridgeTest求了30個不同
Lasso
lasso算法在普通最小二乘法的基礎上增加了一個條件,完整寫的話就是
嶺迴歸可以改寫成
可以看出嶺迴歸與lasso只是一個是平方和受限,一個是絕對值和受限。
不同之處就在於當lambda足夠小時,有些權值係數會被迫減到0,有些特徵直接被忽略掉,因此能更好的展示出數據的特點。
但求解上述式子的解時,需要二次規劃,計算複雜,用一種更簡單的算法得到差不多的效果。
前向逐步迴歸
前向逐步算法是一種貪心算法,每一步都儘可能較小誤差,一開始所有的權重設爲1,每一步的決策時對某個權重增加或減小一個很小的值。
流程:
數據標準化,使其分佈滿足0均值和單位方差
在每輪迭代過程中:
設置當前最小誤差lowestError爲正無窮
對每個特徵:
增大或縮小:
改變一個係數得到一個新的w
計算新w下的誤差
如果誤差Error小於當前最小誤差lowestError:設置Wbest等於當前的w
將w設置爲新的Wbest
python實現:
def stageWise(xArr,yArr,eps=0.01,numIt=100):
xMat = mat(xArr); yMat=mat(yArr).T
yMean = mean(yMat,0)
yMat = yMat - yMean
xMat = regularize(xMat)
m,n=shape(xMat)
ws = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy()
returnMat = zeros((numIt,n))
for i in range(numIt):
#print ws.T
lowestError = inf;
for j in range(n):
for sign in [-1,1]:
wsTest = ws.copy()
wsTest[j] += eps*sign
yTest = xMat*wsTest
rssE = rssError(yMat.A,yTest.A)
if rssE < lowestError:
lowestError = rssE
wsMax = wsTest
ws = wsMax.copy()
returnMat[i,:]=ws.T
return returnMat