如何用CountVectorizer筛选非3-gram子集的1、2-gram及3-gram?
问题
我有以下句子:["hello", "foo bar baz"],想要提取1-gram、2-gram和3-gram,但只保留不包含于任何3-gram中的1-gram、2-gram,以及3-gram本身。比如这个例子里,期望的词汇表是["hello", "foo bar baz"]。如果用CountVectorizer设置ngram_range=(1,3),会得到单字词"foo"、"bar"、"baz"以及对应的双字词,而直接设置ngram_range=(3,3)又不符合需求。请问有没有无需复杂变通的实现方法?
解决方案
可以分两步简单实现,逻辑清晰且无需复杂变通:
- 先提取所有3-gram,同时收集这些3-gram中包含的所有1-gram和2-gram(也就是需要排除的子gram)
- 提取全部1-3gram,过滤掉那些属于“需排除子gram”的项,剩下的就是符合要求的词汇表
结合CountVectorizer的代码示例如下:
from sklearn.feature_extraction.text import CountVectorizer # 输入语料 corpus = ["hello", "foo bar baz"] # 第一步:提取3-gram并收集需排除的子gram vec_3gram = CountVectorizer(ngram_range=(3, 3)) vec_3gram.fit(corpus) three_grams = set(vec_3gram.get_feature_names_out()) excluded_grams = set() for gram in three_grams: words = gram.split() # 收集所有1-gram子项 excluded_grams.update(words) # 收集所有2-gram子项 excluded_grams.update(f"{words[i]} {words[i+1]}" for i in range(len(words)-1)) # 第二步:提取全范围N-gram并过滤 vec_all = CountVectorizer(ngram_range=(1, 3)) vec_all.fit(corpus) all_grams = vec_all.get_feature_names_out() # 过滤规则:保留不在排除列表里的项,或者本身是3-gram的项 target_vocab = [gram for gram in all_grams if gram not in excluded_grams or gram in three_grams] print(target_vocab) # 输出: ['hello', 'foo bar baz']
这个方法没有复杂的技巧,完全基于CountVectorizer的基础功能,通过两步过滤就得到了目标结果。
内容的提问来源于stack exchange,提问作者CutePoison
相关产品推荐
相关产品推荐

