1.局部线性加权回归本质
就是在普通线性回归函数推导过程中的J(theta)每一项前面加一个权值,一般是如下的函数
所以想要预测的点(x的值)不同,回归函数就不一样,相当于根据预测点,离预测点较近的样本权值就大,离预测点远的样本权值就小。
2.线性回归和logistic回归比较
其实logistic回归的本质就是线性回归,解释如下:
回归函数模型:
其中x0,x1......xn表示的是不同的影响因素,也就是不同的自变量,比如f(x)是预测房价的话,影响房价的可能是地段,面积等因素,就是不同的自变量。
sigmoid函数:
logistic回归模型的预测函数
也就是广义的线性回归函数
3.logistic回归模型推导
注1:P(y=1|X;θ)表示在X变量为某个值的条件下,θ为参数的情况下y=1的概率大小。
这里直接假设概率大小就为hθ(X),一方面是因为sigmoid函数刚好在0-1之间,并且比较符合要求,
最后一项中中可以把j忽视去理解。
用logistic回归解决的是分类问题,也就是将数据分成两类,而sigmoid函数图像如上所示,当X远远大于0或者小于0时,一定是1类或者0类,而在0附近时,可能是1类,可能是0类,这就有一个0-1的概率,我们可以假定当概率小于0.5,就归为0类,当概率大于等于0.5就归为1类。现在使用最小似然法,让已发生的样本的概率最大,来求出参数。所以假设hθ(X)为概率值。
Python代码演示
import numpy as np
import matplotlib.pyplot as plt
# 读取文本数据,返回数据集和目标值
def loadDataSet():
dataMat = []
labelMat = []
fr = open('testSet.txt')
for line in fr.readlines():
lineArr = line.strip().split()#strip()指示移除首尾的空格,并不会改变字符串中间的值,比如有个字符串是' -0.017612 14.053064 0 ',经过strip()后为'-0.017612 14.053064 0'
# 将字符串按默认的空格切分成一个字符串列表
# 该数据集中,添加了一列并初始化为1,便于后续的计算,但是在其他数据集中,一般没有必要添加
dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
labelMat.append(int(lineArr[2]))
return dataMat,labelMat
# 运算的核心函数Sigmoid
def sigmoid(inX):
return 1.0 / (1+np.exp(-inX))
# 核心函数alpha*gradient更新回归系数
def gradAscent(dataMatIn, classLabels):
# 为了便于计算,mat将两个列表数据转换为numpy的数组
dataMatrix = np.mat(dataMatIn)# 每一组坐标存储到dataMatrix矩阵中,所以dataMatrix是一个3列多行的矩阵,其中第一行都是1,是因为常数项为1,这个可以参考梯度下降法
labelMat = np.mat(classLabels).transpose() # transpose矩阵转置,每一组坐标对应的类存储到labelMat矩阵中,所以labelMat矩阵是1列多行
m,n = np.shape(dataMatrix)#返回dataMatrix的行数和列数
alpha = 0.001 # 设置步长
maxCycles = 50000 # 设置循环次数
weights = np.ones((n,1)) # 初始化每个特征的回归系数为1,weights为theta
h = sigmoid(dataMatrix*weights)
error = (labelMat - h)
print(alpha * dataMatrix.transpose() * error)
#h = sigmoid(dataMatrix*weights)
#error = (labelMat - h)
#weights = weights + alpha * dataMatrix.transpose() * error
#while not np.all(np.absolute(error)<=0.6):#这是另外一种判断方法,让所有样本误差都小于0.6,但是这种方法精度不高,由于有一些点的误差是迭代很多次也不能降到0.5以下的,所以建议直接填写迭代次数。
for k in range(maxCycles):
# 得到每一行的sigmoid值 (两个相乘得到z值)
h = sigmoid(dataMatrix*weights) # 矩阵相乘 sigmoid(sum(每个特征*每个系数)) 行*列,由于是矩阵相乘,所以在相乘时便求和了,就是(theta^T)*X
# 用一直更新的回归系数求预测值,然后与真实值之间求误差,误差越来越小,则系数更新变化也越来越小,最后趋于稳定
error = (labelMat - h) # 每行分类与对应sigmoid相减 误差值越来越小了
# 数据集转置*误差 每条样本*该样本的误差值
weights = weights + alpha * dataMatrix.transpose() * error
return weights
#画图像的函数,可以忽略
def plotBestFit(weights):
dataMat,labelMat=loadDataSet()
dataArr = np.array(dataMat)
n = np.shape(dataArr)[0]
xcord1 = []; ycord1 = []
xcord2 = []; ycord2 = []
for i in range(n):
if int(labelMat[i])== 1:
xcord1.append(dataArr[i,1])
ycord1.append(dataArr[i,2])
else:
xcord2.append(dataArr[i,1])
ycord2.append(dataArr[i,2])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
ax.scatter(xcord2, ycord2, s=30, c='green')
x = np.arange(-3.0, 3.0, 0.1)
y = (-weights[0]-weights[1]*x)/weights[2] #由sigmoid=0这个分界点 使用唯一非常量Z 来构造函数
ax.plot(x, y)
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
dataArr,labelMat = loadDataSet()
weights = gradAscent(dataArr,labelMat)
print(weights)
plotBestFit(weights.getA())