Logistics回归模型通常被用于处理二分类问题,它是一种用于分析各个影响因素(x1,x2,…xn)与分类结果y之间关系的有监督学习方法。虽然它的名字是“回归”,但实际却是一种分类学习方法。这里的“回归”一词源于最佳拟合,表示要找到最佳拟合参数集,因此,logistic训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化方法。
1.Logistic回归概述
我们都知道使用线性模型可以进行回归学习,但若要做的是分类任务改如何处理?只需要找一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值联系起来。
考虑二分类任务,其输出标记y的取值为0和1,而线性回归模型产生的预测值是实值,于是需将实值z转换为0/1值。通过Sigmoid函数引入非线性因素,可以实现实值z转换为0/1值,处理二分类问题。
1.1 Sigmoid函数
首先我们先介绍Sigmoid函数,也称为逻辑函数
g(x)=11+e−xg(x) = frac{1}{1+e^{-x}}
其函数图像如下
从上图可以看出sigmoid函数是一个s形的曲线,它的取值是[0,1]之间,在远离0的地方函数的值会很快接近0或者1。它的这个特性对于解决二分类问题十分重要。
逻辑回归的假设函数形式如下:
y=g(ωTx+b)g(z)=11+e−zy=g(omega^Tx+b )quad g(z) = frac{1}{1+e^{-z}}
所以:
y=g(ωTx+b)变为y=11+e−ωTx+by=g(omega^Tx+b )quad 变为 y = frac{1}{1+e^{-{omega^Tx+b}}}
其中x是我们的输入,w和b为我们要求取的参数
若将y视为样本x作为正例的可能性,则1-y是其反例可能性,两者的比值为y1−yfrac{y}{1-y}称为“几率”,反映了x作为正例的相对可能性
样本作为正例的相对可能性的对数
lny1−y=lnp(y=1∣x)p(y=0∣x)=ωTx+bln frac{y}{1-y}=lnfrac{p(y=1|x)}{p(y=0|x)}=omega^Tx+b
因此有:
p(y=1∣x)=eωTx+b1+eωTx+bp(y=1|x) = frac{e^{omega^Tx+b}}{1+e^{omega^Tx+b}}
p(y=1∣x)=11+eωTx+bp(y=1|x) = frac{1}{1+e^{omega^Tx+b}}
上面两个式子分别表示y=1和y=0的概率。上述过程我们通过sigmoid函数将z值映射到0到1之间,获得数值之后就可以进行分类。如定义阈值为0.5,y*为分类结果,则y∗=1,ifP(y=1∣x)>0.5,y∗=0,ifP(y=1∣x)⩽0.5y^*=1,ifP(y=1|x)>0.5,y^*=0,ifP(y=1|x)leqslant0.5实际应用时特定的情况可以选择不同的阈值。接下来我们要解决的问题就是获得最佳回归系数,即求解w和b得值。
1.2 基于最优化方法的最佳回归系数确定
1.2.1 极大似然估计
极大似然估计的方法步骤:
- 确定待求解的未知参数θ1,θ2,…θntheta_1,theta_2,…theta_n,如均值、方差或特定分布函数的参数等;
- 计算每个样本X1,X2,…,XnX_1,X_2,…,X_n的概率密度为f(Xi;θ1,θ2,…θm)f(X_i;theta_1,theta_2,…theta_m);
- 根据样本的概率密度累乘构造似然函数L(θ1,θ2,…θm)=∏f(Xi;θ1,θ2,…θm)L(theta_1,theta_2,…theta_m)=prod{f(X_i;theta_1,theta_2,…theta_m)};
- 通过似然函数最大化(求导为0),求解未知参数θ,为了降低计算难度,可采用对数加法替换概率乘法,通过导数为0/极大值来求解未知参数。
我们可通过“极大似然法”来估计w和b,给定数据集{(xi,yi)(x_i,y_i)}i=1m{}^m_{i=1}最大化样本属于其真实标记的概率,等同于最大化对数似然函数
l(ω,b)=∑i=1mlnp(yi∣xi;ω,b)l(omega,b)=sum_{i=1}^mlnp(y_i|x_i;omega,b)
方便于讨论,令β=(ω;b),x,=(x;1)beta=(omega;b),x^,=(x;1),则ωTx+bomega^Tx+b可简化为βTx,beta^Tx^,
令p1(x,;β)=p(y=1∣x,;β),p0(x,;β)=p(y=0∣x,;β)=1−p1(x,;β)p_1(x^,;beta)=p(y=1|x^,;beta),p_0(x^,;beta)=p(y=0|x^,;beta)=1-p_1(x^,;beta),则上述式中的似然项可重写为
p(yi∣xi;ω,b)=yip1(x,;β)+(1−yi)p0(x,;β)p(y_i|x_i;omega,b)=y_ip_1(x^,;beta)+(1-y_i)p_0(x^,;beta)
根据sigmoid函数,似然函数可重写为
l(ω,b)=∑i=1m(−yiβTxi+ln(1+eβTxi))l(ω,b)=sum_{i=1}^m(-y_ibeta^Tx_i+ln(1+e^{beta^Tx_i}))
最大化对数似然函数等价于最小化l(β)l(beta),l(β)l(beta)是关于βbeta的高阶可导连续凸函数,经典的数值优化算法如梯度下降法可求得其最优解
1.2.2梯度上升法
梯度上升法基本的思想是:要找到某函数的 最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇,则函数f(x,y)的梯度由 下式表示:
∇f(x,y)=[∂f(x,y)∂x∂f(x,y)∂y]nabla f(x,y)=begin{bmatrix}
frac{partial f(x,y)}{partial x}\
quad\
frac{partial f(x,y)}{partial y}
end{bmatrix}
这个梯度意味着要沿x的方向移动∂f(x,y)∂xfrac{partial f(x,y)}{partial x},沿y的方向移动∂f(x,y)∂xfrac{partial f(x,y)}{partial x}其中,函数f(x,y) 必须要在待计算的点上有定义并且可微。如下图:
梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2。如此循环迭代,直到满足停止条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向。我们知道了移动的反向,那移动量的大小是多少。该量值称为步长,记做α。用向量来表示的话,梯度上升算法的迭代公式如下:
ω:=ω+α∇ωf(ω)omega:=omega+alphanabla_omega f(omega)
该公式将一直被迭代执行,直至达到某个停止条件为止,比如迭代次数达到某个指定值或算法达到某个可以允许的误差范围
1.2.3梯度下降算法
梯度下降算法,它与上述的梯度上升算法是一样的,只是公式中的加法需要变成减法。因此,对应的公式可以写成:
ω:=ω−α∇ωf(ω)omega:=omega-alphanabla_omega f(omega)
梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。
2.Logistic实例分析
利用Logistic回归模型根据身高、体重和肺活量预测性别
2.1 准备数据
2.2使用梯度上升算法进行分类
sigmoid函数:
# sigmoid函数
def sigmoid(inX):
return 1.0 / (1 + exp(-inX))
梯度上升算法:
# 梯度上升算法
def gradAscent(dataMatIn, classLabels): # dataMatIn数据集、classLabels数据标签
dataMatrix = mat(dataMatIn) # 转换为NumPy矩阵
labelMat = mat(classLabels).transpose() # 转换为NumPy矩阵,并且矩阵转置
m, n = shape(dataMatrix) # 获取数据集矩阵的大小,m为行数,n为列数
alpha = 0.001 # 目标移动的步长
maxCycles = 500 # 迭代次数
weights = ones((n, 1)) # 权重初始化为1
for k in range(maxCycles): # 重复矩阵运算
h = sigmoid(dataMatrix * weights) # 矩阵相乘,计算sigmoid函数
error = (labelMat - h) # 计算误差
weights = weights + alpha * dataMatrix.transpose() * error # 矩阵相乘,更新权重
return weights
使用Logistic 回归方法进行分类并不需要做很多工作,所需做的只是把测试集上每个特征向量乘以最优化方法得来的回归系数,再将该乘积结果求和,最后输入到Sigmoid函数中即可。如果对应的Sigmoid值大于0.5就预测类别标签为1,否则为0。
# 分类函数
def classifyVector(inX, weights):
prob = sigmoid(sum(inX * weights)) # 计算sigmoid值
if prob > 0.5: # 概率大于0.5,返回分类结果1.0
return 1.0
else: # 概率小于等于0.5,返回分类结果0.0
return 0.0
def colicTest1():
# 读取测试集和训练集,并对数据进行格式化处理
frTrain = open("D:syyMachineLearningdatadataTrain.txt") # 读取训练集文件
frTest = open('D:syyMachineLearningdatadataTest.txt') # 读取测试集文件
trainingSet = [] # 创建数据列表
trainingLabels = [] # 创建标签列表
for line in frTrain.readlines(): # 按行读取
currLine = line.strip().split('t') # 分隔
lineArr = []
for i in range(3):
lineArr.append(float(currLine[i]))
trainingSet.append(lineArr)
trainingLabels.append(float(currLine[3]))
# 使用改进的随即上升梯度训练
trainWeights = gradAscent(array(trainingSet), trainingLabels)
errorCount = 0 # 错误数
numTestVec = 0.0
for line in frTest.readlines(): # 遍历每行数据
numTestVec += 1.0 # 测试集数量加1
currLine = line.strip().split('t')
lineArr = []
for i in range(3):
lineArr.append(float(currLine[i]))
if int(classifyVector(array(lineArr), trainWeights)) != int(currLine[3]):
errorCount += 1 # 预测结果与真值不一致,错误数加1
errorRate = (float(errorCount) / numTestVec) # 计算错误率
print("测试的错误率为: %f" % errorRate)
return errorRate
# 求结果的平均值
def multiTest():
numTests = 10
errorSum = 0.0
for k in range(numTests):
errorSum += colicTest1()
print("在 %d 迭代之后, 平均错误率为: %f" % (numTests, errorSum / float(numTests)))
运行结果如图:
从上述实验结果来看,使用逻辑回归进行性别分类的错误率较高
3.实验总结
- 逻辑回归的优点:直接对分类的可能性建模,无需事先假设数据分布,避免了假设分布不准确带来的问题,不仅预测出类别,还可得到近似概率预测
- 缺点:容易欠拟合,分类精度不高,数据特征有缺失或特征空间很大时效果不好