Очень хороший вопрос!Хотя это не pytorch
вопрос, а sklearn
one =)
Я рекомендую сначала пройти этот https://www.kaggle.com/alvations/basic-nlp-with-nltk, esp.секция " Векторизация со sklearn "
TL; DR
Если мы используем 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_)
[out]:
{'brown': 0,
'dog': 1,
'fox': 2,
'jumps': 3,
'lazy': 4,
'mr': 5,
'over': 6,
'quick': 7,
'the': 8}
Мы не говорили векторизатору убрать знаки препинания, токены и строчные буквы, как они это делали?
Кроме того, всловарь, это стоп-слово, мы хотим, чтобы оно исчезло ... И прыжки не остановлены и не лемматизированы!
Если мы посмотрим на документацию CountVectorizer в sklearn, мы увидим:
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'} или вызываемый
Должна ли функциябыть сделаны из слова или символа н-граммы.Опция 'char_wb' создает n-граммы символов только из текста внутри границ слова;n-грамм по краям слов дополняется пробелом.Если передан вызываемый объект, он используется для извлечения последовательности признаков из необработанного необработанного ввода.
препроцессор : вызываемый или нет (по умолчанию)
ПереопределитьСтадия предварительной обработки (преобразования строки) с сохранением этапов создания токенов и n-грамм.
tokenizer : вызываемый или нет (по умолчанию)
Переопределить этап токенизации строки при сохраненииэтапы предварительной обработки и генерации n-грамм.Применяется только в том случае, если анализатор == 'word'.
stop_words : строка {'english'}, список или None (по умолчанию)
Если 'english', aиспользуется встроенный список стоп-слов для английского языка.Если список, предполагается, что этот список содержит стоп-слова, и все они будут удалены из полученных токенов.Применяется только если анализатор == «слово».Если Нет, стоп-слова не будут использоваться.
нижний регистр : логический, по умолчанию 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 : string Регулярное выражение, обозначающее, что составляет "токен", используется только если analyzer == 'word'
.По умолчанию регулярное выражение выбирает токены из 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']