新闻中心
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 无法直接处理这种语义解析,我们需要构建一个自定义的词袋模型来实现这一特定需求。
核心概念:带负号词汇的处理逻辑
自定义词袋模型的核心在于对每个词汇进行预处理,以识别其潜在的“符号”信息:
- 正向词汇: 如果一个词汇没有特殊前缀(例如 K9G3P9),则其对对应特征的贡献为 +1。
- 负向词汇: 如果一个词汇以连字符 - 开头(例如 -Q207KL41),我们将其视为其“基础词汇”(即去除 - 后的词汇 Q207KL41)的一个负向出现,因此其对对应特征的贡献为 -1。
这种处理方式确保了 Q207KL41 和 -Q207KL41 都映射到同一个特征 Q207KL41,但贡献值相反。
自定义词袋模型实现
我们将通过编写一个Python函数来实现上述逻辑。该函数将接收一个包含文本的Pandas Series,并返回一个表示
词袋模型的DataFrame,其中包含词汇的(可能为负的)计数。
Motiff妙多
Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”
334
查看详情
实现步骤:
-
初始化数据结构:
- 使用 collections.defaultdict 来动态构建词汇表(将每个唯一的词汇映射到一个唯一的整数索引)。
- 为每个文档创建一个 defaultdict(int) 作为其特征计数器。
-
遍历文档与词汇:
- 迭代输入的每个文档。
- 将每个文档文本按空格拆分为独立的词汇(token)。
-
识别符号并更新计数:
- 对于每个词汇,检查它是否以 - 开头且长度大于1(以避免处理单独的 - 符号)。
- 如果满足条件,移除 - 并设置符号 sign = -1;否则,设置 sign = 1。
- 将处理后的词汇(已去除 -)添加到词汇表(如果尚未存在),并获取其对应的索引。
- 根据 sign 值更新当前文档中该词汇的计数。
-
构建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
以上就是Python中处理带负号词汇的自定义词袋模型实现的详细内容,更多请关注其它相关文章!
# 转换为
# 南通网站建设详细内容
# 大同特色关键词排名查询
# 青浦区百度网站优化定制
# 邢台网站推广工作
# 石柱县公司网站建设
# 新手如何建个网站推广
# 思齐seo官网
# 七台河网站建设服务
# 山东网站网络推广介绍
# 灰色词推广网站怎么做
# 将其
# 适用于
# 两次
# word
# 数为
# 数据结构
# 自然语言
# 词汇表
# 自定义
# 文档
# 排列
# python函数
# 自然语言处理
# csv
# 工具
# app
# python
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
sublime如何优雅地处理行尾空格_sublime自动清理多余空白字符配置
C++的std::forward_list怎么用_C++ STL中单向链表容器的特点与应用
Golang如何测试channel通信行为_Golang channel通信测试与分析方法
qq游戏免费畅玩入口_qq游戏电脑版快速启动
C++如何生成随机数_C++ random库使用方法与范围设置
精准捕获:如何在页面中监听除特定元素外的所有点击事件
解决Flask中Quill编辑器内容提交失败及TypeError的指南
斑马英语APP如何开启夜间护眼阅读_斑马英语APP夜间模式与低蓝光设置教程
sublime如何配置Go语言开发环境_sublime搭建Golang编译运行系统
蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
“音游” × “怪文书” 题材的节奏冒险游戏 《晕晕电波症候群》确定于2026年4月发售!
mc.js免安装版 mc.js一键畅玩入口
极兔快递快件信息查询系统 极兔快递官网运单号追踪
蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台
Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】
J*aScript中管理异步API调用:确保操作顺序与数据一致性
如何在更新Composer依赖后自动运行测试_使用post-update-cmd钩子触发PHPUnit
如何有效阻止外部脚本意外修改内联样式的高度属性
Win11怎么合并任务栏图标 Win11开启任务栏合并减少图标占空间【方法】
NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略
我的世界官方游戏入口 我的世界官网平台直达链接
解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南
浏览器打开即用 美图秀秀网页版入口
深入理解J*a链表中的IPosition接口与使用
Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址
动漫共和国防屏蔽稳定域名-动漫共和国官方正版直达通道
Animex动漫社网入口地址 Animex动漫社网正版在线入口
TikTok评论显示延迟如何处理 TikTok评论刷新优化方法
J*aScript打印功能_j*ascript输出控制
百度网盘网页版入口 百度网盘网页版官方登录网址
内存疯狂猛猛涨价:主板销量直接腰斩!
win11怎么查看应用耗电情况 Win11电池设置查看应用能耗排行榜【优化】
TikTok网页版直接登录 TikTok网页端官方平台入口
4399体育竞技小游戏_4399小游戏赛事入口
PHP中SSG-WSG API的AES加密实践:正确使用初始化向量
html5 app怎么运行环境_配html5 app运行环境【教程】
J*a如何使用AtomicInteger控制计数_J*a无锁计数器性能分析
Lar*el Form Request中唯一性验证在更新操作中的正确实现
c++中的std::basic_string的SSO优化_c++短字符串优化深度解析
QQ邮箱网页版入口登录 QQ邮箱在线邮箱官方通道
腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程
HTML长属性值处理:表单action路径优化与代码规范应对
漫蛙漫画官方首页 漫蛙2漫画在线阅读入口
GemBox Document HTML转PDF垂直文本渲染问题及解决方案
Go语言中JSON数据解码与字段访问指南
菜鸟取件码是什么怎么查 最全查询渠道汇总
c++ dfs和bfs代码 c++深度广度优先搜索算法
msn官网入口地址手机版 msn官方网站手机最新链接
高德地图公交到站提醒失败如何解决 高德提醒权限设置


2025-11-26
浏览次数:次
返回列表