Lesson 4.1 逻辑回归模型构建与多分类学习方法

news2024/11/17 14:39:39

文章目录

  • 一、广义线性模型(Generalized liner model)的基本定义
  • 二、对数几率模型与逻辑回归
    • 1. 对数几率模型(logit model)
    • 2. 逻辑回归与 Sigmoid 函数
    • 3. Sigmoid 函数性质
  • 三、逻辑回归模型输出结果与模型可解释性
  • 四、多分类学习与多分类逻辑回归
    • 1. OvO 策略
    • 2. OvR 策略
    • 3. MvM 策略

  • 首先,我们来讨论关于逻辑回归的基本原理。
  • 逻辑回归的基本原理,从整体上来划分可以分为两个部分,其一是关于模型方程的构建,也就是方程的基本形态,当然也包括模型的基本性质及其结果解读;其二则是模型参数求解,即在构建完模型之后如何利用数学工具求解最佳参数。基本划分情况如下:
  • 模型构建部分:可以从广义线性回归(Generalized liner model)+ 对数几率函数(logit function)角度理解,也可以从随机变量的逻辑斯蒂分布(logistic distribution)角度出发进行理解。
  • 参数求解部分:可以借助极大似然估计(Maximum Likelihood Estimate)方法求解,可以借助 KL 离散度基本理论构建二分类交叉熵损失函数求解。
# 科学计算模块
import numpy as np
import pandas as pd

# 绘图模块
import matplotlib as mpl
import matplotlib.pyplot as plt

# 自定义模块
from ML_basic_function import *

一、广义线性模型(Generalized liner model)的基本定义

  • 在前文中我们了解到关于线性回归的局限性,这种局限性的根本由模型本身的简单线性结构(自变量加权求和预测因变量)导致的。
  • 如果说线性回归是在一个相对严格的条件下建立的简单模型,那么在后续实践应用过程中,人们根据实际情况的不同,在线性回归的基础上又衍生出了种类繁多的线性类模型。
  • 其中,有一类线性模型,是在线性回归基础上,在等号的左边或右边加上了一个函数,从而能够让模型更好的捕捉一般规律,此时该模型就被称为广义线性模型,该函数就被称为联系函数
  • 广义线性模型的提出初衷上还是为了解决非线性相关的预测问题,例如,现在有数据分布如下:
# 数据集特征
np.random.seed(24)
x = np.linspace(0, 4, 20).reshape(-1, 1)
x = np.concatenate((x, np.ones_like(x)), axis=1)
x
#array([[0.        , 1.        ],
#       [0.21052632, 1.        ],
#       [0.42105263, 1.        ],
#       [0.63157895, 1.        ],
#       [0.84210526, 1.        ],
#       [1.05263158, 1.        ],
#       [1.26315789, 1.        ],
#       [1.47368421, 1.        ],
#       [1.68421053, 1.        ],
#       [1.89473684, 1.        ],
#       [2.10526316, 1.        ],
#       [2.31578947, 1.        ],
#       [2.52631579, 1.        ],
#       [2.73684211, 1.        ],
#       [2.94736842, 1.        ],
#       [3.15789474, 1.        ],
#       [3.36842105, 1.        ],
#       [3.57894737, 1.        ],
#       [3.78947368, 1.        ],
#       [4.        , 1.        ]])

# 数据集标签
y = np.exp(x[:, 0] + 1).reshape(-1, 1)
y
#array([[  2.71828183],
#       [  3.35525011],
#       [  4.1414776 ],
#       [  5.11193983],
#       [  6.30980809],
#       [  7.78836987],
#       [  9.61339939],
#       [ 11.86608357],
#       [ 14.64663368],
#       [ 18.07874325],
#       [ 22.31509059],
#       [ 27.54413077],
#       [ 33.99847904],
#       [ 41.96525883],
#       [ 51.79887449],
#       [ 63.93677707],
#       [ 78.91892444],
#       [ 97.41180148],
#       [120.23806881],
#       [148.4131591 ]])
  • 此时 x 和 y 的真实关系为 y = e ( x + 1 ) y=e^{(x+1)} y=e(x+1)
  • 但如果以线性方程来进行预测,即: y = w T ⋅ x + b y= w^T \cdot x + b y=wTx+b
  • 当然,我们可以令 w ^ = [ w 1 , w 2 , . . . w d , b ] T \hat w = [w_1,w_2,...w_d, b]^T w^=[w1,w2,...wd,b]T x ^ = [ x 1 , x 2 , . . . x d , 1 ] T \hat x = [x_1,x_2,...x_d, 1]^T x^=[x1,x2,...xd,1]T,从而将上述方程改写为: y = w ^ T ⋅ x ^ y= \hat w^T \cdot \hat x y=w^Tx^
  • 则模型输出结果为:
np.linalg.lstsq(x, y, rcond=-1)[0]
#array([[ 30.44214742],
#       [-22.37576724]])
  • y = 30.44 x − 22.38 y=30.44x-22.38 y=30.44x22.38
  • 则模型预测结果为:
