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.
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).
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.
x
jest; czy to spektrogram przebiegu, czy co?