Linearing Regression:
算法:
python实现:
# coding=utf-8
from numpy import *
import matplotlib.pyplot as plt
filename = 'D:\machinelearninginaction\Ch08\ex0.txt'
numLen = len(open(filename).readline().split(('\t'))) - 1
dataMat = []
labelMat = []
fp = open(filename)
for line in fp.readlines():
lineAttr = []
print line
curLine = line.strip().split('\t')
for i in range(numLen):
lineAttr.append(float(curLine[i]))
dataMat.append(lineAttr)
labelMat.append(float(curLine[-1]))
print 'X:\n',dataMat,'\n','Y:\n',labelMat
#获取到的样本数据和标签数据
xMat = mat(dataMat)
yMat = mat(labelMat).T
xTx = xMat.T*xMat
if linalg.det(xTx) == 0:
print 'xTx mat is can\'t do inverse' #xTx不可以求逆矩阵
else:
ws = xTx.I*(xMat.T*yMat)
print 'The LinearRegression coef is:\n',ws
#现在可以根据获取的coef求出线性回归下的yhat
yhat = xMat * ws
print 'new y is:\n ',yhat
#绘制线性回归线
plt.scatter(xMat[:,1],yMat,color='black',marker='o')
plt.scatter(xMat[:,1],yhat,)
plt.show()
运行后可以得到回归系数ws: [[ 3.00774324] [ 1.69532264]]
也就是说我们得到的回归函数是: y = 3.008X0 + 1.695X1 + e
具体的算法就不多介绍了,网上很多,算法实现图如下:
上图是样本的位置,线性回归之后,可以看到回归线如下:
线性回归的使用与局限:
回归问题一般是对于连续数据的预测,比如预测价格的生长空间等,是很有用的算法。
因为线性回归是寻找到达回归线的个点的距离的平方之和的最小值, 所以理所当然的存在欠拟合和过拟合的问题。如果样本点的噪声过大,比如上图的样本点有几个点离回归线很远,可以认为这类点就是噪声点,这样势必会导致差方之和变大, 这样自然会导致最后的线性回归函数产生误差,导致欠拟合。
Ridge Regression:
算法:
普通线性回归的问题中,最小二乘回归求解的最小化问题是:,这个问题解存在且唯一的条件是
列满秩:
, 所以, 如果样本数大于特征数,则普通线性回归就不适用了。原因是xTx不可逆。这时候就需要岭回归出马了。
通过对普通线性回归的基础上加上一个惩罚因子
I 代表的是单位矩阵。通过引入这个惩罚因子能够减少不重要的参数,这种技术价叫做shrinkage(缩减技术)
python实现:
# coding=utf-8
from numpy import *
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)
labelMat.append(float(curLine[-1]))
return dataMat,labelMat
def ridgeRegress(xMat,yMat,lam = 0.2):
xTx = xMat.T*xMat
Imat = eye(shape(xMat)[1]) #创建的单位矩阵
punish = lam * Imat
punish = xTx + punish
if linalg.det(punish) == 0:
print 'punish mat is can\'t do inverse'
return
else:
ws = punish.I * (xMat.T * yMat)
return ws
#归一化处理
def normalize(xMat,yMat):
ymeans = mean(yMat,0)
yMat = yMat - ymeans
xmeans = mean(xMat,0)
xVar = var(xMat,0)
xMat = (xMat - xmeans)/xVar
return xMat,yMat
abx,aby = loadDataSet('D:\machinelearninginaction\Ch08\\abalone.txt')
abx,aby = normalize(mat(abx),mat(aby).T)
numtest = 30
wMat = zeros((numtest,shape(abx)[1]))
for i in range(numtest):
print exp(i-10)
ws = ridgeRegress(abx,aby,exp(i-10))
wMat[i,:] = ws.T
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(wMat)
plt.show()
这里对数据做了归一化处理,处理的目的就是希望对所有的特征都公平对待(当然也可以不用处理,这样通过Ridge可以分析哪些特征可有可无,之后会讨论)。关于归一化的介绍可以看这里。
在这里我对lambda设置了30个值,并且将这30个值得对应洗漱矩阵会话出来如下
X轴代表lambda,测试数据有8个特征,用8种颜色代表可以看出随着lambda的增大,系数最终会优化为0。
Ridge的可以在数据分析的过程中,优化掉不是很重要的参数,当然过度的优化最终导致就是所有的参数的系数都是0,模型也没有意义,所以在中间的某一点达到最优。
从这个图中也能看出哪些 特征值多回归影响比较大。
Ridge通过上述方式补足了对于线性回归欠拟合的处理。