线性模型(linear model)就是试图经过属性的线性组合来进行预测的函数,基本形式以下:
python
线性回归要求均方偏差最小:
git
咱们把上式写成矩阵的形式:
github
最小二乘法的代码以下:web
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
然而,现实状况是不少时候,
咱们在介绍岭回归以前先看一下局部加权线性回归。这首针对线性回归容易出现“欠拟合”现象提出的,由于它求的是具备最小均方偏差的无偏估计。若是模型欠拟合将不能取得最好的效果。因此有些方法在估计中引入一些误差,从而下降均方偏差。其中一个方法就是局部加权线性回归(Locally Wegihted Linear Regression,LWLR),咱们给待预测点附近的每一个点赋予必定的权重。回归系数
dom
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): #next 2 lines create weights matrix
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
文末给出的下载连接中regreesion.py文件中,有个线性加权回归例子。机器学习
就是在
ide
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 #to eliminate X0 take mean off of Y
#regularize X's
xMeans = mean(xMat,0) #calc mean then subtract it off
xVar = var(xMat,0) #calc variance of Xi then divide by it
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
ridgeRegres用于计算回归系数,ridgeTest用于在一组
一样在使用特征时,都要先进行归一化处理。svg
LASSO是least absolute shrinkage and selection operator的简称。咱们注意到增长以下约束,最小二乘法回归会获得与岭回归同样的公式:
函数
虽然用绝对值取代了平方和,但结果却差异很大。在
前向逐步回归能够获得与LASSO差很少的结果,但更加简单,是一种贪心算法,每一步都尽量减小偏差。一开始,全部权重设为1,而后每一步所作的决策是对某个权重增长或减小一个很小的值。
代码以下:
def stageWise(xArr,yArr,eps=0.01,numIt=100):
xMat = mat(xArr); yMat=mat(yArr).T
yMean = mean(yMat,0)
yMat = yMat - yMean #can also regularize ys but will get smaller coef
xMat = regularize(xMat)
m,n=shape(xMat)
returnMat = zeros((numIt,n)) #testing code remove
ws = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy()
for i in range(numIt):#could change this to while loop
#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
逐步线性回归主要优势在于它能够帮助人们理解现有模型并作出改进。当构建一个模型后,运行该算法找出重要的特征,这样就能够及时中止对那些不重要特征的收集。当应用缩减方法时,模型增长了误差(bias),也减小了方差。
上面是回归任务,若是咱们须要的是分类任务呢?咱们只须要找一个单调可微函数将分类任务的真实标记与线性回归的预测值就能够了。
二分类最理想的是“单位阶跃函数”(unit-step function)。可是此函数不连续,因而咱们但愿找一个单调可微的替代函数:
在此处咱们简便起见,直接采用梯度上升算法。咱们知道梯度算子老是指向函数值最快的方向。咱们每次向增加最快的方向移动一个值,称为步长,记为
def gradAscent(dataMatIn, classLabels):
dataMatrix = mat(dataMatIn)
labelMat = mat(classLabels).transpose()
m,n = shape(dataMatrix)
alpha = 0.001
maxCycles = 500
weights = ones((n,1))
for k in range(maxCycles):
h = sigmoid(dataMatrix*weights)
error = (labelMat - h) #vector subtraction
weights = weights + alpha * dataMatrix.transpose()* error
return weights
代码中求导很差操做,这里咱们用差分能够起到一样的效果。
梯度上升算法在每次更新回归系数时要遍历整个数据集,改进方法是一次仅用一个样本点来更新回归系数,称为“随机梯度上升算法”,这是一种在线算法。上述代码仍有改进之处,好比
改进后的随机梯度上升代码以下:
def stocGradAscent(dataMatrix, classLabels, numIter=150):
m,n = shape(dataMatrix)
weights = ones(n) #initialize to all ones
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(1.0+j+i)+0.0001 #apha decreases with iteration, does not
randIndex = int(random.uniform(0,len(dataIndex)))#go to 0 because of the constant
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex] - h
weights = weights + alpha * error * dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights
这里用个例子来使用Logistic回归来预测患有疝病的马存活问题。可是咱们发现了样本数据缺失问题,一般的解决方法有:
这里咱们所有用0来代替缺失值,这样在更新时不会影响系数。即特征对应0时,系数将保持0.5。咱们在数据中还发现了标签缺失,这个在强化学习中能够经过更靠近某些标签就将其标记为那个标签,在本例中因为此类较少,咱们直接丢弃。
(Linear Discriminant Analysis,LDA)与LDA(Latent Dirichlet Allocation)算法不要搞混了哦,虽然简写都是同样的。
LDA的思想很简单:设法将样例投影到一条直线上,使得同类样例的投影点近可能接近,异类样例的投影尽量原理,在对新样本进行分类时,将其投影到这条直线上,再根据投影点位置来肯定分类。
二分类问题推广到多分类主要用拆解法,主要策略有:
- 一对一
- 一对多
- 多对多
这样那个容易碰到类别不平衡问题,就是某类的数据量特别大或者特别少。
最后就是本文数据集和代码的下载地址啦,请点击这里。