Почему функция извлечения текста не возвращает все возможные имена объектов? - PullRequest
0 голосов
/ 04 марта 2019

Вот фрагмент кода из книги Обработка естественного языка с 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() фильтровать и другие слова?

1 Ответ

0 голосов
/ 04 марта 2019

Очень хороший вопрос!Хотя это не 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']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...