前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >对数几率回归 —— Logistic Regression

对数几率回归 —— Logistic Regression

作者头像
IT派
发布于 2018-07-30 03:38:11
发布于 2018-07-30 03:38:11
9800
举报
文章被收录于专栏:IT派IT派

1 原理

1.1 引入

首先,在引入LR(Logistic Regression)模型之前,非常重要的一个概念是,该模型在设计之初是用来解决0/1二分类问题,虽然它的名字中有回归二字,但只是在其线性部分隐含地做了一个回归,最终目标还是以解决分类问题为主。

为了较好地掌握 logistic regression 模型,有必要先了解 线性回归模型 和 梯度下降法 两个部分的内容,可参考以下两篇文章:

  • 线性回归 —— Liner Regression
  • 梯度下降法 —— 经典的优化方法

先回想一下线性回归,线性回归模型帮助我们用最简单的线性方程实现了对数据的拟合,然而,这只能完成回归任务,无法完成分类任务,那么 logistics regression 就是在线性回归的基础上添砖加瓦,构建出了一种分类模型。

如果在线性模型 (

) 的基础上做分类,比如二分类任务,即

,直觉上我们会怎么做?最直观的,可以将线性模型的输出值再套上一个函数

,最简单的就是“单位阶跃函数”(unit-step function),如下图中红色线段所示。

也就是把

看作为一个分割线,大于 z 的判定为类别0,小于 z 的判定为类别1。

但是,这样的分段函数数学性质不太好,它既不连续也不可微。我们知道,通常在做优化任务时,目标函数最好是连续可微的。那么如何改进呢?

这里就用到了对数几率函数 (形状如图中黑色曲线所示):

单位阶跃函数与对数几率函数(来源于周志华《机器学习》)

它是一种“Sigmoid”函数,Sigmoid 函数这个名词是表示形式S形的函数,对数几率函数就是其中最重要的代表。这个函数相比前面的分段函数,具有非常好的数学性质,其主要优势如下:

  • 使用该函数做分类问题时,不仅可以预测出类别,还能够得到近似概率预测。这点对很多需要利用概率辅助决策的任务很有用。
  • 对数几率函数是任意阶可导函数,它有着很好的数学性质,很多数值优化算法都可以直接用于求取最优解。

总的来说,模型的完全形式如下:

其实,LR 模型就是在拟合

这条直线,使得这条直线尽可能地将原始数据中的两个类别正确的划分开。

1.2 损失函数

对于任何机器学习问题,都需要先明确损失函数,LR模型也不例外,在遇到回归问题时,通常我们会直接想到如下的损失函数形式 (平均误差平方损失 MSE):

但在 LR 模型要解决的二分类问题中,损失函数式什么样的呢?先给出这个损失函数的形式,可以看一看思考一下,然后再做解释。

这个损失函数通常称作为 对数损失 (logloss),这里的对数底为自然对数 e ,其中真实值 y是有 0/1 两种情况,而推测值

由于借助对数几率函数,其输出是介于0~1之间连续概率值。仔细查看,不难发现,当真实值 y=0 时,第一项为0,当真实值 y=1时,第二项为0,所以,这个损失函数其实在每次计算时永远都只有一项在发挥作用,那这不就可以转换为分段函数了吗,分段的形式如下:

不难发现,当真实值 y 为1时,输出值

越接近1,则 L 越小,当真实值 y 为 0 时,输出值

越接近于0,则 L 越小 (可自己手画一下

函数的曲线)。该分段函数整合之后就是上面我们所列出的 logloss 损失函数的形式。

1.3 优化求解

现在我们已经确定了模型的损失函数,那么接下来就是根据这个损失函数,不断优化模型参数从而获得拟合数据的最佳模型。

重新看一下损失函数,其本质上是 L 关于模型中线性方程部分的两个参数 w 和 b 的函数:

其中,

现在的学习任务转化为数学优化的形式即为:

由于损失函数连续可微,我们就可以借助 梯度下降法 进行优化求解,对于连个核心参数的更新方式如下:

计算到这里,很有意思的事情发生了:

计算了半天原来变得如此简单,就是推测值

和真实值 Y 之间的差值,其实这也是得益于对数几率函数本身很好的数学性质。

再接再厉,求得:


