0

0

Python中处理带负号词汇的自定义词袋模型实现

心靈之曲

心靈之曲

发布时间:2025-11-26 13:15:41

|

277人浏览过

|

来源于php中文网

原创

Python中处理带负号词汇的自定义词袋模型实现

本文详细介绍了如何在python中实现一个自定义的词袋(bag of words, bow)模型,以处理文本中带有负号前缀的词汇。传统bow模型会将带负号的词汇视为独立项,而本教程将指导您如何将-词汇解析为对应词汇的负数计数,从而实现更精细的文本特征表示,尤其适用于科学术语等特定数据集。

引言:传统词袋模型的局限性

词袋模型(Bag of Words, BOW)是一种广泛应用于自然语言处理(NLP)的文本表示方法,它将文本视为一个无序的词语集合,并统计每个词语的出现频率。在Python中,sklearn.feature_extraction.text.CountVectorizer 是实现标准词袋模型的常用工具。然而,对于某些特定类型的文本数据,例如科学术语、医学报告或情感分析场景,词汇前缀可能带有特定的语义。

考虑以下文本示例:Q207KL41 -Q207KL41 -Q207KL41。 如果使用标准 CountVectorizer,它会将 Q207KL41 和 -Q207KL41 识别为两个独立的特征,并分别计数。但实际需求可能是将 -Q207KL41 理解为 Q207KL41 的一个负向出现,即 -Q207KL41 应该使得 Q207KL41 的计数减一。在这种情况下,上述文本中 Q207KL41 的最终计数应为 +1 - 1 - 1 = -1。

由于 CountVectorizer 无法直接处理这种语义解析,我们需要构建一个自定义的词袋模型来实现这一特定需求。

核心概念:带负号词汇的处理逻辑

自定义词袋模型的核心在于对每个词汇进行预处理,以识别其潜在的“符号”信息:

  1. 正向词汇: 如果一个词汇没有特殊前缀(例如 K9G3P9),则其对对应特征的贡献为 +1。
  2. 负向词汇: 如果一个词汇以连字符 - 开头(例如 -Q207KL41),我们将其视为其“基础词汇”(即去除 - 后的词汇 Q207KL41)的一个负向出现,因此其对对应特征的贡献为 -1。

这种处理方式确保了 Q207KL41 和 -Q207KL41 都映射到同一个特征 Q207KL41,但贡献值相反。

立即学习Python免费学习笔记(深入)”;

智川X-Agent
智川X-Agent

中科闻歌推出的一站式AI智能体开发平台

下载

自定义词袋模型实现

我们将通过编写一个Python函数来实现上述逻辑。该函数将接收一个包含文本的Pandas Series,并返回一个表示词袋模型的DataFrame,其中包含词汇的(可能为负的)计数。

实现步骤:

  1. 初始化数据结构:
    • 使用 collections.defaultdict 来动态构建词汇表(将每个唯一的词汇映射到一个唯一的整数索引)。
    • 为每个文档创建一个 defaultdict(int) 作为其特征计数器。
  2. 遍历文档与词汇:
    • 迭代输入的每个文档。
    • 将每个文档文本按空格拆分为独立的词汇(token)。
  3. 识别符号并更新计数:
    • 对于每个词汇,检查它是否以 - 开头且长度大于1(以避免处理单独的 - 符号)。
    • 如果满足条件,移除 - 并设置符号 sign = -1;否则,设置 sign = 1。
    • 将处理后的词汇(已去除 -)添加到词汇表(如果尚未存在),并获取其对应的索引。
    • 根据 sign 值更新当前文档中该词汇的计数。
  4. 构建DataFrame:
    • 将所有文档的特征计数器(字典)列表转换为Pandas DataFrame。
    • 使用 fillna(0) 填充因某些词汇未在特定文档中出现而导致的 NaN 值。
    • 将DataFrame的列名从索引映射回实际的词汇,以提高可读性。
    • 将DataFrame的数据类型转换为 np.int8,以优化内存使用,前提是词汇计数在 [-128, 127] 范围内。

示例代码

import io
import pandas as pd
import numpy as np
from collections import defaultdict

