Сколько особых значений хранить в пакете 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,

Другие вопросы по тегам