逻辑回归(Logistic Regression)

逻辑回归(Logistic Regression)是一种用于分类问题的算法。

建立一个Logistic Regression模型,需要以下三部分工作:

  • 构造预测函数
  • 构建损失函数
  • 最小化损失函数,求解θ

1.构造预测函数

逻辑回归和线性回归都是广义的线性模型,而逻辑回归的本质就是由线性回归变化而来的。这里简单介绍下线性回归模型:

1-1.gif

θ统称为模型的参数,其中θ0为截距,θ1-θn是模型的系数。
线性回归的任务就是构造一个预测函数z来映射输入的特征矩阵x和标签y的线性关系,而构造预测函数的核心就是找出模型的参数θ,线性回归模型通常用最小二乘法来求解参数。

但是在二分类问题中,我们想要函数输出0或1,那么就需要用到联系函数(link function),将线性回归方程z变换为g(z),并且使得g(z)的值分布在(0,1)之间,且当g(z)接近0时样本的标签为类别0,当g(z)接近1时样本的标签为类别1,这样就得到了一个分类模型。这个联系函数对于逻辑回归来说就是Sigmoid函数:

1-2.gif
Sigmoid.png

Sigmoid函数是一个S型的函数,当自变量z趋于正无穷时,因变量g(z)趋近于1,当自变量z趋于负无穷时,g(z)趋近于0,它可以将任意实数映射到(0,1)区间。

通过将线性回归模型与Sigmoid函数相结合,就可以得到逻辑回归模型的一般形式:

1-3.gif

其中,g(z)就是逻辑回归返回的标签值,此时y(x)的取值都在(0,1)之间。令y(x)除以1-y(x)就得到了形似几率odds(一个事件的odds指的是该事件发生的概率与不发生的概率之比),在此基础上取对数可以得到:

1-4.gif

从公式1-4可看出g(z)的形似几率取对数的本质就是线性回归z,实际上我们是对线性回归模型的预测结果取对数几率来让其结果无限逼近0和1。因此,这个模型也被称为“对数几率回归”(logistic regression),也就是逻辑回归。

2.构建损失函数

yθ(x)函数的值有特殊的含义,它表示预测结果为1的概率。因此对于输入项x,预测分类结果为1和0的概率分别为:

2-1.gif

公式2-1可以合并为:
2-2.gif

取似然函数为:

2-3.gif

对数似然函数为:

2-4.gif

最大似然函数就是求使l(θ)取最大值时的θ,这里可以通过梯度上升算法求解,得到的θ就是最佳参数。但是在Andrew Ng的课程中将损失函数J(θ)取为下式:

2-5.gif

因为乘了系数-1/m,所以使J(θ)取最小值的θ就为最佳参数。

3.最小化损失函数,求解θ

使用梯度下降算法(Gradient descent)求解使得损失函数J(θ)取最小值的θ,由梯度下降算法可得θ的更新过程如下:

3-1.gif

其中j表示样本的第j个特征,α表示步长(也称为学习率),后半部分对J(θ)的参数求偏导并以向量形式表示,就是损失函数的梯度。
对J(θ)求偏导:

3-2.gif

其中

3-3.gif

所以θ的更新过程可以写成(i表示第i个样本,j表示样本的第j个特征,α表示步长):

3-4.gif

对该公式进行迭代,直到收敛(J(θ)在每一步的迭代中都会减小,如果某一步J(θ)减小的值小于一个很小的值ε(例如0.001),则判定收敛)或者达到某个停止条件为止(比如达到指定的迭代次数)

3.1 梯度下降算法的实例

3.1.1 单变量函数的梯度下降

假设单变量函数J(θ)=θ^2,J'(θ)=2θ即函数的梯度,初始化起点为θ0=1,步长α为0.4,那么根据梯度下降的迭代公式进行计算可得到:
θ0=1
θ1=θ0-αJ'(θ0)=1-0.42=0.2
θ2=θ1-αJ'(θ1)=0.2-0.40.4=0.04
θ3=θ2-αJ'(θ2)=0.04-0.40.08=0.008
θ4=θ3-αJ'(θ3)=0.008-0.40.016=0.0016
...
我们发现进行了四次迭代,已经接近函数的最小值点0了。

