线性独立成分分析(ICA)与鸡尾酒会问题
2019獨角獸企業重金招聘Python工程師標準>>>
對于雞尾酒會問題,一種簡單的情況如下:有n個人在同時說話,同時又m個聲音接收器捕捉到了信號之間的線性組合,于是我們可以得到m組聲音數據。那么,如何利用這m組接收到的聲音信號恢復成原來的n組獨立信號呢?
在上個世紀末,雞尾酒會問題催生了各種盲源分離問題,也有不少機器學習算法被應用于此問題。其中,獨立成分分析是簡便且有效的一種。
##問題分析 設原始信號為S1、S2、...、Sn,一定存在一個mn的權重矩陣A,使得每個聲音接收器對應A中一行。如m=n=2時,令A=[[0.6, 0.4], [0.45, 0.55]],則第一個麥克風接收到的信號為x1=0.6S1+0.4S2,第二個麥克風接收到的信號為x2=0.45S1+0.55S2。即$$AS=x$$ 將該公式左右同乘以A的逆矩陣$$W=A^{-1}$$,得$$A^{-1}AS=A^{-1}x$$,即$$S=Wx$$,這樣問題就解決了(當m≠n時,A不是方陣,此時可以乘A的偽逆)。于是問題來了:如何求A的逆矩陣W?
##獨立成分分析(Independent Component Analysis) ICA算法始于Bell和Sejnowski,下面用極大似然估計簡單推導一下ICA的求解過程:
###引理:已知x的概率分布$$f_{x}(x)$$,若$$Y=Ax$$,則對其累積分布函數有$$F_{Y}(y)=P{Y\leq y}=P{Ax\leq y}=P{x\leq y/A}=F_{X}(y/A)$$。求導得$$f_{Y}(y)=frac{f_{X}(x/A)}{|A|}$$。
每個信號源$$S_{i}$$都有其概率密度$$p_{i}(s)$$,在第j時刻,向量s的聯合概率密度為$p(s_{j})=\prod_{i=1}^{n} p_{i}(s_{i,j})$。通過引理,我們可以將該式轉化為$$L(x_{j})=|W|p_{i}(Wx_{j})=|W|\prod_{i=1}^{n} p_{i}(w_{i}^{T}x_{j})$$。 于是可以得到似然函數$$L(x)=\prod_{j=1}^{m} p(x_{j})=\prod_{j=1}^{m} [|W|\prod_{i=1}^{n} p_{i}(w_{i}^{T}x_{j})]$$ 現在似然函數還是個連乘的形式,不便計算。我們將其取對數,得到對數似然函數$$l(x)=\sum_{j=1}^{m} [\sum_{i=1}^{n} ln p_{i}(w_{i}^{T}x_{j}) + ln|W|]$$ 這種形式的似然函數就可以當做我們的成本函數cost function了,即$$J(W)=\sum_{j=1}^{m} [\sum_{i=1}^{n} ln p_{i}(w_{i}^{T}x_{j}) + ln|W|]$$ 但是,式中的$$p_{i}$$,即先驗概率$$p(s)$$是未知的,但是我們可以假定它服從某種已知的分布。一般的,我們可以假設$$p(s)$$的累積分布函數$$F(s)$$是sigmoid函數。當然了,假設它們服從正態分布(erf函數),甚至可以使用tanh、arctan當做s的累積分布函數,這些先驗假設都是可行的。 以sigmoid函數為例,令$$g(s)=frac{1}{1+e^{-s}}$$,易知$$g'(s)=g(s)(1-g(s))$$、$$g''(s)=g'(s)(1-2g(s))$$。帶入對數似然函數得$$J(W)=\sum_{i=1}^{m}[\sum_{j=1}^{n} ln g'(wx) + ln|W|]$$。 將對數似然函數對$$W$$求偏導,得$$\frac{\partial J(W)}{\partial W}=[1-2g(Wx)]x + (W^{-1})^{T}$$。 到了這一步,相信大家已經知道下面怎么做了:梯度上升到最大值,求出此時的$$W$$即可。也就是$$W += \alpha * (1-2g(W*x) + (W^{-1})^{T})$$。這時候一般梯度上升、隨機梯度上升和mini-batch算法就可以派上用場了。 用python實現出來的代碼如下:
def sigmoid(x):return 1.0 / (1 + np.exp(-x))def ica(x):# x = np.array(x)n = len(x[0])m = len(x)w = np.eye(n)iw = np.zeros([n, n])w1 = np.zeros([n, n])alpha = 0.001for time in range(200):for i in range(m):for j in range(n):# 使用sigmoid函數作為CDFt = 1 - 2 * sigmoid(np.dot(w[j], x[i]))w1[j] = t * x[i]# 使用arctan函數作為CDF# t = -2 * np.dot(w[j], x[i]) / (1 + np.dot(w[j] ** 2, x[i] ** 2)) # w1[j] = t * x[i]# 使用tanh函數作為CDF# t = -2 * x[i] * np.tanh(np.dot(w[j], x[i]))# w1[j] = t# 使用erf函數(正態分布)的CDF# t = -2 * np.dot(w[j], x[i])# w1[j] = t * x[i]iw = np.linalg.inv(w.transpose())w1 += iw * alphaw1 = w1.transpose() * alphaw += w1# print time, ":\t"# print wreturn w##仿真結果 首先,使用python模擬,生成一個掃描波、一個正弦波如下;使用權重矩陣$$A=\begin{pmatrix} 0.6 & 0.4 \ 0.45 & 0.55 \end{pmatrix}\$$對原始信號進行加權,得到的混合信號如下:
原始信號:
混合信號:
import numpy as np from matplotlib import pyplot as pltdef show(s1, s2, label1, label2):x = [i for i in range(1000)]plt.plot(x, s1, 'r', label = label1)plt.hold(True)plt.plot(x, s2, 'g', label = label2)plt.hold()plt.legend()plt.show()if __name__ == "__main__":s1 = np.array([np.sin(float(x) / 20) for x in range(1000)])s2 = np.array([float(x) / 50 for x in range(50)] * 20)show(s1, s2, 'Signal 1', 'Signal 2')A = np.array([[0.6, 0.4], [0.45, 0.55]])x = np.dot(A, np.array([s1, s2])).transpose()show(x[:,0], x[:,1], 'Mic 1', 'Mic 2')# x -= x.mean()w = ica(x)[ps1, ps2] = np.dot(x, w).transpose()show(ps1, ps2, 'Component 1', 'Component 2')將混合信號x輸入給ICA算法,并使用得到的W進行還原,得到的結果如下:
雖然有些局部失真,但得到這種結果已經很不錯了。下面是使用其他CDF函數得到的結果:
陳政/arc001 原創作品轉載請注明出處
我的博客即將搬運同步至騰訊云+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=6klbojckkbuw
轉載于:https://my.oschina.net/bgbfbsdchenzheng/blog/691384
總結
以上是生活随笔為你收集整理的线性独立成分分析(ICA)与鸡尾酒会问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode热题100使用摩尔投票法
- 下一篇: Scrapy spiders介绍