Сколько особых значений хранить в пакете R lsa
Я использовал функцию lsa в пакете R lsa, чтобы получить семантическое пространство. Входные данные представляют собой матрицу терм-документа. Проблема в том, что функция dimcalc_share(), используемая lsa по умолчанию, кажется неправильной. На странице справки функции сказано, что функция "находит первую позицию в нисходящей последовательности сингулярных значений, где их сумма соответствует или превышает указанную долю". Под словами я понимаю, что функция хранит n-е по величине единичные значения, так что сумма этих значений превышает определенный процент от суммы всех сингулярных значений. Исходный код функции
function(share=0.5)
{
function(x){
if(any(which(cumsum(s/sum(s))<=share))){
d=max(which(cumsum(s/sum(s))<=share))+1
}
else{
d=length(s)
}
return(d)
}
}
У меня есть два вопроса с исходным кодом: 1. почему плюс 1 к d? 2. если доля первого сингулярного значения больше, чем share, функция сохранит все сингулярные значения, в то время как я полагаю, что функция должна просто сохранить первое.
1 ответ
Ваш первый вопрос "почему + 1
?"
Давайте посмотрим, как работают эти функции:
# create some files
td = tempfile()
dir.create(td)
write( c("dog", "cat", "mouse"), file=paste(td, "D1", sep="/") )
write( c("ham", "mouse", "sushi"), file=paste(td, "D2", sep="/") )
write( c("dog", "pet", "pet"), file=paste(td, "D3", sep="/") )
# LSA
data(stopwords_en)
myMatrix = textmatrix(td, stopwords=stopwords_en)
myMatrix = lw_logtf(myMatrix) * gw_idf(myMatrix)
myLSAspace = lsa(myMatrix, dims=dimcalc_share())
as.textmatrix(myLSAspace)
D1 D2 D3
cat 0.3616693 0.6075489 0.3848429
dog 0.4577219 0.2722711 1.2710784
mouse 0.5942734 1.3128719 0.1357196
ham 0.6075489 1.5336529 -0.1634938
sushi 0.6075489 1.5336529 -0.1634938
pet 0.6099616 -0.2591316 2.6757285
Так, lsa
получает размеры от dimcalc_share()
на основе входной матрицы и заданной доли (по умолчанию 0,5) и выполняет разложение по сингулярным значениям для сопоставления исходного TDM с новым LSAspace
,
Эти измерения являются числом особых значений для уменьшения размерности в LSA. dimcalc_share()
находит первую позицию в нисходящей последовательности сингулярных значений s, где их сумма (деленная на сумму всех значений) соответствует или превышает указанную долю.
Функция написана так, что это d
равно max()
позиция <= share
:
> # Break it apart
> s <- myMatrix
> share <- .5
>
> any(which(cumsum(s/sum(s)) <= share)) #TRUE
[1] TRUE
> cumsum(s/sum(s)) <= share
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> d = max(which(cumsum(s/sum(s)) <= share)) + 1
> d
[1] 10
Если вы только использовали d -1
, что даст вам 9 вместо 10, то вы бы вместо этого иметь позицию, где cumsum
все еще <=
в share
, Это не сработает:
> myMatrix = lw_logtf(myMatrix) * gw_idf(myMatrix)
> myLSAspace2 = lsa(myMatrix, dims=d-1)
Error in SVD$u[, 1:dims] : subscript out of bounds
эквивалентно
> dims = 9
> myLSAspace = lsa(myMatrix, dims)
Error in SVD$u[, 1:dims] : subscript out of bounds
Так что функция dimshare_calc()
правильно использовать + 1
,
Ваш второй вопрос, модифицированный для этого примера, звучит так: "Будет ли dimcalc_share() = 18 вместо = 1, если первое значение было> share?"
Если первое значение было > share
тогда первый if
условие вернет false и, как вы предположили, вместо этого будет использовать length(s)
которому 18.
Вы можете задать вопрос о CrossValidated, чтобы подтвердить, что ваша интуиция = 1
правильно (хотя это имеет смысл для меня). Если это так, было бы просто переписать функцию с d = 1
как else
,