[Matlab] cocktail party algorithme SVD mise en œuvre ... dans une ligne de code?


Answers

x(t) est la voix d'origine d'un canal / microphone.

X = repmat(sum(x.*x,1),size(x,1),1).*x)*x' est une estimation du spectre de puissance de x(t) . Bien que X' = 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 .

Valeur singulière La décomposition sur spectrogramme est utilisée pour factoriser le signal en différents composants en fonction des informations spectrales. Les valeurs diagonales dans s sont l'amplitude des différentes composantes du spectre. Les lignes en u et les colonnes en v' sont les vecteurs orthogonaux qui mappent la composante de fréquence avec la grandeur correspondante à l'espace X

Je n'ai pas de données vocales à tester, mais à ma connaissance, au moyen de SVD, les composants qui tombent dans les vecteurs orthogonaux similaires sont, espérons-le, regroupés à l'aide d'un apprentissage non supervisé. Dites, si les 2 premières grandeurs diagonales de s sont groupées, alors u*s_new*v' formera la voix d'une personne, où s_new est la même que s sauf tous les éléments de (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.

Question

Dans une diapositive dans la conférence d'introduction à l'apprentissage automatique par Andrew Ng de Stanford à Coursera, il donne la solution suivante d'une ligne Octave 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 est "source: Sam Roweis, Yair Weiss, Eero Simoncelli" et au bas d'une diapositive précédente est "clips audio avec l'aimable autorisation de Te-Won Lee". Dans la vidéo, le professeur Ng dit,

"Donc, vous pourriez regarder un apprentissage non supervisé comme celui-ci et demander,« Comment est-il compliqué de mettre en œuvre cela? Il semble que pour créer cette application, il semble que ce soit un traitement audio, que vous écrivez une tonne de code, ou que vous vous connectiez à un tas de bibliothèques C ++ ou Java qui traitent l'audio. 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, ce qui peut être fait avec une seule ligne de code ... montré ici.Il a fallu longtemps aux chercheurs 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 très courts.

Les résultats audio séparés joués dans la conférence vidéo ne sont pas parfaits mais, à mon avis, étonnants. Est-ce que quelqu'un a un aperçu de la façon dont cette ligne de code fonctionne si bien? En particulier, quelqu'un connaît-il une référence qui explique le travail de Te-Won Lee, de Sam Roweis, de Yair Weiss et d'Eero Simoncelli par rapport à cette ligne de code?

METTRE À JOUR

Pour démontrer la sensibilité de l'algorithme à la distance de séparation du microphone, la simulation suivante (en octave) sépare les sons de deux générateurs de sons séparés spatialement.

% 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 figures suivantes illustrant les deux sons isolés ayant les bonnes fréquences.

Cependant, la mise à zéro de la distance de séparation du microphone (c.-à-d. DMic = 0) génère 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 assez grande pour produire de bons résultats, mais en réglant la distance de séparation du microphone à 5,25 pouces (dMic = 0,1333 mètres), la simulation générerait les chiffres suivants, moins encourageants. composants de fréquence dans le premier ton isolé.