При использовании хеширования вы заранее устанавливаете размер выходной матрицы. Вы сделали это, установив 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