模式识别编程实践1:身高和/或体重数据进行性别分类

news2024/12/23 6:22:48

🌞欢迎莅临我的个人主页👈🏻这里是我专注于深度学习领域、用心分享知识精粹与智慧火花的独特角落!🍉

🌈如果大家喜欢文章,欢迎:关注🍷+点赞👍🏻+评论✍🏻+收藏🌟,如有错误敬请指正!🪐

🍓“请不要相信胜利就像山坡上的蒲公英一样唾手可得,但是请相信生活中总有美好值得我们全力以赴,哪怕粉身碎骨!”🌹

前言

🌟模式识别导论课程编程实践作业🌟

目录

任务说明

应用单个特征

应用两个特征

数据文件

程序实现思路

读取数据

设置参数

类条件概率密度的最大似然估计

判别函数

结果评价与可视化

完整代码

效果展示

结论分析

一、准确率分析

二、假阳性率分析

三、假阴性率分析

结论

决策表


任务说明

应用单个特征

身高或体重数据作为特征,在正态分布假设下利用最大似然估计分布密度参数,建立最小错误率Bayes分类器,写出得到的决策规则,将该分类器应用到测试样本,考察测试错误情况。在分类器设计时可以考虑采用不同的先验概率(如0.5 vs 0.5、0.75 vs 0.25、0.9 vs 0.1等)进行实验,考察对决策规则和错误率的影响。

应用两个特征

同时采用身高和体重数据作为特征,在正态分布假设下估计概率密度,建立最小错误率Bayes分类器,写出得到的决策规则,将该分类器应用到训练/测试样本,考察训练/测试错误情况,比较相关假设和不相关假设下结果的差异。在分类器设计时可以考察采用不同先验概率(如0.5 vs 0.5、0.75 vs 0.25、0.9 vs 0.1等)进行实验,考察对决策和错误率的影响。

数据文件

🍎下载地址:身高/体重数据文件

🍉文件内容

🫐训练样本集

1、FEMALE.TXT:包含50个女生的身高、体重数据

2、MALE.TXT:包含50个男生的身高、体重数据

🍇测试样本集
1、test1.txt:包含35个同学的身高、体重、性别数据(15个女生、20个男生)

2、test2.txt:包含300个同学的身高、体重、性别数据(50个女生、250个男生)

程序实现思路

注:本系列编程实践均使用Python完成

读取数据

使用numpy库的np.loadtxt读取文本数据

# ----------------------------读取数据---------------------------#
def load_data(filename):
    data = np.loadtxt(filename)
    return data

设置参数