2 代码实现

下面我们开始用 python 自己实现一个简单的 LR 模型。

完整代码可参考:[link]

首先,建立 logistic_regression.py 文件,构建 LR 模型的类,内部实现了其核心的优化函数。

# -*- coding: utf-8 -*- import numpy as np class LogisticRegression(object): def __init__(self, learning_rate=0.1, max_iter=100, seed=None): self.seed = seed self.lr = learning_rate self.max_iter = max_iter def fit(self, x, y): np.random.seed(self.seed) self.w = np.random.normal(loc=0.0, scale=1.0, size=x.shape[1]) self.b = np.random.normal(loc=0.0, scale=1.0) self.x = x self.y = y for i in range(self.max_iter): self._update_step() # print('loss: \t{}'.format(self.loss())) # print('score: \t{}'.format(self.score())) # print('w: \t{}'.format(self.w)) # print('b: \t{}'.format(self.b)) def _sigmoid(self, z): return 1.0 / (1.0 + np.exp(-z)) def _f(self, x, w, b): z = x.dot(w) + b return self._sigmoid(z) def predict_proba(self, x=None): if x is None: x = self.x y_pred = self._f(x, self.w, self.b) return y_pred def predict(self, x=None): if x is None: x = self.x y_pred_proba = self._f(x, self.w, self.b) y_pred = np.array([0 if y_pred_proba[i] < 0.5 else 1 for i in range(len(y_pred_proba))]) return y_pred def score(self, y_true=None, y_pred=None): if y_true is None or y_pred is None: y_true = self.y y_pred = self.predict() acc = np.mean([1 if y_true[i] == y_pred[i] else 0 for i in range(len(y_true))]) return acc def loss(self, y_true=None, y_pred_proba=None): if y_true is None or y_pred_proba is None: y_true = self.y y_pred_proba = self.predict_proba() return np.mean(-1.0 * (y_true * np.log(y_pred_proba) + (1.0 - y_true) * np.log(1.0 - y_pred_proba))) def _calc_gradient(self): y_pred = self.predict() d_w = (y_pred - self.y).dot(self.x) / len(self.y) d_b = np.mean(y_pred - self.y) return d_w, d_b def _update_step(self): d_w, d_b = self._calc_gradient() self.w = self.w - self.lr * d_w self.b = self.b - self.lr * d_b return self.w, self.b

然后,这里我们创建了一个 文件,单独用于创建模拟数据,并且内部实现了训练/测试数据的划分功能。

# -*- coding: utf-8 -*- import numpy as np def generate_data(seed): np.random.seed(seed) data_size_1 = 300 x1_1 = np.random.normal(loc=5.0, scale=1.0, size=data_size_1) x2_1 = np.random.normal(loc=4.0, scale=1.0, size=data_size_1) y_1 = [0 for _ in range(data_size_1)] data_size_2 = 400 x1_2 = np.random.normal(loc=10.0, scale=2.0, size=data_size_2) x2_2 = np.random.normal(loc=8.0, scale=2.0, size=data_size_2) y_2 = [1 for _ in range(data_size_2)] x1 = np.concatenate((x1_1, x1_2), axis=0) x2 = np.concatenate((x2_1, x2_2), axis=0) x = np.hstack((x1.reshape(-1,1), x2.reshape(-1,1))) y = np.concatenate((y_1, y_2), axis=0) data_size_all = data_size_1+data_size_2 shuffled_index = np.random.permutation(data_size_all) x = x[shuffled_index] y = y[shuffled_index] return x, ydef train_test_split(x, y): split_index = int(len(y)*0.7) x_train = x[:split_index] y_train = y[:split_index] x_test = x[split_index:] y_test = y[split_index:] return x_train, y_train, x_test, y_test

最后,创建 train.py 文件,调用之前自己写的 LR 类模型实现分类任务,查看分类的精度。

# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt import data_helper from logistic_regression import * # data generation x, y = data_helper.generate_data(seed=272) x_train, y_train, x_test, y_test = data_helper.train_test_split(x, y) # visualize data # plt.scatter(x_train[:,0], x_train[:,1], c=y_train, marker='.') # plt.show() # plt.scatter(x_test[:,0], x_test[:,1], c=y_test, marker='.') # plt.show() # data normalization x_train = (x_train - np.min(x_train, axis=0)) / (np.max(x_train, axis=0) - np.min(x_train, axis=0)) x_test = (x_test - np.min(x_test, axis=0)) / (np.max(x_test, axis=0) - np.min(x_test, axis=0)) # Logistic regression classifier clf = LogisticRegression(learning_rate=0.1, max_iter=500, seed=272) clf.fit(x_train, y_train) # plot the result split_boundary_func = lambda x: (-clf.b - clf.w[0] * x) / clf.w[1] xx = np.arange(0.1, 0.6, 0.1) plt.scatter(x_train[:,0], x_train[:,1], c=y_train, marker='.') plt.plot(xx, split_boundary_func(xx), c='red') plt.show() # loss on test set y_test_pred = clf.predict(x_test) y_test_pred_proba = clf.predict_proba(x_test) print(clf.score(y_test, y_test_pred)) print(clf.loss(y_test, y_test_pred_proba)) # print(y_test_pred_proba)

输出结果图如下:

输出的分类结果图

