特征工程
基本概念
特征工程是对已经得到的数据进行数据预处理,对于单个特征,可以做单位化 (令特征向量模长为 1),归一化 (等比例缩小所有数值令最大值为 1) 等,对于多个特征,往往通过降维和特征选择来得到数据更短的向量表示,这种操作往往可以加快后续模型计算速度并得到更好的效果。
特征选择指的是从整体特征当中选取部分特征作为后续讨论的目标,例如一张人脸图片,我们可以通过特征提取的方式提取五官,脸型等来作为分类或者聚类时讨论的目标,但是由于每张照片上人脸所处于图片的位置以及方向不同,会导致五官并不在同一个像素区间内,所以并不能通过直接选取固定像素块来进行特征选择。特征选择中常用的特征选择方式共有三种:过滤法,包裹法,嵌入法。
过滤法
过滤法是依照特征本身的性质或者特征之间的相关性来进行筛选,例如有依照方差和相关系数进行筛选。
- 方差法:如果说一个特征在所有样本下的变化是很小的,即具有较小的方差,那么不管是分类还是回归任务中,它对结果的影响往往也很小,所以可以剔除掉方差小于阈值的特征
- 互信息法:互信息可以看成是一个随机变量中包含的关于另一个随机变量的信息量,其定义为
\[I(x,y) = \sum_{x\in X}\sum_{y\in Y}p(x,y)\ln\dfrac{p(x,y)}{p(x)p(y)}
\]
其中 \((X,Y)\) 表示二元随机变量, \(p(x,y)\) 表示联合密度, \(p(x),p(y)\) 表示边际密度。显然互信息总是正的,当计算出的互信息越大时,说明两个向量互相影响的越明显,反之则越不明显。不同于方差法,互信息法是将特征变量与结果变量作为计算目标,即考虑特征对结果的影响大小,当然也可以用相关系数作为比较两个变量的相关性。
我们给出计算互信息的 matlab 函数
function mi = calmi(u1, u2)
%
x = [u1, u2];
n = length(u1);
[xrow, xcol] = size(x);
bin = zeros(xrow,xcol);
pmf = zeros(n, 2);
for i = 1:2
minx = min(x(:,i));
maxx = max(x(:,i));
binwidth = (maxx - minx) / n;
edges = minx + binwidth*(0:n);
histcEdges = [-Inf edges(2:end-1) Inf];
[occur,bin(:,i)] = histc(x(:,i),histcEdges,1); % 通过直方图方式计算单个向量的直方图分布
pmf(:,i) = occur(1:n)./xrow;
end
% 计算 u1 和 u2 的联合概率密度
jointOccur = accumarray(bin,1,[n,n]); %(xi,yi)两个数据同时落入 n*n 等分方格中的数量即为联合概率密度
jointPmf = jointOccur./xrow;
Hx = -(pmf(:,1))'*log2(pmf(:,1)+eps);
Hy = -(pmf(:,2))'*log2(pmf(:,2)+eps);
Hxy = -(jointPmf(:))'*log2(jointPmf(:)+eps);
MI = Hx+Hy-Hxy;
mi = MI/sqrt(Hx*Hy);
end
最后,给出一个利用方差过滤和互信息法计算主要特征的例子。给定变量 fea 和分类结果 gnd ,进行如下操作:
- 过滤 fea 中方差大于 0.05 的特征
- 对剩余的特征计算互信息,并查找互信息最大的前 15 个特征的原始列标
% 加载数据
load('data.mat');
[row, col] = size(fea);
var_value = zeros(1,col);
% 计算每一列的方差
for i = 1:col
var_value(i) = std(fea(:,i))^2;
end
% 筛选方差 > 0.05 的下标
ind = find(var_value > 0.05);
n = length(ind);
res = zeros(1,n);
max15 = zeros(1,15);
% 在筛选后的列标中计算互信息
for i = 1:n
index = ind(i);
res(i) = calmi(fea(:,index),gnd);
end
% 排序结果
s = sort(res);
% 查找前 15 个最大值的列标
for i = 1:15
max15(i) = find(res == s(n+1-i));
end
disp(max15);
这里有一个疏忽,查找的列标是过滤后的,而不是原始列标。