AI开发:逻辑回归 - 实战演练- 垃圾邮件的识别(二)

news2024/12/4 3:10:50

接上一篇AI开发:逻辑回归 - 实战演练- 垃圾邮件的识别(一)

new_email 无论为什么文本,识别结果几乎都是垃圾邮件,因此我们需要对源码的逻辑进行梳理一下:

在代码中,new_email 无论赋值为何内容都被识别为垃圾邮件(spam),很可能是以下原因之一导致的:

1. 模型训练数据偏差

  • 如果训练数据中垃圾邮件的数量占绝大多数,模型可能会倾向于将所有输入都分类为垃圾邮件。这种问题叫 类别不平衡
  • 解决方法:
    • 平衡数据集:增加非垃圾邮件的样本数量或减少垃圾邮件的样本数量。
    • 使用加权损失函数:在模型训练中对少数类赋予更高的权重。
    • 使用过采样(如 SMOTE)或欠采样技术调整数据分布。

2. 决策边界问题

  • 如果模型的决策边界定义不明确(比如分类器的阈值设置过低或过高),可能会导致模型将所有样本错误分类为某一类别。
  • 解决方法:
    • 检查分类器的阈值(例如,对于逻辑回归,默认阈值为 0.5),并调整为更合理的值。
    • 可视化模型的概率分布,分析垃圾邮件和非垃圾邮件的分类结果。

3. 特征处理问题

  • 如果 new_email 的输入特征没有正确提取(例如特征全为零或异常值),分类器可能会默认分类为垃圾邮件。
  • 解决方法:
    • 检查 new_email 的特征提取过程,确保提取后的特征与训练集特征保持一致。
    • 验证输入数据是否经过与训练数据相同的预处理步骤(如分词、TF-IDF 向量化等)。

4. 过拟合问题

  • 如果模型在训练过程中过拟合,它可能会将所有未知输入归类为训练集中出现频率较高的类别。
  • 解决方法:
    • 重新训练模型,使用正则化技术(如 L1 或 L2)。
    • 增加训练数据的多样性,避免模型记住训练集中的特定模式。

5. 代码逻辑问题

  • 检查预测逻辑是否正确,比如是否意外硬编码了返回值。
  • 示例问题:
    if predicted_label == 1:
        return "Spam"
    else:
        return "Spam"  # 错误逻辑,导致所有都被识别为垃圾邮件
    

6. 模型性能问题

  • 如果模型本身性能很差,可能是因为特征不足或算法选择不当,导致分类效果失败。
  • 解决方法:
    • 评估模型性能(如查看混淆矩阵、F1 分数)。
    • 尝试使用更强的分类器(如随机森林、SVM 或深度学习模型)。

对代码的检查建议

  1. 打印输入特征: 打印出 new_email 的特征向量,检查特征是否异常。

  2. 验证模型输出: 检查模型的概率预测输出(如 predict_proba 方法),确认阈值是否设置合理。

  3. 调试代码: 确认是否存在逻辑错误,特别是在预处理和分类阶段。

因此我们调试一个单独的测试单元:

基于之前的代码,结合分析问题的原因,进行修改以确保模型能够正常工作并准确分类新邮件。以下是一些改进:


修改代码的核心点

  1. 处理类别不平衡
    使用 class_weight='balanced' 或对数据进行平衡处理。

  2. 检查输入特征
    确保 new_email 的特征提取与训练数据一致。

  3. 调整决策阈值
    添加概率输出,并允许用户调整分类阈值。

  4. 增加性能调试信息
    输出模型的预测概率和特征向量,方便检查。


修订后的代码测试单元

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix

# 示例数据
data = {
    'email': [
        "Win a free iPhone", 
        "Your account is locked, click here", 
        "Meeting tomorrow at 10 AM", 
        "How are you doing today?"
    ],
    'label': [1, 1, 0, 0]
}
data_df = pd.DataFrame(data)

# 特征提取
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(data_df['email'])
y = data_df['label']

# 训练测试集划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 处理类别不平衡
model = LogisticRegression(class_weight='balanced')  # 添加 class_weight
model.fit(X_train, y_train)

# 测试模型
y_pred = model.predict(X_test)
print("分类报告:\n", classification_report(y_test, y_pred))

# 测试混淆矩阵
print("混淆矩阵:\n", confusion_matrix(y_test, y_pred))

