CourseraのStanfordのAndrew Ngによる機械学習の入門講義内のスライドでは、空間的に分離された2つのマイクでオーディオソースが録音されていることから、カクテルパーティーの問題に対する次の1行のOctaveソリューションを紹介します。
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');
スライドの下部にあるのは「ソース:サム・ロワイス、ヤー・ワイス、エーロ・シモンチェリ」であり、以前のスライドの下部にあるのは「テ・ウォン・リーの好意によるオーディオクリップ」です。 Ng教授はビデオで次のように述べています。
「だから、このような教師なし学習を見て、「これを実装するのはどれくらい複雑か?」このアプリケーションを構築するために、このオーディオ処理を行うように思われます。大量のコードを記述するか、C++の束にリンクするか、オーディオを処理するJavaライブラリこのオーディオを実行するのは本当に複雑なプログラムのようです。オーディオを分離するなど、今聞いたとおりに実行するアルゴリズムが判明しました。このコード行を見つけるのに研究者は長い時間がかかったので、これは簡単な問題とは言いませんが、適切なプログラミング環境を使用すると、多くの学習アルゴリズムが本当に短いプログラムになることがわかります」
ビデオ講義で再生された分離されたオーディオ結果は完璧ではありませんが、私の意見では驚くべきものです。その1行のコードがどのようにうまく機能するかについての洞察はありますか?特に、その1行のコードに関して、Te-Won Lee、Sam Roweis、Yair Weiss、Eero Simoncelliの作業を説明するリファレンスを知っている人はいますか?
[〜#〜] update [〜#〜]
マイクの分離距離に対するアルゴリズムの感度を示すために、次のシミュレーション(オクターブで)は、2つの空間的に分離されたトーンジェネレーターからトーンを分離します。
% 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分間実行した後、シミュレーションにより、2つの分離されたトーンの周波数が正しいことを示す次の3つの図が生成されます。
ただし、マイクの分離距離をゼロに設定すると(つまり、dMic = 0)、シミュレーションは代わりに次の3つの図を生成し、シミュレーションは2番目のトーンを分離できなかったことを示します(svdの行列で返される単一の有意な対角項によって確認されます)。
スマートフォンのマイク分離距離が十分な大きさで良好な結果が得られることを期待していましたが、マイク分離距離を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)
は、1つのチャンネル/マイクからの元の音声です。
X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'
は、x(t)
のパワースペクトルの推定値です。 _X' = X
_ですが、行と列の間隔はまったく同じではありません。各行は信号の時間を表し、各列は周波数です。これは spectrogram と呼ばれるより厳密な式の推定と単純化だと思います。
特異値分解 スペクトログラムは、スペクトル情報に基づいて信号をさまざまな成分に分解するために使用されます。 s
の対角値は、さまざまなスペクトル成分の大きさです。 u
の行と_v'
_の列は、対応する大きさの周波数成分をX
空間にマッピングする直交ベクトルです。
私はテストする音声データを持っていませんが、私の理解では、SVDによって、コンポーネントは類似の直交ベクトルに分類され、教師なし学習の助けを借りてクラスタ化されることを願っています。 sの最初の2つの斜めの大きさがクラスター化されている場合、_u*s_new*v'
_は1人の声を形成します。ここで_s_new
_はs
と同じですが、_(3:end,3:end)
_は削除されます。
sound-formed matrix と [〜#〜] svd [〜#〜] についての2つの記事は参考用です。