3.1.2 多变量函数的梯度下降

假设目标函数为J(θ)= θ1^2 + θ2^2,通过梯度下降算法计算该函数的最小值。函数的梯度为<2θ1,2θ2>,假设初始起点为(1,3),初始化步长为0.1,进行迭代:
θ0=(1,3)
θ1=(1,3)-0.1(2,6)=(0.8,2.4)
θ2=(0.8,2.4)-0.1
(0.16,4.8)=(0.64,1.92)
θ3=(0.64,1.92)-0.1*(1.28,3.84)=(0.512,1.536)
...
随着迭代的不断进行,已经越来越接近该函数的最小值点(0,0)了。

3.2 批量梯度下降法(Batch Gradient Descent)

批量梯度下降算法是梯度下降算法的最常用形式,即在更新参数时利用所有的样本来进行更新,上面公式3-4就是逻辑回归的批量梯度下降算法,由于1/m是一个常量,α也是一个常量,所以可省略1/m,故参数的更新过程可写成:

BGD.gif

由于有m个样本,所以求梯度的时候就用了所有m个样本的梯度数据。

此外,梯度下降算法还包括随机梯度下降法(Stochastic Gradient Descent)、小批量梯度下降法(Mini-batch Gradient Descent),这里就不展开了,下次再比较一下这几个算法的区别吧。

4.逻辑回归的代码实现

接下来用python实现一个简单的逻辑回归算法。
首先加载数据:

def loaddata(filename):
    dataSet = pd.read_table(filename, header=None)
    dataSet.columns = ['X1', 'X2', 'label']
    dataSet.insert(0, 'X0', 1) #增加常量列并赋值为1,对应θ0
    columns = [i for i in dataSet.columns if i != 'label']
    data_x = dataSet[columns]
    data_y = dataSet[['label']]
    return data_x,data_y

构造预测函数和损失函数,最后利用批量梯度下降法求参数θ:

#sigmoid函数
def sigmoid(y):
    s = 1.0/(1.0+np.exp(-y))
    return s

def cost(xMat,weights,yMat):
    m, n = xMat.shape
    hypothesis = sigmoid(np.dot(xMat, weights))  # 预测值
    cost = (-1.0 / m) * np.sum(yMat.T * np.log(hypothesis) + (1 - yMat).T * np.log(1 - hypothesis))  # 损失函数
    return cost

def BGD_LR(data_x,data_y,alpha=0.1,maxepochs=10000,epsilon=0.0001):
    xMat = np.mat(data_x)
    yMat = np.mat(data_y)
    m,n = xMat.shape
    weights = np.ones((n,1)) #初始化模型参数
    epochs_count = 0
    while epochs_count < maxepochs:
        loss = cost(xMat,weights,yMat) 
        hypothesis = sigmoid(np.dot(xMat,weights)) 
        error = hypothesis -yMat #预测值与实际值误差
        print(loss)
        grad = (1.0/m)*np.dot(xMat.T,error) #损失函数的梯度
        last_weights = weights #上一轮迭代的参数
        weights = weights - alpha*grad #参数更新
        if (abs(cost(xMat, weights, yMat) - cost(xMat,last_weights,yMat))) < epsilon: #终止条件
            break
        epochs_count += 1
    print('迭代到第{}次,结束迭代!'.format(epochs_count))
    return weights

计算模型预测准确率:

def acc(weights, test_x, test_y):
    xMat_test = np.mat(test_x)
    m, n = xMat_test.shape
    result = []
    for i in range(m):
        proba = sigmoid(np.dot(xMat_test[i,:], weights))
        if proba < 0.5:
            preict =  0
        else:
            preict = 1
        result.append(preict)
    test_x_ = test_x.copy()
    test_x_['predict'] = result
    acc = (test_x_['predict']==test_y['label']).mean()
    return acc
result.png

当设置步长为0.1,损失精度为0.0001时,最终当迭代至第571次时,损失精度已经小于0.0001了,训练集的准确率达到了0.96。至此,一个简单的逻辑回归模型就完成了~

本文代码地址:https://github.com/DaHuangTyro/Daily_Machine_Learning

参考

https://blog.csdn.net/xiaoxiangzi222/article/details/55097570
https://www.jianshu.com/p/c7e642877b0e

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容