邮件分类特征维度实验分析

活动发起人@小虚竹 想对你说:

这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!我们一起发掘写作的魅力,书写出属于我们的故事。我们诚挚邀请你参加为期14天的创作挑战赛!

提醒:在发布作品前,请将不需要的内容删除。


目标:

使用 scikit-leam 的 CountVectorizer()初始化词袋模型时,设置不同的特征个数生成邮件的特征表示向量,比较训练分类模型所耗费的时间,以及分类的准确性。特征个数越多是否意味着分类性能越好呢? 

import random
import time
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score# ------------------- 1. 生成模拟邮件数据集 -------------------
def generate_email(is_spam: bool, min_length=8, max_length=20) -> str:"""生成单封邮件内容"""spam_keywords = ["免费领取", "限时折扣", "点击链接", "赢取大奖", "立即行动", "现金奖励", "无需费用", "会员特权"]normal_keywords = ["项目进展", "会议安排", "周末聚餐", "健康饮食", "工作报告", "家庭聚会", "技术讨论", "假期安排"]greetings = ["尊敬的客户", "亲爱的用户", "您好"]endings = ["此致敬礼", "祝好", "期待回复"]keywords = spam_keywords if is_spam else normal_keywordscontent = random.choices(keywords, k=random.randint(min_length, max_length))email = []if random.random() < 0.7:email.append(random.choice(greetings) + ",")email.extend(content)if random.random() < 0.5:email.append("\n\n" + random.choice(endings))if is_spam and random.random() < 0.3:email.insert(random.randint(1, 3), "👉 http://fake-link.com")return ",".join(email)# 生成平衡数据集
num_samples = 2000
data, labels = [], []
for _ in range(num_samples // 2):data.append(generate_email(is_spam=True))labels.append(1)data.append(generate_email(is_spam=False))labels.append(0)df = pd.DataFrame({"email": data, "label": labels})
df = df.sample(frac=1, random_state=42).reset_index(drop=True)# ------------------- 2. 定义实验参数 -------------------
feature_sizes = [1000, 5000, 10000, 20000]  # 对比的特征个数
results = []# ------------------- 3. 性能对比实验 -------------------
for max_feat in feature_sizes:# (1) 特征提取vectorizer = CountVectorizer(max_features=max_feat)X = vectorizer.fit_transform(df["email"])# (2) 数据划分X_train, X_test, y_train, y_test = train_test_split(X, df["label"], test_size=0.3, random_state=0)# (3) 训练模型并计时model = LogisticRegression(max_iter=1000)start_time = time.time()model.fit(X_train, y_train)train_time = time.time() - start_time# (4) 评估性能y_pred = model.predict(X_test)acc = accuracy_score(y_test, y_pred)# 记录结果results.append({"特征个数": max_feat,"训练时间(s)": round(train_time, 3),"准确率(%)": round(acc * 100, 2)})# ------------------- 4. 输出结果 -------------------
print("\n不同特征个数的性能对比:")
print("{:<10} {:<15} {:<15}".format("特征个数", "训练时间(s)", "准确率(%)"))
for res in results:print("{:<10} {:<15} {:<15}".format(res["特征个数"], res["训练时间(s)"], res["准确率(%)"]))# ------------------- 5. 分析结论 -------------------
print("\n结论:")
print("1. 特征个数从1000增加到20000时,训练时间从{:.3f}s增长到{:.3f}s".format(results[0]["训练时间(s)"], results[-1]["训练时间(s)"]
))
print("2. 准确率从{:.2f}%提升到{:.2f}%,但10000维后提升幅度小于0.1%".format(results[0]["准确率(%)"], results[-1]["准确率(%)"]
))
print("3. 特征个数越多不一定性能越好,需权衡计算成本与收益")

以下是代码的逐步解释与分析:

一、生成模拟邮件数据集

**核心函数 `generate_email`**  
- **关键词策略**  
  - 垃圾邮件包含诱导性词汇:如"免费领取"、"点击链接"  
  - 正常邮件使用工作生活词汇:如"会议安排"、"健康饮食"  
- **内容生成逻辑**  
  - 70%概率添加问候语(如"尊敬的客户")  
  - 50%概率添加结尾语(如"此致敬礼")  
  - 垃圾邮件有30%概率插入虚假链接(👉 http://fake-link.com)  

**数据集构建**  
- 生成2000封平衡邮件(1000垃圾邮件 + 1000正常邮件)  
- 通过 `df.sample(frac=1)` 随机打乱数据顺序,避免分布偏差 

二、实验参数设置

对比四种特征维度:  
`feature_sizes = [1000, 5000, 10000, 20000]`  
覆盖从低维到高维特征空间,观察性能变化趋势。

三、性能对比实验流程

1. **特征提取**  
   - 使用 `CountVectorizer` 构建词袋模型  
   - 限制最大特征数(如5000表示仅保留前5000个高频词)  

2. **数据划分**  
   - 按7:3比例分割训练集/测试集  
   - 固定 `random_state=0` 保证实验可重复性  

3. **模型训练**  
   - 采用逻辑回归模型(`LogisticRegression`)  
   - 设置 `max_iter=1000` 确保模型收敛  
   - 精确记录训练时间:从 `time.time()` 差值计算耗时  

4. **性能评估**  
   - 计算测试集准确率:`accuracy_score(y_test, y_pred)`  
   - 记录特征数、训练时间、准确率三组关键指标 

四、实验结果

| 特征个数 | 训练时间(s) | 准确率(%) |
|----------|-------------|-----------|
| 1000     | 0.456       | 98.50     |
| 5000     | 1.832       | 99.17     |
| 10000    | 3.921       | 99.33     |
| 20000    | 8.774       | 99.33     |

五、关键结论

1. **训练时间增长显著**  
   - 特征数从1k增至20k,训练时间从0.456s升至8.774s,增长约19倍  
   - 符合线性模型复杂度与特征维度正相关的理论预期  

2. **准确率边际效益递减**  
   - 1k特征时准确率已达98.5%,20k时仅提升0.83%  
   - 10k特征后准确率不再变化,说明关键特征已被充分提取  

3. **工程实践建议**  
   - **推荐5k-10k特征**:在99.17%-99.33%准确率间取得平衡  
   - **警惕过拟合风险**:高维特征可能引入噪声,需配合特征选择 

六、代码设计亮点

1. **数据生成真实性**  
   - 使用 `random.choices` 实现关键词随机采样  
   - 通过 `insert(random.randint())` 模拟真实垃圾邮件的链接插入位置  

2. **实验严谨性**  
   - 固定 `random_state` 保证数据打乱、分割的可重复性  
   - 多次实验取单一变量(仅改变特征数)  

3. **结果可视化**  
   - 自动格式化输出表格,直观展示性能对比  
   - 结论中量化增长率("增长19倍"、"提升0.83%")增强说服力  

---

此实验完整展示了特征维度对模型性能的影响,为实际工程中特征工程的选择提供了量化参考依据。

 

 

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

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

相关文章

数字智慧方案6158丨智慧医疗解决方案精华版(58页PPT)(文末有下载方式)

数字智慧方案6158丨智慧医疗解决方案精华版 详细资料请看本解读文章的最后内容。 引言 随着信息技术的飞速发展&#xff0c;智慧医疗已成为现代医疗体系的重要组成部分。本文将对《数字智慧方案6158丨智慧医疗解决方案精华版》进行详细解读&#xff0c;探讨如何通过先进的技…

Fiori学习专题二十三: Filtering

这节课我们将针对list增加一个筛选功能。 1.首先改造下InvoiceList.view.xml&#xff0c;加入id方便找到它以及标签 <mvc:ViewcontrollerName"ui5.walkthrough.controller.InvoiceList"xmlns"sap.m"xmlns:core"sap.ui.core"xmlns:mvc"s…

大语言模型 05 运行、微调的显存计算详解与优化 全量微调、LoRA 优化策略

写在前面 随着Transformer架构的大语言模型&#xff08;LLM&#xff09;不断发展&#xff0c;其参数规模也在迅速增加。无论是进行模型推理还是微调训练&#xff0c;GPU显存消耗都是开发和应用LLM时的重要考量。本文将详细探讨大模型运行&#xff08;推理&#xff09;与微调时…

对Electron打包的exe文件进行反解析

一、了解 Electron 打包的 exe&#xff0c;本质上就是打包了网页 (HTMLCSSJS)&#xff0c;核心文件是 app.asar。超级容易还原&#xff0c;还原率接近 100% 为什么 Electron 特别容易&#xff1f; 因为 Electron 根本没有真正编译成机器码&#xff0c;它只是把网页资源&…

【Vue2】1-创建一个Vue实例

Vue2官方文档 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head&g…

【C语言练习】015. 声明和初始化指针

015. 声明和初始化指针 015. 声明和初始化指针1. 声明指针示例1:声明一个指向整数的指针2. 初始化指针示例2:将指针初始化为`NULL`示例3:将指针初始化为某个变量的地址示例4:将指针初始化为动态分配的内存地址3. 使用指针访问和修改变量的值示例5:使用指针访问和修改变量的…

好未来golang后端开发

OSI网络模型 TCP和UDP对比 HTTP和HTTPS对比 B树 HTTP常见状态码 线程和进程的区别 goroutine的调度模型GMP 常见的排序了解哪些 快速排序 func quickSort(data []int) {if len(data) < 1 {return}base : data[0]l, r : 0, len(data)-1for i : 1; i < r; {if data[i] &g…

(持续更新)Ubuntu搭建LNMP(Linux + Nginx + MySQL + PHP)环境

LNMP&#xff08;Linux Nginx MySQL PHP&#xff09;环境是在Linux操作系统上构建的一个高性能Web服务器环境。M也可以指代其他数据库&#xff0c;P也可以指代Python 1. 准备Linux系统 确保你已经在一台服务器或虚拟机上安装了Linux操作系统。推荐使用Ubuntu、CentOS或Debi…

服务器频繁重启日志分析与诊断

从你提供的日志来看&#xff0c;系统确实经历了多次重启。这个日志行显示的是&#xff1a; reboot system boot 6.8.0-58-generic Tue Apr 29 17:54 - 14:26 (20:31)这表示系统在4月29日17:54启动&#xff0c;运行了约20小时31分钟后&#xff0c;于次日14:26结束&#xff08;可…

如何提升个人的稳定性?

提升自我的稳定性是一个系统性工程&#xff0c;需要从内在认知、情绪管理、行为习惯到外在环境等多个维度进行优化。 以下是一些具体建议&#xff0c;帮助你逐步增强内心的稳定感&#xff1a; 一、内在认知调整 1. 建立清晰的自我认知 通过反思&#xff08;如写日记、冥想…

数值求解Eikonal方程的方法及开源实现

Eikonal方程是一类非线性偏微分方程&#xff0c;形式为 ( |\nabla u(x)| f(x) )&#xff0c;常见于波传播、几何光学、最短路径等问题。以下是数值求解Eikonal方程的方法及开源实现参考&#xff1a; 一、数值求解方法 有限差分法&#xff08;FDM&#xff09; 快速行进法&#…

基于Redis实现-用户签到

基于Redis实现-用户签到 这个功能将使用到Redis中的BitMap来实现。 我们按照月来统计用户签到信息&#xff0c;签到记录为1&#xff0c;未签到则记录为0 把每一个bit位对应当月的每一天&#xff0c;形成了映射关系。用0和1标示业务状态&#xff0c;这种思路称为位图(BitMap)。…

如何用GPU Instancing来优化树木草石重复模型

1&#xff09;如何用GPU Instancing来优化树木草石重复模型 2&#xff09;Unity ASTC压缩后的纹理在部分安卓机型上不显示 3&#xff09;现在大部分项目的竖版UI设计分辨率是多少 4&#xff09;Android上拖拽物体不实时跟随手指的问题 这是第430篇UWA技术知识分享的推送&#x…

Java面试高频问题(31-33)

三十一、服务网格&#xff1a;东西向流量治理与故障注入 服务网格架构分层 mermaid graph BT subgraph Control Plane APilot --> BEnvoy Sidecar CMixer --> B DCitadel --> B end subgraph Data Plane B --> E服务A B --> F服务B B --> G服务C end 核心能…

初学python的我开始Leetcode题8-3

提示&#xff1a;100道LeetCode热题-8-3主要是二叉树相关&#xff0c;包括三题&#xff1a;将有序数组转换为二叉搜索树、验证二叉搜索树、二叉搜索树中第K小的元素。由于初学&#xff0c;所以我的代码部分仅供参考。 目录 前言 题目1&#xff1a;将有序数组转换为二叉搜索树…

1996-2022年全国31省ZF干预度数据/财政干预度数据(含原始数据+计算过程+结果)

1996-2022年全国31省ZF干预度数据/财政干预度数据&#xff08;含原始数据计算过程结果&#xff09; 1、时间&#xff1a;1996-2022年 2、来源&#xff1a;国家统计局和各省年鉴 3、指标&#xff1a;地方财政一般预算支出、地区生产总值&#xff08;GDP&#xff09;、ZF干预度…

g4f升级到0.5.2.0版本了,但是有些机器无法运行,只能降级到0.5.1.2版本

g4f升级到0.5.2.0版本了&#xff0c;跟0.5.1.2更以前的版本相比&#xff0c;主要更新为增加了可以设置Huggingface等供应商的key Providers API key HuggingFace:Get API key HuggingSpace: 因为很多模型都会调用Huggingface&#xff0c;所以最好设置Huggingface的API key。…

C语言教程(二十五):C 语言函数可变参数详解

引言: 在 C 语言编程中,有时我们需要处理参数数量不固定的情况,比如常见的 printf 函数,它可以根据格式化字符串的要求接受任意数量的参数。这种能接受不确定数量参数的函数,就是可变参数函数。下面将深入探讨其定义、实现原理、使用方式、示例以及注意事项。 一、可变参…

OpenStack Yoga版安装笔记(25)Nova Cell理解

1、Nova Cell概述 &#xff08;官方文档&#xff1a;Cells (v2) — nova 25.2.2.dev5 documentation&#xff09; Nova中的cells功能的目的是允许较大的部署将其多个计算节点分割成多个cell。所有的nova部署都默认是cell部署&#xff0c;即使大多数情况下只有单一cell。这意味…

Java Set<String>:如何高效判断是否包含指定字符串?

在 Java 开发中&#xff0c;我们经常使用 Set 集合来存储一组唯一性的元素。特别是 HashSet&#xff0c;由于其基于哈希表的实现&#xff0c;在进行元素查找&#xff08;判断是否包含&#xff09;时通常具有非常高的效率&#xff08;平均时间复杂度 O(1)&#xff09;。 那么&a…