凌云时刻 · 技术

导读:在这一篇笔记中我们继续来学习分类算法逻辑回归(Logistic Regression)。

作者 | 计缘

来源 | 凌云时刻(微信号:linuxpk)

定义损失函数

回顾完对数后,我们再来看看逻辑回归的损失函数,没错,我们就是要使用对数的函数来表示:

如果,那么损失函数为:如果,那么损失函数为:

我们来看看这两个函数为什么符合之前我们定义的损失函数的描述‍‍。首先  的曲‍‍线为:

之前说了,概率的值域‍‍在(0,1)(0,1)之间,所以上图曲线的x轴以下的曲线是没有意义的,所以‍‍对于  ,‍‍它的曲线是:‍‍

从上面的曲线图可以很容易的发现,‍‍‍‍‍‍‍‍‍‍当  趋近于0的时候,‍‍  趋‍‍近于正无穷,这个正无穷其实就是一个很大的损失惩罚,因‍‍为当  趋近于0时‍‍,  应该也是趋‍‍近于0,但是这‍‍里  ‍‍定义的是1。‍‍当  在‍‍不断趋近1的过程中‍‍,  的‍‍值逐渐减小,既损失逐渐减小,‍‍当  趋‍‍近于1时‍‍,  应‍‍该也是趋近于0,和这里定义的是一致的,所以  的‍‍值是0,说明没有损失。‍‍

下面再来看‍‍看  的‍‍曲线:‍‍‍‍‍‍‍‍‍‍

同理因为概率的‍‍值域在(0,1)之间,‍‍所以  的‍‍曲线‍‍为:

这条曲线同样可以解释我们之前定义的损失趋势。

此时我们找到的损失函数还是根据不同的分类分成了两个,其实将其合成一个也很简单:

如此一来‍‍,当  时,损失函‍‍数为  ,‍‍‍‍当  时,损‍‍失函数为  。‍‍‍‍

上面的公式,是针对一个样本数据的,那么如果有多个样本数据,其实就是将这些样本数据的损失值加起来然后在求一下平均值:

下面我们要做的就是找‍‍到一组  值,使得上面‍‍的  达到最‍‍‍‍小值。

损失函数的梯度

上面的公式是没法像线性回归那样求出一个正规方程解的,所以我们需要使用梯度下降法来求得‍‍使  最小的一‍‍组  。‍‍下面我们先把公式都列出来:

  • 多元线性回归公式:  ,‍‍注意这里的  ‍‍是加上了值全部为1的一列的矩阵,而为了方便推导,这里‍‍的  是一‍‍个列向量,就‍‍不写成  了。

  • Sigmoid函数:  。

  • 逻辑回归概率公式:

  • 逻辑回归损失函数:

在第五篇笔记中我们知道,求损失函数的梯度就是对  这个列向量逐个元素求导:

我们从里往外来看,先从Sigmoid函数求导入手。

 Sigmoid函数求导

先变换一下Sigmoid函数:

然后对Sigmoid函数求导,这里遵循求导链式法则以及求导基本法则:

  • 复合函数  的导数  为:

  • 代数函数导数:

  • 数学常数的指数求导还是它自己:

所以可得Sigmoid函数的导数为:

 Sigmoid函数的对数求导

下面再往外扩展,来看一下  的导数。这里遵循的导数法则为:

  • 对以2为底的对数求导:

  • 复合函数   的导数  为:

所以  ‍‍的导数为:

log(σ(t))‘=1σ(t)⋅σ(t)‘=1(1+et)−1⋅(1+e−t)−2⋅e−t=(1+e−t)−1⋅e−t=e−t1+e−t=1+e−t−11+e−t=1−11+e−t=1−σ(t)

‍‍  的导数为:

 逻辑回归损失函数求导

当我们知道了Sigmoid函数和Sigmoid函数的对数的求导结果后,我们对逻辑回归损失函数求导就很容易了(这里对‍‍第  ‍‍个  ‍‍求‍‍导),先来看前半部分:

