Ngrams с использованием hash_vectorizer в text2vec

Я пытался создать ngrams, используя функцию hash_vectorizer в text2vec, когда заметил, что она не меняет размеры моего dtm с изменением значений.

h_vectorizer = hash_vectorizer(hash_size = 2 ^ 14, ngram = c(2L, 10L))
dtm_train = create_dtm(it_train, h_vectorizer)
dim(dtm_train)

В приведенном выше коде размеры не меняются, будь то 2-10 или 9-10.

vocab = create_vocabulary(it_train, ngram = c(1L, 4L))
ngram_vectorizer = vocab_vectorizer(vocab)
dtm_train = create_dtm(it_train, ngram_vectorizer)

В приведенном выше коде размеры меняются, но я также хочу использовать hash_vectorizor, поскольку он экономит место. Как мне это использовать?


person Akhil    schedule 14.12.2017    source источник


Ответы (1)


При использовании хеширования вы заранее устанавливаете размер выходной матрицы. Вы сделали это, установив hash_size = 2 ^ 14. Это остается неизменным независимо от окна ngram, указанного в модели. Однако значения в выходной матрице меняются.

(В ответ на комментарии ниже:) Ниже вы найдете минимальный пример с двумя очень простыми строками, чтобы продемонстрировать разные выходные данные для двух разных окон ngram, используемых в файле hash_vectorizer. Для случая биграмм я добавил выходную матрицу vocab_vectorizer для сравнения. Вы понимаете, что вам нужно установить достаточно большой размер хеш-функции, чтобы учесть все термины. Если он слишком мал, хэш-значения отдельных терминов могут конфликтовать.

Ваш комментарий о том, что вам всегда нужно сравнивать результаты подхода vocab_vectorizer и подхода hash_vectorizer, ведет в неправильном направлении, потому что тогда вы потеряете преимущество в эффективности/памяти, которое может быть получено с помощью подхода хеширования, который позволяет избежать создания словаря. В зависимости от ваших данных и желаемого результата хеширование может относиться к точности (и интерпретируемости терминов в dtm) против эффективности. Следовательно, это зависит от вашего варианта использования, является ли хеширование разумным или нет (что особенно важно для задач классификации на уровне документа для больших коллекций).

Я надеюсь, что это дало вам общее представление о хэшировании и о том, что вы можете или не можете ожидать от него. Вы также можете проверить несколько сообщений о хэшировании на странице quora, Википедия (или также здесь). Или также обратитесь к подробным исходным источникам, перечисленным на text2vec.org.

library(text2vec)
txt <- c("a string string", "and another string")

it = itoken(txt, progressbar = F)


#the following four example demonstrate the effect of the size of the hash
#and the use of signed hashes (i.e. the use of a secondary hash function to reduce risk of collisions)
vectorizer_small = hash_vectorizer(2 ^ 2, c(1L, 1L)) #unigrams only
hash_dtm_small = create_dtm(it, vectorizer_small)
as.matrix(hash_dtm_small)
#    [,1] [,2] [,3] [,4]
# 1    2    0    0    1
# 2    1    2    0    0  #collision of the hash values of and / another

vectorizer_small_signed = hash_vectorizer(2 ^ 2, c(1L, 1L), signed_hash = TRUE) #unigrams only
hash_dtm_small = create_dtm(it, vectorizer_small_signed)
as.matrix(hash_dtm_small)
#     [,1] [,2] [,3] [,4]
# 1    2    0    0    1
# 2    1    0    0    0 #no collision but some terms (and / another) not represented as hash value

vectorizer_medium = hash_vectorizer(2 ^ 3, c(1L, 1L)) #unigrams only
hash_dtm_medium = create_dtm(it, vectorizer_medium)
as.matrix(hash_dtm_medium)
#    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# 1    0    0    0    1    2    0    0    0
# 2    0    1    0    0    1    1    0    0 #no collision, all terms represented by hash values


vectorizer_medium = hash_vectorizer(2 ^ 3, c(1L, 1L), signed_hash = TRUE) #unigrams only
hash_dtm_medium = create_dtm(it, vectorizer_medium)
as.matrix(hash_dtm_medium)
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# 1    0    0    0    1    2    0    0    0
# 2    0   -1    0    0    1    1    0    0 #no collision, all terms represented as hash values
                                            #in addition second hash function generated a negative hash value


