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

 mobiledu2502862441 发布于 2023-02-12 15:36

在Stanford的Andrew Ng在Coursera的机器学习入门讲座中的一篇幻灯片中,他给出了以下一行Octave解决方案,因为音频源由两个空间分离的麦克风录制:

[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的工作的参考资料?

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

图1 图2 图3

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

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

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

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

2 个回答
  • 2年后我也想弄明白这一点.但我得到了答案; 希望它能帮到某个人.

    你需要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);
    

    在此输入图像描述

    2023-02-12 15:37 回答
  • 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的两篇文章供您参考.

    2023-02-12 15:38 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有