Алгоритм коктейльной партии SVD-реализация... в одной строке кода?

В слайде в вводной лекции по компьютерному обучению Стэнфорда Эндрю Нг в Coursera он дает следующее однострочное решение Octave для проблемы с коктейлем, учитывая, что аудиоисточники записываются двумя пространственно разделенными микрофонами:

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

В нижней части слайда находится "источник: Сэм Роуис, Яир Вайс, Ээро Симончелли", а внизу слайда - "Аудиоклипы, любезно предоставленные Те-Вон Ли". Профессор Нг в видео говорит:

"Итак, вы можете посмотреть на неконтролируемое обучение, подобное этому, и спросить:" Насколько сложно реализовать это? "Похоже, что для создания этого приложения кажется, что нужно сделать эту обработку звука, вы бы написали тонну кода или, возможно, ссылку на кучу С++ или Java-библиотек, обрабатывающих аудио. Похоже, это было бы действительно сложная программа для этого аудио: отключение звука и т.д. Оказывается, алгоритм делает то, что вы только что слышали, что может быть сделано только с одной строкой кода... показано здесь. чтобы придумать эту строку кода, поэтому я не говорю, что это непростая задача. Но оказывается, что при использовании правильной среды программирования многие алгоритмы обучения будут действительно короткими программами".

Разделенные звуковые результаты, воспроизводимые в лекции, не идеальны, но, на мой взгляд, потрясающие. У кого-нибудь есть представление о том, как эта одна строка кода работает так хорошо? В частности, кто-нибудь знает ссылку, которая объясняет работу Те-Вона Ли, Сэма Роуиса, Яира Вайса и Ээро Симончелли относительно этой одной строки кода?

UPDATE

Чтобы продемонстрировать чувствительность алгоритма к расстоянию разделения микрофона, следующее моделирование (в Octave) разделяет тональные сигналы от двух пространственно разделенных генераторов тона.

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

Примерно через 10 минут выполнения на моем ноутбуке симуляция генерирует следующие три цифры, иллюстрирующие два изолированных тона, которые имеют правильные частоты.

Figure 1Figure 2Figure 3

Однако установка расстояния разделения микрофона до нуля (т.е. dMic = 0) заставляет симуляцию вместо этого генерировать следующие три цифры, иллюстрирующие симуляцию, не может изолировать второй тон (подтвержденный одним значительным диагональным термином, возвращаемым в svd s матрица).

Figure 1 with no mic separationFigure 2 with no mic separationFigure 3 with no mic separation

Я надеялся, что расстояние для ветки микрофона на смартфоне будет достаточно большим для получения хороших результатов, но установление расстояния разделения микрофона до 5,25 дюймов (т.е. dMic = 0,1333 м) заставляет моделирование генерировать следующие, менее обнадеживающие, цифры, иллюстрирующие компоненты более высокой частоты в первом изолированном тоне.

Figure 1 on smartphoneFigure 2 on smartphoneFigure 3 on smartphone

Ответ 1

Я тоже пытался понять это, 2 года спустя. Но я получил ответы; надеюсь, это поможет кому-то.

Вам нужно 2 аудиозаписи. Вы можете получить примеры аудио из http://research.ics.aalto.fi/ica/cocktail/cocktail_en.cgi.

ссылка для реализации http://www.cs.nyu.edu/~roweis/kica.html

ok, здесь код -

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

введите описание изображения здесь

Ответ 2

x(t) - это оригинальный голос с одного канала/микрофона.

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x' - оценка спектра мощности x(t). Хотя X' = X, интервалы между строками и столбцами не совпадают. Каждая строка представляет время сигнала, в то время как каждый столбец является частотой. Я предполагаю, что это оценка и упрощение более строгого выражения, называемого spectrogram.

Разложение сингулярного значения на спектрограмме используется для факторизации сигнала на разные компоненты на основе информации о спектре. Диагональные значения в s - это величина различных компонентов спектра. Строки в u и столбцы в v' являются ортогональными векторами, которые отображают частотную составляющую с соответствующей величиной в пространство X.

У меня нет голосовых данных для тестирования, но, по моему мнению, с помощью SVD компоненты попадают в аналогичные ортогональные векторы, мы надеемся, будем кластеризоваться с помощью неконтролируемого обучения. Скажем, если сгруппированы первые две диагональные величины из s, то u*s_new*v' образует голос одного человека, где s_new совпадает с s, за исключением того, что все элементы в (3:end,3:end) устранены.

Две статьи о звуковой матрице и SVD для вашей справки.