def custom_bow_vectorizer(documents: pd.Series) -> pd.DataFrame:
    """
    自定义词袋模型向量化函数,支持处理带有负号前缀的词汇。
    例如,"-term" 将被计为 "term" 的负数出现。

    Args:
        documents (pd.Series): 包含待处理文本的 Pandas Series。

    Returns:
        pd.DataFrame: 向量化后的词袋模型 DataFrame,其中包含词汇的计数(可能为负)。
    """
    processed_features = []
    # 使用 defaultdict 动态构建词汇表:key为词汇,value为递增的索引
    vocabulary = defaultdict(lambda: len(vocabulary))

    for document in documents:
        # 为当前文档初始化一个词汇计数器
        feature_counter = defaultdict(int)

        # 处理非字符串类型数据,如NaN,将其视为空字符串
        if not isinstance(document, str):
            document = ""

        for token in document.split():
            sign = 1
            # 检查词汇是否以负号开头,并确保不是只有一个"-"的token
            if token.startswith("-") and len(token) > 1:
                token = token[1:] # 移除负号
                sign = -1

            # 将处理后的词汇添加到词汇表(如果尚未存在),并获取其索引
            feature_idx = vocabulary[token] 
            # 更新当前文档中该词汇的计数
            feature_counter[feature_idx] += sign
        processed_features.append(feature_counter)

    # 从字典列表创建DataFrame,并用0填充NaN值
    df_features = pd.DataFrame.from_records(processed_features)
    df_features = df_features.fillna(0)

    # 重新映射列名,将内部索引替换为实际的词汇
    # 首先创建一个从索引到词汇的映射
    idx_to_word = {v: k for k, v in vocabulary.items()}
    # 确保列的顺序与词汇表构建的顺序一致,并重命名列
    # 注意:DataFrame.from_records 可能会按键的哈希值顺序创建列,
    # 为了保证一致性,我们通常会根据原始词汇表的顺序来重新排列和命名列
    # 这里我们假设 df_features.columns 已经是词汇索引,所以直接排序后映射
    sorted_cols_by_idx = sorted(df_features.columns)
    df_features = df_features[sorted_cols_by_idx].rename(columns=idx_to_word)

    # 优化:将数据类型转换为 np.int8,适用于计数范围较小的情况
    df_features = df_features.astype(np.int8)

    return df_features

# 示例数据
s = """RepID,Txt
1,K9G3P9 4H477 -Q207KL41 98464 Q207KL41
2,D84T8X4 -D9W4S2 -D9W4S2 8E8E65 D9W4S2 
3,-05L8NJ38 K2DD949 0W28DZ48 207441 K2D28K84
4,TERM1 -TERM1 TERM2 -TERM2 -TERM2""" # 增加一个更清晰的示例
df_reps = pd.read_csv(io.StringIO(s))

print("原始数据:")
print(df_reps)
print("\n处理后的词袋模型:")
result_df = custom_bow_vectorizer(df_reps["Txt"])
print(result_df)

运行与结果分析

运行上述代码,我们将得到以下输出:

原始数据:
   RepID                                Txt
0      1  K9G3P9 4H477 -Q207KL41 98464 Q207KL41
1      2   D84T8X4 -D9W4S2 -D9W4S2 8E8E65 D9W4S2 
2      3  -05L8NJ38 K2DD949 0W28DZ48 207441 K2D28K84
3      4       TERM1 -TERM1 TERM2 -TERM2 -TERM2

处理后的词袋模型:
   K9G3P9  4H477  Q207KL41  98464  D84T8X4  D9W4S2  8E8E65  05L8NJ38  K2DD949  0W28DZ48  207441  K2D28K84  TERM1  TERM2
0       1      1         0      1        0       0       0         0        0         0       0         0      0      0
1       0      0         0      0        1      -1       1         0        0         0       0         0      0      0
2       0      0         0      0        0       0       0        -1        1         1       1         1      0      0
3       0      0         0      0        0       0       0         0        0         0       0         0      0     -1

结果解读:

  • 第一行(RepID 1): 文本为 K9G3P9 4H477 -Q207KL41 98464 Q207KL41。
    • K9G3P9 和 4H477 各出现一次,计数为 1。
    • Q207KL41 出现两次(一次正向,一次负向),所以 1 + (-1) + 1 = 1。输出中 Q207KL41 的计数为 0,这与预期 1 + (-1) + 1 = 1 不符。
    • 修正检查: 原始问题描述中 Q207KL41 -Q207KL41 -Q207KL41 应该为 -1。在 1,K9G3P9 4H477 -Q207KL41 98464 Q207KL41 中,Q207KL41 出现 +1,-Q207KL41 出现 -1,Q207KL41 再次出现 +1。总和为 1 + (-1) + 1 = 1。
    • 代码输出: Q207KL41 计数为 0。
    • 原因分析: 仔细检查输入 1,K9G3P9 4H477 -Q207KL41 98464 Q207KL41。
      • K9G3P9: +1
      • 4H477: +1
      • -Q207KL41: -1 for Q207KL41
      • 98464: +1
      • Q207KL41: +1 for Q207KL41
      • Total for Q207KL41: -1 + 1 = 0. 代码输出是正确的。
  • 第二行(RepID 2): 文本为 D84T8X4 -D9W4S2 -D9W4S2 8E8E65 D9W4S2。
    • D84T8X4 和 8E8E65 各计数为 1。
    • D9W4S2 出现一次正向,两次负向。所以 `1 + (-1) + (-1

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

79

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

32

2026.01.31

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

337

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

224

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6607

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

842

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1092

2023.12.21

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.9万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号