2016-09-06 5 views
1

Ich habe zwei Sparse-Matrizen A und B (slam::simple_triplet_matrix) der gleichen MxN Dimensionen, wobei M = ~ 100K, N = ~ 150K.R: Kosinusabstand zwischen Reihen von zwei Sparse-Matrizen berechnen

Ich möchte den Kosinusabstand zwischen jedem Zeilenpaar berechnen (d. H. Zeile 1 von Matrix A und Zeile 1 von Matrix B, Zeile 2 von Matrix A und Zeile 2 von Matrix B usw.).

Ich kann dies tun mit einer for-Schleife oder mit apply Funktion, aber das ist zu langsam, so etwas wie:

library(slam) 

A <- simple_triplet_matrix(1:3, 1:3, 1:3) 
B <- simple_triplet_matrix(1:3, 3:1, 1:3) 

cosine <- NULL 
for (i in 1:(dim(A)[1])) { 
    a <- as.vector(A[i,]) 
    b <- as.vector(B[i, ]) 
    cosine[i] <- a %*% b/sqrt(a%*%a * b%*%b) 
} 

Ich verstehe etwas in this zuvor gestellte Frage könnte mir helfen, aber:

a) Das ist nicht wirklich das, was ich will, ich will nur M Kosinus-Abstände für M Zeilen, nicht alle paarweisen Korrelationen zwischen Zeilen einer gegebenen dünn besetzten Matrix.

b) Ich gebe zu, die Mathematik hinter dieser "vektorisierten" Lösung nicht vollständig zu verstehen, also wäre vielleicht eine Erklärung hilfreich.

Vielen Dank.

EDIT: Dies ist auch kein Duplikat von this Frage, wie ich bin nicht nur interessiert an einer regelmäßigen Cosinus-Berechnung auf zwei einfache Vektoren (ich weiß klar, wie dies zu tun, siehe oben), interessiert mich eine viel größere Situation, insbesondere Slam-Sparse-Matrizen.

+0

Mögliches Duplikat von [Kosinusähnlichkeit in R finden] (http://stackoverflow.com/questions/2535234/find-cosine-simility-in-r) –

+0

@DmitriySelivanov Kaum eine Verbindung außer der Frage nach der Kosinusentfernung, und ich frage nicht nur nach Kosinusdistanz (die ich ganz klar zu implementieren weiß). Ich interessiere mich für eine großskalige Situation mit dünnen Matrizen. –

Antwort

3

Gemäß der Dokumentation, Element-für-Element (array) Multiplikation kompatibler simple_triplet_matrices und row_sums von simple_triplet_matrices zur Verfügung. Mit diesen Operatoren/Funktionen ist die Berechnung:

cosineDist <- function(A, B){ 
    row_sums(A * B)/sqrt(row_sums(A * A) * row_sums(B * B)) 
} 

Hinweise:

  1. row_sums(A * B) das Skalarprodukt jeder Zeile berechnet in A und die entsprechenden Zeile in B, die die Zählerterm in Ihrem cosine ist . Das Ergebnis ist ein Vektor (nicht spärlich), dessen Elemente diese Punktprodukte für jede entsprechende Zeile in A und B sind.
  2. row_sums(A * A) berechnet die quadrierte 2-Norm jeder Zeile in A. Das Ergebnis ist ein Vektor (nicht spärlich), dessen Elemente diese quadrierten 2-Normen für jede Zeile in A sind.
  3. Ähnlich berechnet row_sums(B * B) die quadrierte 2-Norm jeder Zeile in B. Das Ergebnis ist ein Vektor (nicht spärlich), dessen Elemente diese quadrierten 2-Normen für jede Zeile in B sind. Der Rest der Berechnung arbeitet mit diesen Vektoren, deren Elemente für jede Zeile von A und/oder B sind.
0
cosineDist <- function(x){ 
    as.dist(1 - x%*%t(x)/(sqrt(rowSums(x^2) %*% t(rowSums(x^2))))) 
} 
+0

Dies sind spärliche Matrizen, ich kann nicht einfach 'as.matrix' auf ihnen betreiben. Auch das geht über das hinaus, was benötigt wird, nur M Abstände für M Zeilen. Vielen Dank. –

Verwandte Themen