最后的那‍‍个  是第  个  ‍‍‍‍‍‍‍‍前‍‍‍‍面的系数,再来看后半部分:

‍‍

此时对整个损失函数求导就是上面两部分相加:

所以逻辑回归损失函数的梯度为:

大家再来回顾一下第五篇笔记中线性回归的梯度:

可以发现这两个梯度在形态上是非常相似的,因为线性回归的梯度通过向量化可以优化为:

所以逻辑回归的梯度最终可以写为:

实现逻辑回归算法

因为逻辑回归拟合损失函数使用的是梯度下降法,所以我们封装逻辑回归算法时大部分都可以套用我们之前封装的线性回归梯度下降方法,需要修改的只是损失函数、预测和评分里的一些代码。

import numpy as np
from .metrics import accuracy_scoreclass LogisticRegression:def __init__(self):# 截距theta0self.intercept_ = None# 系数,theta1 ... thetaNself.coef_ = None# theta列向量self._theta = None# 定义Sigmoid私有函数def _sigmoid(self, t):return 1. / (1. + np.exp(-t))# 使用批量梯度下降法,根据训练数据集X_train,y_train训练LogisticRegression模型def fit(self, X_train, y_train, is_debug=False, eta=0.01, n_iters=1e4):assert X_train.shape[0] == y_train.shape[0], \"特征数据矩阵的行数要等于样本结果数据的行数"# 定义逻辑回归损失函数def L(theta, X_b, y):# 定义逻辑回归概率公式y_hat = self._sigmoid(X_train.dot(theta))try:return -np.sum(y*np.log(y_hat)+(1-y)*np.log(1-y_hat)) / len(X_b)except:return float('inf')# 定义逻辑回归梯度def dL(theta, X_b, y):return X_b.T.dot(self._sigmoid(X_b.dot(theta)) - y) / len(X_b)def dL_debug(theta, X_b, y, epsilon=0.01):# 开辟大小与theta向量一致的向量空间result = np.empty(len(theta))# 便利theta向量中的每一个thetafor i in range(len(theta)):# 复制一份theta向量theta_1 = theta.copy()# 将第i个theta加上一个距离,既求该theta正方向的thetatheta_1[i] += epsilon# 在复制一份theta向量theta_2 = theta.copy()# 将第i个theta减去同样的距离,既求该theta负方向的thetatheta_2[i] -= epsilon# 求出这两个点连线的斜率,既模拟该theta的导数result[i] = (L(theta_1, X_b, y) - L(theta_2, X_b, y)) / (2 * epsilon)return result# 实现批量梯度下降法def gradient_descent(X_b, y, initial_theta, eta, difference=1e-8):theta = initial_thetai_iter = 0while i_iter < n_iters:# 当is_debug为True时走debug的求梯度的方法,反之走梯度公式的方法if is_debug:gradient = dL_debug(theta, X_b, y)else:gradient = dL(theta, X_b, y)last_theta = thetatheta = theta - eta * gradientif (abs(L(theta, X_b, y) - L(last_theta, X_b, y)) < difference):breaki_iter += 1return theta# 构建X_bX_b = np.hstack([np.ones((len(X_train), 1)), X_train])# 初始化theta向量为元素全为0的向量initial_theta = np.zeros(X_b.shape[1])self._theta = gradient_descent(X_b, y_train, initial_theta, eta)self.intercept_ = self._theta[0]self.coef_ = self._theta[1:]return self# 计算概率,给定待预测数据集X_predict,返回表示X_predict的结果概率向量def predict_probability(self, X_predict):assert self.intercept_ is not None and self.coef_ is not None, \"截距和系数都不为空,表示已经经过了fit方法"assert X_predict.shape[1] == len(self.coef_), \"要预测的特征数据集列数要与theta的系数数量相等"X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])# 返回0,1之间的浮点数return self._sigmoid(X_b.dot(self._theta))# 给定待预测数据集X_predict,返回表示X_predict的结果向量def predict(self, X_predict):assert self.intercept_ is not None and self.coef_ is not None, \"截距和系数都不为空,表示已经经过了fit方法"assert X_predict.shape[1] == len(self.coef_), \"要预测的特征数据集列数要与theta的系数数量相等"probability = self.predict_probability(X_predict)# 将概率转换为0和1的向量,True对应1,False对应0return np.array(probability >= 0.5, dtype='int')# 根据测试数据集X_test和y_test确定当前模型的准确度def score(self, X_test, y_test):y_predict = self.predict(X_test)return accuracy_score(y_test, y_predict)def __repr__(self):return "LinearRegression()"

