逻辑回归(logistic regression)
基本概念
逻辑回归虽然名字中带有回归,但应该是历史遗留问题。他主要解决的问题是二分类问题,也可以解决多分类(Multi-class)问题。在二分类的逻辑回归中目标变量的取值只能为0和1,逻辑回归主要应用于研究目标事件发生的概率。其与上一篇文章讲的多重线性回归主要的部分都差不多,主要是因变量不同,线性回归的因变量是连续的,也因此被归为一个家族——广义线性模型(generalized linear model).
模型
逻辑回归的模型是利用最大似然估计的方法,构造了一个sigmoid函数,将线性回归的假设函数值投影到(0,1)之间。很多教材将投影后的值直接告诉学习者说,这就是 y取某一类的概率值,即P(y = Ck|x,θ). 比如给定一个肿瘤的尺寸,经过hθ作用后输出结果为他为恶性或良性(取决于你类的定义)的概率值。但是数学证明也并不复杂,利用贝叶斯公式可以比较简单的推导出来,借鉴知乎上的一个回答。Andrea 在模型中介绍了决策边界(decision boundary)以便我们能更好的理解模型。决策边界是针对特定的输入变量X(i),有一个参数为θ的超平面(取决于X中特征的个数,如果i为2,则就是一条直线,下面以直线为例),在这条线上方的我们将其划分为某一类,在这条线下方的为另外一类。这条线或者超平面称为决策边界。图中的是由不同的训练集确定的不同的决策边界,图一是一条直线,图二是一个圆。决策边界由训练集学习得到参数θ决定,理论上可以为任意形状
要注意理解假设函数和决策边界函数的区别与联系。决策边界是假设函数的属性,由假设函数的参数决定。
在逻辑回归中,假设函数(h=g(z))用于计算样本属于某类别的可能性;决策函数(h=1(g(z)>0.5))用于计算(给出)样本的类别;决策边界(θ^Tx=0)是一个方程,用于标识出分类函数(模型)的分类边界。
原文:https://blog.csdn.net/walilk/article/details/51107380?utm_source=copy
策略
logistic regression 采用的策略也为代价函数的方式(cost function), 只不过这里不再是适用线性回归模型的均方误差的代价函数,而是采用交叉熵(cross entropy),关于交叉熵的直观理解,《神经网络与深度学习》中说的比较直观。
交叉熵是对「出乎意料」(译者注:原文使用suprise)的度量。神经元的目标是去计算函数y, 且y=y(x)。但是我们让它取而代之计算函数a, 且a=a(x)。假设我们把a当作y等于1的概率,1−a是y等于0的概率。那么,交叉熵衡量的是我们在知道y的真实值时的平均「出乎意料」程度。当输出是我们期望的值,我们的「出乎意料」程度比较低;当输出不是我们期望的,我们的「出乎意料」程度就比较高。
其实从函数的角度也不难理解代价函数在计算什么。在二分类问题下,y的取值只能为0或1,当y = 0, 代价函数只有第二项为log(1-hθ),当hθ预测也为零,那么损失函数为0,如果预测为1那么损失函数为无穷大,即完全预测错误的话会有一个很大的惩罚(penalty),那如果预测为0.6,表示其属于正类的概率为0.6,那么交叉熵计算的就是我们出乎意料(竟然不是0 orz)的程度了。
关于交叉熵的推导,其实利用的是极大似然函数。
方法
关于求解θ的方法,Andrea 提出了很多高级算法,包括共轭梯度,拟牛顿法(BFGS)等,但是只是介绍了如何在Octave中调用而没有介绍细节,所以这里还是使用梯度下降法来求解。首先对于sigmoid 函数有一个性质就是g'(x) = g(x)(1-g(x)),这在之后的推到中也常用到。
发现最后的形式和线性回归一样,只不过hθ的形式改变了而已。所以也难怪他们都叫做泛线性回归模型(generalized linear regression).
多分类问题
如果实际的问题目标变量不止有两种,采用的方法叫做一对多(1 vs all)。就是在计算某一类的时候将其他类全部作为第二类,从而转化为二分类问题。最后在每一类都会计算出一个hθi(i = 1,2,3...),最后返回最大的hθ,直观上的理解就是这些划分到这所类的不同概率中取最大的,作为最可能被分到的类。这也朴素的反映了神经网络的思想,毕竟逻辑回归本质上就是一个没有隐藏层的神经网络。
但是我之前上过一门数据挖掘到网课中提到了一个错分类权重的问题,就是说不同错分类之间的权重或者说严重性是不同的。比如,你把一个癌症患者分类为健康和把一个健康患者分类为癌症,一种情况会导致贻误治疗时机,一种情况不过是多花一点检查费用而已,在这种情况下,可能需要不同的惩罚项来约束,而不能简单的将其描述为一对多。
附代码(python)
import matplotlib.pyplot as plt
import numpy as np
class Logistic_Regression(object):
def __init__(self):
self.theta = None
self.theta0 = None
self.alpha = 0.001
def sigmoid(self,x):
y = 1.0 / (1+np.exp(-x))
return y
def cost(self,X_train,y):
m = X_train.shape[0]
h = (self.sigmoid(X_train.dot(self.theta)+self.theta0)).reshape((-1,1))
c0 = 0
for i in range(m):
c0 += y[i]*np.log(h[i]) +(1-y[i])*np.log(1-h[i])
cost = -c0/m
dtheta = (self.alpha/m)*(X_train.T.dot(h-y))
dtheta0 = (self.alpha/m)*np.sum(h-y)
return cost,dtheta,dtheta0
def train(self,X_train,y,iter = 5000):
m = X_train.shape[0]
n = X_train.shape[1]
self.theta = np.ones(n).reshape((-1,1))
self.theta0 = 0
cost_list = []
colors = []
for item in Y_train:
if item == 1:
colors.append("red")
else:
colors.append("blue")
x = np.linspace(3, 8, 1000)
plt.ion()
for i in range(iter):
c, dtheta, dtheta0 = self.cost(X_train,y)
cost_list.append(c)
self.theta -= dtheta
self.theta0 -= dtheta0
if i % 500 == 0:
plt.clf()
plt.scatter(X_train[:, 0], X_train[:, 1], c=colors)
x2 = -(self.theta[0] / self.theta[1]) * x + self.theta0 / self.theta[1]
plt.plot(x, x2, "g-")
plt.pause(0.5)
return cost_list
def predict(self,X_test):
y_pred = self.sigmoid(X_test.dot(self.theta)+self.theta0)
return y_pred
if __name__ == "__main__":
iris = load_iris()
data = iris.data
target = iris.target
X = data[:100,:2]
X_train = X[:-20,:2]
X_test = X[-20:,:2]
Y = target[:100]
Y_train = Y[:-20].reshape((-1,1))
Y_test = Y[-20:].reshape((-1,1))
logisticR = Logistic_Regression()
L = logisticR.train(X_train,Y_train)
theta = logisticR.theta
theta0 = logisticR.theta0