Я генерирую матрицу, используя пакет lsa в R. После создания матрицы я хотел бы вычислить сходство косинусов между определенными парами документов (столбцов) в матрице.Применение функции между определенными парами столбцов в матрице в R
В настоящее время я делаю это с вложенными петлями, и это monstrously slow. В приведенном ниже коде есть 150 исходных идентификаторов и 6413 targetIDs, в общей сложности 961,950 сравнений. Спустя полтора часа на моей машине с номером-хрустом она достигла всего ~ 300 тыс. Из них.
Для получения дополнительной информации, sourceIDs и targetIDs векторы имен столбцов, загруженные в двух файлов, содержащих эти имена. Я хочу применить косинусную функцию между всеми парами source-> target. Столбцы индексируются по имени документа, которое является строкой.
Я уверен, что существует гораздо более быстрый способ сделать это с помощью применить, но я просто не могу обернуть вокруг себя голову.
library(lsa)
# tf function
real_tf <- function(m)
{
return (sweep(m, MARGIN=2, apply(m, 2, max), "/"))
}
#idf function
real_idf <- function(m)
{
df = rowSums(lw_bintf(m), na.rm=TRUE)
return (log(ncol(m)/df))
}
#load corpus
lsa.documents <- textmatrix(args[1], minWordLength=1, minDocFreq=0)
# compute tf-idf
lsa.weighted_documents <- real_tf(lsa.documents) * real_idf(lsa.documents)
# compute svd
lsa.nspace <- lsa(lsa.weighted_documents, dims = as.integer(args[5]))
lsa.matrix <- diag(lsa.nspace$sk) %*% t(lsa.nspace$dk)
# compute similarities
lsa.sourceIDs <- scan(args[2], what = character())
lsa.targetIDs <- scan(args[3], what = character())
lsa.similarities <- data.frame(SourceID=character(), TargetID=character(), Score=numeric(), stringsAsFactors=FALSE)
k <- 1
for (i in lsa.sourceIDs)
{
for (j in lsa.targetIDs)
{
lsa.similarities[k,] <- c(i, j, cosine(lsa.matrix[,i], lsa.matrix[,j]))
k <- k + 1
}
}
lsa.ranklist <- lsa.similarities[order(lsa.similarities$Score, decreasing=TRUE),]
# save ranklist
write.table(lsa.ranklist, args[4], sep="\t", quote=FALSE, col.names=FALSE, row.names=FALSE)
Edit: Воспроизводимые пример
# cosine function from lsa package
cosine <- function(x, y)
{
return (crossprod(x,y)/sqrt(crossprod(x)*crossprod(y)))
}
theMatrix <- structure(c(-0.0264639232505822, -0.0141165039351167, -0.0280459775632757,
-0.041211247161448, -0.00331565717239375, -0.0291161345945683,
-0.0451167802746869, -0.0116214407383401, -0.0381080747718958,
-1.36693644389599, 0.274747343110076, 0.128100677705483, -0.401760905661056,
-1.24876927957167, 0.368479552862631, -0.459711112157286, -0.544344448332346,
-0.765378939625159, -1.28612431910459, 0.293455499695499, 0.025167452173962
), .Dim = c(3L, 7L), .Dimnames = list(NULL, c("doc1", "doc2", "doc3",
"doc4", "doc5", "doc6", "doc7")))
sources <- c("doc1", "doc2", "doc3")
targets <- c("doc4", "doc5", "doc6", "doc7")
similarities <- data.frame(SourceID=character(), TargetID=character(), Score=numeric(), stringsAsFactors=FALSE)
k <- 1
for (i in sources)
{
for (j in targets)
{
similarities[k,] <- c(i, j, cosine(theMatrix[,i], theMatrix[,j]))
k <- k + 1
}
}
ranklist <- similarities[order(similarities$Score, decreasing=TRUE),]
write.table(ranklist, "C:\\Temp\\outputfile.txt", sep="\t", quote=FALSE, col.names=FALSE, row.names=FALSE)
Который производит (OutputFile.txt):
doc1 doc6 0.962195242094352
doc3 doc6 0.893461576046585
doc2 doc6 0.813856201398669
doc2 doc7 0.768837903803964
doc2 doc4 0.730093288388069
doc3 doc7 0.675640649189972
doc3 doc4 0.635982900340315
doc1 doc7 0.53871688669971
doc1 doc4 0.499235059782688
doc1 doc5 0.320383772495164
doc3 doc5 0.226751624753921
doc2 doc5 0.144680489733846
Было бы проще, если бы вы должны были обеспечить более воспроизводимый пример, так как даже после установки 'lsa' я, видимо, нужна установить что-то другое (Java?). Я бы просто дал базовый образец данных с 'dput' и ожидаемый результат. Я полагаю, что сам пакет lsa не имеет отношения к проблеме матричной совокупности. –
Из того, что я мог понять в вашем коде, у вас есть два вектора равной длины, содержащие некоторые значения.В качестве вывода вы хотите иметь значения косинуса для всех комбинаций элементов этих начальных векторов. Если это правильно, то 'external()', вероятно, вам поможет. –
@Maxim, если это ответ, тогда OP действительно плохо под угрозой! – flodel