Проблемы с использованием пользовательского словаря для TfidfVectorizer scikit-learn

Я пытаюсь использовать пользовательский словарь в scikit-learn для некоторых задач кластеризации и получаю очень странные результаты.

Программа работает нормально, если не используется пользовательский словарь, и я доволен созданием кластера. Однако я уже определил группу слов (около 24 000), которые хотел бы использовать в качестве пользовательского словаря.

Слова хранятся в таблице SQL Server. Я пробовал до сих пор 2 подхода, но в конце я получаю те же результаты. Первый — создать список, второй — создать словарь. Код для создания словаря выглядит так:

myvocab = {}
vocabulary = []

count = 0

for row in results:
    skillName = re.sub(r'&#?[a-z0-9]+;', ' ', row['SkillName']) 
    skillName = unicode(skillName,"utf-8")  
    vocabulary.append(skillName)  #Using a list 
    myvocab[str(skillName)] = count #Using a dictionary
    count+=1

Затем я использую словарь (либо версию списка, либо словарь, оба они дают одинаковый результат в конце) в TfidfVectorizer следующим образом:

vectorizer = TfidfVectorizer(max_df=0.8, 
                         stop_words='english' ,ngram_range=(1,2) ,vocabulary=myvocab)
X = vectorizer.fit_transform(dataset2)

Форма X (651, 24321), так как у меня есть 651 экземпляр для кластеризации и 24321 слово в словаре.

Если я распечатаю содержимое X, вот что я получу:

(14, 11462) 1.0
(20, 10218) 1.0
(34, 11462) 1.0
(40, 11462) 0.852815313278
(40, 10218) 0.52221264006
(50, 11462) 1.0
(81, 11462) 1.0
(84, 11462) 1.0
(85, 11462) 1.0
(99, 10218) 1.0
(127, 11462)    1.0
(129, 10218)    1.0
(132, 11462)    1.0
(136, 11462)    1.0
(138, 11462)    1.0
(150, 11462)    1.0
(158, 11462)    1.0
(186, 11462)    1.0
(210, 11462)    1.0

:   :

Как видно, в большинстве случаев присутствует только слово из словаря (что неверно, так как их не менее 10), а во многих случаях не найдено ни одного слова. Кроме того, найденные слова, как правило, всегда одинаковы в экземплярах, что не имеет смысла.

Если я напечатаю feature_names, используя:

feature_names = np.asarray(vectorizer.get_feature_names())

Я получил:

['.NET' '10K' '21 CFR Part 11' ..., 'Zend Studio' 'Zendesk' 'Zenworks']

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

Кто-нибудь знает, что происходит?

(Я не использую конвейер, поэтому эта проблема не может быть связана с предыдущей ошибкой, которая уже исправлена)


person FRiverai    schedule 20.02.2013    source источник


Ответы (3)


Одна вещь, которая кажется мне необычной, это то, что при создании векторизатора вы указываете ngram_range=(1,2). Это означает, что вы не можете получить функцию '21 CFR Part 11' с помощью стандартного токенизатора. Я подозреваю, что «отсутствующие» функции — это n-граммы для n>2. Сколько из предварительно выбранных вами словарных единиц являются униграммами или биграммами?

person mbatchkarov    schedule 20.02.2013
comment
Я пробовал использовать разные варианты ngram_range от (1,1) до (1,5) и всегда получаю одинаковые результаты. Количество однограммовых словарных единиц составляет 9692, 2-граммовых: 13215, 3-граммовых: 1337, 4-граммовых: 77. Я не думаю, что проблема в этом. - person FRiverai; 21.02.2013

Я почти уверен, что это вызвано (возможно, сбивающим с толку) значением по умолчанию min_df=2, чтобы отрезать любую функцию из словаря, если она не встречается в наборе данных хотя бы дважды. Не могли бы вы подтвердить, явно установив min_df=1 в своем коде?

person ogrisel    schedule 20.02.2013
comment
Я меняю значение на min_df=1, и результат точно такой же. Если я напечатаю TdidfVectorizer, это то, что я получу: TfidfVectorizer(analyzer=word, binary=False, charset=utf-8, charset_error=strict, dtype=‹type 'long'›, input=content, lowercase=True, max_df= 0.8, max_features=Нет, max_n=Нет, min_df=1, min_n=Нет, ngram_range=(1, 2), norm=l2, препроцессор=Нет, smooth_idf=True, stop_words=английский, strip_accents=Нет, sublinear_tf=False, token_pattern=(?u)\b\w\w+\b, tokenizer=Нет, use_idf=True, словарь=Нет) - person FRiverai; 21.02.2013
comment
Тогда, может быть, ваше dataset2 не то, что ожидает TfidfVectorizer? Проверьте параметр input в документации TfidfVectorizer. Вы можете TfidfVectorizer(**params).build_analyzer()(dataset2) проверить результаты этапа анализа текста (препроцессинг, токенизация + извлечение n-грамм). - person ogrisel; 21.02.2013
comment
Я широко использовал этот набор данных для классификации и кластеризации, но теперь, когда я пытаюсь использовать свой собственный словарь, у меня возникли проблемы. Тем не менее, я сделаю то, что вы предлагаете, и отчитаюсь о результатах. - person FRiverai; 21.02.2013

В цикле for-in Python он не мог использовать count+=1, чтобы счетчик добавлял единицу в каждом цикле. Вы можете использовать for i in range(n): чтобы заменить его. Потому что значение count останется равным 1.

person Yunchao He    schedule 07.07.2015