原理介绍

K-L变换是模式识别中常用的一种特征提取方法,出发点是从一组特征中计算出一组按重要性从大到小排列的新特征,它们是原有特征的线性组合,并且相互之间是不相关的。K-L变化能考虑到不同的分类信息,实现监督的特征提取,本文首先讨论从数据的协方差矩阵作为产生矩阵的K-L变换,接下来讨论从类平均向量中提取判别信息的K-L变换。

K-L变换原理

K-L变换的流程基本如下,第一步,首先从D维原始数据x \in R^D中建立一个包含分类判别信息的方阵作为K-L变换的产生矩阵\Psi =R^{D \times D},第二步,求解\Psi的特征值并从大到小排序得到\lambda=\{ \lambda _1,\lambda _2,...,\lambda _D \}和这些特征值对应的特征向量u=\{u_1, u_2, ... , u_D\},第三步,选择前d个特征值\lambda_j, j=1,2,...,d对应的特征向量u_j,j=1,2,...,d组成了变换矩阵W=\{u_1, u_2, ..., u_d\},变换后的特征可以表示为y=W^Tx,y \in R^d,这样就实现了K-L变换。

可以证明,新的特征所能代表的样本间的差异信息占全部差异信息的比例是\alpha =\frac{\sum_{i=1}^d\lambda_i}{\sum_{j=1}^D\lambda_j}。通常,选取新特征的维数可以根据上式的比例来确定。

协方差矩阵作为产生矩阵

当K-L变换的产生矩阵为数据协方差矩阵\sum=E[(x-u)(x-u)^T],这里的u为样本的均值,这时无法考虑到分类判别信息。

从类平均向量中提取判别信息

如果要用最少的维数来保持原空间中类平均向量中的信息,则可以在使特征空间互不相关的前提下最优压缩类平均向量中包含的分类信息。算法分为两大步骤:

1、用总类内离散度矩阵S_w=\sum_{i=1}^cp_iE_i[(x-\bar{m_i})(x-\bar{m_i})^T]做K-L变换,其中S_w为类内离散度矩阵,p_i\bar{m_i}分别为第i组数据的先验概率和均值,此次K-L变换可以消除特征间的相关性。写成矩阵形式就是U^TS_wU=\triangle,令B=U\triangle^{-\frac{1}{2}},从而使S{_w}{^'}=B^TS_wB=I

这一步称为为白化变化,之后再进行任何正交归一变换类内离散度矩阵都不会再改变。变换后的类间离散度矩阵成为S{_b}{^'}=B^TS_bBS_b=\sum_{i=1}^cP_iE_i[(x-\bar{m_i})(x-\bar{m_i})^T]

2、用S_b^'再进行K-L变换,以压缩包含在类均值向量中的信息。对于一个c类问题,S_b^'的秩最大为c-1,因此这一步最多有d=c-1个非零的特征值,对应的特征向量组成的变换矩阵记为V^'=\begin{bmatrix} v_1, v_2,...,v_d\end{bmatrix}

考虑到上一步的变换,总的变换矩阵是W=U\triangle^{-\frac{1}{2}}V^{'}

基于K-L变换分类阈值选择

  1. y_1=\frac{\bar{Y_1}+\bar{Y_2}}{2}
  2. y_2=\frac{N_1\bar{Y_1}+N_2\bar{Y_2}}{N_1+N_2}=\frac{N_1W^T\bar{X_1}+N_2W^T\bar{X_2}}{N_1+N_2}
  3. y_3=\bar{Y_1}+(\bar{Y_2}-\bar{Y_1})\frac{\sum_{k=1}^{N_1}(Y_{k1}-\bar{Y_1})^2}{\sum_{k=1}^{N_1}(Y_{k1}-\bar{Y_1})^2+\sum_{k=1}^{N_2}(Y_{k2}-\bar{Y_2})^2}
function [ W, Y ] = PCATransform( X, m )
%=======================================================
%function [ W ] = PCATransform( X, m ) PCA变换
%输入参数:X 原始数据(N * l)
%         m 变换后维数
%输出参数:W 变化矩阵 (N * m)
%         Y 变换的矩阵(m * l)
%编程环境:MATLAB R2017a
%Date:2018/11/1
%=======================================================

%=======================================================
% 第一步:计算产生矩阵
% 第二步:特征值和特征向量
% 第三步:返回投影矩阵和变换后的矩阵
%=======================================================

[N, l] = size(X);
E = sum(X, 2) / l;
V = (X - E) * (X - E)' / (l - 1);
% V = cov(X(1, :), X(2, :));

[t, W] = KLTransform(V, 1);

if size(W, 2) > m
    W(:, m+1: end) = [];
end

Y = W' * X;
end



function [ W, Y ] = ClassAverageTransform( X, m )
%=====================================================
%function [ W, Y ] = ClassAverageTransform( X, m )
%包含在类平均向量中判别信息的最优压缩
%输入参数:X 原始数据,类型为元胞(c * N * l)
%         m 变换后维数
%输出参数:W 变化矩阵 (N * m)
%         Y 变换的矩阵(m * l)
%编程环境:MATLAB R2017a
%Date:2018/11/1
%=====================================================

%=====================================================
% 第一步:用总类内离散度矩阵做K-L变换
% 第二步:白化变化
% 第三步:用变换后的类间相似度矩阵做K-L变换
% 第四步:特征值和特征向量
% 第五步:返回投影矩阵和变换后的矩阵
%=====================================================

c = length(X);
N = size(X{1}, 1);
Sw = zeros(N, N);
Sb = zeros(N, N);
EE = zeros(N, c);
E = zeros(N, 1);
L = 0;

for i = 1 : c
    EE(:, i) = sum(X{i}, 2) / size(X{i}, 2);
    Sw = Sw + (X{i} - EE(:, i)) * (X{i} - EE(:, i))' / (size(X{i}, 2) -1) / c;
    E = E + sum(X{i}, 2);
    L = L + size(X{i}, 2);
end

E = E / L;

for i = 1 : c
    Sb = Sb + (EE(:, i) - E) * (EE(:, i) - E)' / c;
end

[l1, U1] = KLTransform(Sw, 1);
B = U1 * sqrt(diag(l1) ^ -1);
Sb1 = B' * Sb * B;
[l2, U2] = KLTransform(Sb1, 1);

W = B * U2;
Y = cell(1, c);
for i = 1 : c
    Y{i} = W' * X{i};
end

end



function [l, U] = KLTransform( OriginX, e )
%========================================================
% function [U, l] = KLTransform( OriginX ):K-L变换
% 输入参数:OriginX  进行K-L变化的矩阵,要为方阵
%          e  变换后特征值占据的比例
% 输出参数:l  特征值向量
%          U  特征值向量对应的特征矩阵
% 编程环境 MATLAB R2017a
% Date:2018/11/1
%========================================================

[UU, ll] = eig(OriginX);
ll = diag(ll)';

for i = 1 : length(ll)
    for j = i+1 : length(ll)
        if ll(i) < ll(j)
            temp = ll(i);
            ll(i) = ll(j);
            ll(j) = temp;
            temp = UU(:, i);
            UU(:, i) = UU(:, j);
            UU(:, j) = temp;
        end
    end
end

for i = 1 : length(ll)
    if ~ (sum(ll(1: i)) / sum(ll) < e)
        l = ll(1: i);
        U = UU(:, 1: i);
        break;
    end
end

l = ll;
U = UU;

end

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