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 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 机器学习强基计划4-4:详解半朴素贝叶斯分类AODE原理(附Python实现) -> 正文阅读

[人工智能]机器学习强基计划4-4:详解半朴素贝叶斯分类AODE原理(附Python实现)

0 写在前面

机器学习强基计划聚焦深度和广度,加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理;“广”在分析多个机器学习模型:决策树、支持向量机、贝叶斯与马尔科夫决策、强化学习等。

🚀详情:机器学习强基计划(附几十种经典模型源码合集)


1 独依赖假设

机器学习强基计划4-3:详解朴素贝叶斯分类原理 | 例题分析 | Python实现中我们介绍了朴素贝叶斯之所以“朴素”,是因为其给定了很强的属性独立性假设。然而,属性独立性假设在实际上很难成立,因此引入半朴素贝叶斯分类器(Semi-Na?ve Bayes Classifier),其核心思想是:适当考虑部分属性的相互依赖,从而既简化了联合概率计算,又不至于彻底忽略属性间的强依赖关系

在这里插入图片描述

半朴素贝叶斯分类器最常见的建模策略是独依赖估计(One-Dependent Estimator, ODE),即假设每个属性在类别外最多依赖于一个属性

f ? ( x ) = a r g max ? C ∈ Y P ( C ) ∏ i = 1 d P ( x i ∣ C , p a i ) {f^*\left( \boldsymbol{x} \right) =\underset{C\in \mathcal{Y}}{\mathrm{arg}\max}P\left( C \right) \prod_{i=1}^d{P\left( x_i|C, pa_i \right)}} f?(x)=CYargmax?P(C)i=1d?P(xi?C,pai?)

其中 p a i pa_i pai?为属性 x i x_i xi?所依赖的父属性。若对 ? x i \forall x_i ?xi?确定了其 p a i pa_i pai?,则可按朴素贝叶斯的方式进行贝叶斯分类,因此问题的核心转换为如何确定 p a i pa_i pai?

另一个问题是,可以假设属性依赖多个父属性吗?答案是:高阶依赖估计的准确性要求训练样本随指数级增加,在有限样本条件下,一般不适合采用。

2 AODE原理

先介绍一个比较直接的想法——假设所有属性都依赖于同一个父属性,称该属性为超父(super-parent),这种半朴素贝叶斯分类器称为SPODE(Super-Parent ODE)算法。

f ? ( x ) = a r g max ? C ∈ Y P ( C ) ∏ i = 1 d P ( x i ∣ C , p a ) f^*\left( \boldsymbol{x} \right) =\underset{C\in \mathcal{Y}}{\mathrm{arg}\max}P\left( C \right) \prod_{i=1}^d{P\left( x_i|C, pa \right)} f?(x)=CYargmax?P(C)i=1d?P(xi?C,pa)

建立在SPODE的基础上,AODE(Averaged ODE)算法是一种基于集成学习机制、更为强大的ODE分类器,其将每个属性作为超父构造SPODE,再加权计算各属性间的平均依赖,即

f ? ( x ) = a r g max ? C ∈ Y ∑ i = 1 , ∣ D x i ∣ ? m d P ( C , x i ) ∏ j = 1 d P ( x j ∣ C , x i ) f^*\left( \boldsymbol{x} \right) =\underset{C\in \mathcal{Y}}{\mathrm{arg}\max}\sum_{i=1,|\boldsymbol{D}_{x_i}|\geqslant m}^d{P\left( C,x_i \right) \prod_{j=1}^d{P\left( x_j|C, x_i \right)}} f?(x)=CYargmax?i=1,Dxi???md?P(C,xi?)j=1d?P(xj?C,xi?)

其中 D x i \boldsymbol{D}_{x_i} Dxi??为第 i i i属性上取值为 x i x_i xi?的样本子集, m m m默认设为30。类似地,AODE的拉普拉斯平滑修正为

