广义的线性模型是最最常用和我个人认为最重要的
- 最小二乘
class
sklearn.linear_model.
LinearRegression
(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1)fit_intercept=True表示是否计算截距,就是最后的那个 Y=w1X1+w2X2+b的b,normalize表示是都需要标准化
from sklearn import linear_model reg = linear_model.LinearRegression() reg.fit ([[0, 0], [1, 1], [2, 2]], [0, 1, 2]) reg.coef_
- 岭回归
这是对上面的一个优化, 变成了, 是控制系数收缩量的复杂性参数: 的值越大,收缩量越大,这样系数对共线性的鲁棒性也更强
class
sklearn.linear_model.
Ridge
(alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver='auto', random_state=None)alpha就是公式上的alpha,正则话参数,后面几个和最小二乘一样
solver的选择如下列表:{"auto","svd","cholesky","sparse_cg","lsqr","sag"}
'auto'根据数据类型自动选择求解器;'svd'使用X的奇异值分解来计算岭系数;'cholesky'使用标准的scipy.linalg.solve函数来获得封闭形式的解决方案;'sparse_cg'使用scipy.sparse.linalg.cg中的共轭梯度求解器;'lsqr'使用专用的正则化最小二乘例程scipy.sparse.linalg.lsqr;'sag'使用随机平均梯度下降
from sklearn.linear_model import Ridge import numpy as np n_samples, n_features = 10, 5 np.random.seed(0) y = np.random.randn(n_samples) X = np.random.randn(n_samples, n_features) clf = Ridge(alpha=1.0) clf.fit(X, y)对于有些矩阵,矩阵中某个元素的一个很小的变动,会引起最后计算结果误差很大,这种矩阵称为“病态矩阵”。有些时候不正确的计算方法也会使一个正常的矩阵在运算中表现出病态。对于高斯消去法来说,如果主元(即对角线上的元素)上的元素很小,在计算时就会表现出病态的特征。
回归分析中常用的最小二乘法是一种无偏估计。对于一个适定问题,X通常是列满秩的采用最小二乘法,定义损失函数为残差的平方,最小化损失函数上述优化问题可以采用梯度下降法进行求解,也可以采用如下公式进行直接求解当X不是列满秩时,或者某些列之间的线性相关性比较大时, 的行列式接近于0,即 接近于奇异,上述问题变为一个不适定问题,此时,计算时误差会很大,传统的最小二乘法缺乏稳定性与可靠性。为了解决上述问题,我们需要将不适定问题转化为适定问题:我们为上述损失函数加上一个正则化项,变为其中,我们定义 ,于是:上式中, 是单位矩阵。随着的增大, 各元素的绝对值均趋于不断变小,它们相对于正确值的偏差也越来越大。趋于无穷大时,趋于0。其中, 随 的改变而变化的轨迹,就称为岭迹。实际计算中可选非常多的值,做出一个岭迹图,看看这个图在取哪个值的时候变稳定了,那就确定值了。
岭回归是对最小二乘回归的一种补充,它损失了无偏性,来换取高的数值稳定性,从而得到较高的计算精度。
PS:奇异矩阵就是行列式=0;也代表着行列式的向量有线性相关;线性相关也就意味着最起码有两个向量式Y=AX+B的关系,也就是说有一行向量根本不起作用,也就是说在一个方阵中有M个变量,却只有M-1个方程式,那么根本解不了方程,既然解不了方程,你这个最小二乘的结果.....是不是有点....不对了,所以才出现了岭回归。(个人理解)
所以在看到属性式如下:工资,房产,......., [ label ] 这样的数据,就不要用最小二乘拟合了,试试岭回归,因为工资和房产有线性关系,感觉结果不如后者(个人感觉....没有测试过);还有一种情况,就是一个属性的值一直都很小很接近,比如0.000012,0.000011,0.000013;这样的数据,我感觉这样一来一条属性就费了,那在一个方阵中有一个属性不起作用,也就是一列都是0,方程也解不了啊,建议不要用最小二乘拟合。
线性回归 工作原理
读入数据,将数据特征x、特征标签y存储在矩阵x、y中 验证 x^Tx 矩阵是否可逆 使用最小二乘法求得 回归系数 w 的最佳估计
线性回归 开发流程
收集数据: 采用任意方法收集数据 准备数据: 回归需要数值型数据,标称型数据将被转换成二值型数据 分析数据: 绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后,可以将新拟合线绘在图上作为对比 训练算法: 找到回归系数 测试算法: 使用 R^2 或者预测值和数据的拟合度,来分析模型的效果 使用算法: 使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签
线性回归 算法特点
优点:结果易于理解,计算上不复杂。 缺点:对非线性的数据拟合不好。 适用于数据类型:数值型和标称型数据。
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 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#岭回归
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): # 因为alpha不同,效果不同所以可以看看不同的alpha对解过有什么不一样
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
- Lasso回归(上面的岭回归是二范数--最优化理论第一章讲的就是范数)
class
sklearn.linear_model.
Lasso
(alpha=1.0, fit_intercept=True, normalize=False, precompute=False, copy_X=True, max_iter=1000, tol=0.0001, warm_start=False, positive=False, random_state=None, selection='cyclic')参数中有一个max_iter,最大迭代次数,因为Losso不是平方,是绝对值计算,所以不能直接求解,只能迭代求解
from sklearn import linear_model clf = linear_model.Lasso(alpha=0.1) clf.fit([[0,0], [1, 1], [2, 2]], [0, 1, 2]) print(clf.coef_) print(clf.intercept_)Lasso回归是Ridger回归发展的,如果有太多的特征,可以用此方法
因为是线性,所以比非线性解算方便。但是L1范数的惩罚项,带有绝对值,求导之后存在尖点,所以需要通过迭代算法来进行求解,不能直接得到解析解。迭代求解方法:
(1)坐标轴下降法
(2)最小角回归法(Least Angle Regression,LAR)
(3)前向选择法(Forward Selection method)
(4)前向梯度法(Forward stagewise method)
逐步向前回归模拟:
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):
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