IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> Logistic 回归 -> 正文阅读

[人工智能]Logistic 回归

创作背景

本菜鸡最近想学学 机器学习,这不,刚开始。
如果觉得我这篇文章写的好的话,能不能给我 点个赞评论 一波。如果要点个 关注 的话也不是不可以🤗

回归与分类的区别

  • 回归 要预测的结果是 具体的数值,根据训练数据预测某一输入对应的输出数据。输出的结果是 实数
  • 分类 要判断的结果是 类别,根据训练数据预测 分类正确的概率 (属于 [0, 1]),进而输出 判断的类别

回归向分类的转变

既然都是 预测,使用相同的 x ,只是输出从原来的 实数 变成了 类别,那我们就用一个函数将结果从 实数集 映射到 [0, 1] 中,然后再转成对应分类不就行了呗。

  • 举个栗子:
    • 有两个类别的实例,o 代表正例,x 代表负例
    • 可以找到一个超平面 w T x + b = 0 {w}^{T}x+b=0 wTx+b=0 将两类实例分隔开,即 正确分类
    • 其中, w ∈ R n w \in {\mathbb{R}}^{n} wRn 为超平面的 法向量 b ∈ R b \in \mathbb{R} bR偏置
    • 超平面上方的点都满足 w T x + b > 0 {w}^{T}x+b>0 wTx+b>0
    • 超平面下方的点都满足 w T x + b < 0 {w}^{T}x+b<0 wTx+b<0
    • 可以根据以下 x 的线性函数值(与 0 的比较结果)判断实例类别: z = g ( x ) = w T x + b z=g(x)={w}^{T}x+b z=g(x)=wTx+b
    • 分类函数以 z 为输入,输出预测的类别: c = H ( z ) = H ( g ( x ) ) c=H(z)=H(g(x)) c=H(z)=H(g(x))
  • 以上是 线性分类器 的基本模型。

有个方法可以实现 线性分类器 ,那就是 Logistic 回归。

  • Logistic 回归是一种 广义线性 模型,使用 线性判别式函数 对实例进行分类。

而一般实现这种分类方法的函数是 sigmoid 函数。(因为其中最为出名的是 logistic 函数,所以也被称为 logistic 函数)。

饱和函数

先看一下 饱和函数,至于为什么要看这个函数,因为 Sigmoid 函数都需要满足这个函数,具体见下述 sigmoid (也即 logistic) 函数。

  • x < 0 时,导数值 x ≥ 0 时,导数值 ,即,将导函数为 正态分布 的分布函数称为 饱和函数
  • 看一下图像。
    在这里插入图片描述

一些饱和函数

  • 单位阶跃函数 δ
  • e r f ( π 2 x ) erf(\frac{\sqrt {\pi}}{2}x) erf(2π ??x)
  • 2 π arctan ? ( π 2 x ) \frac{2}{\pi} \arctan {(\frac{\pi}{2}x)} π2?arctan(2π?x)
  • 2 π g d ( π 2 x ) \frac{2}{\pi} gd(\frac{\pi}{2}x) π2?gd(2π?x)
  • x 1 + ∣ x ∣ \frac{x}{1+|x|} 1+xx?

图像如下
在这里插入图片描述
它们的导函数是服从 正态分布 的,图像如下
在这里插入图片描述
所以,最理想的分类函数为 单位阶跃函数直上直下的,是 饱和函数 的一种。如下图
在这里插入图片描述

