токенизировать строку на основе определенного пользователем словаря - PullRequest
1 голос
/ 22 марта 2019

Я хотел бы маркировать список строк в соответствии с моим самоопределенным словарем.

Список строк выглядит следующим образом:

lst = ['vitamin c juice', 'organic supplement'] 

Словарь с самоопределением:

dct = {0: 'organic', 1: 'juice', 2: 'supplement', 3: 'vitamin c'}

Мой ожидаемый результат:

сок витамина С -> [(3,1), (1,1)] органическая добавка -> [(0,1), (2,1)]

Мой текущий код:

import gensim
import gensim.corpora as corpora
from gensim.utils import tokenize
dct = corpora.Dictionary([list(x) for x in tup_list]) 
corpus = [dct.doc2bow(text) for text in [s for s in lst]]

Полученное сообщение об ошибке: TypeError: doc2bow expects an array of unicode tokens on input, not a single string Однако я не хочу просто маркировать "витамин С" как vitamin и c.Вместо этого я хочу использовать токены на основе моих существующих слов dct.То есть это должно быть vitamin c.

Ответы [ 2 ]

1 голос
/ 22 марта 2019

Сначала вам нужно будет перевернуть словарь, чтобы ключевые слова стали ключевыми. Затем вы можете использовать регулярные выражения, чтобы разбить записи списка на ключевые слова. Затем используйте ключевые слова против обратного словаря, чтобы найти соответствующие токены

например:

lst = ['vitamin c juice', 'organic supplement'] 
dct = {0: 'organic', 1: 'juice', 2: 'supplement', 3: 'vitamin c'}

import re
from collections import Counter
keywords      = { keyword:token for token,keyword in dct.items() }  # inverted dictionary
sortedKw      = sorted(keywords,key=lambda x:-len(x))               # keywords in reverse order of size
pattern       = re.compile( "|".join(sortedKw) )                    # regular expression
lstKeywords   = [ pattern.findall(item) for item in lst ]           # list items --> keywords
tokenGroups   = [ [keywords[word] for word in words] for words in lstKeywords ]  # keyword lists to lists of indexes
result        = [ list(Counter(token).items()) for token in tokenGroups ] # lists of token indexes to (token,count) 
print(result) # [[(3, 1), (1, 1)], [(0, 1), (2, 1)]]

Регулярное выражение имеет вид: keyword1 | keyword2 | keyword3

Потому что "|" Оператор в регулярных выражениях никогда не бывает жадным, более длинные ключевые слова должны появляться первыми в списке. Это причина их сортировки перед построением выражения.

После этого нужно просто преобразовать элементы списка в списки ключевых слов (это делает re.findall ()), а затем использовать инвертированный словарь, чтобы превратить каждое ключевое слово в индекс токена.

[ОБНОВЛЕНИЕ] Для подсчета количества вхождений токенов список ключевых слов, преобразованных в список индексов токенов, загружается в объект Counter (из модулей сбора), который выполняет счетная операция в специализированном словаре.

1 голос
/ 22 марта 2019

Я могу думать только об очень неэффективных способах реализации токенизатора, который распознает подстроки, включая пробелы. Однако, если вы не настаиваете на пропусках, вот простой способ, изменив vitamin c на vitamin_c:


lst = ['vitamin_c juice', 'organic supplement']
dct = {0: 'organic', 1: 'juice', 2: 'supplement', 3: 'vitamin_c'}

word2index = {key: val for val, key in dct.items()}

tokenized = [[word2index[word] for word in text.split()] for text in lst]

Если вы не настаиваете на своем предопределенном отображении dct, вы также можете создать его с помощью:

vocab = set([word for text in lst for word in text.split()])
word2index = {word: ind for ind, word in enumerate(sorted(vocab))}
...