Bağımsız Bileşen Analizi
Bir kokteyl partisindesiniz ve aynı anda birden çok kişi konuşuyor. Yani birden çok kaynaktan ses geliyor. $N$ kişi konuşuyor olsun. Siz de odanın değişik yerlerine $N$ tane mikrofon koyup kayıt almış olun. Bu kayıtların hepsi muhakkak ki kaynaklardan çıkan seslerin doğrusal bileşimlerinden oluşuyor olacaklar. Kaynakları görmüyorsunuz fakat bileşimlerini görüyorsunuz, ya da duyuyorsunuz. Kör kaynak problemi denilen bu problem için bir yöntemimiz var!
Bu yazıda bağımsız bileşenler analizi (ICA – independent component analysis) ile bu kaynakları nasıl elde edeceğimize bakalım.
Öncelikle basit sinyaller ile işe başlayalım:
# -*- coding: utf-8 -*- import numpy as np import pylab as plt from sklearn.decomposition import FastICA # Örnek veriyi üretelim np.random.seed(0) nSamples = 1000 time = np.linspace(0, 10, nSamples) s1 = np.sin(2 * time) # Sinyal 1 : sinüsoid s2 = np.sign(np.sin(3 * time)) # Sinyal 2 : kare dalga S = np.c_[s1, s2] S += 0.1 * np.random.normal(size=S.shape) # Gürültü ekle S /= S.std(axis=0) # Düzgele
Şimdi sinyalleri karıştıralım ve sonuçları ICA ile ayrıştıralım:
A = np.array([[1, 1], [0.8, 2]]) # Karışım matrisi X = np.dot(S, A.T) # Gözlemleri oluştur # ICA hesapla ica = FastICA() S_ = ica.fit(X).transform(X) # Kaynakları tahmin et A_ = ica.get_mixing_matrix() # Karışım matrisini tahmin et assert np.allclose(X, np.dot(S_, A_.T))
Ve sonuçlara bakalım:
plt.figure()
ax1 = plt.subplot(3, 1, 1)
plt.plot(S)
plt.title(u'Gerçek Kaynaklar')
plt.setp(ax1.get_xticklabels(), visible=False)
ax2 = plt.subplot(3, 1, 2, sharex=ax1)
plt.plot(X)
plt.title(u'Gözlemler (karışım sinyali)')
plt.setp(ax2.get_xticklabels(), visible=False)
plt.subplot(3, 1, 3, sharex=ax1)
plt.plot(S_)
plt.title(u'ICA tarafından bulunan kaynaklar')
plt.savefig('ica.png')

Bulunan sinyaller doğru. Fakat sıraları ve ölçekleri bilinemiyor. Yeşil renkle çizilen kare dalganın ters yönde çıkması da bu ölçek katsayısı ile ilgili. Negatif bir sayıyla çarparsanız özgün halinde olduğu gibi ters çıkacaktır.
Şimdi daha güzel bir örnek üstünde bakalım. Büyük usta Kemal Sunal’ın iki ses kaydını alalım:
Bunları önceden aynı boyuta getirmiştim.
Sonra onları karıştıralım ve yeni sinyaller elde edelim:
İki sinyalde de iki ses karışmış. İşimiz zor gibi. Haydi, ICA ile gözlemler üstünden kaynakları tahmin edelim:
Bunlar için alttaki kodu kullanabilirsiniz:
import numpy as np
from sklearn.decomposition import FastICA
from scipy.io.wavfile import read, write
Fs, s1 = read('kibarfeyzo.wav')
Fs, s2 = read('gunah.wav')
nSamples = len(s1)
assert len(s1) == len(s2)
s1 = np.float32(s1)
s2 = np.float32(s2)
S = np.c_[s1, s2]
A = np.array([[1, 0.8], [1, 2]]) # Karışım matrisi
X = np.dot(S, A) # Gözlemleri üret
ica = FastICA()
S_ = ica.fit(X).transform(X) # Kaynakları tahmin et
x1, x2 = X[:,0], X[:,1]
x1 = x1 / np.max(np.abs(x1)) * 255
x2 = x2 / np.max(np.abs(x2)) * 255
write('x1.wav', Fs, np.uint8(x1))
write('x2.wav', Fs, np.uint8(x2))
s1, s2 = S_[:,0], S_[:,1]
s1 = s1 / np.max(np.abs(s1)) * 255
s2 = s2 / np.max(np.abs(s2)) * 255
write('s1.wav', Fs, np.uint8(s1))
write('s2.wav', Fs, np.uint8(s2))


2 yorum
Selam İsmail, bu harika bir işlemmiş yahu. Sağolasın haberdar ettiğin için.
Bağımsız Bileşenler Analizi’ni stereo bir ses kaydının iki kanalına uygularsak ne olur peki? Laylay…
Rica ederim Uğur :) Eğer kanallar arasında fark varsa 2 bağımsız bileşene ayıracaktır. Deneyip bakmak lazım.