Algorithme de cocktail Implémentation SVD… en une ligne de code?

88

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.

Figure 1 Figure 2 figure 3

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).

Figure 1 sans séparation de micro Figure 2 sans séparation de micro Figure 3 sans séparation de micro

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.

Figure 1 sur smartphone Figure 2 sur smartphone Figure 3 sur smartphone

gregS
la source
1
J'ai de vagues souvenirs de cette conférence, mais je ne me souviens pas de ce que xc'est; est-ce le spectrogramme de la forme d'onde, ou quoi?
Isaac
Le professeur Ng, à t = 5:30 dans la vidéo d'introduction 4 sur l'apprentissage non supervisé, semble suggérer que x est un vecteur des échantillons audio. Peut-être que la section repmat de l'argument svd met en œuvre une sorte de normalisation de puissance du signal.
gregS

Réponses:

28

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);

entrez la description de l'image ici

Jack Z
la source
1
Êtes-vous en mesure de trouver une référence qui explique plus explicitement la raison d'être de cette ligne de code?
Hans
Pourriez-vous s'il vous plaît expliquer comment fonctionne le mixage du signal dans le lien que vous avez fourni? En utilisant votre code, il est bon d'extraire deux sources sonores des deux fichiers mixtes téléchargés sur le site. Cependant, lorsque j'essaie de mélanger moi-même deux signaux séparés, il semble que l'algorithme ne puisse pas produire le résultat correct. J'utilise la manière naïve d'obtenir les signaux mixés: mic1 = 0,3 * piste1 + 0,5 * piste2, mic2 = 0,5 * piste1 + 0,3 * piste2. Ce sont les signaux que j'ai essayé de transmettre à l'algorithme. Merci beaucoup!
yc2986
Je suis un peu nouveau sur Matlab. J'ai des erreurs à la ligne 3 en disant qu'il a du mal à concaténer 2 matrices de dimensions différentes. Comment dois-je gérer ce problème?
mshrestha
1
J'ai essayé ce code mais cela ne fonctionne pas très bien ... (ne vous blâme pas !!)
compris le
17

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 de x(t). Cependant 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 .

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 ssont la grandeur des différentes composantes du spectre. Les lignes uet les colonnes de v'sont les vecteurs orthogonaux qui mappent la composante de fréquence avec l'amplitude correspondante à l' Xespace.

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_newest la même chose ssauf 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.

lennon310
la source
1
gregS, mathématiquement une matrice n-par-2 x peut encore former un X avec l'opération repmat. Cependant, le spectrogramme ne peut afficher que le canal à chaque fois. Je pense donc qu'il est plus logique d'utiliser n-par-1 x à chaque fois et de traiter le problème comme une régression linéaire (deux équations matricielles). Deux autres approches possibles sont (i) la moyenne de deux canaux comme n-par-2 x; ou (ii) les lier ensemble pour construire un 2 * n-par-2 x.
lennon310
2
GregS, j'ai reconsidéré votre question. Cela peut fonctionner si vous implémentez repmat sur un x n-par-2. Physiquement, il peut être considéré comme une moyenne de la puissance de deux canaux à chaque fois et chaque fréquence.
lennon310
J'ai trouvé cet article après avoir regardé la vidéo d'introduction de Machine Learning (le cours vient de recommencer). Je me demandais si vous aviez réussi à reproduire la séparation audio montrée dans la vidéo, ou si elle avait été développée pendant le cours.
siritinga
@siritinga, veuillez rechercher la publication d'Andrew Ng sur l'apprentissage non supervisé / profond sur l'audio, merci
lennon310
1
Pourquoi $ X $ est-il la puissance du spectre de $ x $? Toujours selon la réponse de Jack Z, $ x $ n'est pas la voix originale de l'enregistrement mais une sorte de réciproque traitée de la valeur propre de la covariance de la voix originale.
Hans