利用贝叶斯分类,需要不同类别的先验概率与条件概率密度,在此我们设先验概率为一组可以调整的参数,如0.5 vs 0.5、0.75 vs 0.25、0.9 vs 0.1等(第一个是女生的概率,第二个是男生的概率

# -----------------------先验概率(女,男)-----------------------#
prior_probs = [(0.5, 0.5), (0.75, 0.25), (0.9, 0.1)]

类条件概率密度的最大似然估计

计算类条件概率密度需要根据特定的概率分布模型以及估计得到的参数来计算。

1️⃣首先是计算用于估计概率分布的参数,这个可以用最大似然估计得到。对于单特征,需要计算样本均值和标准差,对于多特征,需要计算样本均值和协方差矩阵

# ----------------------------最大似然估计-----------------------#
def max_estimate(data, multi_feature):
    if multi_feature:
        return np.mean(data, axis=0), np.cov(data, rowvar=False)
    else:
        return np.mean(data), np.std(data)

2️⃣概率分布模型根据要求使用的是正态分布

3️⃣计算类条件概率密度

单特征情况下,使用norm.pdf()(norm是scipy.stats.norm模块)来计算单变量正态分布的概率密度函数值,也就是单特征下的类条件概率密度。

多特征情况下,使用multivariate_normal.pdf(multivariate_normal是scipy.stats.multivariate_normal模块)来计算多变量正态分布的概率密度函数值,即多特征下的类条件概率密度。

#--------------------类条件概率密度---------------------#
# -------------------单特征-------------------#
p_female = norm.pdf(FEATURE, female_data[0], female_data[1])
p_male = norm.pdf(FEATURE, male_data[0], male_data[1])
# -------------------多特征-------------------#
p_female = multivariate_normal.pdf(FEATURE, female_data[0], female_data[1])
p_male = multivariate_normal.pdf(FEATURE, male_data[0], male_data[1])

判别函数

利用贝叶斯判别需要2个参数:先验概率和类条件概率密度

现在先验概率已经通过假设得到,类条件概率密度通过最大似然估计和正态分布得到,那么两个相乘就是后验概率,我们最终只需要比较后验概率就可以判定数据所属类别

# -------------------单特征--------------------#
# ---------------------------后验概率-------------------------------#
p_female = norm.pdf(FEATURE, female_data[0], female_data[1]) * prior_female
p_male = norm.pdf(FEATURE, male_data[0], male_data[1]) * prior_male
# -------------------多特征-------------------#
p_female = multivariate_normal.pdf(FEATURE, female_data[0], female_data[1]) * prior_female
p_male = multivariate_normal.pdf(FEATURE, male_data[0], male_data[1]) * prior_male
# ---------------------------判断---------------------------#
if p_female > p_male:
     predictions.append(2)  # 女性
else:
     predictions.append(1)  # 男性

补充:根据给定的文本数据来看,1代表男生的标签,2表示女生的标签

结果评价与可视化

⭐️性能评估部分我使用了准确率、错误率和混淆矩阵

🍑准确率和错误率

准确率:预测正确的样本占整个样本的比例

错误率分为假阳性率和假阴性率,这里我假设的男生是正样本、女生是负样本

# -------------------------计算错误率------------------------------#
def error_rate(predictions, true_labels):
    # -------------------阳性(男)--------------------------------#
    positive = np.sum(true_labels == 1)
    # --------------------阴性(女)-------------------------------#
    negative = np.sum(true_labels == 2)
    TP = np.sum((predictions == 1) & (true_labels == 1))
    TN = np.sum((predictions == 2) & (true_labels == 2))
    FP = np.sum((predictions == 1) & (true_labels == 2))
    FN = np.sum((predictions == 2) & (true_labels == 1))
    # -------------------准确率-------------------------#
    accuracy = (TP + TN) / (positive + negative)
    # -------------------假阳性率-------------------------#
    FPR = FP / negative
    # -------------------假阴性率-------------------------#
    FNR = FN / positive
    return accuracy, FPR, FNR

🥥混淆矩阵

TN:预测为阳性实际为阳性

TP:预测为阴性实际为阴性

FN:预测为阳性实际为阴性

FP:预测为阴性实际为阳性

利用内置函数confusion_matrix对预测结果和实际标签进行计算,结果需要注意对角线的值

from sklearn.metrics import confusion_matrix
# -------------------------计算混淆矩阵----------------------------#
cm = confusion_matrix(true_labels, prediction, labels=[1, 2])
confusion_matrices.append((prior_female, prior_male, cm))

⭐️可视化部分仅对混淆矩阵实现

传入混淆矩阵参数,使用seaborn库实现热力图可视化,同时我把界面美化了一下

# --------------------------可视化混淆矩阵-------------------------#
def draw_matrix(confusion_matrices):
    for prior_female, prior_male, cm in confusion_matrices:
        cmap = sns.diverging_palette(0, 230, 90, 60, as_cmap=True)
        sns.heatmap(cm, annot=True, fmt='d', cmap=cmap, linewidths=5, xticklabels=['Female', 'Male'],
                    yticklabels=['Female', 'Male'], square=True)
        plt.title(f'Prior Female: {prior_female}, Prior Male: {prior_male}')
        # plt.savefig(f'confusion_matrix_{prior_female}_{prior_male}.png')
        plt.show()

完整代码

🥕项目目录

        本部分我写了比较详细的注释(主要是便于后期随时修改),只需要改变几个参数就可以实现单特征(身高/体重)或多特征的性别分类任务

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib

matplotlib.use('TkAgg')
from scipy.stats import norm, multivariate_normal
from sklearn.metrics import confusion_matrix

# ----------------------训练数据集----------------------#
FEMALE = r'test1\data\FEMALE.TXT'
MALE = r'test1\data\MALE.TXT'
# ----------------------测试数据集----------------------#
#   测试数据集选择:1: test1.txt     2: test2.txt
# -----------------------------------------------------#
test_num = 2
TEST1 = r'test1\data\test1.txt'
TEST2 = r'test1\data\test2.txt'
# -----------------------先验概率(女,男)-----------------------#
prior_probs = [(0.5, 0.5), (0.75, 0.25), (0.9, 0.1)]
# -----------------------选择单特征/多特征-----------------------#
#       True:多特征 
#       False:单特征(需要设置特征选项)
# -------------------------------------------------------------#
multi_feature = True
# -------------------------特征--------------------------------#
# 身高: 0 体重: 1
# -------------------------------------------------------------#
feature = 1


# ----------------------------读取数据---------------------------#
def load_data(filename):
    data = np.loadtxt(filename)
    return data

# ----------------------------最大似然估计-----------------------#
def max_estimate(data, multi_feature):
    if multi_feature:
        return np.mean(data, axis=0), np.cov(data, rowvar=False)
    else:
        return np.mean(data), np.std(data)

# --------------------------贝叶斯判别函数-------------------------#
def bayes_classifier(test_data, multi_feature, feature, prior_male, prior_female, male_data, female_data):
    predictions = []
    for row in test_data:
        # -------------------单特征-------------------#
        if not multi_feature:
            FEATURE = row[feature]
            # ---------------------------后验概率-------------------------------#
            p_female = norm.pdf(FEATURE, female_data[0], female_data[1]) * prior_female
            p_male = norm.pdf(FEATURE, male_data[0], male_data[1]) * prior_male
        # -------------------多特征-------------------#
        else:
            FEATURE = row[:2]
            p_female = multivariate_normal.pdf(FEATURE, female_data[0], female_data[1]) * prior_female
            p_male = multivariate_normal.pdf(FEATURE, male_data[0], male_data[1]) * prior_male
            # ---------------------------判断---------------------------#
        if p_female > p_male:
            predictions.append(2)  # 女性
        else:
            predictions.append(1)  # 男性
    return np.array(predictions)

# -------------------------计算错误率------------------------------#
def error_rate(predictions, true_labels):
    # -------------------阳性(男)--------------------------------#
    positive = np.sum(true_labels == 1)
    # --------------------阴性(女)-------------------------------#
    negative = np.sum(true_labels == 2)
    TP = np.sum((predictions == 1) & (true_labels == 1))
    TN = np.sum((predictions == 2) & (true_labels == 2))
    FP = np.sum((predictions == 1) & (true_labels == 2))
    FN = np.sum((predictions == 2) & (true_labels == 1))
    # -------------------准确率-------------------------#
    accuracy = (TP + TN) / (positive + negative)
    # -------------------假阳性率-------------------------#
    FPR = FP / negative
    # -------------------假阴性率-------------------------#
    FNR = FN / positive
    return accuracy, FPR, FNR

# --------------------------可视化混淆矩阵-------------------------#
def draw_matrix(confusion_matrices):
    for prior_female, prior_male, cm in confusion_matrices:
        cmap = sns.diverging_palette(0, 230, 90, 60, as_cmap=True)
        sns.heatmap(cm, annot=True, fmt='d', cmap=cmap, linewidths=5, xticklabels=['Female', 'Male'],
                    yticklabels=['Female', 'Male'], square=True)
        plt.title(f'Prior Female: {prior_female}, Prior Male: {prior_male}')
        # plt.savefig(f'confusion_matrix_{prior_female}_{prior_male}.png')
        plt.show()


if __name__ == '__main__':
    # -------------------测试数据集-------------------#
    if test_num == 1:
        test_data = load_data(TEST1)
    elif test_num == 2:
        test_data = load_data(TEST2)
    # -------------------类别标签---------------------#
    true_labels = test_data[:, 2]
    # -------------------混淆矩阵---------------------#
    confusion_matrices = []
    # -------------------------------------------------------------#
    #                       单特征
    # -------------------------------------------------------------#
    if not multi_feature:
        females = load_data(FEMALE)[:, feature]
        males = load_data(MALE)[:, feature]
    # -------------------------------------------------------------#
    #                       多特征
    # -------------------------------------------------------------#
    else:
        females = load_data(FEMALE)
        males = load_data(MALE)
    # --------------------最大似然估计---------------------#
    female_data = max_estimate(females, multi_feature)
    male_data = max_estimate(males, multi_feature)
    # -------------------不同先验概率测试-------------------#
    for prior_female, prior_male in prior_probs:
        prediction = bayes_classifier(test_data, multi_feature, feature, prior_male, prior_female, male_data,
                                      female_data)
        # -------------------------计算混淆矩阵----------------------------#
        cm = confusion_matrix(true_labels, prediction, labels=[1, 2])
        confusion_matrices.append((prior_female, prior_male, cm))
        # ----------------------------计算错误率---------------------------#
        accuracy, FPR, FNR = error_rate(prediction, true_labels)
        if not multi_feature:
            if feature:
                print(
                    f"Feature: Weight | Female: {prior_female:.2f} | Male: {prior_male:.2f} | 准确率: {accuracy * 100:.2f}% | 假阳性率: {FPR * 100:.2f}% | 假阴性率: {FNR * 100:.2f}%")
            else:
                print(
                    f"Feature: Height | Female: {prior_female:.2f} | Male: {prior_male:.2f} | 准确率: {accuracy * 100:.2f}% | 假阳性率: {FPR * 100:.2f}% | 假阴性率: {FNR * 100:.2f}%")
        else:
            print(
                f"Feature: Weight and Height | Female: {prior_female:.2f} | Male: {prior_male:.2f} | 准确率: {accuracy * 100:.2f}% | 假阳性率: {FPR * 100:.2f}% | 假阴性率:{FNR * 100:.2f}%")
    # ----------------------------绘制混淆矩阵---------------------------#
    draw_matrix(confusion_matrices)

效果展示

仅展示test2.txt测试集的测试结果

🥪终端

🍟混淆矩阵

结论分析

一、准确率分析

        随着赋予女性的先验概率从 0.50 增加到 0.90准确率呈现下降趋势。这表明当越来越倾向于预测为女性时,整体的正确分类比例在降低。可能的原因是,过度偏向某一类别会导致对另一类别的误判增多,从而降低了整体的准确率。

二、假阳性率分析

        在三种不同的先验概率设置下,假阳性率始终保持在 2.00%。这说明无论如何调整女性和男性的先验概率,将实际为男性而错误判断为女性的情况相对稳定且比例较低

三、假阴性率分析

        随着女性先验概率的增加,假阴性率不断升高。这意味着当更倾向于预测为女性时,将实际为男性错误判断为女性的情况增多,导致男性被误判的比例上升。

结论

  •   当阈值更加倾向于预测女性(即Female阈值较高)时,假阴性率增加,这表示更多的女性被错误地排除。
  • 假阳性率在整个过程中保持相对稳定,说明模型在区分非女性方面较为一致
  • 随着Female阈值的增加,整体的准确率下降,这可能表明模型在该数据集上更倾向于预测男性  

​​​​​​​决策表

  

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

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

相关文章

回溯大总结

目录 0、基础什么是回溯?回溯法解决的问题回溯模板 1、组合问题77. 组合216.组合总和III17. 电话号码的字母组合39. 组合总和:40.组合总和II 0、基础 什么是回溯? 回溯是一种穷举的搜索算法,并不是一个高效的算法,当…

高并发内存池(五):ThreadCache、CentralCache和PageCache的内存回收机制、阶段性代码展示和释放内存过程的调试

目录 ThreadCache的内存回收机制 补充内容1 补充内容2 补充内容3 补充内容4 ListTooLong函数的实现 CentralCache的内存回收机制 MapObjectToSpan函数的实现 ReleaseListToSpans函数的实现 PageCache的内存回收机制 补充内容1 补充内容2 ReleaseSpanToPageCache函…

【Spine】引入PhotoshopToSpine脚本

引入 右键Photoshop图标,选择属性 打开文件所在位置 找到目录下的\Presets\Scripts文件夹。 找到Spine目录下的\scripts\photoshop文件夹下的PhotoshopToSpine.jsx 复制它,丢到Photoshop刚才找的那个目录下。 使用 打开.psd文件,检查不要…

二叉树:总结篇!【需要掌握的二叉树技能都在这里啦】

文章目录 前言二叉树理论基础二叉树理论基础二叉树的遍历方式深度优先遍历广度优先遍历 N叉树的遍历方式求二叉树的属性二叉树:是否对称二叉树:求最大深度二叉树:求最小深度二叉树:求有多少个节点二叉树:是否平衡二叉树…

外贸财务软件精选,提升管理效率与精准度

ZohoBooks、QuickBooks等六款会计软件各具特色,支持多币种、国际化等功能,适合不同规模外贸企业。其中,ZohoBooks功能全面,QuickBooks操作简便,SageIntacct适合复杂业务,用友U8和金蝶K/3面向中大型企业&…

CommandLineRunner 和 ApplicationRunner

CommandLineRunner 和 ApplicationRunner 背景: 项目启动之前,预先加载数据。比如,权限容器、特殊用户数据等。通常我们可以使用监听器、事件来操作。但是,springboot提供了一个简单的方式来实现此类需求,即&#xf…

《Linux从小白到高手》理论篇(九):Linux的资源监控管理

本篇介绍Linux的资源监控管理。 1、CPU 资源管理 进程调度: Linux 采用公平的进程调度算法,确保每个进程都能获得合理的 CPU 时间。调度算法会根据进程的优先级、等待时间等因素来决定哪个进程获得 CPU 使用权。 可以通过调整进程的优先级来影响其获得…

C++继承实例讲解

C类继承的基本概念 base class,基类、父类 derived class,派生类、子类 C中的类可以扩展,创建保留基类特征的新类,这个过程称之为继承。类继承也可以描述为:派生类继承基类的成员,并在其上添加自己的成员…

【hot100-java】【单词搜索】

回溯 回溯可以使用DFS剪枝解决 class Solution {public boolean exist(char[][] board, String word) {char[] wordsword.toCharArray();for(int i0;i<board.length;i){for(int j0;j<board[0].length;j){if(dfs(board,words,i,j,0)) return true;}}return false;}boolean…

关于Elastic Search与MySQL之间的数据同步

目录 前言 思路分析 同步调用 异步通知 监听binlog 选择 实现数据同步 思路 运行项目 声明交换机、队列 1&#xff09;引入依赖 2&#xff09;声明队列交换机名称 3&#xff09;声明队列交换机 发送MQ消息 接收MQ消息 前言 Elastic Search中的酒店数据来自于MyS…

TypeScript 算法手册【插入排序】

文章目录 TypeScript 算法手册 - 插入排序1. 插入排序简介1.1 插入排序定义1.2 插入排序特点 2. 插入排序步骤过程拆解2.1 选择当前元素2.2 寻找插入位置2.3 插入元素 3. 插入排序的优化3.1 二分查找插入排序案例代码和动态图 4. 插入排序的优点5. 插入排序的缺点总结 【 已更新…

48.哀家要长脑子了!

1.376. 摆动序列 - 力扣&#xff08;LeetCode&#xff09; 看问题抓本质 本质&#xff01;&#xff01;识别和追踪数组中元素值的变化趋势。摆动序列是什么&#xff0c;什么是摆动序列&#xff0c;就是差值正负正负的来&#xff0c;最后要求摆动序列的子序列的长度的话&#x…

如何在KEIL的Debug模式下导出数据

我们知道&#xff0c;利用Keil编写程序时&#xff0c;可以实时显示数据的值&#xff0c;如上图所示&#xff0c;实时显示Voltage和fre的值&#xff0c;那如何导出该数据呢&#xff0c;下边进行详细说明。 首先&#xff0c;进入Debug模式&#xff0c;点击调试里边的函数编辑器。…

计算机毕业设计 基于Python的摄影平台交流系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

GPU、AI、CUDA

文章目录 1.千层面层多层 2. CPU与GPU架构差异3.大规模矩阵操作4.专为并行计算设计的库 1.千层面 神经网络的本质是千层面&#xff0c;由一层一层的线性代数方程组成&#xff0c;每个方程都表示一段数据与另一段数据相关的可能性 层 神经网络的每一次层可以看作是一次线性代…

泰勒图 ——基于相关性与标准差的多模型评价指标可视化比较-XGBoost、sklearn

1、基于相关性与标准差的多模型评价指标可视化比较 # 数据读取并分割 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split plt.rcParams[font.family] = Times New Roman plt.rcParams[axes.unic…

工单管理系统功能解析,企业运营效率提升利器

工单管理系统如ZohoDesk提供工单生成分配、跟踪、数据分析、客户服务管理及移动兼容等功能&#xff0c;提升效率、增强服务、便于监管和降低成本&#xff0c;是现代企业信息化建设的重要部分。 一. 工单管理系统一般有哪些功能 1. 工单生成与分配 工单管理系统的基础功能是创…

Webstorm 中对 Node.js 后端项目进行断点调试

首先&#xff0c;肯定需要有一个启动服务器的命令脚本。 然后&#xff0c;写一个 debug 的配置&#xff1a; 然后&#xff0c;debug 模式 启动项目和 启动调试服务&#xff1a; 最后&#xff0c;发送请求&#xff0c;即可调试&#xff1a; 这几个关键按钮含义&#xff1a; 重启…

8.数据结构与算法-双向链表

双向链表的结构定义 从第二个指针找到下一个元素 从第一个指针找到上一个元素 双向循环列表 从第二个指针找到下一个元素&#xff0c;第二个指针可以往前循环找到链表开头 从第一个指针找到上一个元素&#xff0c;第一个指针可以往前循环昭侯链表结尾 双向链表的插入 双向链…

NLP:BERT的介绍并使用该模型计算文本相似度

1. BERT 1.1 Transformer Transformer架构是一种基于自注意力机制(self-attention)的神经网络架构&#xff0c;它代替了以前流行的循环神经网络和长短期记忆网络&#xff0c;已经应用到多个自然语言处理方向。   Transformer架构由两个主要部分组成&#xff1a;编码器(Encod…