红色直线即为 LR 模型中的线性方程,所以本质上 LR 在做的就是不断拟合这条红色的分割边界使得边界两侧的类别正确率尽可能高。因此,LR 其实是一种线性分类器,对于输入数据的分布为非线性复杂情况时,往往需要我们采用更复杂的模型,或者继续在特征工程上做文章。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT派 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
30行代码徒手实现logistic回归
采用的数据集是sklearn中的breast cancer数据集,30维特征,569个样本。训练前进行MinMax标准化缩放至[0,1]区间。按照75/25比例划分成训练集和验证集。
lyhue1991
2020/07/17
5710
python实现感知机
感知机是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1二值。感知机对应于输入空间中将实例划分为正负两类的分离超平面,属于判别模型。
西西嘛呦
2020/08/26
4570
python实现感知机
干货 | 基于Python实现五大常用分类算法(原理+代码)
K-Nearest Neighbors (KNN) 是一种懒惰学习算法和分类算法。此外,KNN是机器学习中最简单的方法。利用KNN进行分类,预测新点的分类。
CDA数据分析师
2021/08/05
20.3K2
干货 | 基于Python实现五大常用分类算法(原理+代码)
python实现线性回归之lasso回归
Lasso回归于岭回归非常相似,它们的差别在于使用了不同的正则化项。最终都实现了约束参数从而防止过拟合的效果。但是Lasso之所以重要,还有另一个原因是:Lasso能够将一些作用比较小的特征的参数训练为0,从而获得稀疏解。也就是说用这种方法,在训练模型的过程中实现了降维(特征筛选)的目的。
西西嘛呦
2020/08/26
3.6K0
python实现线性回归之lasso回归
【Python】机器学习之SVM支持向量机
(3)通过鸢尾花的花萼(sepal)和花瓣(petal)的长和宽,建立SVM分类器来判断样本属于山鸢尾(Iris Setosa)、变色鸢尾(Iris Versicolor)还是维吉尼亚鸢尾(Iris Virginica)。
SarPro
2024/02/20
2550
【Python】机器学习之SVM支持向量机
神经网络python实现
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/details/81158209
bear_fish
2018/09/14
6190
神经网络python实现
TensorFlow 2.0 - Keras Pipeline、自定义Layer、Loss、Metric
文章目录 1. Keras Sequential / Functional API 2. 自定义 layer 3. 自定义 loss 4. 自定义 评估方法 学习于:简单粗暴 TensorFlow 2 1. Keras Sequential / Functional API tf.keras.models.Sequential([layers...]),但是它不能表示更复杂的模型 mymodel = tf.keras.models.Sequential([ tf.keras.layers.Flat
Michael阿明
2021/02/19
1K0
python实现线性回归之简单回归
代码来源:https://github.com/eriklindernoren/ML-From-Scratch
西西嘛呦
2020/08/26
5280
python实现线性回归之简单回归
分类-对数几率回归(逻辑回归)算法
对数几率回归(Logistic Regression),也称逻辑回归,虽然名字中含有回归,但其实是一种分类算法。找一个单调可微函数将分类任务中的真实标记与线性回归模型的预测值联系起来,是一种广义线性回归。
唔仄lo咚锵
2022/10/07
1.1K0
分类-对数几率回归(逻辑回归)算法
算法入门(六)—— 一文搞懂逻辑回归(内附Kaggle实战源码与数据集)
大家好!欢迎来到我们的“算法入门”系列。今天我们要聊聊机器学习中的一位“老朋友”——逻辑回归。如果你对它的名字感觉既熟悉又陌生,别担心,今天我们会带你一起深入了解它的原理、公式以及在实践中的应用。最重要的是,我们会通过一个Kaggle实战项目,让你能够轻松上手!
万事可爱^
2025/01/23
1540
算法入门(六)—— 一文搞懂逻辑回归(内附Kaggle实战源码与数据集)
python实现多层感知机
多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图:
西西嘛呦
2020/08/26
2.4K0
python实现多层感知机
斯坦福CS231n项目实战(三):Softmax线性分类
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/red_stone1/article/details/79284768
红色石头
2019/05/25
8750
机器学习 | 简单而强大的线性回归详解
回归分析是一种预测性的建模技术,它研究的是因变量和自变量之间的关系。它能够表明自多个自变量对一个因变量的影响强度。这种技术通常用于预测分析、时间序列模型以及发现变量之间的因果关系。回归分析是一种通过建立模型来研究变量之间相互关系的密切程度、结构状态及进行模型预测的有效工具,是建模和分析数据的重要工具。
数据STUDIO
2021/06/24
1.5K0
机器学习14:模型评估与性能提升
6.2,验证曲线、学习曲线、ROC曲线、准确度、精确率、召回率、F1_Score
用户5473628
2019/08/08
1.1K0
【TensorFlow】TensorFlow 的 Logistic Regression
本文介绍了如何使用TensorFlow实现逻辑回归分类器对Iris数据集进行分类,并对比了sklearn中逻辑回归的分类效果。通过实验,发现TensorFlow的逻辑回归分类器在测试集上的准确率高于sklearn。
Alan Lee
2018/01/02
1.6K0
【TensorFlow】TensorFlow 的 Logistic Regression
1.6w字超全汇总!56个sklearn核心操作!!!
其中,X是特征数据,y是目标数据,test_size是测试集的比例(可以是0到1之间的值),random_state是随机种子,用于保证每次划分的结果一致。
Python编程爱好者
2024/05/13
4290
1.6w字超全汇总!56个sklearn核心操作!!!
机器学习-对数几率回归(逻辑回归)算法
对数几率回归(Logistic Regression),也称逻辑回归,虽然名字中含有回归,但其实是一种分类算法。找一个单调可微函数将分类任务中的真实标记与线性回归模型的预测值联系起来,是一种广义线性回归。
唔仄lo咚锵
2023/05/23
8970
机器学习-对数几率回归(逻辑回归)算法
python实现线性回归之岭回归
上述式子中w为长度为n的向量,不包括偏置项的系数 θ0,θ是长度为n+1的向量,包括偏置项系数θ0;m为样本数,n为特征数。
西西嘛呦
2020/08/26
1.7K0
python实现线性回归之岭回归
基于SVM的思想做CIFAR-10图像分类
回顾一下之前的SVM,找到一个间隔最大的函数,使得正负样本离该函数是最远的,是否最远不是看哪个点离函数最远,而是找到一个离函数最近的点看他是不是和该分割函数离的最近的。
西红柿炒鸡蛋
2018/09/07
1.7K0
Logistic regression intuition and conditional probabilities使用sc-learn训练logistic regression 模型使用正则化(r
logit函数输入参与p属于(0,1),函数值为整个实数域,可以在特征值与逻辑比率之间建立线性关系 这里 样本x属于分类1的条件概率 现在如何去预测一个特定样本属于一个特定类的概率,转化一个函数形式, 注意这里是y=1的概率,后面算似然函数特别注意这点,这里y|x只有两个分类,y=1|x,y=0|x,P(y=0|x)=1-P(y=1|x),注意下面的处理手法, 似然函数 将问题转化一下,求lnL最大值,也就是求-lnL最小值,易知-lnL>0 为了更好掌握损失函数J(w),看一下单个样本的例子 y
用户1733462
2018/06/07
6160
推荐阅读
相关推荐
30行代码徒手实现logistic回归
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档