# 新邮件分类
new_email = "Meeting schedule confirmed"  # 替换为任何测试字符串
new_email_features = vectorizer.transform([new_email])
predicted_prob = model.predict_proba(new_email_features)[0]  # 获取概率
predicted_label = (predicted_prob[1] > 0.5).astype(int)  # 自定义阈值,默认 0.5

print(f"预测概率:{predicted_prob}")
print(f"预测结果:{'Spam' if predicted_label == 1 else 'Not Spam'}")

修改内容说明

  1. 类别不平衡处理:

    • LogisticRegression 中增加 class_weight='balanced',让模型在训练时对垃圾邮件和非垃圾邮件赋予相同权重。
  2. 可调阈值:

    • 默认设置阈值为 0.5,但可以修改为更低或更高以优化精度和召回率。
  3. 模型输出可视化:

    • 添加 predict_proba 输出,显示垃圾邮件和非垃圾邮件的概率,便于调试。
  4. 新增输入检查:

    • 确保 new_email 特征提取与训练数据一致。

测试案例

试试将 new_email 替换为以下字符串,观察输出:

  • "Win a free vacation now!"(垃圾邮件)
  • "Lunch meeting tomorrow at noon"(非垃圾邮件)
  • "Click here to reset your password"(垃圾邮件)

如果模型仍然总是输出垃圾邮件,请注意以下的关键点:

  1. 数据集是否过于不平衡。
  2. classification_report 的输出。
  3. predict_proba 的详细概率分布。

这样不断调试,我们可以进一步优化代码。

以下是改进了处理流程、模型平衡和调试信息的展示:


改进内容

  1. 处理类别不平衡

    • 使用 class_weight='balanced' 或直接进行数据采样平衡,避免模型倾向于输出多数类。
    • 打印垃圾邮件和正常邮件的分布以确保平衡性。
  2. 特征优化

    • 增加 TfidfVectorizer 的参数调整,如 max_featuresngram_range,以优化特征表达。
  3. 可调阈值

    • 使用概率预测,支持调整垃圾邮件分类的阈值。
  4. 增加调试信息

    • 输出分类报告和混淆矩阵,用于评估模型性能。
  5. 文件路径和异常处理

    • 添加对文件夹路径检查的提示和文件读取异常的处理。

在第一篇文章基础上改进后的全部代码

import os
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix
import numpy as np

# 步骤 1:读取文件内容
def read_files(folder_path):
    if not os.path.exists(folder_path):
        raise FileNotFoundError(f"文件夹 {folder_path} 不存在,请检查路径!")
    
    texts = []
    for filename in os.listdir(folder_path):
        file_path = os.path.join(folder_path, filename)
        if os.path.isfile(file_path):
            try:
                with open(file_path, 'r', encoding='utf-8') as file:
                    texts.append(file.read())
            except Exception as e:
                print(f"无法读取文件 {filename}:{e}")
    return texts

# 假设 A 文件夹为垃圾邮件文件夹,B 文件夹为正常邮件文件夹
folder_A = "path_to_folder_A"  # 垃圾邮件文件夹路径
folder_B = "path_to_folder_B"  # 正常邮件文件夹路径

# 读取文件内容
spam_texts = read_files(folder_A)
ham_texts = read_files(folder_B)

# 数据和标签
texts = spam_texts + ham_texts
labels = [1] * len(spam_texts) + [0] * len(ham_texts)

print(f"垃圾邮件数量: {len(spam_texts)}, 正常邮件数量: {len(ham_texts)}")

# 特征提取
vectorizer = TfidfVectorizer(stop_words='english', max_features=1000, ngram_range=(1, 2))
X = vectorizer.fit_transform(texts)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.3, random_state=42)

# 步骤 2:处理类别不平衡
model = LogisticRegression(class_weight='balanced', random_state=42)
model.fit(X_train, y_train)

# 步骤 3:评估模型
y_pred = model.predict(X_test)
print("分类报告:\n", classification_report(y_test, y_pred))
print("混淆矩阵:\n", confusion_matrix(y_test, y_pred))

# 步骤 4:判定新的邮件是否是垃圾邮件
def predict_spam_or_ham(new_email_text, threshold=0.5):
    new_email_vec = vectorizer.transform([new_email_text])
    predicted_prob = model.predict_proba(new_email_vec)[0]
    print(f"预测概率:{predicted_prob}")
    return "垃圾邮件" if predicted_prob[1] > threshold else "正常邮件"

