Implementacja SVD algorytmu koktajlowego… w jednej linii kodu?

88

Na slajdzie w ramach wykładu wprowadzającego na temat uczenia maszynowego, wygłoszonego przez Andrew Ng ze Stanforda w Coursera, przedstawia następujące jedno liniowe rozwiązanie problemu koktajlowego, biorąc pod uwagę, że źródła dźwięku są nagrywane przez dwa oddzielone przestrzennie mikrofony:

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

U dołu slajdu znajduje się „źródło: Sam Roweis, Yair Weiss, Eero Simoncelli”, a na dole wcześniejszego slajdu „Klipy audio dzięki uprzejmości Te-Won Lee”. W filmie profesor Ng mówi:

„Więc możesz spojrzeć na takie uczenie się bez nadzoru i zapytać:„ Jak skomplikowane jest wdrożenie tego? ”. Wygląda na to, że aby zbudować tę aplikację, wydaje się, że trzeba przetworzyć dźwięk, napisać mnóstwo kodu lub może połączyć się z zestawem bibliotek C ++ lub Java, które przetwarzają dźwięk. Wygląda na to, że byłoby to naprawdę skomplikowany program do wykonania tego dźwięku: oddzielanie dźwięku itd. Okazuje się, że algorytm robi to, co właśnie usłyszałeś, co można zrobić za pomocą tylko jednej linii kodu ... pokazanego tutaj. Badaczom zajęło to dużo czasu aby wymyślić tę linię kodu. Nie twierdzę więc, że jest to łatwy problem. Ale okazuje się, że przy użyciu odpowiedniego środowiska programistycznego wiele algorytmów uczenia się będzie naprawdę krótkimi programami. "

Oddzielone wyniki dźwiękowe odtwarzane w wykładzie wideo nie są idealne, ale moim zdaniem niesamowite. Czy ktoś ma wgląd w to, jak ten jeden wiersz kodu działa tak dobrze? W szczególności, czy ktoś zna odniesienie, które wyjaśnia pracę Te-Wona Lee, Sama Roweisa, Yaira Weissa i Eero Simoncelli w odniesieniu do tej jednej linii kodu?

AKTUALIZACJA

Aby zademonstrować czułość algorytmu na odległość separacji mikrofonów, poniższa symulacja (w oktawie) oddziela tony z dwóch generatorów tonów oddzielonych przestrzennie.

% 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;

Po około 10 minutach wykonywania na moim laptopie symulacja generuje następujące trzy cyfry ilustrujące, że dwa izolowane tony mają prawidłowe częstotliwości.

Ryc.1 Rysunek 2 Rysunek 3

Jednak ustawienie odległości separacji mikrofonów na zero (tj. DMic = 0) powoduje, że symulacja zamiast tego generuje następujące trzy cyfry ilustrujące symulację, która nie mogła wyodrębnić drugiego tonu (potwierdzonego pojedynczym znaczącym składnikiem diagonalnym zwróconym w macierzy svd).

Rysunek 1 bez separacji mikrofonów Rysunek 2 bez separacji mikrofonów Rysunek 3 bez separacji mikrofonów

Miałem nadzieję, że odległość separacji mikrofonów w smartfonie byłaby wystarczająco duża, aby uzyskać dobre wyniki, ale ustawienie odległości separacji mikrofonów na 5,25 cala (tj. DMic = 0,1333 metra) powoduje, że symulacja generuje następujące, mniej niż zachęcające, liczby ilustrujące wyższe składowe częstotliwości w pierwszym izolowanym tonie.

Rysunek 1 na smartfonie Rysunek 2 na smartfonie Rysunek 3 na smartfonie

gregS
źródło
1
Mam niejasne wspomnienia z tego wykładu, ale nie pamiętam, co xjest; czy to spektrogram przebiegu, czy co?
Izaak
Profesor Ng, przy t = 5:30 we wprowadzającym wideo 4 dotyczącym uczenia się bez nadzoru, wydaje się sugerować, że x jest wektorem próbek audio. Być może ta sekcja repmat w argumencie svd implementuje jakiś rodzaj normalizacji mocy sygnału.
gregS

Odpowiedzi:

28

Ja też próbowałem to rozgryźć 2 lata później. Ale otrzymałem odpowiedzi; miejmy nadzieję, że to komuś pomoże.

Potrzebujesz 2 nagrań audio. Możesz pobrać przykłady audio z http://research.ics.aalto.fi/ica/cocktail/cocktail_en.cgi .

