为 TfidfVectorizer scikit-learn 使用自定义词汇的问题

Posted

技术标签:

【中文标题】为 TfidfVectorizer scikit-learn 使用自定义词汇的问题【英文标题】:Problems using a custom vocabulary for TfidfVectorizer scikit-learn 【发布时间】:2013-02-05 20:52:42 【问题描述】:

我正在尝试在 scikit-learn 中使用自定义词汇表来执行一些聚类任务,但结果非常奇怪。

程序在不使用自定义词汇表时运行正常,我对集群创建感到满意。但是,我已经确定了一组单词(大约 24,000 个),我想将它们用作自定义词汇表。

单词存储在 SQL Server 表中。到目前为止,我已经尝试了 2 种方法,但最后得到了相同的结果。第一个是创建列表,第二个是创建字典。创建字典的代码是这样的:

myvocab = 
vocabulary = []

count = 0

for row in results:
    skillName = re.sub(r'&#?[a-z0-9]+;', ' ', row['SkillName']) 
    skillName = unicode(skillName,"utf-8")  
    vocabulary.append(skillName)  #Using a list 
    myvocab[str(skillName)] = count #Using a dictionary
    count+=1

然后我在 TfidfVectorizer 中使用词汇表(列表版本或字典,它们最后都给出相同的结果)如下:

vectorizer = TfidfVectorizer(max_df=0.8, 
                         stop_words='english' ,ngram_range=(1,2) ,vocabulary=myvocab)
X = vectorizer.fit_transform(dataset2)

X 的形状是 (651, 24321),因为我有 651 个实例要聚类,词汇表中有 24321 个单词。

如果我打印 X 的内容,这就是我得到的:

(14, 11462) 1.0
(20, 10218) 1.0
(34, 11462) 1.0
(40, 11462) 0.852815313278
(40, 10218) 0.52221264006
(50, 11462) 1.0
(81, 11462) 1.0
(84, 11462) 1.0
(85, 11462) 1.0
(99, 10218) 1.0
(127, 11462)    1.0
(129, 10218)    1.0
(132, 11462)    1.0
(136, 11462)    1.0
(138, 11462)    1.0
(150, 11462)    1.0
(158, 11462)    1.0
(186, 11462)    1.0
(210, 11462)    1.0

:   :

可以看出,在大多数情况下,只有词汇表中的单词存在(这是错误的,因为至少有 10 个),而且在很多情况下,甚至没有找到一个单词。此外,找到的单词在各个实例中往往总是相同的,这是没有意义的。

如果我使用 :

打印 feature_names
feature_names = np.asarray(vectorizer.get_feature_names())

我明白了:

['.NET' '10K' '21 CFR Part 11' ..., 'Zend Studio' 'Zendesk' 'Zenworks']

我必须说,当使用的词汇表是根据输入文档确定的词汇表时,程序运行良好,所以我强烈怀疑问题与使用自定义词汇表有关。

有人知道发生了什么吗?

(我没有使用管道,所以这个问题与之前已经修复的错误无关)

【问题讨论】:

【参考方案1】:

让我觉得不寻常的一件事是,当您创建矢量化器时,您指定了ngram_range=(1,2)。这意味着您无法使用标准标记器获得功能'21 CFR Part 11'。我怀疑“缺失”的特征是n>2 的 n-gram。您预先选择的词汇项目中有多少是一元词或二元词?

【讨论】:

我尝试对 ngram_range 使用从 (1,1) 到 (1,5) 的不同变体,但我总是得到相同的结果。 1-gram 词汇的数量是 9692,2-gram:13215,3-gram:1337,4-gram:77。我不认为这就是问题所在。【参考方案2】:

我很确定这是由min_df=2 的(可能令人困惑的)默认值造成的,如果它在数据集中至少没有出现两次,它会从词汇表中截断任何特征。您能否通过在代码中明确设置min_df=1 来确认?

【讨论】:

我将值改为min_df=1,结果完全一样。如果我打印 TdidfVectorizer 这就是我得到的: TfidfVectorizer(analyzer=word, binary=False, charset=utf-8, charset_error=strict, dtype=, input=content, lowercase=True, max_df= 0.8, max_features=None, max_n=None, min_df=1, min_n=None, ngram_range=(1, 2), norm=l2, preprocessor=None, smooth_idf=True, stop_words=english, strip_accents=None, sublinear_tf=False, token_pattern=(?u)\b\w\w+\b, tokenizer=None, use_idf=True, words=None) 那么也许您的dataset2 不是TfidfVectorizer 所期望的?检查TfidfVectorizer 文档中的input 参数。您可以到TfidfVectorizer(**params).build_analyzer()(dataset2)查看文本分析步骤(预处理、标记化+n-gram提取)的结果。 我已将该数据集广泛用于分类和聚类,但现在我尝试使用自己的词汇表,但我遇到了问题。不过,我会按照你的建议去做并报告结果【参考方案3】:

在 Python for-in 循环中,不能使用 count+=1 让 count 在每个循环中加一。您可以使用 for i in range(n): 来替换它。因为 count 的值会保持为 1。

【讨论】:

以上是关于为 TfidfVectorizer scikit-learn 使用自定义词汇的问题的主要内容,如果未能解决你的问题,请参考以下文章

Scikit-Learn TfidfVectorizer

为啥 scikit-learn 中的 TfidfVectorizer 会显示这种行为?

scikit-learn 的 TfidfVectorizer 在线版

scikit-learn TfidfVectorizer 忽略某些单词

将特征名称更新到 scikit TFIdfVectorizer

scikit-learn 中的 TfidfVectorizer:ValueError:np.nan 是无效文档