{ P ( C , x i ) = ∣ D C , x i ∣ + 1 ∣ D ∣ + N × N i P ( x j ∣ C , x i ) = ∣ D C , x i , x j ∣ + 1 ∣ D C , x i ∣ + N j \begin{cases} P\left( C,x_i \right) =\frac{|\boldsymbol{D}_{C,x_i}|+1}{|\boldsymbol{D}|+N\times N_i}\\ P\left( x_j|C,x_i \right) =\frac{|\boldsymbol{D}_{C,x_i,x_j}|+1}{|\boldsymbol{D}_{C,x_i}|+N_j}\\\end{cases} ? ? ??P(C,xi?)=D+N×Ni?DC,xi??+1?P(xj?C,xi?)=DC,xi??+Nj?DC,xi?,xj??+1??

简单说,AODE就是SPODE的加权平均版本

在这里插入图片描述

接下来基于上述原理开始编程,并和朴素贝叶斯分类做个比较,看性能有没提升

3 Python实现

3.1 计算类先验概率

'''
* @breif: 计算类先验概率P(C, xi)
* @param[in]: None
* @retval: None

{
    C1: { 
            超父属性(只能是离散属性)
            pa1: {
                    超父属性值
                    px1: {
                            p: p(C1, x1)
                            N: n(C1, x1)
                        }
                    ...
                    pxn: ...
                    num(pa1): int 属性a1的可取值数
                }
            ...
            pan: ...
        }
    ...
    Cn: ...
    num: 类别数
}

'''    
def calPrior(self):
    # 可选的类别数
    label = np.unique(self.y)
    self.prior['num'] = len(label)

    # 计算先验概率
    for _label in label:
        self.prior[_label] = {}
        # 获取标签取值_label的样本集
        labelIndex = np.squeeze(np.argwhere(np.squeeze(self.y)==_label))
        labelX = self.X[:, labelIndex]           
        # 超父特征层
        for i in range(self.d):
            # 属性i的可选属性值列表
            attr = np.unique(self.X[i, :])
            # 可选属性数
            attrNum = len(attr)
            # 离散属性(只有离散属性能作为超父属性)
            if attrNum <= 0.85 * self.m:
                self.prior[_label][str(i)] = {}
                self.prior[_label][str(i)]['num'] = attrNum
                # 计算每个取值的联合先验概率
                for a in attr:
                    self.prior[_label][str(i)][a] = {}
                    n = int(sum(labelX[i, :] == a))
                    self.prior[_label][str(i)][a]['p'] = (n + self.laplace) / (self.m + self.prior['num'] * attrNum)
                    self.prior[_label][str(i)][a]['N'] = n

3.2 计算属性后验概率

'''
* @breif: 计算属性后验概率P(xj|C, xi)
* @param[in]: None
* @retval: None

{
    C1: { 
            超父属性(只能是离散属性)
            pa1: {
                    超父属性值
                    px1: {
                            常规属性
                            a1: {
                                    type: discrete 离散属性
                                    x1: p(x1)
                                    ...
                                    xn: p(xn)
                                    num(a1): int 属性b1的可取值数
                                }
                            a2: {
                                    type: continous 连续属性
                                    mean: 样本均值
                                    std: 标准差
                                }
                        }
                    ...
                    pxn: ...
                }
            ...
            pan: ...
        }
    ...
    Cn: ...
    num: 类别数
}

'''
def calPosterior(self):
    if not self.prior:
        raise ValueError("please calculate prior first!")
    # 可选的类别数
    label = np.unique(self.y)
    self.posterior['num'] = len(label)

    # 标签层
    for _label in label:
        self.posterior[_label] = {}
        # 获取标签取值_label的样本集
        labelIndex = np.squeeze(np.argwhere(np.squeeze(self.y)==_label))
        labelX = self.X[:, labelIndex]
        
        # 超父特征层
        for pa, paDict in self.prior[_label].items():
            self.posterior[_label][pa] = {}

            # 超父属性值层
            for paVal, paValDict in paDict.items():
                if isinstance(paValDict, dict):
                    self.posterior[_label][pa][paVal] = {}

                    # 常规属性层
                    for i in range(self.d):
                        # 常规属性为超父属性则跳过
                        if i == pa:
                            continue

                        # 获取超父属性值为paVal的样本子集
                        paIndex = np.squeeze(np.argwhere(labelX[int(pa), :]==paVal))
                        paLabelX = labelX[:, paIndex].reshape(self.d, -1)
                        _, mpa = paLabelX.shape

                        self.posterior[_label][pa][paVal][str(i)] = {}
                        # 属性i的可选属性值列表
                        attr = np.unique(self.X[i, :])
                        # 可选属性数
                        attrNum = len(attr)
                        # 离散属性
                        if attrNum <= 0.85 * self.m:
                            self.posterior[_label][pa][paVal][str(i)]['num'] = attrNum
                            self.posterior[_label][pa][paVal][str(i)]['type'] = 'discrete'
                            # 计算每个取值的后验概率
                            for a in attr:
                                n = int(sum(paLabelX[i, :] == a))
                                self.posterior[_label][pa][paVal][str(i)][a] = \
                                    (n + self.laplace) / (self.prior[_label][pa][paVal]['N'] + attrNum)
                        # 连续属性
                        else:
                            self.posterior[_label][pa][paVal][str(i)]['type'] = 'continous'
                            # 发生的概率足够大,才会产生足够的样本
                            if mpa > 1:
                                self.posterior[_label][pa][paVal][str(i)]['std'] = paLabelX[i, :].std(ddof=1)
                                self.posterior[_label][pa][paVal][str(i)]['mean'] = paLabelX[i, :].mean()
                            else:
                                self.posterior[_label][pa][paVal][str(i)]['std'] = self.sigmaEpi
                                self.posterior[_label][pa][paVal][str(i)]['mean'] = 0

3.3 预测

采用机器学习强基计划2-3:图文详解决策树预剪枝、后剪枝原理+Python实现的数据集训练,获得准确率如下

model = AODE(X, y)
# 训练模型
model.train()
# 模型预测
predictY = model.predict(X)
print("错误:", np.sum(predictY!=y.T), "个\n准确率为:", np.sum(predictY==y.T)/y.size)

>>> 错误: 0>>> 准确率为: 1.0

而在机器学习强基计划4-3:详解朴素贝叶斯分类原理 | 例题分析 | Python实现中准确率只有83.2%,可见适当的依赖性假设有助于提高分类准确率

完整代码联系下方博主名片获取


🔥 更多精彩专栏


👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:42:06  更:2022-10-08 20:43:08 
 
开发: 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年12日历 -2024/12/28 3:47:07-

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