yhat = x[:, 0] * 30.44 - 22.38
yhat
#array([-22.38      , -15.97157895,  -9.56315789,  -3.15473684,
#         3.25368421,   9.66210526,  16.07052632,  22.47894737,
#        28.88736842,  35.29578947,  41.70421053,  48.11263158,
#        54.52105263,  60.92947368,  67.33789474,  73.74631579,
#        80.15473684,  86.56315789,  92.97157895,  99.38      ])

# 观察模型预测和真实结果
plt.plot(x[:, 0], y, 'o')
plt.plot(x[:, 0], yhat, 'r-')

在这里插入图片描述

  • 能够发现,线性模型预测结果和真实结果差距较大。
  • 但此时如果我们在等号右边加上以 e e e 为底的指数运算,也就是将线性方程输出结果进行以 e e e 为底的指数运算转换之后去预测 y,即将方程改写为 y = e ( w ^ T ⋅ x ^ ) y=e^{(\hat w^T \cdot \hat x)} y=e(w^Tx^)
  • 等价于 l n y = w ^ T ⋅ x ^ lny = \hat w^T \cdot \hat x lny=w^Tx^
  • 即相当于是线性方程输出结果去预测 y y y 取以 e e e 为底的对数运算之后的结果。此时我们可以带入 l n y lny lny 进行建模。
np.linalg.lstsq(x, np.log(y), rcond=-1)[0]
#array([[1.],
#       [1.]])
  • 可得到方程 l n y = x + 1 lny=x+1 lny=x+1
  • 等价于 y = e ( x + 1 ) y=e^{(x+1)} y=e(x+1)
  • 即解出原方程。
  • 通过上面的过程,我们不难发现,通过在模型左右两端加上某些函数,能够让线性模型也具备捕捉非线性规律的能力。而在上例中,这种捕捉非线性规律的本质,是在方程加入 ln 对数函数之后,能够使得模型的输入空间(特征所在空间)到输出空间(标签所在空间)进行了非线性的函数映射。
  • 而这种连接线性方程左右两端、并且实际上能够拓展模型性能的函数,就被称为联系函数,而加入了联系函数的模型也被称为广义线性模型。广义线性模型的一般形式可表示如下: g ( y ) = w ^ T ⋅ x ^ g(y)=\hat w^T \cdot \hat x g(y)=w^Tx^
  • 等价于 y = g − 1 ( w ^ T ⋅ x ^ ) y = g^{-1}(\hat w^T \cdot \hat x) y=g1(w^Tx^)
  • 其中 g ( ⋅ ) g(·) g() 为联系函数(link function), g − 1 ( ⋅ ) g^{-1}(·) g1() 为联系函数的反函数。而如上例中的情况,也就是当联系函数为自然底数的对数函数时,该模型也被称为对数线性模型(logit linear model)。
  • 这里需要注意,一般来说广义线性模型要求联系函数必须是单调可微函数。
  • 从广义线性模型的角度出发,当联系函数为 g ( x ) = x g(x)=x g(x)=x 时, g ( y ) = y = w ^ T ⋅ x ^ g(y)=y=\hat w^T \cdot \hat x g(y)=y=w^Tx^,此时就退化成了线性模型。而能够通过联系函数拓展模型捕捉规律的范围,这也就是广义的由来。

二、对数几率模型与逻辑回归

  • 逻辑回归也被称为对数几率回归。接下来,我们从广义线性模型角度理解逻辑回归。

1. 对数几率模型(logit model)

  • 几率(odd)与对数几率
  • 几率不是概率,而是一个事件发生与不发生的概率的比值。
  • 假设某事件发生的概率为 p,则该事件不发生的概率为 1-p,该事件的几率为: o d d ( p ) = p 1 − p odd(p)=\frac{p}{1-p} odd(p)=1pp
  • 在几率的基础上取(自然底数的)对数,则构成该事件的对数几率(logit): l o g i t ( p ) = l n p 1 − p logit(p) = ln\frac{p}{1-p} logit(p)=ln1pp
  • 这里需要注意的是,logit 的是 log unit 对数单元的简写,和中文中的逻辑一词并没有关系。对数几率模型也被称为对数单位模型(log unit model)。
  • 对数几率模型
  • 如果我们将对数几率看成是一个函数,并将其作为联系函数,即 g ( y ) = l n y 1 − y g(y)=ln\frac{y}{1-y} g(y)=ln1yy,则该广义线性模型为: g ( y ) = l n y 1 − y = w ^ T ⋅ x ^ g(y)=ln\frac{y}{1-y}=\hat w^T \cdot \hat x g(y)=ln1yy=w^Tx^
  • 此时模型就被称为对数几率回归(logistic regression),也被称为逻辑回归。

