修改添加注释,逻辑回归和回归

This commit is contained in:
chenyyx
2017-07-06 20:03:50 +08:00
parent 8de61578d9
commit d526490cc6
3 changed files with 135 additions and 34 deletions

View File

@@ -19,7 +19,7 @@ def loadDataSet(file_name):
fr = open(file_name)
for line in fr.readlines():
lineArr = line.strip().split()
# 将 X0 的值设为 1.0
# 为了方便计算,我们将 X0 的值设为 1.0 ,也就是在每一行的开头添加一个 1.0 作为 X0
dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
@@ -57,6 +57,7 @@ def gradAscent(dataMatIn, classLabels):
# print 'weights====', weights
# n*3 * 3*1 = n*1
h = sigmoid(dataMatrix*weights) # 矩阵乘法
# print 'hhhhhhh====', h
# labelMat是实际值
error = (labelMat - h) # 向量相减
# 0.001* (3*m)*(m*1) 表示在每一个列上的一个误差情况,最后得出 x1,x2,xn的系数的偏移量
@@ -110,6 +111,17 @@ def stocGradAscent1(dataMatrix, classLabels, numIter=150):
# 可视化展示
def plotBestFit(dataArr, labelMat, weights):
'''
Desc:
将我们得到的数据可视化展示出来
Args:
dataArr:样本数据的特征
labelMat:样本数据的类别标签,即目标变量
weights:回归系数
Returns:
None
'''
n = shape(dataArr)[0]
xcord1 = []; ycord1 = []
xcord2 = []; ycord2 = []
@@ -146,8 +158,8 @@ def main():
# 因为数组没有是复制n份 array的乘法就是乘法
dataArr = array(dataMat)
# print dataArr
# weights = gradAscent(dataArr, labelMat)
weights = stocGradAscent0(dataArr, labelMat)
weights = gradAscent(dataArr, labelMat)
# weights = stocGradAscent0(dataArr, labelMat)
# weights = stocGradAscent1(dataArr, labelMat)
# print '*'*30, weights

View File

@@ -182,7 +182,6 @@ plt.show()
# Logistic Regression 3-class Classifier 逻辑回归 3-类 分类器
'''
print(__doc__)
import numpy as np
@@ -224,11 +223,11 @@ plt.xticks(())
plt.yticks(())
plt.show()
'''
# Logistic function 逻辑回归函数
# 这个类似于咱们之前讲解 logistic 回归的 Sigmoid 函数,模拟的阶跃函数
'''
print(__doc__)
import numpy as np
@@ -276,5 +275,7 @@ plt.xlim(-4, 10)
plt.legend(('Logistic Regression Model', 'Linear Regression Model'),
loc="lower right", fontsize='small')
plt.show()
'''

View File

