Dans une diapositive de la conférence d'introduction sur l'apprentissage automatique par Andrew Ng de Stanford à Coursera, il donne la solution Octave en une ligne suivante au problème du cocktail, étant donné que les sources audio sont enregistrées par deux microphones spatialement séparés:
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');
Au bas de la diapositive se trouve «source: Sam Roweis, Yair Weiss, Eero Simoncelli» et au bas d'une diapositive précédente se trouve «Extraits audio avec l'aimable autorisation de Te-Won Lee». Dans la vidéo, le professeur Ng dit:
«Vous pourriez donc examiner un apprentissage non supervisé comme celui-ci et vous demander:« À quel point est-ce compliqué de le mettre en œuvre? Il semble que pour construire cette application, il semble que vous fassiez ce traitement audio, vous écririez une tonne de code, ou peut-être vous lieriez à un tas de bibliothèques C ++ ou Java qui traitent l'audio. Il semble que ce serait vraiment un programme compliqué pour faire cet audio: séparer l'audio et ainsi de suite. Il s'avère que l'algorithme fait ce que vous venez d'entendre, cela peut être fait avec une seule ligne de code ... montré ici. Cela a pris beaucoup de temps aux chercheurs pour trouver cette ligne de code. Donc je ne dis pas que c'est un problème facile. Mais il s'avère que lorsque vous utilisez le bon environnement de programmation, de nombreux algorithmes d'apprentissage seront des programmes vraiment courts. "
Les résultats audio séparés joués dans la conférence vidéo ne sont pas parfaits mais, à mon avis, étonnants. Quelqu'un a-t-il un aperçu de la façon dont cette ligne de code fonctionne si bien? En particulier, est-ce que quelqu'un connaît une référence qui explique le travail de Te-Won Lee, Sam Roweis, Yair Weiss et Eero Simoncelli par rapport à cette seule ligne de code?
MISE À JOUR
Pour démontrer la sensibilité de l'algorithme à la distance de séparation du microphone, la simulation suivante (en octave) sépare les tonalités de deux générateurs de sons spatialement séparés.
% 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;
Après environ 10 minutes d'exécution sur mon ordinateur portable, la simulation génère les trois chiffres suivants illustrant que les deux tonalités isolées ont les fréquences correctes.
Cependant, régler la distance de séparation du microphone à zéro (c'est-à-dire dMic = 0) amène la simulation à générer à la place les trois chiffres suivants illustrant que la simulation n'a pas pu isoler une deuxième tonalité (confirmée par le seul terme diagonal significatif renvoyé dans la matrice de svd).
J'espérais que la distance de séparation du microphone sur un smartphone serait suffisamment grande pour produire de bons résultats, mais en réglant la distance de séparation du microphone sur 5,25 pouces (c'est-à-dire dMic = 0,1333 mètre), la simulation génère les chiffres suivants, moins qu'encourageants, illustrant plus haut composantes de fréquence dans la première tonalité isolée.
x
c'est; est-ce le spectrogramme de la forme d'onde, ou quoi?Réponses:
J'essayais de comprendre cela aussi, 2 ans plus tard. Mais j'ai eu mes réponses; j'espère que cela aidera quelqu'un.
Vous avez besoin de 2 enregistrements audio. Vous pouvez obtenir des exemples audio sur http://research.ics.aalto.fi/ica/cocktail/cocktail_en.cgi .
la référence pour la mise en œuvre est http://www.cs.nyu.edu/~roweis/kica.html
ok, voici le code -
[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);
la source
x(t)
est la voix originale d'un canal / microphone.X = repmat(sum(x.*x,1),size(x,1),1).*x)*x'
est une estimation du spectre de puissance dex(t)
. CependantX' = X
, les intervalles entre les lignes et les colonnes ne sont pas du tout les mêmes. Chaque ligne représente l'heure du signal, tandis que chaque colonne est la fréquence. Je suppose que c'est une estimation et une simplification d'une expression plus stricte appelée spectrogramme .La décomposition en valeurs singulières sur spectrogramme est utilisée pour factoriser le signal en différentes composantes en fonction des informations de spectre. Les valeurs diagonales en
s
sont la grandeur des différentes composantes du spectre. Les lignesu
et les colonnes dev'
sont les vecteurs orthogonaux qui mappent la composante de fréquence avec l'amplitude correspondante à l'X
espace.Je n'ai pas de données vocales à tester, mais d'après ce que je comprends, au moyen de SVD, les composants tombent dans les vecteurs orthogonaux similaires et, espérons-le, seront regroupés à l'aide d'un apprentissage non supervisé. Disons que si les 2 premières grandeurs diagonales de s sont regroupées, alors
u*s_new*v'
formera la voix d'une personne, oùs_new
est la même choses
sauf que tous les éléments à(3:end,3:end)
sont éliminés.Deux articles sur la matrice formée par le son et SVD sont pour votre référence.
la source