odniesienie do implementacji to http://www.cs.nyu.edu/~roweis/kica.html

ok, oto kod -

[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);

wprowadź opis obrazu tutaj

Jack Z
źródło
1
Czy jesteś w stanie znaleźć odniesienie, które wyjaśnia bardziej szczegółowo uzasadnienie tego wiersza kodu?
Hans
Czy mógłbyś wyjaśnić, jak działa miksowanie sygnałów w podanym łączu? Korzystając z kodu dobrze jest wyodrębnić dwa źródła dźwięku z dwóch mieszanych plików pobranych z witryny. Jednak gdy próbuję samodzielnie miksować dwa oddzielne sygnały, wydaje się, że algorytm nie może wygenerować prawidłowego wyniku. Używam naiwnego sposobu, aby uzyskać mieszane sygnały: mic1 = 0,3 * track1 + 0,5 * track2, mic2 = 0,5 * track1 + 0,3 * track2. To są sygnały, które próbowałem przekazać algorytmowi. Dziękuję Ci bardzo!
yc2986
Jestem trochę nowy w Matlab. Mam błędy w linii 3, mówiąc, że ma problem z konkatenacją 2 macierzy o różnych wymiarach. Jak mam sobie z tym poradzić?
mshrestha
1
Wypróbowałem ten kod, ale nie działa zbyt dobrze ... (nie
obwiniam
17

x(t) to oryginalny głos z jednego kanału / mikrofonu.

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'jest oszacowaniem widma mocy x(t). Chociaż X' = Xodstępy między wierszami i kolumnami wcale nie są takie same. Każdy wiersz przedstawia czas sygnału, a każda kolumna to częstotliwość. Myślę, że jest to oszacowanie i uproszczenie bardziej ścisłego wyrażenia zwanego spektrogramem .

Rozkład wartości osobliwych na spektrogramie służy do rozkładania sygnału na różne składowe na podstawie informacji o widmie. Wartości przekątne w ssą wielkościami różnych składników widma. Wiersze wi ukolumny w v'to wektory ortogonalne, które odwzorowują składową częstotliwości z odpowiednią wielkością w Xprzestrzeni.

Nie mam danych głosowych do przetestowania, ale w moim rozumieniu, za pomocą SVD, składowe mieszczą się w podobnych wektorach ortogonalnych, miejmy nadzieję, zostaną zgrupowane przy pomocy uczenia się bez nadzoru. Powiedzmy, że jeśli pierwsze 2 diagonalne wielkości z s są skupione, to u*s_new*v'utworzą jednoosobowy głos, gdzie s_newjest to samo, z swyjątkiem wszystkich elementów w (3:end,3:end).

Dwa artykuły na temat matrycy uformowanej dźwiękiem i SVD są w celach informacyjnych.

lennon310
źródło
1
gregS, matematycznie macierz x n-na-2 może nadal tworzyć X z operacją repmat. Jednak spektrogram może za każdym razem pokazywać tylko kanał. Myślę więc, że bardziej sensowne jest używanie za każdym razem n-1 x i traktowanie problemu jako regresji liniowej (dwa równania macierzowe). Inne dwa możliwe podejścia to (i) uśrednianie dwóch kanałów jako n-2 x; lub (ii) związanie ich razem w celu skonstruowania 2 * n-2 x.
lennon310
2
GregS, ponownie rozważyłem twoje pytanie. Może działać, jeśli zaimplementujesz repmat na n-na-2 x. Fizycznie można to postrzegać jako średnią moc z dwóch kanałów w każdym czasie i dla każdej częstotliwości.
lennon310,
Znalazłem ten post po obejrzeniu filmu wprowadzającego do uczenia maszynowego (kurs właśnie się wznowił). Zastanawiałem się, czy udało ci się odtworzyć separację audio pokazaną na wideo, czy też została opracowana podczas kursu.
siritinga
@siritinga proszę przeszukać publikację Andrew Ng dotyczącą nienadzorowanego / głębokiego uczenia się audio, dzięki
lennon310
1
Dlaczego $ X $ jest potęgą widma $ x $? Również zgodnie z odpowiedzią Jacka Z, $ x $ nie jest oryginalnym głosem z nagrania, ale pewnego rodzaju przetworzoną odwrotnością wartości własnej kowariancji głosu oryginalnego.
Hans