下面我们在Jupyter Notebook中使用Scikit Learn提供的鸢尾花数据验证我们封装的逻辑回归的方法:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsiris = datasets.load_iris()
X = iris.data
y = iris.target

因为鸢尾花数据中有三类鸢尾花,而逻辑回归在一开始就讲过是一个解决二分类问题的算法,所以我们只取前两类的鸢尾花数据来验证,并且只用每类鸢尾花的前两个特征,方便绘图:

# 只取前两类的鸢尾花数据
X = X[y<2, :2]
y = y[y<2]plt.scatter(X[y==0, 0], X[y==0, 1], color='red')
plt.scatter(X[y==1, 0], X[y==1, 1], color='blue')
plt.show()

from myML.LogisticRegression import LogisticRegression
from myML.modelSelection import train_test_splitX_train, y_train, X_test, y_test = train_test_split(X, y, seed=666)log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
log_reg.score(X_test, y_test)
# 结果
1.0log_reg.predict_probability(X_test)
# 概率结果
array([ 0.92972035,  0.98664939,  0.14852024,  0.17601199,  0.0369836 ,0.0186637 ,  0.04936918,  0.99669244,  0.97993941,  0.74524655,0.04473194,  0.00339285,  0.26131273,  0.0369836 ,  0.84192923,0.79892262,  0.82890209,  0.32358166,  0.06535323,  0.20735334])log_reg.predict(X_test)
# 分类结果
array([1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0])y_test
# 测试数据结果
array([1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0])

可以看到我们封装的逻辑回归算法对鸢尾花的分类是100%准确的,当然也是因为当前的数据比较简单。

END

往期精彩文章回顾

机器学习笔记(十九):逻辑回归

机器学习笔记(十八):模型正则化

机器学习笔记(十七):交叉验证

机器学习笔记(十六):多项式回归、拟合程度、模型泛化

机器学习笔记(十五):人脸识别

机器学习笔记(十四):主成分分析法(PCA)(2)

机器学习笔记(十三):主成分分析法(PCA)

机器学习笔记(十二):随机梯度下降

机器学习笔记(十一):优化梯度公式

机器学习笔记(十):梯度下降

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