@@ -48,7 +48,7 @@ def standRegres(xArr,yArr):
xArr :输入的样本数据,包含每个样本数据的 feature
yArr :对应于输入数据的类别标签,也就是每个样本对应的目标变量
Returns:
ws回归系数
'''
# mat()函数将xArryArr转换为矩阵 mat().T 代表的是对矩阵进行转置操作
@@ -71,67 +71,155 @@ def standRegres(xArr,yArr):
def lwlr(testPoint,xArr,yArr,k=1.0):
'''
Description
局部加权线性回归
局部加权线性回归,在待预测点附近的每个点赋予一定的权重,在子集上基于最小均方差来进行普通的回归。
Args
testPoint
xArr
yArr
k:
testPoint样本点
xArr样本的特征数据,即 feature
yArr每个样本对应的类别标签,即目标变量
k:关于赋予权重矩阵的核的一个参数,与权重的衰减速率有关
Returns:
testPoint * ws数据点与具有权重的系数相乘得到的预测点
Notes:
这其中会用到计算权重的公式w = e^((x^((i))-x) / -2k^2)
理解x为某个预测点x^((i))为样本点,样本点距离预测点越近,贡献的误差越大(权值越大),越远则贡献的误差越小(权值越小)。
关于预测点的选取在我的代码中取的是样本点。其中k是带宽参数控制w钟形函数的宽窄程度类似于高斯函数的标准差。
算法思路假设预测点取样本点中的第i个样本点共m个样本点遍历1到m个样本点含第i个算出每一个样本点与预测点的距离
也就可以计算出每个样本贡献误差的权值可以看出w是一个有m个元素的向量写成对角阵形式
'''
xMat = mat(xArr); yMat = mat(yArr).T
m = shape(xMat)[0] # 获得xMat矩阵的行数
weights = mat(eye((m))) # eye()返回一个对角线元素为1其他元素为0的二维数组创建权重矩阵
for j in range(m): # 下面两行创建权重矩阵
diffMat = testPoint - xMat[j,:] # 遍历数据集,计算每个样本点对应的权重值
weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))#k控制衰减的速度
# mat() 函数是将array转换为矩阵的函数 mat().T 是转换为矩阵之后,再进行转置操作
xMat = mat(xArr)
yMat = mat(yArr).T
# 获得xMat矩阵的行数
m = shape(xMat)[0]
# eye()返回一个对角线元素为1其他元素为0的二维数组创建权重矩阵weights该矩阵为每个样本点初始化了一个权重
weights = mat(eye((m)))
for j in range(m):
# testPoint 的形式是 一个行向量的形式
# 计算 testPoint 与输入样本点之间的距离,然后下面计算出每个样本贡献误差的权值
diffMat = testPoint - xMat[j,:]
# k控制衰减的速度
weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))
# 根据矩阵乘法计算 xTx ,其中的 weights 矩阵是样本点对应的权重矩阵
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)) # 计算出回归系数的一个估计
# 计算出回归系数的一个估计
ws = xTx.I * (xMat.T * (weights * yMat))
return testPoint * ws
def lwlrTest(testArr,xArr,yArr,k=1.0): # 循环所有的数据点并将lwlr运用于所有的数据点
def lwlrTest(testArr,xArr,yArr,k=1.0):
'''
Description
测试局部加权线性回归,对数据集中每个点调用 lwlr() 函数
Args
testArr测试所用的所有样本点
xArr样本的特征数据即 feature
yArr每个样本对应的类别标签即目标变量
k控制核函数的衰减速率
Returns
yHat预测点的估计值
'''
# 得到样本点的总数
m = shape(testArr)[0]
# 构建一个全部都是 0 的 1 * m 的矩阵
yHat = zeros(m)
# 循环所有的数据点并将lwlr运用于所有的数据点
for i in range(m):
yHat[i] = lwlr(testArr[i],xArr,yArr,k)
# 返回估计值
return yHat
def lwlrTestPlot(xArr,yArr,k=1.0): # 首先将 X 排序其余的都与lwlrTest相同这样更容易绘图
yHat = zeros(shape(yArr))
def lwlrTestPlot(xArr,yArr,k=1.0):
'''
Description:
首先将 X 排序其余的都与lwlrTest相同这样更容易绘图
Args
xArr样本的特征数据即 feature
yArr每个样本对应的类别标签即目标变量实际值
k控制核函数的衰减速率的有关参数这里设定的是常量值 1
Return
yHat样本点的估计值
xCopyxArr的复制
'''
# 生成一个与目标变量数目相同的 0 向量
yHat = zeros(shape(yArr))
# 将 xArr 转换为 矩阵形式
xCopy = mat(xArr)
# 排序
xCopy.sort(0)
# 开始循环,为每个样本点进行局部加权线性回归,得到最终的目标变量估计值
for i in range(shape(xArr)[0]):
yHat[i] = lwlr(xCopy[i],xArr,yArr,k)
return yHat,xCopy
def rssError(yArr,yHatArr): # yArr 和 yHatArr 两者都需要是数组
def rssError(yArr,yHatArr):
'''
Desc:
计算分析预测误差的大小
Args:
yArr真实的目标变量
yHatArr预测得到的估计值
Returns:
计算真实值和估计值得到的值的平方和作为最后的返回值
'''
return ((yArr-yHatArr)**2).sum()
def ridgeRegres(xMat,yMat,lam=0.2): # 岭回归
def ridgeRegres(xMat,yMat,lam=0.2):
'''
Desc
这个函数实现了给定 lambda 下的岭回归求解。
如果数据的特征比样本点还多,就不能再使用上面介绍的的线性回归和局部现行回归了,因为计算 (xTx)^(-1)会出现错误。
如果特征比样本点还多n > m也就是说输入数据的矩阵x不是满秩矩阵。非满秩矩阵在求逆时会出现问题。
为了解决这个问题,我们下边讲一下:岭回归,这是我们要讲的第一种缩减方法。
Args
xMat样本的特征数据即 feature
yMat每个样本对应的类别标签即目标变量实际值
lam引入的一个λ值使得矩阵非奇异
Returns
经过岭回归公式计算得到的回归系数
'''
xTx = xMat.T*xMat
denom = xTx + eye(shape(xMat)[1])*lam # 按照书上的公式计算计算回归系数
if linalg.det(denom) == 0.0: # 检查行列式是否为零,即矩阵是否可逆
# 岭回归就是在矩阵 xTx 上加一个 λI 从而使得矩阵非奇异,进而能对 xTx + λI 求逆
denom = xTx + eye(shape(xMat)[1])*lam
# 检查行列式是否为零即矩阵是否可逆行列式为0的话就不可逆不为0的话就是可逆。
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) # 计算Y均值
yMat = yMat - yMean # Y的所有的特征减去均值
# 标准化 x
xMeans = mean(xMat,0) # X计算平均值
xVar = var(xMat,0) # 然后计算 X的方差
'''
Desc
函数 ridgeTest() 用于在一组 λ 上测试结果
Args
xArr样本数据的特征即 feature
yArr样本数据的类别标签即真实数据
Returns
wMat将所有的回归系数输出到一个矩阵并返回
'''
xMat = mat(xArr)
yMat=mat(yArr).T
# 计算Y的均值
yMean = mean(yMat,0)
# Y的所有的特征减去均值
yMat = yMat - yMean
# 标准化 x计算 xMat 平均值
xMeans = mean(xMat,0)
# 然后计算 X的方差
xVar = var(xMat,0)
# 所有特征都减去各自的均值并除以方差
xMat = (xMat - xMeans)/xVar
# 可以在 30 个不同的 lambda 下调用 ridgeRegres() 函数。
numTestPts = 30
wMat = zeros((numTestPts,shape(xMat)[1]))# 创建30 * m 的全部数据为0 的矩阵
# 创建30 * m 的全部数据为0 的矩阵
wMat = zeros((numTestPts,shape(xMat)[1]))
for i in range(numTestPts):
ws = ridgeRegres(xMat,yMat,exp(i-10))# exp返回e^x
# exp() 返回 e^x
ws = ridgeRegres(xMat,yMat,exp(i-10))
wMat[i,:]=ws.T
return wMat