目录
逻辑回归首先假定问题域满足Bernoulli分布,模型设计如下:
公式1->线性回归:
也可表达为:
这里\(\Theta\)为模型参数,是一个向量,x为输入的特征向量
上述公式被用来解决满足高斯分布的回归问题。对于分类问题,需要在上述公式的基础上设计阈值,然后比较上述公式的输出和阈值大小,从而进行分类。一般情况下,使用公式2作为阈值分类时,存在两个问题,一是其曲线不够光滑,存在突变,导致某一点不连续,在数学处理时不方便,二是阈值如何选取? 假设t0=10,现在有一个样本进来,最后计算出来的值为10.01,你说这个样本分类应该是为1还是0呢?
公式2:
为了解决阈值函数存在的上边两个问题,这里引入sigmoid函数来代替阈值分类。在公式1的基础上添加sigmoid函数即构建了逻辑回归的基本表达形式
公式3->逻辑回归:
选择sigmoid函数来代替阈值分类的原因是它有两个优点:
根据样本求解最优参数的推导过程如下图所示:
对数损失函数(logarithmic loss function)或对数似然损失函数(log-likehood loss function)
如果损失函数越小,表明模型越好
逻辑回归的对数似然损失函数公式如下:
将上式合并表达:
全样本的损失函数可以表达为:
可使用批量梯度求解,但由于计算量太高,一般使用随机梯度下降,计算示例代码如下:
# coding=utf-8
from numpy import *
import matplotlib.pyplot as plt
# Sigmoid激活函数,这里也给了tanh激活函数
def sigmoid(X):
return 1.0/(1+exp(-X))
#return 2*1.0/(1+exp(-2*X))-1 # tanh(x):mean value is 0
# 用于显示后面梯度上升训练过程中的weights
def trainingProcessDisplay(weights):
fig = plt.figure()
n = len(weights)
x = range(n)
ax1 = fig.add_subplot(311)
ax1.plot(x,weights[:,0])
plt.ylabel('w0')
ax = fig.add_subplot(312)
ax.plot(x,weights[:,1])
plt.ylabel('w1')
ax = fig.add_subplot(313)
ax.plot(x,weights[:,2])
plt.ylabel('w2')
plt.xlabel('Iterations')
plt.show()
# 梯度上升,每次更新都是计算出所有样本之间的误差(数据量很大时计算很耗时)
def gradAscent(data,labels, alpha = 0.001, numIter=500):
dataMatrix = mat(data)
labelMat = mat(labels).transpose()
m,n = shape(dataMatrix)
weights = ones((n,1))
for k in range(numIter):
h = sigmoid(dataMatrix*weights) # 激活输出
error = labelMat - h # 误差计算,上图中的蓝色框公式
weights = weights + alpha*dataMatrix.transpose()*error # 权值更新,这里使用批量数据
return array(weights)
# 梯度上升,每次使用单个样本进行更新,error为标量
def stocGradAscent0(data,labels, alpha = 0.001, numIter=500):
m,n = shape(data)
weights = ones(n)
for j in range(numIter):
for i in range(m):
h = sigmoid(sum(data[i]*weights))
error = labels[i]-h
weights = weights + alpha*error*data[i]
return weights
# 随机梯度上升,每次迭代过程中顺序不一样,同样也是单样本更新
def stocGradAscent1(data,labels, numIter=500):
m,n = shape(data)
weights = ones(n)
allWeights = ones((numIter,n))
for j in range(numIter):
allWeights[j] = weights
dataIndex = range(m)
random.shuffle(dataIndex)
for i in range(m):
alpha = 4/(1.0+i+j) + 0.0001
index = dataIndex[i]
h = sigmoid(sum(data[index]*weights))
error = labels[index] - h
weights = weights + alpha *error*data[index]
trainingProcessDisplay(allWeights)
return weights
# 结果可视化:在这里回归出来的是直线
def resultVisualization(data,labels,weights):
n = shape(data)[0]
x1 = [];y1=[];x2=[];y2=[]
for i in range(n):
if int(labels[i])==1:
x1.append(data[i][1]);y1.append(data[i][2])
else:
x2.append(data[i][1]);y2.append(data[i][2])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(x1,y1,s=30,c='red',marker='s')
ax.scatter(x2,y2,s=30,c='green')
x = arange(-5.0,5.0,0.1)
# div = weights[2]
# if weights[2]==0: div = 0.00001
y = (-weights[0]-weights[1]*x)/weights[2]
ax.plot(x,y)
plt.xlabel('X1');plt.ylabel('X2')
plt.show()
# 测试
def testLR():
data,labels = loadData("data.txt")
dataArr = array(data)
#weights = gradAscent(dataArr,labels)
#weights = stocGradAscent0(dataArr,labels)
weights = stocGradAscent1(dataArr,labels)
#print weights
resultVisualization(dataArr,labels,weights)
if __name__ == "__main__":
testLR()
[参考](https://zhuanlan.zhihu.com/p/54197906](https://zhuanlan.zhihu.com/p/54197906)
优点:
缺点:
线性回归:
逻辑回归:
总之,线性回归和逻辑回归有很多相似之处,最大的区别就是因变量不同。它们同属于一个家族,即广义线性模型(GLM),因变量如果是连续的,就是多重线性回归,如果是离线的,就是逻辑回归(逻辑回归的因变量可以是二分类也可以是多分类)
广义线性模型(GLM/Generalized Linear Model)符合指数分布的一般模型可以转换成广义线性模型,广义线性模型即可构建因变量和自变量之间的关系。GLM常用的分布有三种: