Cocktailparty-Algorithmus SVD-Implementierung… in einer Codezeile?

87

In einer Folie in der Einführungsvorlesung über maschinelles Lernen von Stanfords Andrew Ng in Coursera gibt er die folgende einzeilige Oktavlösung für das Cocktailparty-Problem, da die Audioquellen von zwei räumlich getrennten Mikrofonen aufgezeichnet werden:

[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');

Am unteren Rand der Folie befindet sich "Quelle: Sam Roweis, Yair Weiss, Eero Simoncelli" und am unteren Rand einer früheren Folie "Audioclips mit freundlicher Genehmigung von Te-Won Lee". In dem Video sagt Professor Ng:

"Sie könnten sich also unbeaufsichtigtes Lernen wie dieses ansehen und fragen: 'Wie kompliziert ist es, dies umzusetzen?' Es scheint, als würden Sie zum Erstellen dieser Anwendung eine Menge Code schreiben oder eine Verknüpfung zu einer Reihe von C ++ - oder Java-Bibliotheken herstellen, die Audio verarbeiten. Es scheint, als wäre dies eine echte kompliziertes Programm, um dieses Audio zu machen: Audio trennen und so weiter. Es stellt sich heraus, dass der Algorithmus das tut, was Sie gerade gehört haben, was mit nur einer Codezeile gemacht werden kann ... hier gezeigt. Es hat lange gedauert Ich sage also nicht, dass dies ein einfaches Problem ist. Aber es stellt sich heraus, dass viele Lernalgorithmen wirklich kurze Programme sind, wenn Sie die richtige Programmierumgebung verwenden. "

Die getrennten Audioergebnisse in der Videovorlesung sind nicht perfekt, aber meiner Meinung nach erstaunlich. Hat jemand einen Einblick, wie diese eine Codezeile so gut funktioniert? Kennt jemand eine Referenz, die die Arbeit von Te-Won Lee, Sam Roweis, Yair Weiss und Eero Simoncelli in Bezug auf diese eine Codezeile erklärt?

AKTUALISIEREN

Um die Empfindlichkeit des Algorithmus gegenüber dem Abstand zwischen Mikrofonen zu demonstrieren, trennt die folgende Simulation (in Oktave) die Töne von zwei räumlich getrennten Tongeneratoren.

% define model 
f1 = 1100;              % frequency of tone generator 1; unit: Hz 
f2 = 2900;              % frequency of tone generator 2; unit: Hz 
Ts = 1/(40*max(f1,f2)); % sampling period; unit: s 
dMic = 1;               % distance between microphones centered about origin; unit: m 
dSrc = 10;              % distance between tone generators centered about origin; unit: m 
c = 340.29;             % speed of sound; unit: m / s 

% generate tones
figure(1);
t = [0:Ts:0.025];
tone1 = sin(2*pi*f1*t);
tone2 = sin(2*pi*f2*t);
plot(t,tone1); 
hold on;
plot(t,tone2,'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -1 1]); legend('tone 1', 'tone 2');
hold off;

% mix tones at microphones
% assume inverse square attenuation of sound intensity (i.e., inverse linear attenuation of sound amplitude)
figure(2);
dNear = (dSrc - dMic)/2;
dFar = (dSrc + dMic)/2;
mic1 = 1/dNear*sin(2*pi*f1*(t-dNear/c)) + \
       1/dFar*sin(2*pi*f2*(t-dFar/c));
mic2 = 1/dNear*sin(2*pi*f2*(t-dNear/c)) + \
       1/dFar*sin(2*pi*f1*(t-dFar/c));
plot(t,mic1);
hold on;
plot(t,mic2,'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -1 1]); legend('mic 1', 'mic 2');
hold off;

% use svd to isolate sound sources
figure(3);
x = [mic1' mic2'];
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');
plot(t,v(:,1));
hold on;
maxAmp = max(v(:,1));
plot(t,v(:,2),'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -maxAmp maxAmp]); legend('isolated tone 1', 'isolated tone 2');
hold off;

Nach ungefähr 10 Minuten Ausführung auf meinem Laptop generiert die Simulation die folgenden drei Abbildungen, die zeigen, dass die beiden isolierten Töne die richtigen Frequenzen haben.

Abbildung 1 Figur 2 Figur 3

Wenn Sie jedoch den Abstand zwischen den Mikrofonen auf Null setzen (dh dMic = 0), generiert die Simulation stattdessen die folgenden drei Abbildungen, die veranschaulichen, dass die Simulation keinen zweiten Ton isolieren konnte (bestätigt durch den einzelnen signifikanten diagonalen Term, der in der Matrix von svd zurückgegeben wird).

Abbildung 1 ohne Mikrofontrennung Abbildung 2 ohne Mikrofontrennung Abbildung 3 ohne Mikrofontrennung

Ich hatte gehofft, dass der Mikrofonabstand auf einem Smartphone groß genug ist, um gute Ergebnisse zu erzielen. Wenn Sie jedoch den Mikrofonabstand auf 5,25 Zoll (dh dMic = 0,1333 Meter) einstellen, generiert die Simulation die folgenden, weniger als ermutigenden Zahlen, die höhere Werte darstellen Frequenzkomponenten im ersten isolierten Ton.

Abbildung 1 auf dem Smartphone Abbildung 2 auf dem Smartphone Abbildung 3 auf dem Smartphone

gregS
quelle
1
Ich habe vage Erinnerungen an diesen Vortrag, kann mich aber nicht erinnern, was xist; ist es das Spektrogramm der Wellenform oder was?
Isaac
Professor Ng scheint bei t = 5: 30 im Einführungsvideo 4 zum unbeaufsichtigten Lernen darauf hinzudeuten, dass x ein Vektor der Audio-Samples ist. Vielleicht implementiert dieser repmat-Abschnitt im svd-Argument eine Art Leistungsnormalisierung des Signals.
Gregs

Antworten:

27

Ich habe auch 2 Jahre später versucht, dies herauszufinden. Aber ich habe meine Antworten bekommen; hoffentlich hilft es jemandem.

Sie benötigen 2 Audioaufnahmen. Audiobeispiele finden Sie unter http://research.ics.aalto.fi/ica/cocktail/cocktail_en.cgi .

Referenz für die Implementierung ist http://www.cs.nyu.edu/~roweis/kica.html

ok, hier ist Code -

[x1, Fs1] = audioread('mix1.wav');
[x2, Fs2] = audioread('mix2.wav');
xx = [x1, x2]';
yy = sqrtm(inv(cov(xx')))*(xx-repmat(mean(xx,2),1,size(xx,2)));
[W,s,v] = svd((repmat(sum(yy.*yy,1),size(yy,1),1).*yy)*yy');

a = W*xx; %W is unmixing matrix
subplot(2,2,1); plot(x1); title('mixed audio - mic 1');
subplot(2,2,2); plot(x2); title('mixed audio - mic 2');
subplot(2,2,3); plot(a(1,:), 'g'); title('unmixed wave 1');
subplot(2,2,4); plot(a(2,:),'r'); title('unmixed wave 2');

audiowrite('unmixed1.wav', a(1,:), Fs1);
audiowrite('unmixed2.wav', a(2,:), Fs1);

Geben Sie hier die Bildbeschreibung ein

Jack Z.
quelle
1
Können Sie eine Referenz finden, die die Gründe für diese Codezeile genauer erläutert?
Hans
Könnten Sie bitte erklären, wie die Signalmischung in dem von Ihnen angegebenen Link funktioniert? Mit Ihrem Code können Sie zwei Tonquellen aus den beiden von der Site heruntergeladenen gemischten Dateien extrahieren. Wenn ich jedoch versuche, zwei separate Signale selbst zu mischen, kann der Algorithmus anscheinend nicht das richtige Ergebnis ausgeben. Ich benutze den naiven Weg, um die gemischten Signale zu erhalten: mic1 = 0,3 * Spur1 + 0,5 * Spur2, mic2 = 0,5 * Spur1 + 0,3 * Spur2. Dies ist das Signal, das ich versucht habe, dem Algorithmus zuzuführen. Vielen Dank!
yc2986
Ich bin ein bisschen neu in Matlab. Ich habe Fehler in Zeile 3, die besagen, dass es Probleme gibt, 2 Matrix mit verschiedenen Dimensionen zu verketten. Wie soll ich mit diesem Problem umgehen?
Mshrestha
1
Ich habe diesen Code ausprobiert, aber er funktioniert nicht sehr gut ... (ohne dich zu beschuldigen !!)
anderstood
17

x(t) ist die Originalstimme von einem Kanal / Mikrofon.

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'ist eine Schätzung des Leistungsspektrums von x(t). Obwohl X' = X, sind die Abstände zwischen den Zeilen und Spalten überhaupt nicht das gleiche. Jede Zeile repräsentiert die Zeit des Signals, während jede Spalte die Frequenz ist. Ich denke, dies ist eine Schätzung und Vereinfachung eines strengeren Ausdrucks namens Spektrogramm .

Die Singularwertzerlegung im Spektrogramm wird verwendet, um das Signal basierend auf Spektruminformationen in verschiedene Komponenten zu zerlegen. Diagonale Werte in ssind die Größe verschiedener Spektralkomponenten. Die Zeilen in uund Spalten in v'sind die orthogonalen Vektoren, die die Frequenzkomponente mit der entsprechenden Größe auf den XRaum abbilden .

Ich habe keine Sprachdaten zum Testen, aber nach meinem Verständnis werden die Komponenten mittels SVD in die ähnlichen orthogonalen Vektoren fallen und hoffentlich mit Hilfe von unbeaufsichtigtem Lernen geclustert. Sagen wir, wenn die ersten 2 diagonalen Größen von s gruppiert sind, dann u*s_new*v'bilden sie die Ein-Personen-Stimme, wobei s_newdie gleiche ist, saußer dass alle Elemente bei (3:end,3:end)eliminiert werden.

Zwei Artikel über die klanggeformte Matrix und SVD dienen als Referenz.

lennon310
quelle
1
gregS, mathematisch gesehen kann eine n-mal-2-Matrix x mit der repmat-Operation immer noch ein X bilden. Das Spektrogramm kann jedoch jedes Mal nur den Kanal anzeigen. Daher halte ich es für sinnvoller, jedes Mal n-mal-1 x zu verwenden und das Problem als lineare Regression (zwei Matrixgleichungen) zu behandeln. Weitere zwei mögliche Ansätze sind (i) Mittelung von zwei Kanälen als n-mal-2 x; oder (ii) sie zusammenbinden, um ein 2 * n-mal-2 x zu konstruieren.
Lennon310
2
gregS, ich habe deine frage noch einmal überdacht. Es kann funktionieren, wenn Sie repmat auf einem n-by-2 x implementieren. Physikalisch kann es als Durchschnitt der Leistung von zwei Kanälen zu jeder Zeit und jeder Frequenz angesehen werden.
Lennon310
Ich habe diesen Beitrag gefunden, nachdem ich mir das Einführungsvideo zum maschinellen Lernen angesehen habe (der Kurs hat gerade wieder begonnen). Ich habe mich gefragt, ob Sie es geschafft haben, die im Video gezeigte Audio-Trennung zu reproduzieren, oder ob sie während des Kurses entwickelt wurde.
Siritinga
@siritinga bitte suchen Sie Andrew Ngs Veröffentlichung über unbeaufsichtigtes / tiefes Lernen auf Audio, danke
lennon310
1
Warum ist $ X $ die Potenz des Spektrums von $ x $? Auch nach der Antwort von Jack Z ist $ x $ nicht die Originalstimme aus der Aufnahme, sondern eine Art verarbeiteter Kehrwert des Eigenwerts der Kovarianz der Originalstimme.
Hans