首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >鸡尾酒会算法SVD实现..。在一行代码中?

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

Stack Overflow用户
提问于 2013-12-06 02:11:10
回答 2查看 45K关注 0票数 91

在斯坦福大学(Stanford)的安德鲁·吴( Andrew Ng )在Cour何时举办的关于机器学习的开场白中,他给出了关于鸡尾酒会问题的以下一行八度解决方案,因为音频源是由两个空间分隔的麦克风记录的:

代码语言:javascript
复制
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');

在幻灯片的底部是“来源:山姆·罗威斯,耶尔·维斯,埃罗·西蒙塞利”,而前面幻灯片的底部是“李德元提供的音频剪辑”。吴教授在视频中说,

“因此,你可能会看到这样的无监督学习,并问,‘实现这是多么复杂?’看起来,为了构建这个应用程序,似乎要进行音频处理,您需要编写大量的代码,或者链接到一堆处理音频的C++或Java库。这似乎是一个非常复杂的程序来做这个音频:分离出音频,等等。结果就是你刚才听到的算法,只需一行代码就可以完成.就在这里。研究人员花了很长时间才想出这一行代码。所以我不是说这是个容易的问题。但事实证明,当你使用正确的编程环境时,许多学习算法实际上都是很短的程序。“

视频讲座中分开播放的音频结果并不完美,但在我看来,令人惊讶。有谁对这一行代码的性能有任何洞察力吗?尤其是,有没有人知道有什么参考资料可以解释李德元、罗威斯、魏斯和埃罗·西蒙塞利关于这一行代码的工作?

更新

为了证明该算法对麦克风分离距离的敏感性,下面的仿真(以八度为单位)将音调从两个空间分离的音调发生器中分离出来。

代码语言:javascript
复制
% 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矩阵中返回的单个显着对角线项确认)。

我希望智能手机上的麦克风分离距离足够大,可以产生良好的效果,但是将麦克风的分离距离设置为5.25英寸(即dMic = 0.1333米)会导致模拟生成下面的图,而不是鼓舞人心的,这些数字说明了第一个孤立音调中的高频成分。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-09 19:39:59

两年后我也在努力想办法解决这个问题。但我得到了答案,希望它能帮助到别人。

你需要两张录音。您可以从en.cgi获得音频示例。

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

好吧,这是密码-

代码语言:javascript
复制
[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);

票数 31
EN

Stack Overflow用户

发布于 2013-12-06 19:29:25

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

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'是对x(t)功率谱的估计。尽管是X' = X,但行和列之间的间隔一点也不相同。每一行代表信号的时间,而每一列都是频率。我想这是对一个更严格的表达式spectrogram的估计和简化。

利用谱图上的Singular Value Decomposition对信号进行分解,根据光谱信息将信号分解成不同的分量。s中的对角线值是不同光谱分量的大小。u中的行和v'中的列是正交向量,它们将具有相应幅度的频率分量映射到X空间。

我没有语音数据可供测试,但据我所知,通过SVD,这些分量属于相似的正交向量,希望借助无监督学习进行聚类。比方说,如果s的前2个对角线震级是聚在一起的,那么u*s_new*v'将形成一个人的声音,其中s_news是相同的,除了(3:end,3:end)的所有元素都被消除了。

关于sound-formed matrixSVD的两篇文章供您参考。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20414667

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档