2016-07-20 14 views
4

Ich interessiere mich für Statistiken über verschiedene zufällig ausgewählte Teilmengen einer großen Datenmatrix, und jetzt ist ein Flaschenhals in meinem Code die tatsächliche Unterabtastung. Das erscheint mir komisch, da es bei den unterabgetasteten Daten ziemlich viele O (N^2) -Distanzberechnungen gibt. Ich modifiziere die Subsamples überhaupt nicht, schaue sie nur an.Der schnellste Weg, um Sätze von Spalten aus großen Arrays in Julia zu unterteilen

using Distributions, Distances 

function test_subsetting(X; batch_size=500, nloops=100) 
    nfeatures, nsamples = size(X) 
    ref_samples = X[:,1:10] 
    batch_inds = zeros(batch_size) 
    batch = zeros(nfeatures,batch_size) 
    d_matrix = zeros(batch_size,batch_size) 
    for i = 1:nloops 
     batch_inds = sort(sample(1:nsamples, batch_size, replace = false)) 
     batch = X[:,batch_inds] 
     d_matrix = pairwise(SqEuclidean(), batch, ref_samples) 
    end 
end 

Als ich es testen, indem 50000 Probenmatrix auf einem 5000-Funktion aus:

X_test = randn(5000,50000); 

Ich sehe, dass ich etwa die Hälfte meiner Zeit in _unsafe_getindex in multidimensional.jl verbringen, und die andere Hälfte der Abstandsberechnung zu tun .

Gibt es eine effizientere Möglichkeit, dieses Problem anzugehen?

+1

Wenn Sie Ihre Matrix X zuerst vollständig mischen und dann nachfolgende Stapel von 'n'-Spalten daraus ziehen (wenn Sie es nach Bedarf neu mischen), könnte das die Dinge beschleunigen. Sie könnten auch in Betracht ziehen, Dinge zu parallelisieren. Diese Art des Samplings ist sehr gut geeignet, um diese Funktion für mehrere Arbeiter gleichzeitig auszuführen. –

+0

Parallelisierung ist ein interessanter Gedanke, aber die Statistiken, die ich für jeden Batch verwende, werden verwendet, um die Statistik des nächsten Stapels in der nächsten Runde zu beeinflussen (das ist in meinem Beispiel nicht klar), also glaube ich nicht, dass es parallelisiert . Im Idealfall möchte ich das auf Dinge skalieren, die nicht in den Speicher passen, also ist es nicht der richtige Weg. – Rory

+0

Ich denke, ich muss die 'batch' erstellen, oder vielleicht eine Stand-in, die nicht wirklich neuen Speicher für ein neues Array zuweisen, sondern nur die Daten in' X' und fakes es - ich sammle 'sub' und 'view' machen Dinge wie diese, aber ich konnte sie nicht dazu bringen, mit der' paarweisen' Funktion von 'distances.jl' zu arbeiten. – Rory

Antwort

3

Dies funktioniert für mich auf julia 0,5:

julia> using Distances, Distributions 

julia> X = randn(500,1000); 

julia> S = sample(1:1000,500,replace=false); 

julia> M = view(X, :, S); 

julia> S2 = sample(1:1000,500,replace=false); 

julia> R = view(X, :, S2); 

julia> pairwise(SqEuclidean(), M, R) 
500×500 Array{Float64,2}: 
    994.67 ... 
... 

view auf julia 0,5 slice genannt wird (oder sub, hier würden sie gleich sein) auf julia 0,4. Nicht zu verwechseln mit ArrayViews.view, die etwas ähnliches tut, aber mit einer völlig anderen Implementierung.

Theoretisch scheint es, Sie sollten view mit slice ersetzen können, aber es scheint, dass es eine At_mul_B! Methode auf Julia 0.4 fehlt. Sie könnten also stecken bleiben und eine Kopie machen.

+0

Ich denke, es ist an der Zeit, auf 0,5 zu aktualisieren. Danke für die Klärung der verschiedenen 'View'-Implementierungen. – Rory

2

Sie können Ihre "Sampling" -Zeit komplett verkürzen, wenn Sie eine große Matrix randomisierter Indizes "vorgenerieren" möchten, die Sie dann zur Laufzeit referenzieren. Sie können dieser Matrix sogar ein bisschen "Reihen und Spalten" geben, die vor jedem Gebrauch mit minimalen Kosten mischen.

Auch, warum müssen Sie überhaupt sortieren? Sicherlich, dass das den Stichprobenpunkt vereitelt und unnötige Berechnungen einführt?

+0

Ich sortierte die Samples mit dem Gedanken, dass der Array-Zugriff etwas schneller sein könnte, wenn die Spalten in sequentieller Reihenfolge sind. Die Reihenfolge der Teilstichproben spielt keine Rolle, da die an ihnen durchgeführten Statistiken unter Permutation invariant sind. Die Verwendung einer großen vorgenerierten Master-Liste ist ein interessanter Gedanke, aber der Flaschenhals generiert nicht die Beispielindizes, sondern verwendet diese Indizes, um auf eine Teilmenge der Einträge in der Datenmatrix zuzugreifen. – Rory

+0

Es ist die Zeile 'batch = X [:, batch_inds]', die unnötigerweise langsam erscheint - ich habe mich gefragt, ob jemand Gedanken über die Verwendung von 'view' oder' sub' oder etwas Ähnliches hatte. – Rory

+0

@Rory loswerden 'sort' dann. Sortieren ist eine sehr kostspielige Operation, und Sie tun mit der Absicht, eine * micro * -Optimierung zu erzielen !! Außerdem basiert es auf einem Missverständnis und es wird tatsächlich nichts tun. Julia ist Spalte-Haupt-Reihenfolge, grob bedeutet, dass alle Elemente in einer einzelnen Spalte (d. H. Die Zeilenelemente dieser Spalte) zusammenhängend im Speicher gespeichert sind. Dies bedeutet, dass zwei Elemente in der gleichen * Zeile *, die in benachbarten * Spalten * sind, in Bezug auf die Speicheradresse tatsächlich ziemlich weit voneinander entfernt sind. Ihre Sortierung "Optimierung" würde hier also keinen großen Unterschied machen. –