2. 逻辑回归与 Sigmoid 函数

  • 对数几率函数与 Sigmoid 函数
  • 如果我们希望将上述对数几率函数反解出来,也就是改写为 y = f ( x ) y=f(x) y=f(x) 形式,则可参照下述形式:
  • 方程左右两端取自然底数: y 1 − y = e w ^ T ⋅ x ^ \frac{y}{1-y}=e^{\hat w^T \cdot \hat x} 1yy=ew^Tx^
  • 方程左右两端 +1 可得: y + ( 1 − y ) 1 − y = 1 1 − y = e w ^ T ⋅ x ^ + 1 \frac{y+(1-y)}{1-y}=\frac{1}{1-y}=e^{\hat w^T \cdot \hat x}+1 1yy+(1y)=1y1=ew^Tx^+1
  • 方程左右两端取倒数可得: 1 − y = 1 e w ^ T ⋅ x ^ + 1 1-y=\frac{1}{e^{\hat w^T \cdot \hat x}+1} 1y=ew^Tx^+11
  • 1- 方程左右两端可得: y = 1 − 1 e w ^ T ⋅ x ^ + 1 = e w ^ T ⋅ x ^ e w ^ T ⋅ x ^ + 1 = 1 1 + e − ( w ^ T ⋅ x ^ ) = g − 1 ( w ^ T ⋅ x ^ ) \begin{aligned} y &= 1-\frac{1}{e^{\hat w^T \cdot \hat x}+1}\\ &=\frac{e^{\hat w^T \cdot \hat x}}{e^{\hat w^T \cdot \hat x}+1} \\ &=\frac{1}{1+e^{-(\hat w^T \cdot \hat x)}} = g^{-1}(\hat w^T \cdot \hat x) \end{aligned} y=1ew^Tx^+11=ew^Tx^+1ew^Tx^=1+e(w^Tx^)1=g1(w^Tx^)
  • 因此,逻辑回归基本模型方程为: y = 1 1 + e − ( w ^ T ⋅ x ^ ) y = \frac{1}{1+e^{-(\hat w^T \cdot \hat x)}} y=1+e(w^Tx^)1
  • 同时我们也能发现,对数几率函数的反函数为: f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+ex1
  • 我们可以简单观察该函数的函数图像:
np.random.seed(24)
x = np.linspace(-10, 10, 100)
y = 1 / (1 + np.exp(-x))
plt.plot(x, y)

在这里插入图片描述

  • 能够看出该函数的图像近似 S 形,这种类似 S 形的函数,也被称为 Sigmoid 函数。
  • 注:Sigmoid 严格定义是指形如 S 型的函数,并不是特指某个函数
  • 也就是说,从严格意义来讨论,函数 f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+ex1 只能被称为是 Sigmoid 函数的一种。但实际上,由于该函数是最著名且通用的 Sigmoid 函数,因此大多数时候,我们在说Sigmoid函数的时候,其实就是在指 f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+ex1 函数。

3. Sigmoid 函数性质

  • Sigmoid 函数性质与一阶导函数
  • 对于 Sigmoid 函数来说,函数是单调递增函数,并且自变量在实数域上取值时,因变量取值范围在 (0,1) 之间。并且当自变量取值小于 0 时,因变量取值小于 0.5,当自变量取值大于 0时,因变量取值大于 0.5。
  • 并且,我们简单查看 Sigmoid 导函数性质。
  • 令: S i g m o i d ( x ) = 1 1 + e − x Sigmoid(x) = \frac{1}{1+e^{-x}} Sigmoid(x)=1+ex1
  • 对其求导可得: S i g m o i d ′ ( x ) = ( 1 1 + e − x ) ′ = ( ( 1 + e − x ) − 1 ) ′ = ( − 1 ) ( 1 + e − x ) − 2 ⋅ ( e − x ) ′ = ( 1 + e − x ) − 2 ( e − x ) = e − x ( 1 + e − x ) 2 = e − x + 1 − 1 ( 1 + e − x ) 2 = 1 1 + e − x − 1 ( 1 + e − x ) 2 = 1 1 + e − x ( 1 − 1 1 + e − x ) = S i g m o i d ( x ) ( 1 − S i g m o i d ( x ) ) \begin{aligned} Sigmoid'(x) &= (\frac{1}{1+e^{-x}})' \\ &=((1+e^{-x})^{-1})' \\ &=(-1)(1+e^{-x})^{-2} \cdot (e^{-x})' \\ &=(1+e^{-x})^{-2}(e^{-x}) \\ &=\frac{e^{-x}}{(1+e^{-x})^{2}} \\ &=\frac{e^{-x}+1-1}{(1+e^{-x})^{2}} \\ &=\frac{1}{1+e^{-x}} - \frac{1}{(1+e^{-x})^2} \\ &=\frac{1}{1+e^{-x}}(1-\frac{1}{1+e^{-x}}) \\ &=Sigmoid(x)(1-Sigmoid(x)) \end{aligned} Sigmoid(x)=(1+ex1)=((1+ex)1)=(1)(1+ex)2(ex)=(1+ex)2(ex)=(1+ex)2ex=(1+ex)2ex+11=1+ex1(1+ex)21=1+ex1(11+ex1)=Sigmoid(x)(1Sigmoid(x))
  • 我们发现,Sigmoid 函数的导函数可以简单的用 Sigmoid 函数本身来表示。接下来我们验证 Sigmoid 导函数特性,首先简单定义 Sigmoid 函数:
