鸡尾酒会算法SVD实现…在一行代码中?


88

在斯坦福大学的Andrew Ng在Coursera的机器学习入门演讲的幻灯片中,他给出了鸡尾酒会问题的以下一行八度音阶解决方案,因为音频源是由两个空间分开的麦克风录制的:

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

幻灯片的底部是“来源:Sam Roweis,Yair Weiss和Eero Simoncelli”,幻灯片的底部是“由Te-Won Lee提供的音频剪辑”。吴教授在影片中说:

“因此,您可能会看这样的无监督学习,并问,'实施此过程有多复杂?” 似乎要构建此应用程序,似乎要进行音频处理,您将编写大量代码,或者链接到处理音频的一堆C ++或Java库中。处理音频的复杂程序:分离音频等,结果证明该算法可以完成您刚刚听到的操作,只需一行代码即可完成……如此处所示,这花费了研究人员很长时间因此,我并不是说这是一个简单的问题。但是事实证明,当您使用正确的编程环境时,许多学习算法实际上都是很短的程序。”

在视频讲座中播放的单独音频结果并不完美,但在我看来,这是惊人的。有人对那一行代码的性能有何见解?特别是,没有人知道参考文献来解释Te-Won Lee,Sam Roweis,Yair Weiss和Eero Simoncelli在那一行代码方面的工作吗?

更新

为了证明算法对麦克风分离距离的敏感性,下面的模拟(以八度为单位)将音调与两个空间分离的音调发生器分离。

% 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分钟后,模拟生成以下三个图形,说明两个隔离的音调具有正确的频率。

图1 图2 图3

但是,将麦克风的分离距离设置为零(即dMic = 0)会使模拟生成以下三个图形,这些图形说明模拟无法隔离第二个音调(由svd矩阵中返回的单个有效对角线项确认)。

图1没有麦克风分离 图2没有麦克风分离 图3没有麦克风分离

我希望智能手机上的麦克风间距足够大,以产生良好的效果,但是将麦克风间距设置为5.25英寸(即dMic = 0.1333米)会导致模拟产生以下结果,但不令人鼓舞,这些数字说明了第一隔离音中的频率分量。

智能手机上的图1 智能手机上的图2 智能手机上的图3


1
我对这次演讲记忆犹新,但不记得是什么x。是波形的频谱图,还是什么?
艾萨克(Isaac)2013年

Ng教授在无监督学习的入门视频4中的t = 5:30时似乎暗示x是音频样本的向量。也许svd参数中的repmat部分正在实现信号的某种功率归一化。
gregS 2013年

Answers:


28

两年后,我也试图弄清楚这一点。但是我得到了答案。希望它将对某人有所帮助。

您需要2录音。您可以从http://research.ics.aalto.fi/ica/cocktail/cocktail_en.cgi获得音频示例。

实施参考是http://www.cs.nyu.edu/~roweis/kica.html

好的,这是代码-

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

在此处输入图片说明


1
您是否能够找到可以更明确地说明该代码行原理的参考?
汉斯(Hans)

您能否解释一下您提供的链接中信号混合的工作原理?使用您的代码,最好从网站上下载的两个混合文件中提取两个声音源。但是,当我尝试自己将两个单独的信号混合在一起时,似乎该算法无法输出正确的结果。我正在使用幼稚的方式来获得混合信号:mic1 = 0.3 * track1 + 0.5 * track2,mic2 = 0.5 * track1 + 0.3 * track2。这些是我尝试提供给算法的信号。非常感谢你!
yc2986 '16

我对Matlab有点陌生。我在第3行出现错误,说在连接2个不同维度的矩阵时遇到问题。我应该如何处理这个问题?
mshrestha

1
我尝试了该代码,但效果不佳...(不

17

x(t) 是来自一个通道/麦克风的原始声音。

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'是对的功率谱的估计x(t)。尽管X' = X,行和列之间的间隔根本不相同。每行代表信号的时间,而每列代表频率。我想这是对称为光谱图的更严格表达的估计和简化。

频谱图上的奇异值分解用于根据频谱信息将信号分解为不同的分量。对角线值s是不同频谱分量的大小。中的行u和中的列v'是正交向量,这些向量将频率分量和相应的幅度映射到X空间。

我没有要测试的语音数据,但据我了解,借助SVD,希望将落入相似正交向量中的分量在无监督学习的帮助下进行聚类。假设如果将s的前2个对角线幅度进行聚类,u*s_new*v'则将形成一个人声,其中除的所有元素都s_new相同。s(3:end,3:end)

有关声矩阵SVD的两篇文章供您参考。


1
gregS,在数学上,n乘2的矩阵x仍然可以通过repmat操作形成X。但是,频谱图每次只能显示频道。因此,我认为每次使用n-by-1 x并将该问题视为线性回归(两个矩阵方程式)更有意义。另两种可能的方法是(i)将两个通道平均为n-by-2 x;或(ii)将它们结合在一起以构建2 * n×2 x。
lennon310 2013年

2
格雷格斯,我重新考虑了你的问题。如果在n x 2 x上实现repmat,则可能会起作用。从物理上讲,它可以看作是每个时间和每个频率来自两个通道的平均功率。
lennon310 2013年

我在观看机器学习的介绍视频后才找到这篇文章(该课程刚刚再次开始)。我想知道您是否能够再现视频中显示的音频分离,还是在课程中开发的。
siritinga 2014年

@siritinga,请搜索Andrew Ng关于音频的无监督/深度学习的出版物,谢谢
lennon310

1
为什么$ X $具有$ x $频谱的功效?同样根据Jack Z的回答,$ x $不是录音中的原始语音,而是原始语音协方差特征值的某种处理后的倒数。
汉斯(Hans)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.