#the following two examples deomstrate the difference between 
#two hash vectorizers one with unigrams, one allowing for bigrams
#and one vocab vectorizer with bigrams
vectorizer = hash_vectorizer(2 ^ 4, c(1L, 1L)) #unigrams only
hash_dtm = create_dtm(it, vectorizer)
as.matrix(hash_dtm)
#    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16]
# 1    0    0    0    0    0    0    0    0    0     0     0     1     2     0     0     0
# 2    0    0    0    0    0    0    0    0    0     1     0     0     1     1     0     0

vectorizer2 = hash_vectorizer(2 ^ 4, c(1L, 2L)) #unigrams + bigrams
hash_dtm2 = create_dtm(it, vectorizer2)
as.matrix(hash_dtm2)
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16]
# 1    1    0    0    1    0    0    0    0    0     0     0     1     2     0     0     0
# 2    0    0    0    0    0    1    1    0    0     1     0     0     1     1     0     0

v <- create_vocabulary(it, c(1L, 2L))
vectorizer_v = vocab_vectorizer(v) #unigrams + bigrams
v_dtm = create_dtm(it, vectorizer_v)
as.matrix(v_dtm)
#   a_string and_another a another and string_string another_string string
# 1        1           0 1       0   0             1              0      2
# 2        0           1 0       1   1             0              1      1


sum(Matrix::colSums(as.matrix(hash_dtm)) > 0)
#[1] 4   - these are the four unigrams a, string, and, another
sum(Matrix::colSums(hash_dtm2) > 0)
#[1] 8   - these are the four unigrams as above plus the 4 bigrams string_string, a_string, and_another, another_string 
sum(Matrix::colSums(v_dtm) > 0)
#[1] 8 - same as hash_dtm2
person Manuel Bickel    schedule 14.12.2017
comment
Привет, Мануэль, я проверил 1-1, 1-2 и 1-4. сумма по ним составила 12850, 16384 и 16384 соответственно. я согласен, что ваша логика имеет смысл, а также я получил свой код из виньетки, но как я могу убедиться? - person Akhil; 14.12.2017
comment
Однако, когда я проверяю сумму (colSums (as.matrix (dtm_train))), я получаю разные суммы для всех вариантов. почему вы проверили (›0) ? я предполагаю, что значения будут 0 или 1 (или, может быть, ›1). Не будет отрицательных значений, правильно? - person Akhil; 14.12.2017
comment
(i) Я проверил >0, поскольку установленный размер хеша был больше, чем количество токенов, следовательно, не все элементы хеша будут иметь записи, учитываются только положительные. Для дополнительных пояснений проверьте мой пример с c("a string string", "and another string"). Вы заметите счет 2 в одной из позиций (плюс дополнительная биграмма в другой). (ii) Какой размер хэша вы установили для своего теста 1-4 (возможно, вам нужно его увеличить)/какое количество юниграмм/токенов в ваших данных. (iii) Вы должны предоставить воспроизводимый пример текста, в противном случае членам SO придется продолжать гадать. - person Manuel Bickel; 14.12.2017
comment
Дополнительная проблема: какой dim вашего dtm был создан с vocab_vectorizer в указанном выше тесте 1-1, 1-2, 1-4? - person Manuel Bickel; 14.12.2017
comment
(1) я использовал жуткий набор данных идентификации автора от kaggle. только в наборе поездов более 19 тысяч строк, поэтому я действительно не знаю количество биграмм и выше. (2) я использовал 2 ^ 14 в качестве размера хэша для hash_vectorizer для 1-10 нграмм. этого будет достаточно?. (3) здесь представлены тусклые значения для 1-1 (19579 * 25108), 1-2 (19579 * 246512), 1-4 (19579 * 1100631). эти значения я получил для vocab_vectorizer - person Akhil; 14.12.2017
comment
сумма (colSums (dtm_train)) из векторизатора vocab совпадает с той же суммой из векторизатора хэша. Вот это да. большое облегчение!. Это означает, что даже если dim может быть таким же для хеш-векторизатора, действительно следует проверить сумму (colSums (dtm)). правильно ли я понимаю? - person Akhil; 14.12.2017
comment
Пожалуйста, смотрите мой обновленный ответ. Обратите внимание, что dtms, сгенерированные хэшем или векторизатором vocab, связаны, но не совпадают. Hash dtm не имеет информации о терминах, только хэш-значения признаков. - person Manuel Bickel; 15.12.2017