也就是
H ( z ) = { 0 , x < 0 0.5 , x = 0 1 , x > 0 H(z)= \begin{cases} 0, x<0 \\ 0.5, x=0 \\ 1, x>0 \end{cases} H(z)=??????0,x<00.5,x=01,x>0?

  • 但单位阶跃函数作为分类函数有一个严重缺点,不连续,所以 不是处处可微,使得一些算法不可用(如 梯度下降)。
  • 找一个 输入输出特性与单位阶跃函数类似,并且 单调可微的函数 来代替阶跃函数,sigmoid 函数是一种常用替代函数。

sigmoid 函数(logistic 函数)

sigmoid 函数是一类函数,满足以下函数特征即可:

  • 有极限
  • 单调 函数
  • 满足 饱和函数 (知道我为什么要提到 饱和函数 了吧(●’?’●))

函数定义
σ ( x ) = 1 1 + e ? z \sigma(x)=\frac{1}{1+{e}^{-z}} σ(x)=1+e?z1?

  • 一般 σ \sigma σ 函数就指 logistic 函数

logistic 函数的值域在 (0,1) 之间连续,函数的输出可视为 x 条件下实例为正例的条件概率 ,即
P ( y = 1 ∣ x ) = σ ( g ( x ) ) = 1 1 + e ? ( w T x + b ) P(y=1|x)=\sigma (g(x))=\frac{1}{1+{e}^{-({w}^{T}x+b)}} P(y=1x)=σ(g(x))=1+e?(wTx+b)1?
x 条件下实例为负例的条件概率为
P ( y = 0 ∣ x ) = 1 ? σ ( g ( x ) ) = 1 1 + e ( w T x + b ) P(y=0|x)=1-\sigma (g(x))=\frac{1}{1+{e}^{({w}^{T}x+b)}} P(y=0x)=1?σ(g(x))=1+e(wTx+b)1?

logistic 函数是 对数概率函数反函数,一个事件的概率指该事件发生的概率 p 与该事件不发生的概率 1-p 的比值。

  • 对数概率为
    log ? p 1 ? p \log{\frac{p}{1-p}} log1?pp?
  • 对数概率大于 0 表明 正例 的概率大,反之,则 负例 的概率大。

Logistic 回归模型假设一个实例为正例的对数概率是输入 x 的 线性函数,即:
log ? p 1 ? p = w T x + b \log {\frac{p}{1-p}}={w}^{T}x+b log1?pp?=wTx+b
反求 p ,即:
p = σ ( g ( x ) ) = 1 1 + e ? ( w T x + b ) p = \sigma(g(x))=\frac{1}{1+{e}^{-({w}^{T}x+b)}} p=σ(g(x))=1+e?(wTx+b)1?
logistic 函数有个很好的数学特性, σ ( z ) \sigma(z) σ(z) 一阶导数形式简单,并且关于其本身的函数:
d σ ( z ) d z = σ ( z ) ( 1 ? σ ( z ) ) \frac{d \sigma(z)}{dz} = \sigma(z) (1-\sigma(z)) dzdσ(z)?=σ(z)(1?σ(z))
Logistic 回归模型假设函数为
h w , b ( x ) = σ ( g ( x ) ) = 1 1 + e ? ( w T x + b ) {h}_{w,b}(x) = \sigma (g(x)) = \frac{1}{1+{e}^{-({w}^{T}x+b)}} hw,b?(x)=σ(g(x))=1+e?(wTx+b)1?
b 纳入权向量 w ,假设函数更改为
h w ( x ) = 1 1 + e ? ( w T x ) {h}_{w}(x) = \frac{1}{1+{e}^{-({w}^{T}x)}} hw?(x)=1+e?(wTx)1?

极大似然估计

  • 根据 h w ( x ) {h}_{w}(x) hw?(x) 的概率意义,有

P ( y = 1 ∣ x ) = h w ( x ) P ( y = 0 ∣ x ) = 1 ? h w ( x ) P(y=1|x)={h}_{w}(x) \\ P(y=0|x)=1-{h}_{w}(x) P(y=1x)=hw?(x)P(y=0x)=1?hw?(x)

  • 由此可得,训练集 D 中的某样本 ( x i , y i ) ({x}_{i}, {y}_{i}) (xi?,yi?) ,模型将输入实例 x i {x}_{i} xi? 预测为类别 y i {y}_{i} yi? 的概率为

P ( y = y i ∣ x i ; w ) = h w ( x i ) y i ( 1 ? h w ( x i ) ) 1 ? y i P(y={y}_{i}|{x}_{i};w)={h}_{w}({x}_{i})^{{y}_{i}}(1-{h}_{w}({x}_{i}))^{1-{y}_{i}} P(y=yi?xi?;w)=hw?(xi?)yi?(1?hw?(xi?))1?yi?

  • 训练集 D 各样本独立同分布,定义似然函数 L(w) 描述训练集中 m 个样本同时出现的概率,公式如下:

L ( w ) = Π i = 1 m P ( y = y i ∣ x i ; w ) = ∏ i = 1 m h w ( x i ) y i ( 1 ? h w ( x i ) ) 1 ? y i L(w)=\Pi^{m}_{i=1}{P(y={y}_{i}|{x}_{i};w)} \\ =\prod \limits_{i=1}^{m}{h}_{w}({x}_{i})^{{y}_{i}}(1-{h}_{w}({x}_{i}))^{1-{y}_{i}} L(w)=Πi=1m?P(y=yi?xi?;w)=i=1m?hw?(xi?)yi?(1?hw?(xi?))1?yi?

极大似然法 估计参数 w 的核心思想是

  • 选择参数 w,使得当前已经观测到的数据(训练集中的 m 个样本)最有可能出现(概率最大),即:

w ^ = a r g w m a x ? L ( w ) \hat{w}={arg}_{w}max \, L(w) w^=argw?maxL(w)

  • 为了 方便求极值点 ,可将找 L(w) 的极值点转化为找其对数似然函数 ln(L(w)) 的最大值点,即:

w ^ = a r g w m a x ? l n ( L ( w ) ) \hat{w} = {arg}_{w}max \, ln(L(w)) w^=argw?maxln(L(w))

  • 根据定义,对数似然函数为

l ( w ) = l n ( L ( w ) ) = ∑ i = 1 m y i l n ( h w ( x i ) ) + ( 1 ? y i ) l n ( 1 ? h w ( x i ) ) l(w)=ln(L(w))=\displaystyle \sum ^{m}_{i=1}{{y}_{i}ln({h}_{w}({x}_{i}))}+(1-{y}_{i})ln(1-{h}_{w}({x}_{i})) l(w)=ln(L(w))=i=1m?yi?ln(hw?(xi?))+(1?yi?)ln(1?hw?(xi?))

梯度下降更新公式

对于 Logistic 回归模型,可以定义其损失为:

J ( w ) = ? 1 m ? l ( w ) = ? 1 m ∑ i = 1 m y i ? l n ( h w ( x i ) ) + ( 1 ? y i ) ? l n ( 1 ? h w ( x i ) ) J(w)=-\frac{1}{m} \ l(w)=-\frac{1}{m} \displaystyle \sum ^{m}_{i=1}{{y}_{i} \ ln({h}_{w}({x}_{i}))+(1-{y}_{i}) \ ln(1-{h}_{w}({x}_{i}))} J(w)=?m1??l(w)=?m1?i=1m?yi??ln(hw?(xi?))+(1?yi?)?ln(1?hw?(xi?))

  • 此时,求出损失函数 最小值 与求出对数似然函数 最大值 等价,求损失函数最小值依然可以使用 梯度下降算法 ,最终估计出模型参数 w ^ \hat{w} w^

计算 J(w) 对分量 w j {w}_{j} wj? 的偏导数(就对上边的公式 求导

? ? w j J ( w ) = ? 1 m ∑ i = 1 m y i l n h w ( x i ) + ( 1 ? y i ) l n ( 1 ? h w ( x i ) ) \frac{\partial}{\partial {w}_{j}}J(w)=-\frac{1}{m}\displaystyle \sum^{m}_{i=1}{{y}_{i}ln{h}_{w}({x}_{i})+(1-{y}_{i})ln(1-{h}_{w}({x}_{i}))} ?wj???J(w)=?m1?i=1m?yi?lnhw?(xi?)+(1?yi?)ln(1?hw?(xi?))
= ? 1 m ∑ i = 1 m y i ? ? w j l n h w ( x i ) + ( 1 ? y i ) ? ? w j l n ( 1 ? h w ( x i ) ) =-\frac{1}{m}\displaystyle \sum^{m}_{i=1}{{y}_{i}\frac{\partial }{\partial {w}_{j}}ln{h}_{w}({x}_{i})+(1-{y}_{i})\frac{\partial}{\partial {w}_{j}}ln(1-{h}_{w}({x}_{i}))} =?m1?i=1m?yi??wj???lnhw?(xi?)+(1?yi?)?wj???ln(1?hw?(xi?))
= ? 1 m ∑ i = 1 m y i ? 1 h w ( x i ) ? h w ( x i ) ? z i ? z i w j + ( 1 ? y i ) 1 1 ? h w ( x i ) ( ? ? h w ( x i ) ? z i ) ? z i w j =- \frac{1}{m} \displaystyle \sum^{m}_{i=1}{{y}_{i} \ \frac{1}{{h}_{w}({x}_{i})} \frac{\partial {h}_{w}({x}_{i})}{\partial {z}_{i}} \frac{\partial {z}_{i}}{{w}_{j}} + (1-{y}_{i}) \frac{1}{1-{h}_{w}({x}_{i})} (-\frac{\partial {h}_{w}({x}_{i})}{\partial {z}_{i}}) \frac{\partial {z}_{i}}{{w}_{j}}} =?m1?i=1m?yi??hw?(xi?)1??zi??hw?(xi?)?wj??zi??+(1?yi?)1?hw?(xi?)1?(??zi??hw?(xi?)?)wj??zi??
= ? 1 m ∑ i = 1 m ( y i h w ( x i ) ? ( 1 ? h w ( x i ) h w ( x i ) ? ( 1 ? y i ) h w ( x i ) ? ( 1 ? h w ( x i ) ) ( 1 ? h w ( x i ) ) ) ? z i w j =-\frac{1}{m} \displaystyle \sum^{m}_{i=1}({y}_{i} \frac{{h}_{w}({x}_{i}) \cdot (1-{h}_{w}({x}_{i})}{{h}_{w}({x}_{i})} -(1-{y}_{i}) \frac{{h}_{w}({x}_{i}) \cdot (1-{h}_{w}({x}_{i}))}{(1-{h}_{w}({x}_{i}))}) \frac{\partial {z}_{i}}{{w}_{j}} =?m1?i=1m?(yi?hw?(xi?)hw?(xi?)?(1?hw?(xi?)??(1?yi?)(1?hw?(xi?))hw?(xi?)?(1?hw?(xi?))?)wj??zi??
= ? 1 m ∑ i = 1 m ( y i ? h w ( x i ) ) ? z i w j =- \frac{1}{m} \displaystyle \sum^{m}_{i=1}({y}_{i}-{h}_{w}({x}_{i})) \frac{\partial {z}_{i}}{{w}_{j}} =?m1?i=1m?(yi??hw?(xi?))wj??zi??
= 1 m ∑ i = 1 m ( h w ( x i ) ? y i ) x i j =\frac{1}{m} \displaystyle \sum^{m}_{i=1}({h}_{w}({x}_{i})-{y}_{i}){x}_{ij} =m1?i=1m?(hw?(xi?)?yi?)xij?

  • 其中, h w ( x i ) ? y i {h}_{w}({x}_{i})-{y}_{i} hw?(xi?)?yi? 可解释为模型预测 x i {x}_{i} xi? 为正例的概率与其实际类别之间的 误差

由此可推出梯度 ? J ( w ) \nabla J(w) ?J(w) 计算公式为
? J ( w ) = 1 m ∑ i = 1 m ( h w ( x i ) ? y i ) x i \nabla J(w)=\frac{1}{m} \displaystyle \sum^{m}_{i=1}({h}_{w}({x}_{i})-{y}_{i}){x}_{i} ?J(w)=m1?i=1m?(hw?(xi?)?yi?)xi?

对于随机梯度下降,即 m = 1 时,相应梯度计算公式为
? J ( w ) = ( h w ( x i ) ? y i ) x i \nabla J(w)=({h}_{w}({x}_{i})-{y}_{i}){x}_{i} ?J(w)=(hw?(xi?)?yi?)xi?
设学习率为 η \eta η ,模型参数 w 的更新公式为
w = w ? η ? ? J ( w ) w = w - \eta \ \nabla J(w) w=w?η??J(w)

代码实现

自己实现

既然我们已经了解了 Logistic 模型的数学原理,那现在我们就使用 Python 实现吧!

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

class LogisticRegression:
    
    def __init__(self, w_init=0.0, steps=10000, eta=0.01):
        
        # 训练迭代次数
        self.steps = steps
        
        # 学习率
        self.eta = eta
        
        # 初始化模型参数
        self.w_init = w_init
        
        self.w = None
    
    def __z(self, X):
        '''
        计算 x 与 w 的内积
        '''
        # 矩阵点积:[1*n] ? [n*m] = [1*m]
        return np.dot(self.w, X.T)
    
    def __sigmoid(self, z):
        '''
        Sigmoid 函数
        '''
        return 1. / (1. + np.exp(-z))
    
    def __predict_proba(self, X):
        '''
        预测为正例的概率
        '''
        
        # 求 z
        z = self.__z(X)
        
        # 利用 Sigmoid 函数求预测为 '分类1' 的概率,>=0.5 的为 '分类1' ,否则为 '分类0'
        return self.__sigmoid(z)
    
    def __loss(self, y, y_pred):
        '''
        求损失
        '''
        # 数学公式见上述
        return -np.sum(y * np.log(y_pred) + (1-y)* np.log(1-y_pred)) / y.size
    
    def __preprocess(self, X):
        '''
        预处理 x,x0 = 1
        '''
        m, n = X.shape
        
        # 初始化新矩阵
        X_ = np.zeros((m, n+1))
        # x0 = 1
        X_[:, 0] = 1
        X_[:, 1:] = X
        return X_
    
    def __gradient(self, X, y, y_pred):
        '''
        求梯度
        '''
        # 矩阵乘法:[1*m] * [m*n] = [1*n]
        return np.matmul(y_pred-y, X) / y.size
        
    def train(self, X, y):
        
        # 预处理 X
        X = self.__preprocess(X)
        
        # 生成 w 矩阵
        m, n = X.shape
        self.w = np.full((1, n), self.w_init)
        
        # 创建 step-loss DataFrame,用于绘图
        plot_loss = pd.DataFrame(columns=['step', 'loss'])
        
        for step in range(1, self.steps+1):
            
            # 求 y_hat
            y_pred = self.__predict_proba(X)
            
            # 求损失,存入 DataFrame 中,并输出
            loss = self.__loss(y, y_pred)
            plot_loss.loc[plot_loss.shape[0]+1] = [step, loss]
            
            print('\rEpoch: {} {:>.2f}%: [{}{}] loss={:>.2f}'.format(
                step, step / self.steps * 100,
                '■' * int(step / self.steps * 20),
                '□' * (20 - int(step/self.steps*20)),
                loss
            ), end='')
            
            # 求梯度
            grad = self.__gradient(X, y, y_pred)
            
            # 更新权重 w
            self.w -= self.eta * grad
        
        # 绘制 step-loss 折线图
        plt.plot(plot_loss['step'], plot_loss['loss'])
        plt.xlabel('step')
        plt.ylabel('loss')
        plt.show()
    
    def predict(self, X):
        
        # 预处理 X
        X = self.__preprocess(X)
        # 求 y_hat
        y_pred = self.__predict_proba(X)
        # 转标签
        return np.where(y_pred >= 0.5, 1, 0)

测试一下,训练集就取 x ∈ [ 0 , 10 ] x \in [0, 10] x[0,10]0.1 为步长的 等差数列 y ∈ 0 , 1 y \in {0, 1} y0,1 的二分类数组,将 x ≥ 5 x \geq 5 x5 的数据对应的标签设置为 1 ,其余为 0,弄好以后画个图瞅瞅。代码如下:

train_x = np.arange(0, 11, 0.1).reshape(-1, 1)
train_y = np.where(train_x > 5, 1, 0).reshape(1, -1)

# x = [m*n] = [110*1],即有 110 个 x,每个 x 的维度为 1
# y = [1*m] = [1*110],即有 110 个 y

# 显示网格线
plt.grid()
plt.plot(train_x, train_y[0])
plt.show()

折线图如下
在这里插入图片描述
下边就用我们的模型试一试效果

model = LogisticRegression()
model.train(train_x, train_y)

在这里插入图片描述

可以看到,损失是逐渐 下降 的。

让我们来预测一波试试。

In[]:	model.predict(np.array([[2], [3], [4], [5], [6]]))

-------------------------------------------------------------

Out[]:	array([[0, 0, 0, 1, 1]])

看起来结果还是不错的。

利用 sklearn 实现

不得不佩服强大的 Python 生态,有好多大佬们写好的库,我们直接调用其中的 API 即可,sklearn 就是 Python 机器学习 一个常用的库,用它实现 Logistic 回归,代码如下(数据还是上边的数据):

In[]:	from sklearn.linear_model import LogisticRegression
		lr = LogisticRegression()
		lr.fit(train_x, train_y.reshape(-1, 1))
		lr.predict(np.array([[2], [3], [4], [5], [6]]))

---------------------------------------------------------------

Out[]:	array([0, 0, 0, 1, 1])

在这里插入图片描述
成功咯!!!

参考资料

这可不能忘

[1]刘硕.Python机器学习算法原理、实现与案例[M].北京:清华大学出版社,2019




结尾

有想要一起学习 python 的小伙伴可以扫码进群哦。
在这里插入图片描述
以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。
在这里插入图片描述

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-10-20 12:29:39  更:2021-10-20 12:29:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 8:21:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码