一、线性回归
在现实生活中普遍存在着变量之间的关系,有确定的和非确定的。确定关系指的是变量之间可以使用函数关系式表示,还有一种是属于非确定的(相关),比如人的身高和体重,一样的身高体重是不一样的。
线性回归一般用来做连续值的预测,预测的结果为一个连续值。因训练时学习样本不仅要提供学习的特征向量X,而且还要提供样本的实际结果(标记label),所以它是一种有监督学习。其中
线性回归需要学习得到的是一个映射关系 f:X→y,即当给定新的待预测样本时,我们可以通过这个映射关系得到一个测试样本 X 的预测值 y 。
在线性回归中,假定输入X和输出y之间具有线性相关的关系。
例如当特征向量 X 中只有一个特征时,需要学习到的函数应该是一个一元线性函数 y=a+bx。
当情况复杂时,考虑 X 存在n个特征的情形下,我们往往需要得到更多地系数。我们将 X 到 y 的映射函数记作函数hw(X):
其中,为了在映射函数hw(X)中保留常数项,令 x0 为1,所以特征向量X={1,x1,x2,…,xn},特征系数向量 w={w0,w1,w2,…,wn} 。
当给定一个训练集数据的情况,可以通过某个算法,学习出来一个线性的映射函数 hw(X) 来求得预测值 y。
二、 用线性回归找到最佳拟合直线
应该怎么从一大堆数据里求出回归方程呢?假定输入数据存放在矩阵X中,结果存放在向量y中
而回归系数存放在向量w中:
那么对于给定的数据x1,即矩阵X的第一列数据,预测结果u1将会通过如下公式给出:
三、损失函数(cost):
手里有数据矩阵X和对应的标签向量y,怎么才能找到w呢?这里采用最小二乘法。
a.最小二乘法:
何为最小二乘法,其实很简单。我们有很多的给定点,这时候我们需要找出一条线去拟合它,那么我先假设这个线的方程,然后把数据点代入假设的方程得到观测值,求使得实际值与观测值相减的平方和最小的参数。对变量求偏导联立便可求。
平方误差和可以写做:
用矩阵表示还可以写做:
用矩阵表示的平方误差和对w进行求导:
令上述公式等于0,得到:
w上方的小标记表示,这是当前可以估计出的w的最优解。从现有数据上估计出的w可能并不是数据中的真实w值,所以这里使用了一个”帽”符号来表示它仅是w的一个最佳估计。上述公式中包含逆矩阵,也就是说,这个方程只在逆矩阵存在的时候使用,也即是这个矩阵是一个方阵,并且其行列式不为0。
奇异矩阵
奇异矩阵是线性代数的概念,就是对应的行列式等于0的矩阵。
奇异矩阵的判断方法:首先,看这个矩阵是不是方阵(即行数和列数相等的矩阵。若行数和列数不相等,那就谈不上奇异矩阵和非奇异矩阵)。 然后,再看此方阵的行列式|A|是否等于0,若等于0,称矩阵A为奇异矩阵;若不等于0,称矩阵A为非奇异矩阵。 同时,由|A|≠0可知矩阵A可逆,这样可以得出另外一个重要结论:可逆矩阵就是非奇异矩阵,非奇异矩阵也是可逆矩阵。
import numpy as np
def loadDataSet(fileName):
"""
:param fileName: 文件名
:return:
xArr-x数据集
yArr-y数据集
"""
numFeat = len(open(fileName).readline().split('\t')) -1#一行元素个数减去1
xArr = []
yArr = []
f = open(fileName)
for line in f.readlines():
lineArr = []
curLine = line.split('\t')
for i in range(numFeat):
lineArr.append(float(curLine[i]))#把切分得到的字符串转成float类型
xArr.append(lineArr)
yArr.append(float(curLine[-1]))
return xArr,yArr
def standRegres(xArr,yArr):
"""
:param xArr: x数据集
:param yArr: y数据集
:return:
ws - 回归系数
"""
xMat = np.mat(xArr)
yMat = np.mat(yArr).T
xTx = xMat.T*xMat
if np.linalg.det(xTx) ==0.0:
print('矩阵为奇异矩阵,不能求逆')
return
ws = xTx.I*(xMat.T*yMat)#I为单位矩阵
return ws
if __name__ == '__main__':
fileName = '/home/python/Desktop/untitled/regression/ex1.txt'
xArr, yArr = loadDataSet(fileName)
ws = standRegres(xArr, yArr)
xMat = np.mat(xArr)
yMat = np.mat(yArr)
yHat = xMat*ws
print(np.corrcoef(yHat.T,yMat))
几乎任一数据集都可以用上述方法建模,那么如何判断这些模型的好坏呢?有种方法可以计算预测值yMat序列和真实中y序列的匹配程度,那就是计算这两个序列的相关系数。在Python中Numpy提供了相关系数的计算方法:可以通过corrcoef(yEstimate,yActual)来计算预测值和真实值的相关性。
可以看到,对角线上的数据是1.0,因为yMat和自己的匹配是完美的,而YHat和yMat的相关系数为0.98。
最佳拟合直线方法将数据视为直线进行建模,具有十分不错的表现。数据当中似乎还存在其他的潜在模式。那么如何才能利用这些模式呢?我们可以根据数据来局部调整预测,下面就会介绍这种方法。
2 局部加权线性回归
线性回归的一个问题是有可能出现欠拟合现象,因为它求的是具有小均方误差的无偏估 计。显而易见,如果模型欠拟合将不能取得好的预测效果。所以有些方法允许在估计中引入一 些偏差,从而降低预测的均方误差。
其中的一个方法是局部加权线性回归(Locally Weighted Linear Regression,LWLR)。在该方法中,我们给待预测点附近的每个点赋予一定的权重。与kNN一样,这种算法每次预测均需要事先选取出对应的数据子集。该算法解除回归系数W的形式如下:
其中W是一个矩阵,这个公式跟我们上面推导的公式的区别就在于W,它用来给每个店赋予权重。
LWLR使用”核”(与支持向量机中的核类似)来对附近的点赋予更高的权重。核的类型可以自由选择,最常用的核就是高斯核,高斯核对应的权重如下:
局部加权线性回归,我们通过改变k的值,可以调节回归效果。
def lwlr(testPoint, xArr, yArr, k = 1.0):
"""
局部加权线性回归计算回归系数w
Parameters:
testPoint - 测试样本点
xArr - x数据集
yArr - y数据集
k - 高斯核的k,自定义参数
Returns:
ws - 回归系数
"""
xMat = np.mat(xArr)
yMat = np.mat(yArr).T
m = np.shape(xMat)[0]
weights = np.mat(np.eye((m))) #创建权重对角矩阵
for j in range(m): #遍历数据集计算每个样本的权重
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("矩阵为奇异矩阵,不能求逆")
return
ws = xTx.I * (xMat.T * (weights * yMat)) #计算回归系数
return testPoint * ws
def lwlrTest(testArr, xArr, yArr, k=1.0):
"""
局部加权线性回归测试
Parameters:
testArr - 测试数据集
xArr - x数据集
yArr - y数据集
k - 高斯核的k,自定义参数
Returns:
ws - 回归系数
"""
m = np.shape(testArr)[0] #计算测试数据集大小
yHat = np.zeros(m) for i in range(m): #对每个样本点进行预测
yHat[i] = lwlr(testArr[i],xArr,yArr,k)
return yHat