def sigmoid(x):
    return (1 / (1 + np.exp(-x)))
sigmoid(10)
#0.9999546021312976
  • 据此可定义 Sigmoid 导函数的函数:
def sigmoid_deri(x):
    return (sigmoid(x)*(1-sigmoid(x)))
sigmoid_deri(10)
#4.5395807735907655e-05
  • 进一步,我们可以绘制 Sigmoid 导函数图像:
plt.plot(x, sigmoid_deri(x))

在这里插入图片描述

  • 我们发现,Sigmoid 导函数在实数域上取值大于 0,并且函数图像先递增后递减,并在 0 点取得最大值。据此我们也可以进一步讨论 Sigmoid 函数性质:
plt.plot(x, sigmoid(x))

在这里插入图片描述

  • 由于导函数始终大于 0,因此 Sigmoid 函数始终递增,并且导函数在 0 点取得最大值,因此 Sigmoid 在 0 点变化率最快,而在远离零点的点,Sigmoid 导函数取值较小,因此该区间 Sigmoid 函数变化缓慢。该区间也被称为 Sigmoid 的饱和区间
  • 总结 Sigmoid 函数性质如下:
性质说明
单调性单调递增
变化率0点变化率最大,越远离0点变化率越小
取值范围(0,1)
凹凸性0点为函数拐点,0点之前函数为凸函数,此后函数为凹函数

