В слайде в вводной лекции по компьютерному обучению Стэнфорда Эндрю Нг в 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 минут выполнения на моем ноутбуке симуляция генерирует следующие три цифры, иллюстрирующие два изолированных тона, которые имеют правильные частоты.
Однако установка расстояния разделения микрофона до нуля (т.е. dMic = 0) заставляет симуляцию вместо этого генерировать следующие три цифры, иллюстрирующие симуляцию, не может изолировать второй тон (подтвержденный одним значительным диагональным термином, возвращаемым в svd s матрица).
Я надеялся, что расстояние для ветки микрофона на смартфоне будет достаточно большим для получения хороших результатов, но установление расстояния разделения микрофона до 5,25 дюймов (т.е. dMic = 0,1333 м) заставляет моделирование генерировать следующие, менее обнадеживающие, цифры, иллюстрирующие компоненты более высокой частоты в первом изолированном тоне.
Я тоже пытался понять это, 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);
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 для вашей справки.
x
; это спектрограмма сигнала или как?