# 示例:输入一个新的邮件文本进行预测
new_email = "Congratulations! You've won a free vacation. Claim now!"
result = predict_spam_or_ham(new_email)
print(f"新邮件预测结果: {result}")

# 可尝试调整分类阈值
adjusted_threshold = 0.6
result_adjusted = predict_spam_or_ham(new_email, threshold=adjusted_threshold)
print(f"新邮件预测结果 (调整阈值 {adjusted_threshold}): {result_adjusted}")

改进点详细说明

  1. 类别平衡

    • class_weight='balanced' 用于在数据分布不均衡时平衡类别权重。
    • 打印垃圾邮件和正常邮件数量,及时发现数据分布问题。
  2. 特征优化

    • max_features=1000 限制特征数量,避免高维稀疏特征对模型性能的影响。
    • ngram_range=(1, 2) 增加特征的上下文表达能力。
  3. 分类阈值调整

    • 提供 threshold 参数以灵活调整垃圾邮件判定的概率阈值,适应不同应用场景。
  4. 调试信息

    • classification_reportconfusion_matrix 帮助评估模型的准确率、召回率和精确率。
  5. 文件路径检查和异常处理

    • 在读取文件时检查路径合法性,并捕获异常,防止单个文件导致整个流程中断。

测试步骤

  1. 将垃圾邮件放入 folder_A,正常邮件放入 folder_B
  2. 调整特征提取参数,如 max_featuresngram_range
  3. 替换 new_email 测试不同邮件内容,并观察概率和分类结果。

需要注意的是,这时候还是需要再微调,因为运行程序后你会发现识别还是不准确,在不断调整后,

将 adjusted_threshold = 0.6 改成 adjusted_threshold = 0.555,最后用如下文本分别测试:

# 示例:输入一个新的邮件文本进行预测
#new_email = "Congratulations! You've won a free vacation. Claim now!"
#new_email = "hi Dad , Will you go to China?"
new_email = "Congratulations! You won a chance to travel for free. Claim now!"
new_email = "This is a notice of school opening"
result = predict_spam_or_ham(new_email)
print(f"新邮件预测结果: {result}")

# 可尝试调整分类阈值
adjusted_threshold = 0.555
result_adjusted = predict_spam_or_ham(new_email, threshold=adjusted_threshold)
print(f"新邮件预测结果 (调整阈值 {adjusted_threshold}): {result_adjusted}")

 以下结果清晰展示了成功识别了不同的文本。

当然,因为样本数据量很少,整个模型的识别率还是很低,因此需要不断累计足够的样本,才能更精准地识别出垃圾邮件。 

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

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

相关文章

WPF+MVVM案例实战与特效(三十)- 封装一个系统日志显示控件

文章目录 1、运行效果2、日志控件封装1、文件创建2、DisplayLogPanel.xaml 代码3、DisplayLogPanel.cs 代码4、数据模型5、枚举类型3、自定义控件使用1、LogPanelWindow.xaml2、LogPanelViewModel.cs4、总结1、运行效果 2、日志控件封装 1、文件创建 打开 Wpf_Examples ,在 …

VideoBooth: Diffusion-based Video Generation with Image Prompts

VideoBooth: Diffusion-based Video Generation with Image Prompts 概括 文章提出了一个视频生成模型VideoBooth,输入一张图片和一个文本提示词,即可输出保持图片中物体且符合文本提示词要求的视频。 方法 粗-细两阶段设计:1)…

电子电气架构 --- 面向服务的汽车诊断架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

生成树详解(STP、RSTP、MSTP)