三、逻辑回归模型输出结果与模型可解释性

  • 从整体情况来看,逻辑回归在经过 Sigmoid 函数处理之后,是将线性方程输出结果压缩在了 0-1 之间,用该结果再来进行回归类的连续数值预测肯定是不合适的了。在实际模型应用过程中,逻辑回归主要应用于二分类问题的预测。
  • 一般来说,我们会将二分类的类别用一个两个分类水平取值的离散变量来代表,两个分类水平分别为 0 和 1。该离散变量也被称为 0-1 离散变量。
  • 连续型输出结果转化为分类预测结果
  • 对于逻辑回归输出的 (0,1) 之间的连续型数值,我们只需要确定一个阈值,就可以将其转化为二分类的类别判别结果。通常来说,这个阈值是 0.5,即以 0.5 为界,调整模型输出结果: y c l a = { 0 , y < 0.5 1 , y ≥ 0.5 \begin{equation} y_{cla}=\left\{ \begin{aligned} 0, y<0.5 \\ 1, y≥0.5 \end{aligned} \right. \end{equation} ycla={0,y<0.51,y0.5
  • 其中, y c l a y_{cla} ycla 为类别判别结果,而 y y y 为逻辑回归方程输出结果 s i g m o i d ( w ^ T ⋅ x ^ ) sigmoid(\hat w^T \cdot \hat x) sigmoid(w^Tx^)。例如,有简单数据集如下:
sepal_widthspecies
20
0.51
  • 由于只有一个自变量,因此可假设逻辑回归模型如下: y = 1 1 + e x − 1 y = \frac{1}{1+e^{x-1}} y=1+ex11
  • 带入数据可进一步计算模型输出结果:
x = np.array([2, 0.5]).reshape(-1, 1)
sigmoid(1-x)
#array([[0.26894142],
#       [0.62245933]])
  • 据此,在阈值为 0.5 的情况下,模型会将第一条判别为 0,第二条结果判别为 1,上述过程代码实现如下:
yhat = sigmoid(1-x)                 # 模型预测结果
yhat
#array([[0.26894142],
#       [0.62245933]])

ycla = np.zeros_like(yhat)
ycla                               # 类别判别结果
#array([[0.],
#       [0.]])

thr = 0.5                         # 设置阈值
yhat >= thr                       # 数组判别
#array([[False],
#       [ True]])

ycla[yhat >= thr] = 1            # 布尔索引
ycla
#array([[0.],
#       [1.]])
  • 即:
sepal_widthspecies方程输出结果类别判别结果
200.270
0.510.621
  • 当然,我们也可以将该过程封装为一个函数:
def logit_cla(yhat, thr=0.5):
    """
    逻辑回归类别输出函数:
    :param yhat: 模型输出结果
    :param thr:阈值
    :return ycla:类别判别结果
    """
    ycla = np.zeros_like(yhat)
    ycla[yhat >= thr] = 1
    return ycla
  • 测试函数性能:
logit_cla(yhat)
#array([[0.],
#       [1.]])
  • 关于阈值的选取与 0\1 分类的类别标记:阈值为人工设置的参数,在没有特殊其他要求下,一般取值为 0.5。
  • 关于类别的数值转化,即将哪一类设置为 0 哪一类设置为 1,也完全可以由人工确定,一般来说,我们会将希望被判别或被识别的类设置为 1,例如违约客户、确诊病例等。
  • 逻辑回归输出结果 (y) 是否是概率
  • 决定 y 是否是概率的核心因素,不是模型本身,而是建模流程。
  • 逻辑斯蒂本身也有对应的概率分布,因此输入的自变量其实是可以视作随机变量的,但前提是需要满足一定的分布要求。
  • 如果逻辑回归的建模流程遵照数理统计方法的一般建模流程,即自变量的分布(或者转化之后的分布)满足一定要求(通过检验),则最终模型输出结果就是严格意义上的概率取值。
  • 如果是遵照机器学习建模流程进行建模,在为对自变量进行假设检验下进行模型构建,则由于自变量分布不一定满足条件,因此输出结果不一定为严格意义上的概率。
  • 例如在上例中:
sepal_widthspecies方程输出结果类别判别结果
0.500.270
210.621
  • 我们可以说,第一条样本预测为 1 的概率为 0.38,相比属于类别 1,第一条样本更大概率属于类别 0;而第二条样本属于类别 1 的概率高达 73%,因此第二条样本我们判别其属于类别 1。
  • 并且,根据逻辑回归方程: y = 1 1 + e − ( 1 − x ) y = \frac{1}{1+e^{-(1-x)}} y=1+e(1x)1
  • 可以进一步推导出: l n y 1 − y = 1 − x ln\frac{y}{1-y} = 1-x ln1yy=1x
  • 可解读为 x 每增加 1,样本属于 1 的概率的对数几率就减少 1。
  • 当然,类似的可解释性,也就是自变量变化对因变量变化的贡献程度的解读,对于线性回归同样适用。例如 y = x + 1 y=x+1 y=x+1,我们可以解读为, x x x 每增加 1, y y y 就增加 1。
  • 而这种基于自变量系数的可解释性不仅可以用于自变量和因变量之间的解释,还可用于自变量重要性的判别当中,例如,假设逻辑回归方程如下: l n y 1 − y = x 1 + 2 x 2 − 1 ln\frac{y}{1-y} = x_1+2x_2-1 ln1yy=x1+2x21
  • 则可解读为 x 2 x_2 x2 的重要性是 x 1 x_1 x1 的两倍, x 2 x_2 x2 每增加 1 的效果(令样本为 1 的概率的增加)是 x 1 x_1 x1 增加 1 效果的两倍。
  • 本节结束后,我们需要将此前定义的两个函数,也就是 Sigmoid 函数、Sigmoid 导函数即逻辑回归类别判别函数写入 ML_basic_function.py 中。
  • 逻辑回归的概率表示形式
  • 如果我们将逻辑回归模型输出结果视作样本属于1类的概率,则可将逻辑回归模型改写成如下形式: p ( y = 1 ∣ x ^ ; w ^ ) = 1 1 + e − ( w ^ T ⋅ x ^ ) p(y=1|\hat x;\hat w) =\frac{1}{1+e^{-(\hat w^T \cdot \hat x)}} p(y=1∣x^;w^)=1+e(w^Tx^)1 p ( y = 0 ∣ x ^ ; w ^ ) = e − ( w ^ T ⋅ x ^ ) 1 + e − ( w ^ T ⋅ x ^ ) p(y=0|\hat x;\hat w) =\frac{e^{-(\hat w^T \cdot \hat x)}}{1+e^{-(\hat w^T \cdot \hat x)}} p(y=0∣x^;w^)=1+e(w^Tx^)e(w^Tx^)

四、多分类学习与多分类逻辑回归

  • 此前的讨论都是基于二分类问题(0-1分类问题)展开的讨论,而如果要使用逻辑回归解决多分类,则需要额外掌握一些技术手段。
  • 总的来说,如果要使用逻辑回归解决多分类问题,一般来说有两种方法,其一是将逻辑回归模型改为多分类模型形式,其二则是采用通用的多分类学习方法对建模流程进行改造。
  • 其中将逻辑回归模型改写成多分类模型形式并不常用并且求解过程非常复杂,包括 Scikit-Learn 在内,主流的实现多分类逻辑回归的方法都是采用多分类学习方法。
  • 所谓多分类学习方法,则指的是将一些二分类学习器(binary classifier)推广到多分类的场景中,该方法属于包括逻辑回归在内所有二分类器都能使用的通用方法。
  • 多分类问题描述
  • 当离散型标签拥有两个以上分类水平时,即对多个(两个以上)分类进行类别预测的问题,被称为多分类问题。例如有如下四分类问题简单数据集:

在这里插入图片描述

  • 其中 index 是每条数据编号,labels 是每条数据的标签。
  • 多分类问题解决思路
  • 一般来说,用二分类学习器解决多分类问题,基本思想是先拆分后集成,也就是先将数据集进行拆分,然后多个数据集可训练多个模型,然后再对多个模型进行集成。这里所谓集成,指的是使用这多个模型对后续新进来数据的预测方法。
  • 具体来看,依据该思路一般有三种实现策略,分别是一对一(One vs Ons,简称 OvO)、一对剩余(One vs Rest,简称 OvR)和多对多(Many vs Many,加成 MvM)。

1. OvO 策略

  • 拆分策略
  • OvO 的拆分策略比较简单,基本过程是将每个类别对应数据集单独拆分成一个子数据集,然后令其两两组合,再来进行模型训练。
  • 例如,对于上述四分类数据集,根据标签类别可将其拆分成四个数据集,然后再进行两两组合,总共有 6 种组合,也就是 C 4 2 C^2_4 C42 种组合。
  • 拆分过程如下所示:

在这里插入图片描述

  • 集成策略
  • 当模型训练完成之后,接下来面对新数据集的预测,可以使用投票法从 6 个分类器的判别结果中挑选最终判别结果。

在这里插入图片描述

  • 根据少数服从多数的投票法能够得出,某条新数据最终应该属于类别 1。

2. OvR 策略

  • 拆分策略
  • 和 OvO 的两两组合不同,OvR 策略则是每次将一类的样例作为正例、其他所有数据作为反例来进行数据集拆分。
  • 对于上述四分类数据集,OvR 策略最终会将其拆分为 4 个数据集,基本拆分过程如下:

在这里插入图片描述

  • 此 4 个数据集就将训练 4 个分类器。
  • 注意,在 OvR 的划分策略中,是将 rest 无差别全都划分为负类。当然,如果数据集总共有 N 个类别,则在进行数据集划分时总共将拆分成 N 个数据集。
  • 集成策略
  • 当成,集成策略和划分策略息息相关,对于 OvR 方法来说,对于新数据的预测,如果仅有一个分类器将其预测为正例,则新数据集属于该类。
  • 若有多个分类器将其预测为正例,则根据分类器本身准确率来进行判断,选取准确率更高的那个分类器的判别结果作为新数据的预测结果。

在这里插入图片描述

  • OvO 和 OvR的比较
  • 对于这两种策略来说,尽管 OvO 需要训练更多的基础分类器,但由于 OvO 中的每个切分出来的数据集都更小,因此基础分类器训练时间也将更短。
  • 因此,综合来看在训练时间开销上,OvO 往往要小于 OvR。而在性能方面,大多数情况下二者性能类似。

3. MvM 策略

  • 相比于 OvO 和 OvR,MvM 是一种更加复杂的策略。
  • MvM 要求同时将若干类化为正类、其他类化为负类,并且要求多次划分,再进行集成。一般来说,通常会采用一种名为纠错输出码(Error Correcting Output Codes,简称 ECOC)的技术来实现 MvM 过程。
  • 拆分策略
  • 此时对于上述 4 分类数据集,拆分过程就会变得更加复杂,我们可以任选其中一类作为正类、其余作为负类,也可以任选其中两类作为正类、其余作为负数,以此类推。由此则诞生出了非常多种子数据集,对应也将训练非常多个基础分类器。
  • 当然,将某一类视作正类和将其余三类视作正类的预测结果相同,对调下预测结果即可,此处不用重复划分。
  • 例如,对于上述 4 分类数据集,则可有如下划分方式:

在这里插入图片描述

  • 根据上述划分方式,总共将划分 C 4 1 + C 4 2 = 10 C_4^1+C_4^2=10 C41+C42=10 个数据集,对应构建,对应的我们可以构建 10 个分类器。不过一般来说对于 ECOC 来说我们不会如此详尽的对数据集进行划分,而是再上述划分结果中挑选部分数据集进行建模、
  • 例如就挑选上面显式表示的 4 个数据集来进行建模,即可构建 4 个分类器。
  • 由此我们也不难看出 OvR 实际上是 MvM 的一种特例。
  • 集成策略
  • 接下来我们进行模型集成。值得注意的是,如果是以上述方式划分四个数据集,我们可以将每次划分过程中正例或负例的标签所组成的数组视为每一条数据自己的编码。如下所示:

在这里插入图片描述

  • 同时,我们使用训练好的四个基础分类器对新数据进行预测,也将产生四个结果,而这四个结果也可构成一个四位的新数据的编码。
  • 接下来,我们可以计算新数据的编码和上述不同类别编码之间的距离,从而判断新生成数据应该属于哪一类。

在这里插入图片描述

  • 不拿发现,如果预测足够准确,编码其实是和类别一一对应的。但如果基础分类器预测类别不够准确,编码和类别并不一定会一一对应,有一种三元编码方式,会将这种情况的某个具体编码改为 0 (纠错输出码),意为停用类。
  • 当然,距离计算有很多种方法,此处简单进行介绍,假设 x 和 y 是两组 n 维数据如下所示: x = ( x 1 , x 2 , . . . , x n ) x=(x_1, x_2, ..., x_n) x=(x1,x2,...,xn) y = ( y 1 , y 2 , . . . , y n ) y=(y_1,y_2,...,y_n) y=(y1,y2,...,yn)
  • 欧式距离计算公式如下: d ( x , y ) = ∑ i = 1 n ( x i − y i ) 2 d(x, y) = \sqrt{\sum_{i = 1}^{n}(x_i-y_i)^2} d(x,y)=i=1n(xiyi)2
  • 即对应位置元素依次相减后取其平方和再开平方。
  • 街道距离计算公式如下: d ( x , y ) = ∑ i = 1 n ( ∣ x i − y i ∣ ) d(x, y) =\sum_{i = 1}^{n}(|x_i-y_i|) d(x,y)=i=1n(xiyi)
  • 即对应位置元素依次相减后取其绝对值的和。
  • 闵可夫斯基距离计算公式如下: d ( x , y ) = ∑ i = 1 n ( ∣ x i − y i ∣ ) n n d(x, y) = \sqrt[n]{\sum_{i = 1}^{n}(|x_i-y_i|)^n} d(x,y)=ni=1n(xiyi)n
  • 不难发现,其实街道距离和欧式距离都是闵可夫斯基距离的特例
  • 此处以欧式距离为例计算新数据编码和各类编码之间距离。为了方便运算,此处可定义闵可夫斯基距离计算函数如下:
def dist(x, y, cat = 2):
    """
    闵可夫斯基距离计算函数
    """
    d1 = np.abs(x - y)
    if x.ndim > 1 or y.ndim > 1:
        res1 = np.power(d1, cat).sum(1) # sum(1)将一行的数值累加求和,返回nx1数组
    else:
        res1 = np.power(d1, cat).sum()
    res = np.power(res1, 1/cat)
    return res
  • 验证函数性能:
x = np.array([1, 2])
y = np.array([2, 3])
dist(x, y) # x与y的欧氏距离
#1.4142135623730951

np.sqrt(2) #返回一个非负平方根
#1.4142135623730951
  • 进行编码距离计算:
# 原类别编码矩阵
code_mat = np.array([[1, -1, 1, -1],
                     [-1, -1, 1, -1],
                     [-1, -1, -1, 1],
                     [-1, 1, -1, 1]])# 预测数据编码
data_code = np.array([1, -1, 1, 1])
dist(code_mat, data_code)
#array([2.        , 2.82842712, 2.82842712, 3.46410162])
  • 也可通过以下方式验证:
np.abs(code_mat - data_code)
#array([[0, 0, 0, 2],
#       [2, 0, 0, 2],
#       [2, 0, 2, 0],
#       [2, 2, 2, 0]])

np.sqrt(np.power(np.abs(code_mat - data_code), 2).)sum(1)
#array([2.        , 2.82842712, 2.82842712, 3.46410162])
  • 不难发现,新样本应该属于第一类。至此,我们就完成了 MvM 的一次多分类预测的全流程。
  • ECOC 方法评估
  • 对于 ECOC 方法来说,编码越长预测结果越准确,不过编码越长也代表着需要耗费更多的计算资源,并且由于模型本身类别有限。
  • 因此数据集划分数量有限,编码长度也会有限。不过一般来说,相比 OvR,MvM 方法效果会更好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/174478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CPU缓存一致性

CPU缓存一致性写直达写回缓存一致性总线嗅探MESI协议CPU Cache通常分为三级缓存&#xff0c;L1Cache&#xff0c;L2Cache,L3Cache&#xff0c;级别越低的离CPU越近&#xff0c;访问速度越快&#xff0c;但同时容量越小&#xff0c;价格越贵。在多核的CPU中&#xff0c;每个核都…

今天大年三十,新年快乐,我在这里给大家整理了一下除夕的习俗,来看看吧

今天是大年三十,阿玥在这里祝大家,一来风水,二来平安,阖家欢乐,四季平安,五福临门,六六大顺,七星高照,八方来财,十全十美,新年好! 名字:不晓得 学习:python,c 主页:木有 今天给大家整理一下大年三十的习俗等小知识,就不更python啦 目录 除夕要做的事情有什么…

Meta CTO:真正的全天候轻量化AR眼镜,可能要到2030年

去年Meta发布了售价高达1500美元的VST头显Quest Pro&#xff0c;该头显与Meta的Quest 2等产品在定价、技术路径上有很大不同&#xff0c;其搭载了眼球追踪、彩色VST等更高端的功能&#xff0c;而产品发布后&#xff0c;外界对其反馈也褒贬不一。作为Pro产品线首个产品&#xff…

Markdown基础总结

Markdown Tools TyporaVSCode Markdown Preview Enhanced扩展 有道云笔记… 上述工具都能很好地支持markdown书写 Markdown标题 1 使用 和 - 标记一级和二级标题 和 - 标记语法格式如下&#xff1a; 我展示的是一级标题我展示的是二级标题 ---效果如下: 2 使用 # 号标…

Java设计模式-访问者模式、访问者模式怎么使用,具体是怎么用

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.10 访问者模式 6.10.1 定义 封装一些作用域某种数据结构中的各元素的操作&#xff0c;可以在不改变此数据结构的前提下定义作用于这些元素的新操作 6.10.2 结…

2023年新年烟花代码(背景音乐完整版)

文章目录前言烟花效果展示使用教程查看源码HTML代码CSS代码JavaScript新年祝福前言 大家过年好&#xff01;新春佳节&#xff0c;在这个充满喜悦的日子里&#xff0c;愿新年的钟声带给你一份希望和期待&#xff0c;我相信&#xff0c;时空的距离不能阻隔你我&#xff0c;我的祝…

Solidity 中的数学(第 5 部分:指数和对数

本文是关于在 Solidity 中进行数学运算的系列文章中的第五篇。这次的主题是&#xff1a;指数和对数 介绍 几个世纪以来&#xff0c;对数被用来简化计算。在电子计算器广泛普及之前&#xff0c;计算尺、基于对数的机械计算器是工程师职业的标志。 对数函数连同指数函数&#x…

【matplotlib】21.多图合并【python3、numpy、pandas、matplotlib完结】

#【matplotlib】21.多图合并 2023.1.20 python3、numpy、pandas、matplotlib完结 新年快乐&#xff01;&#xff01; 21.1 多合一显示 21.1.1 均匀分布 方法很简单 就是一张图 分几块 第一张占几块 从哪开始&#xff1b;第二张… plt.subplot() # 打开一个窗口 import ma…

Redis数据类型简介

目录 1、字符串(Strings) 1.1、底层实现 1.2、基本命令 1.3、应用场景 2、列表(Lists) 2.1、底层实现 2.2、基本命令 2.3、应用场景 3、集合(Sets) 3.1、底层实现 3.2、基本命令 3.3、应用场景 4、哈希(Hashes) 4.1、底层实现 4.2、基本命令 4.3、应用场景 5、…

Caché数据库简要记录

前一阵子&#xff0c;实施的小伙伴找过来问我用过 Cach 数据库吗&#xff1f;我当时有点懵&#xff1f;难道是 redis、memcached 之流&#xff1f;后来我特意去搜索了一下&#xff0c;还真是有一款数据库叫做 Cach Database。 这里做一下简单的记录吧&#xff0c;Cach 在医疗系…

Mine Goose Duck 0.1版本发布

我本次制作了一款MC版的Goose Goose Duck模组&#xff0c;游戏版本是Forge 1.19.2。 1.身份物品 熟悉鹅鸭杀的朋友都知道游戏中含有许多的身份&#xff0c;有好人、坏人、中立三个阵营&#xff0c;本次我加入了原作中的一些基本角色&#xff1a; 1.警长 你可以杀死怪物但错…

DFS(三)电话号码的字母组合

数组版本 哈希版本&#xff1a; 一、17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#x…

Elasticsearch7.8.0版本高级查询——范围查询文档

目录一、初始化文档数据二、范围查询文档2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; {"name":"张三","age"…

Git的安装与使用

目录 一、简介 1. Git 是什么&#xff1f; 2. 集中式和分布式 二、Git 环境搭建 1. Linux 下安装 2. Windows 下安装 三、创建版本库 四、把文件添加到版本库 1. 添加并提交 2. 仓库状态 3. 版本回退 &#xff08;1&#xff09;查看提交日志 &#xff08;2&#xff0…

量化交易-因子有效性分析

量化交易-因子有效性分析一、 因子的 IC 分析2. 信息系数3. 举例4. 因子处理4.1 去极值4.2 标准化4.3 市值中性化一、 因子的 IC 分析 判断因子与收益的相关性强度 分析结果 因子平均收益IC meanIC stdIC > 0.02&#xff1a;IC大约0.02的比例&#xff0c;越大越严格IR&…

leetcode刷题记录总结-1. 数组

文章目录一、二分查找[704. 二分查找](https://leetcode.cn/problems/binary-search/)题解小结[35. 搜索插入位置](https://leetcode.cn/problems/search-insert-position/)题解1&#xff1a;暴力解法题解2&#xff1a;二分法[34. 在排序数组中查找元素的第一个和最后一个位置]…

Day865.基础架构 -MySQL实战

基础架构&#xff1a;一条SQL查询语句是如何执行的 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的关于基础架构&#xff1a;一条SQL查询语句是如何执行的的内容。 经常说&#xff0c;看一个事儿千万不要直接陷入细节里&#xff0c;应该先鸟瞰其全貌&#xff0c;这样能够…

01-使用Camera Raw滤镜调色

1.需求展示 点击下载图片素材 原图 调色后, 具有电影感 2.操作步骤 1.打开原图 1.我使用的是ps2018, 打开原图, 图层名字可以自定义 2.拷贝底片建立一个新图层 养成好习惯, 每种操作都建立新图层来进行, 这样如果修坏了, 直接把该图层删除就行了, 还原图片比较快捷 3…

[QMT]03-让QMT支持从Tushare获取数据

QMT安装python第三方库为了兼容性&#xff0c;需要本地使用python3.6.8版本&#xff0c;因为刚刚下载的QMT python版本就是3.6.8.如果你本地有其他python版本的话&#xff0c;建议使用虚拟环境操作。这样不会影响你原有的python版本以及已经安装的第三方库。因为一机装多版本的…

Java设计模式-中介模式/中介模式具体怎么使用,使用场景又是什么

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.8 中介者模式 6.8.1 定义 调停模式&#xff0c;定义一个中介角色来封装一系列对象的之间交互&#xff0c;使元有对象之间的耦合松散&#xff0c;且可以独立改变…