机器学习笔记(二十):逻辑回归(2)相关推荐

  1. Scikit-Learn 机器学习笔记 -- 线性回归、逻辑回归、softmax回归

    Scikit-Learn 机器学习笔记 – 线性回归.逻辑回归.softmax回归 参考文档: handson-ml import numpy as np from matplotlib import ...

  2. sklearn逻辑回归参数设置_【机器学习笔记】:逻辑回归实战练习(二)

    作者:xiaoyu 微信公众号:Python数据科学 知乎:python数据分析师 前言 前几篇介绍了逻辑回归在机器学习中的重要性:5个原因告诉你:为什么在成为数据科学家之前,"逻辑回归&q ...

  3. 机器学习笔记04:逻辑回归(Logistic regression)、分类(Classification)

    之前我们已经大概学习了用线性回归(Linear Regression)来解决一些预测问题,详见: 1.<机器学习笔记01:线性回归(Linear Regression)和梯度下降(Gradien ...

  4. 【机器学习笔记4】逻辑回归模型

    目录 什么是逻辑回归? Sigmoid函数 决策边界 逻辑回归的损失函数 为什么平方误差模型不可行? 对数损失函数 单个样例损失: 整体损失函数 梯度下降算法 补充:F1-score评价指标 F1-S ...

  5. 机器学习笔记I: 基于逻辑回归的分类预测

    逻辑回归的介绍 逻辑回归(Logistic regression,简称LR)虽然其中带有"回归"两个字,但逻辑回归其实是一个分类模型,并且广泛应用于各个领域之中.虽然现在深度学习相 ...

  6. arctanx麦克劳林公式推导过程_机器学习笔记(七)——初识逻辑回归、不同方法推导梯度公式

    一.算法概述 逻辑回归(Logistic)虽带有回归二字,但它却是一个经典的二分类算法,它适合处理一些二分类任务,例如疾病检测.垃圾邮件检测.用户点击率以及上文所涉及的正负情感分析等等. 首先了解一下 ...

  7. 机器学习笔记(七)——初识逻辑回归、不同方法推导梯度公式

    一.算法概述 逻辑回归(Logistic)虽带有回归二字,但它却是一个经典的二分类算法,它适合处理一些二分类任务,例如疾病检测.垃圾邮件检测.用户点击率以及上文所涉及的正负情感分析等等. 首先了解一下 ...

  8. 机器学习(二)逻辑回归

    逻辑回归 原文地址:http://blog.csdn.net/hjimce/article/details/45418933 作者:hjimce 逻辑回归于线性回归的区别: (1)线性回归的函数拟合, ...

  9. 机器学习笔记——线性回归与逻辑回归

    线性回归是什么: 线性回归是回归问题的一种,模型试图去找到y 与 x 的线性关系同时去预测新输入的输出值.模型会找到一条直线使得图像上的每一个点到这条线的欧式距离之和最小,也就是均方误差(MSE)最小 ...

  10. 机器学习笔记 - 线性回归与逻辑回归

    一.线性回归概述 1.概述 线性回归算法是一种预测连续型变量的方法.它的基本思想是通过已给样本点的因变量和自变量的关系,设定一个数学模型,来拟合这些样本点.线性回归算法就是为了找到最佳模型. 线性回归 ...

最新文章

  1. 【通俗理解线性代数】 -- 内积与相关
  2. 进阶学习(3.5) Singleton Pattern 单例模式
  3. boost::function模块boost::lambda::bind用法的测试程序
  4. 4g网络什么时候淘汰_5G时代,4G将淘汰?4G手机会不会像2g,突然失去网络
  5. C# 向listbox添加大量数据项的实践心得
  6. 写java线程导致电脑内存不足_如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码...
  7. Android VNC Server New
  8. mysql复制的工作原理及主从复制的实现
  9. 线程的基本状态 java 1615477073
  10. org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result
  11. asp.net core 支付宝支付( 电脑2.0)
  12. class path resource [spring/] cannot be resolved to URL because it does not exist
  13. 小学多媒体计算机室管理计划,多媒体教室管理工作计划5篇
  14. 微信服务号获取地理位置
  15. 关于vue的@click传递
  16. html 文字竖排效果
  17. 机器学习中分类与聚类的本质区别
  18. softlayer iso_使用SoftLayer创建安全的WordPress博客
  19. ios开发特殊符号大全:字符+键盘符...
  20. lg显示器工厂模式怎么进入_LG液晶显示器进入工厂模式方法.概要

热门文章

  1. SQL null的学问
  2. 关于计算机编程语言 国外网友妙语录
  3. Linux-第一篇linux基本认识
  4. Spring学习手札(二)面向切面编程AOP
  5. python3访问map
  6. 使用sslsplit嗅探tls/ssl连接
  7. [WCF编程]12.事务:事务概述
  8. js--属性和方法(私有/公有)
  9. 在winform里怎么调用WebBrowser控件里的脚本 (转自思归呓语)
  10. ECCV 2018 papers+ oral+ 开源+导读