这是 Natural Language Processing with PyTorch书中的代码段:
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
import seaborn as sns
corpus = ['Time flies flies like an arrow.', 'Fruit flies like a banana.']
one_hot_vectorizer = CountVectorizer()
vocab = one_hot_vectorizer.get_feature_names()
vocab
的值:
vocab = ['an', 'arrow', 'banana', 'flies', 'fruit', 'like', 'time']
为什么提取的要素名称中没有'a'
?如果自动将其排除为太普通的单词,出于同样的原因为什么不排除“ an”?如何使.get_feature_names()
也过滤其他单词?
答案 0 :(得分:7)
很好的问题!虽然这不是一个pytorch
问题,但是一个sklearn
一个=)
我鼓励您首先阅读此https://www.kaggle.com/alvations/basic-nlp-with-nltk,尤其是。 “ 使用sklearn进行矢量化”部分
如果我们使用CountVectorizer
,
from io import StringIO
from sklearn.feature_extraction.text import CountVectorizer
sent1 = "The quick brown fox jumps over the lazy brown dog."
sent2 = "Mr brown jumps over the lazy fox."
with StringIO('\n'.join([sent1, sent2])) as fin:
# Create the vectorizer
count_vect = CountVectorizer()
count_vect.fit_transform(fin)
# We can check the vocabulary in our vectorizer
# It's a dictionary where the words are the keys and
# The values are the IDs given to each word.
print(count_vect.vocabulary_)
[输出]:
{'brown': 0,
'dog': 1,
'fox': 2,
'jumps': 3,
'lazy': 4,
'mr': 5,
'over': 6,
'quick': 7,
'the': 8}
我们没有告诉矢量化程序删除标点符号并标记化小写字母,它们是怎么做到的?
此外,词汇表中有,这是一个停用词,我们希望它消失... 而且跳跃不会被阻止或限制!
如果我们查看sklearn中CountVectorizer的文档,则会看到:
CountVectorizer(
input=’content’, encoding=’utf-8’,
decode_error=’strict’, strip_accents=None,
lowercase=True, preprocessor=None,
tokenizer=None, stop_words=None,
token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1),
analyzer=’word’, max_df=1.0, min_df=1,
max_features=None, vocabulary=None,
binary=False, dtype=<class ‘numpy.int64’>)
更具体地说:
分析器:字符串,{'word','char','char_wb'}或可调用
该功能是否应该由单词或字符n-gram组成。 选项“ char_wb”仅从单词中的文本创建字符n-gram 界限单词边缘的n-gram用空格填充。如果一个 传递了callable,用于提取特征序列 未经处理的原始输入。
预处理器:可调用或无(默认)
覆盖预处理(字符串转换)阶段,而 保留标记化和n-gram生成步骤。
令牌:可调用或无(默认)
在保留字符串标记化步骤的同时保留 预处理和n-gram生成步骤。仅适用于分析仪 =='单词'。
stop_words :字符串{'english'},列表或“无”(默认)
如果为“英语”,则使用内置的英语停用词列表。如果一个 列表,假设该列表包含停用词,所有停用词 从结果令牌中删除。仅在分析器=='word'时适用。 如果为None,则不使用停用词。
小写:布尔值,默认为True
在标记之前将所有字符转换为小写。
但是在http://shop.oreilly.com/product/0636920063445.do中的示例中,这并不是导致问题的停用词。
如果我们明确使用https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/stop_words.py
中的英语停用词>>> from sklearn.feature_extraction.text import CountVectorizer
>>> one_hot_vectorizer = CountVectorizer(stop_words='english')
>>> one_hot_vectorizer.fit(corpus)
CountVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 1), preprocessor=None, stop_words='english',
strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
tokenizer=None, vocabulary=None)
>>> one_hot_vectorizer.get_feature_names()
['arrow', 'banana', 'flies', 'fruit', 'like', 'time']
那么在stop_words
参数保留为None的情况下究竟发生了什么?
让我们尝试一个在输入中添加一些单字符单词的实验:
>>> corpus = ['Time flies flies like an arrow 1 2 3.', 'Fruit flies like a banana x y z.']
>>> one_hot_vectorizer = CountVectorizer()
>>> one_hot_vectorizer.fit(corpus)
CountVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 1), preprocessor=None, stop_words=None,
strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
tokenizer=None, vocabulary=None)
>>> one_hot_vectorizer.get_feature_names()
['an', 'arrow', 'banana', 'flies', 'fruit', 'like', 'time']
他们又都消失了!!!
现在,如果我们深入研究文档,https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/text.py#L738
token_pattern :字符串 表示什么构成“令牌”的正则表达式,仅用于
analyzer == 'word'
。默认的regexp选择令牌为2 或更多字母数字字符(标点符号被完全忽略 并始终被视为令牌分隔符。
啊哈,这就是为什么所有单个字符标记都将被删除的原因!
CountVectorizer
的默认模式为token_pattern=r"(?u)\b\w\w+\b"
,要使其采用单个字符,您可以尝试:
>>> one_hot_vectorizer = CountVectorizer(token_pattern=r"(?u)\b\w+\b")
>>> one_hot_vectorizer.fit(corpus)
CountVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 1), preprocessor=None, stop_words=None,
strip_accents=None, token_pattern='(?u)\\b\\w+\\b', tokenizer=None,
vocabulary=None)
>>> one_hot_vectorizer.get_feature_names()
['1', '2', '3', 'a', 'an', 'arrow', 'banana', 'flies', 'fruit', 'like', 'time', 'x', 'y', 'z']