实数域FASTICA算法讲解及matlab源码

这就是我们在编写盲分离程序(尤其是像fastICA这类算法)的时候总是会遇到一些问题,这是我们没有把程序的基本思想给搞明白,下面,我们将一一讲解如何编写程序,我们将首先从最基础的实数域fastICA算法开始讲解,我们直接给出其不动点的算法
这里写图片描述 (1)
上式的推导可以参看文献A. Hyvarinen and E. Oja. A fast fixed point algorithm for independent component analysis. Neural Computation. 1997, Vol. 9: 1483 - 1492,这是他原始提出的文章,不过你也可以参看文献《盲信号分离算法及其应用_李云霞》(第21页),这是电子科大的一篇博士论文,里面也有详细的推导过程。
一般性的我们先给出其求解的步骤:
(这是我们串行提出的算法)
1)对观测数据X中心化(即去均值)。
2)对数据进行白化处理Z=V*X;V就是我们的白化矩阵
3)设置迭代的最大次数(这是防止不好的收敛门限造成算法的死循环),收敛的门限,设置迭代次数p;
4)设定初始权向量这里写图片描述;
5)令这里写图片描述
6)逐次正交化这里写图片描述
7)令这里写图片描述
8)判断这里写图片描述是否收敛,不收敛返回5).
9)令p=p+1;,如果p<=m(m为我们信号的个数),返回4)。
我们可以看出,这样步骤很是简单,但是在编程实现的时候却还是有问题,究其原因,我总是卡在对于上述步骤5)的求解有问题,下面我们详细解释。
最为重要的是步骤5)的实现,假设我们信号个数为4,传感器的个数也是4,我们采样1000个数据点,哪么我们知道我们的混合信号X为4*1000的矩阵,哪么白化后的信号Z也为4*1000的矩阵,因为我们串行算法每一次提出一个信号,哪么这里写图片描述(它是分离矩阵w的第p列)是一个4*1的矢量。从而可得为1*1000的矢量,我们直接运算步骤5)可以看出不满足矩阵的乘法,因为Z为4*1000,这里写图片描述为1*1000,那么我们的想法就是将其一个一个的运算,亦即我们用Z的第一行与这里写图片描述相乘,这样就行了,之后我们依次将其乘起来就行了,算法如下:

 for i=1:m     
       %选择的G函数是G(y)=-exp(-y^2/2)
            g=(lastwp'*Z).*exp(-0.5*(lastwp'*Z).^2);%一次微分
            dg=(1-(lastwp'*Z).^2).*exp(-0.5*(lastwp'*Z).^2);%二次微分
% /////////////----------------------------------------------
            wp(i,:)=mean(Z(i,:).*g)-mean(dg)*lastwp(i,:);
         end

最后我们实现的算法如下:

function Z=zf_fushang(x)
% 这是对信号源进行负熵分离
% 、、、、、、、、、预白化处理、、、、、、、、、、、、
[m,n]=size(x);
zerox=x-mean(x,2)*ones(1,n);%中心化
Cxx=cov(zerox.');
[vector,value]=eig(Cxx);
value=abs(value);
whiteMatrix=value^(-1/2)*vector';%白化处理
Z=whiteMatrix*zerox;

% 、、、、、、、、、、使用负熵分离信源、、、、、、、、、
maxcount=100;%设定最大的循环次数
minvalue=1E-6;%设定收敛的门限值
w=ones(m,m);%设定初始的权矢量
B=[];
for k=1:m
    wp=w(:,k);
    count=0;
    lastwp=zeros(m,1);
    while abs(abs(wp'*lastwp)-1)>minvalue
        count=count+1;
        lastwp=wp;
        for i=1:m     
       %选择的G函数是G(y)=-exp(-y^2/2)
            g=(lastwp'*Z).*exp(-0.5*(lastwp'*Z).^2);%一次微分
            dg=(1-(lastwp'*Z).^2).*exp(-0.5*(lastwp'*Z).^2);%二次微分
% /////////////----------------------------------------------
            wp(i,:)=mean(Z(i,:).*g)-mean(dg)*lastwp(i,:);
         end
%、、、、、、、、、、、对已经提取的分量进行正交化、、、、、、、、、、、、
        if(k>1)
            wp=wp-w(:,1:(k-1))*w(:,1:(k-1))'*wp;
        end
         wp=wp./norm(wp);
        if count>=maxcount
           fprintf('未找到相应的信号');
           return;
       end
    end
     w(:,k)=wp;
end
Z=w.'*Z;

你可能感兴趣的:(盲源分离相关算法讲解)