В чем разница между векторизатором хеширования и векторизатором tfidf?

11

Я конвертирую корпус текстовых документов в векторы слов для каждого документа. Я пробовал это с помощью TfidfVectorizer и HashingVectorizer

Я понимаю, что HashingVectorizerа не принимает во внимание IDFоценки, как TfidfVectorizerделает. Причина, по которой я все еще работаю с, HashingVectorizerзаключается в гибкости, которую он дает при работе с огромными наборами данных, как объяснено здесь и здесь . (Мой исходный набор данных содержит 30 миллионов документов)

В настоящее время я работаю с образцом 45339 документов, поэтому у меня есть возможность работать с ним TfidfVectorizer. Когда я использую эти два векторизатора в одних и тех же 45339 документах, матрицы, которые я получаю, отличаются.

hashing = HashingVectorizer()
with LSM('corpus.db')) as corpus:
    hashing_matrix = hashing.fit_transform(corpus)
print(hashing_matrix.shape) 

Форма матрицы хеширования (45339, 1048576)

tfidf = TfidfVectorizer()
with LSM('corpus.db')) as corpus:
    tfidf_matrix = tfidf.fit_transform(corpus)
print(tfidf_matrix.shape) 

Форма матрицы tfidf (45339, 663307)

Я хочу лучше понять различия между a HashingVectorizerи a TfidfVectorizer, а также причину, по которой эти матрицы имеют разные размеры - особенно в количестве слов / терминов.

Minu
источник
Можете ли вы поделиться набором данных со мной? (ответ будет удален)
nKarza

Ответы:

7

Основное отличие состоит в том, что HashingVectorizerфункция хэширования применяется к счетчикам частот терминов в каждом документе, где TfidfVectorizerмасштабирует эти счетчики частот терминов в каждом документе, штрафуя термины, которые появляются более широко по всему корпусу. Здесь есть отличное резюме: https://spark.apache.org/docs/latest/mllib-feature-extraction.html

  • Хеш-функции - эффективный способ сопоставления терминов с функциями; это не обязательно должно применяться только к частотам термина, но именно так HashingVectorizerздесь используется. Я подозреваю, что наряду с документами 45339 вектор пространственных объектов имеет длину 1048576, поскольку по умолчанию он равен 2 ^ 20 n_features; Вы можете уменьшить это и сделать его менее затратным для обработки, но с повышенным риском столкновения, когда функция отображает разные термины в одну и ту же функцию: http://preshing.com/20110504/hash-collision-probabilities/

  • В зависимости от варианта использования для векторов слов может быть возможно значительно уменьшить длину вектора хеш-функции (и, следовательно, сложность) с приемлемыми потерями в точности / эффективности (из-за увеличенного столкновения). Scikit-learn имеет некоторые параметры хеширования, которые могут помочь, например alternate_sign.

  • Если матрица хеширования шире словаря, это будет означать, что многие записи столбцов в матрице хеширования будут пустыми, и не только потому, что данный документ не содержит определенного термина, но и потому, что они пусты во всем матрица. Если это не так, он может отправить несколько терминов в один и тот же хеш-объект - это «столкновение», о котором мы говорили. HashingVectorizerимеет настройку, которая работает, чтобы смягчить этот вызываемый, alternate_signкоторый включен по умолчанию, описанный здесь: en.wikipedia.org/wiki/Feature_hashing#Properties

  • «Термин частота - обратная частота документа» берет частоты термина в каждом документе и взвешивает их, штрафуя слова, которые встречаются чаще всего по всему корпусу. Интуиция заключается в том, что термины, найденные ситуативно, с большей вероятностью будут представлять тему конкретного документа. Это отличается от функции хеширования тем, что в корпусе необходимо иметь полный словарь слов, чтобы рассчитать частоту обратных документов. Я ожидаю, что ваши размеры матрицы tf.idf составляют 45339 документов на 663307 слов в корпусе; Мэннинг и др. Предоставляют более подробную информацию и примеры расчетов: https://nlp.stanford.edu/IR-book/html/htmledition/term-frequency-and-weighting-1.html

«Mining of Massive Datasets» Leskovec et al. Содержит массу деталей как по хешированию функций, так и по tf.idf, авторы сделали PDF доступным здесь: http://www.mmds.org/

redhqs
источник
1
Если tfidf vectorizerдля вычислений idf требуется полный словарь слов, не должны ли термины в матрице tfidf быть больше, чем термины в матрице хеширования?
Мина
2
Если матрица хеширования шире словаря, это будет означать, что многие записи столбцов в матрице хеширования будут пустыми, и не только потому, что данный документ не содержит определенного термина, но и потому, что они пусты во всем матрица. Немного не по теме, но выполняете ли вы какую-либо обработку слов в ваших документах перед векторизацией? Стоп-слова, stemming и т.д?
Redhqs
Да, я обрабатываю. Я использую простор.
Мина
1
Подтверждение: Итак, 1048576 - это длина по умолчанию для любой матрицы хеширования, если n_features не упоминается? Если в корпусе действительно только 663307 слов, оставшиеся 385269 функций пусты. Как можно сделать эту матрицу хеширования аккуратной без всех пустых функций?
Мина
1
Правильно - вы можете изменить количество функций, изменив параметр n_features=1048576, если у вас есть время, попробуйте 640k, 320k и посмотрите, сильно ли это повлияет на вашу точность. Это должно как минимум ускорить ваше тренировочное время. Смотрите @ ответ Натана за n_features=5!
Redhqs
5

HashingVectorizerИмеет параметр , n_featuresкоторый 1048576по умолчанию. При хешировании они фактически не вычисляют термины словаря, отображающие уникальный индекс для использования для каждого из них. Вместо этого, вы просто хэш каждого термина и использовать достаточно большой размер , что вы не ожидаете там быть слишком много столкновений: hash(term) mod table_size. Вы можете сделать возвращаемую матрицу любого размера, установив n_features. Вы должны настроить его так, чтобы он соответствовал вашему корпусу, если вы не думаете, что значение по умолчанию является разумным (его увеличение приведет к меньшему количеству столкновений, хотя и займет больше памяти).

from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer()
print(vectorizer.transform(['a very small document']).shape)
(1, 1048576)

small_vectorizer = HashingVectorizer(n_features=5)
print(small_vectorizer.transform(['a very small document']).shape)    
(1, 5)
Натан
источник
0

HashingVectorizer и CountVectorizer (обратите внимание, не Tfidfvectorizer) предназначены для того же. Который должен преобразовать коллекцию текстовых документов в матрицу вхождений токенов.

Если вы хотите получить частоты терминов, взвешенные по их относительной важности (IDF), то вам следует использовать Tfidfvectorizer. Если вам нужны необработанные или нормализованные значения (периодичность), вам следует использовать CountVectorizer или HashingVectorizer.

Чтобы узнать о HashingVectorizer, см. Эту статью о HashingVectorizer против CountVectorizer .

Для получения дополнительной информации о Tfidfvectorizer см. Эту статью о том, как использовать Tfidftransformer и Tfidfvectorizer .

kavgan
источник