
本文详细介绍了如何在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 无法直接处理这种语义解析,我们需要构建一个自定义的词袋模型来实现这一特定需求。
自定义词袋模型的核心在于对每个词汇进行预处理,以识别其潜在的“符号”信息:
这种处理方式确保了 Q207KL41 和 -Q207KL41 都映射到同一个特征 Q207KL41,但贡献值相反。
立即学习“Python免费学习笔记(深入)”;
我们将通过编写一个Python函数来实现上述逻辑。该函数将接收一个包含文本的Pandas Series,并返回一个表示词袋模型的DataFrame,其中包含词汇的(可能为负的)计数。
实现步骤:
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
结果解读:
以上就是Python中处理带负号词汇的自定义词袋模型实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号