получить непревзойденные слова после преобразования CountVectorizer - PullRequest
0 голосов
/ 22 октября 2018

Я использую счетчик векторов, чтобы применить сопоставление строк в большом наборе данных текстов.Я хочу получить слова, которые не соответствуют ни одному из терминов в полученной матрице.Например, если результирующие термины (особенности) после подгонки:

{'hello world', 'world and', 'and stackoverflow', 'hello', 'world', 'stackoverflow', 'and'}

и я преобразовал этот текст:

"oh hello world and stackoverflow this is a great morning"

Я хочу получить строку oh this is a greate morining, поскольку она соответствуетничего в особенностях.Есть ли эффективный способ сделать это?

Я пытался использовать метод inverse_transform, чтобы получить функции и удалить их из текста, но я столкнулся со многими проблемами и продолжительным временем работы.

1 Ответ

0 голосов
/ 22 октября 2018

Преобразование фрагмента текста на основе подобранного словаря вернет вам матрицу с количеством известных слов.

Например, если ваш входной документ такой же, как в вашем примере:

from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer(ngram_range=(1, 2))

docs = ['hello world and stackoverflow']
vec.fit(docs)

Тогда подобранный словарь может выглядеть следующим образом:

In [522]: print(vec.vocabulary_)
{'hello': 2, 
 'world': 5, 
 'and': 0, 
 'stackoverflow': 4, 
 'hello world': 3, 
 'world and': 6, 
 'and stackoverflow': 1}

, который представляет токен для сопоставления индекса.Преобразование некоторых новых документов впоследствии возвращает матрицу с количеством всех известных лексемных токенов. Слова, которых нет в словаре, игнорируются!

other_docs = ['hello stackoverflow', 
              'hello and hello', 
              'oh hello world and stackoverflow this is a great morning']

X = vec.transform(other_docs)

In [523]: print(X.A)
[[0 0 1 0 1 0 0]
[1 0 2 0 0 0 0]
[1 1 1 1 1 1 1]]

Ваш словарь состоит из 7 элементов, следовательно, матрица X содержит 7 столбцов.И мы преобразовали 3 документа, так что это матрица 3x7.Элементы матрицы являются подсчетами того, как часто конкретное слово встречается в документе.Например, для второго документа «привет и привет» у нас есть счет 2 в столбце 2 (0-индексированный) и счет 1 в столбце 0, которые ссылаются на «привет» и «и»,

Обратное преобразование - это сопоставление объектов (т. е. индексов) с элементами словаря:

In [534]: print(vec.inverse_transform([1, 2, 3, 4, 5, 6, 7]))
[array(['and', 'and stackoverflow', 'hello', 'hello world',
   'stackoverflow', 'world', 'world and'], dtype='<U17')]

Примечание: Теперь это индексированное 1к индексам словаря, напечатанным выше.

Теперь давайте перейдем к вашему актуальному вопросу, который идентифицирует все элементы вне словаря (OOV) в данном входном документе.Довольно просто использовать sets, если вас интересуют только униграммы:

tokens = 'oh hello world and stackoverflow this is a great morning'.split()
In [542]: print(set(tokens) - set(vec.vocabulary_.keys()))
{'morning', 'a', 'is', 'this', 'oh', 'great'}

Вещи немного сложнее, если вам интересны биграммы (или любые другие n-граммы, где n> 1), так как сначала вам нужно будет сгенерировать все биграммы из вашего входного документа (обратите внимание, что существуют разные способы создания всех нграмм из входного документа, из которых следующее только одно):

bigrams = list(map(lambda x: ' '.join(x), zip(tokens, tokens[1:])))
In [546]: print(bigrams)
['oh hello', 'hello world', 'world and', 'and stackoverflow', 'stackoverflow     this', 'this is', 'is a', 'a great', 'great morning']

Эта строка выглядитНеобычно, но все это делает zip два списка вместе (второй список начинается со второго элемента), что приводит к кортежу, например ('oh', 'hello'), оператор map просто присоединяет кортеж к одному пробелу вчтобы преобразовать ('oh', 'hello') в 'oh hello', и впоследствии генератор карт преобразуется в list.Теперь вы можете создать объединение униграмм и биграмм:

doc_vocab = set(tokens) | set(bigrams)
In [549]: print(doc_vocab)
{'and stackoverflow', 'hello', 'a', 'morning', 'hello world', 'great morning', 'world', 'stackoverflow', 'stackoverflow this', 'is', 'world and', 'oh hello', 'oh', 'this', 'is a', 'this is', 'and', 'a great', 'great'}

Теперь вы можете сделать то же самое, что и с униграммами выше, чтобы получить все элементы OOV:

In [550]: print(doc_vocab - set(vec.vocabulary_.keys()))
{'morning', 'a', 'great morning', 'stackoverflow this', 'is a', 'is', 'oh hello', 'this', 'this is', 'oh', 'a great', 'great'}

Теперь это представляет все униграммыи биграммы, которых нет в лексиконе вашего векторизатора.

...