目录 1、STP 1.概述 2.基本概念 3.端口角色及其作用 4.报文结构 5.STP的端口状态 6.三种定时器 7.STP选举步骤 8.配置BPDU的比较原则 9.TCN BPDU 10.临时环路的问题 11.传统STP的不足 拓扑变更处理过程 2、RSTP 1.端口角色 2.端口状态 3.P/A(Propo…

基于Python制作一个简易UI界面

基于Python制作一个简易UI界面 目录 基于Python制作一个简易UI界面1 原理简介2 编写程序3 程序测试 1 原理简介 这里用到了Python自带的UI库tkinter。 tkinter 是 Python 的标准 GUI(图形用户界面)库,用于创建和管理图形界面。它提供了一个简…

emp.dll丢失导致游戏/软件无法继续运行:详细描述emp.dll丢失原因并提供解决方案

emp.dll 并不是一个标准的 Windows 系统文件,也不是一个广泛认知的第三方库。因此,它可能是一个特定于某个应用程序或游戏的自定义 DLL 文件。如果 emp.dll 丢失导致了你的软件或游戏无法运行,这通常意味着该文件是程序正常运作所必需的。下面…

IDEA使用HotSwapHelper进行热部署

目录 前言JDK1.8特殊准备DECVM安装插件安装与配置参考文档相关下载 前言 碰到了一个项目,用jrebel启动项目时一直报错,不用jrebel时又没问题,找不到原因,又不想放弃热部署功能 因此思考能否通过其他方式进行热部署,找…

droppath

DropPath 是一种用于正则化深度学习模型的技术,它在训练过程中随机丢弃路径(或者说随机让某些部分的输出变为零),从而增强模型的鲁棒性和泛化能力。 代码解释: import torch import torch.nn as nn # 定义 DropPath…

机器学习算法(六)---逻辑回归

常见的十大机器学习算法: 机器学习算法(一)—决策树 机器学习算法(二)—支持向量机SVM 机器学习算法(三)—K近邻 机器学习算法(四)—集成算法 机器学习算法(五…

Ubuntu24.04初始化教程(包含基础优化、ros2)

将会不断更新。但是所有都是基础且必要的操作。 为重装系统之后的环境配置提供便捷信息来源。记录一些错误的解决方案。 目录 构建系统建立系统备份**Timeshift: 系统快照和备份工具****安装 Timeshift****使用 Timeshift 创建快照****还原快照****自动创建快照** 最基本配置换…

【Maven】Nexus私服

6. Maven的私服 6.1 什么是私服 Maven 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。一些无法从外部仓库下载到的构件,如项目组其他人员开发的…

Gradle vs. Maven: 到底哪个更适合java 项目?

ApiHug ApiHug - API Design & Develop New Paradigm.ApiHug - API Design & Develop New Paradigm.https://apihug.com/ 首先 ApiHug 整个工具链是基于 gradle 构建,包括项目模版, 插件; 说到 Java 项目管理,有两个巨头脱颖而出&a…

Dubbo的集群容错策略有哪些?它们的工作原理是什么?

大家好,我是锋哥。今天分享关于【Dubbo的集群容错策略有哪些?它们的工作原理是什么?】面试题。希望对大家有帮助; Dubbo的集群容错策略有哪些?它们的工作原理是什么? 1000道 互联网大厂Java工程师 精选面试…

分治的思想(力扣965、力扣144、牛客KY11)

引言 分治思想是将问题分解为更小子问题,分别解决后再合并结果。二叉树中常用此思想,因其结构递归,易分解为左右子树问题,递归解决后合并结果。 这篇文章会讲解用分治的思想去解决二叉树的一些题目,顺便会强调在做二…

中国电信张宝玉:城市数据基础设施建设运营探索与实践

11月28日,2024新型智慧城市发展创新大会在山东青岛召开,中国电信数字政府研究院院长张宝玉在大会发表主旨演讲《城市数据基础设施运营探索与实践》。报告内容包括城市数据基础设施的概述、各地典型做法及发展趋势建议三个方面展开。 篇幅限制&#xff0…

【论文阅读】Federated learning backdoor attack detection with persistence diagram

目的:检测联邦学习环境下,上传上来的模型是不是恶意的。 1、将一个模型转换为|L|个PD,(其中|L|为层数) 如何将每一层转换成一个PD? 为了评估第𝑗层的激活值,我们需要𝑐个输入来获…

深度学习案例:ResNet50模型+SE-Net

本文为为🔗365天深度学习训练营内部文章 原作者:K同学啊 一 回顾ResNet模型 ResNet,即残差网络,是由微软研究院的Kaiming He及其合作者于2015年提出的一种深度卷积神经网络架构。该网络架构的核心创新在于引入了“残差连接”&…

js高级-ajax封装和跨域

ajax简介及相关知识 原生ajax AJAX 简介 AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。 按需请求,可以提高网站的性能 AJ…

【AI】Sklearn

长期更新,建议关注、收藏、点赞。 友情链接: AI中的数学_线代微积分概率论最优化 Python numpy_pandas_matplotlib_spicy 建议路线:机器学习->深度学习->强化学习 目录 预处理模型选择分类实例: 二分类比赛 网格搜索实例&…

如何让控件始终处于父容器的居中位置(父容器可任意改变大小)

前言: 大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在C#开发winform程序的时候,有时候需要将一个控件居中显示&#xff0c…