Effective Matlab—编写高效的Matlab代码

关于Matlab的讨论很多,这里我们不讨论具体的API细节,而是集中于高效使用Matlab这一主题,因此本文假设读者已经有了matlab的基本知识(本文不会对API的接口进行专门介绍,这部分可以通过matlab的help文档来解决),并且已经使用matlab一段时间。不能免俗的,本文被命名为Effective Matlab(向Effective C++致敬)。

1. 善用矩阵操作
Matlab对矩阵运算进行了深度优化,因此对于Matlab程序,矩阵操作的效率高于for循环。
1.1 使用repmat
repmat的作用在于对矩阵进行复制,通过repmat,我们可以将一部分for循环改写为矩阵运算,例如
以下函数实现了对数据的“均值归零,方差归一”。

function M = ZeroMeanOneVar(X,x_mean,x_var)
index = x_var<0.0000001;
x_var(index) = 1;
% x_mean(index) = 0;
 
num = size(X,2);
X_mean = repmat(x_mean, 1, num); %复制x_mean为1行num列
M = X - X_mean;
clear X_mean;
X_var = repmat(x_var, 1, num);
M = M ./ X_var;
clear X_var;
flag = isnan(M); 
M(flag) = 0;
end

需要指出的是,通过repmat将for循环转为矩阵运算会增加内存消耗,这种技巧的另外一个名字叫“空间换时间”。

1.2 使用meshgrid
meshgrid的作用在于生成2维或者3维网格,例如我们需要绘制Z = x*exp(-x^2 - y^2), x和y的取值范围均为
[-5, 5]。

x=-5 : .01 : 5;
y=x;
[X,Y] = meshgrid(x,y);
Z = X .* exp(-X.^2 - Y.^2); 
mesh(X,Y,Z)

x=-5 : .01 : 5;
y=x;
[X,Y] = meshgrid(x,y);
Z = X .* exp(-X.^2 - Y.^2);
 
mesh(X,Y,Z)


2. 考虑数值稳定性
2.1 用SVD代替eig
矩阵运算必须时刻牢记数值稳定性,例如eig()运算的数值稳定性不如SVD(), 而求特征值和特征向量对于机器学习中的常见算法PCA来说是必须的,下面展示了一个在PCA算法中应用SVD代替eig的例子。
 % x_poa已经经过减均值操作
    St = X_pca * X_pca';
    [Vt Dt v] = svd(St);
    eig_value_unsort = diag(Dt);
    [eig_value  eig_index]  = sort(eig_value_unsort, 'descend' );
    energy = sum(eig_value);
   
    for i=1:dim
        kept_energy = sum(eig_value(1:i));
        if kept_energy > energy*0.98
            fprintf( '%d dims can preserve 0.98 energy' ,i);
            break ;
        end
    end
   
    W_pca = zeros(dim,pca_dim);  %W_pca????????????????
    for i = 1:pca_dim
        W_pca(:, i) = Vt(:,eig_index(i));
    end

2.2 左除和右除
在matlab中,如果有以下操作:
Inv(A)*B, 建议用左除A\B代替。
A*Inv(B),  建议用右除A/B代替。

A右除B,相当于A右乘B的逆矩阵,A左除B,相当于A的逆矩阵左乘B

 
    

你可能感兴趣的:(Effective Matlab—编写高效的Matlab代码)