3

我有一个调用函数的代码,它给出了系统中每个基因的类型。我可以通过比较每个基因与其子代和父代的顺序来找到它。该代码在少量单元阵列上运行良好,但是当我将数量增加到数千时,它需要几个小时。代码是:

Types=[];
type1=level1_root; % it is fixed value (GO:0008150)
% sample values for p1 and c1 are given below
for k=1:100
    type{k}=type_fc(p1,c1,type1); % a function call - see function below
    type1=type{k}'; %'
    temp1=num2cell(repmat(k+1,length(type1),1));
    type1=[type1 temp1];
    Types=[Types; type1];
 end
 % display the output:
 Types

子功能:

function type=type_fc(p1,c1,type1)
type=[];
for j=1:length(type1)
    for i=1:length(p1)
        a=[p1(i),c1(i)];
        if isequal(a(1), type1(j))
            type=[type a(2)];
        end
    end
end

对于 13 个基因,我有这些样本输入:

p1'= %refer to parent genes  
      'GO:0008150'
      'GO:0016740'
      'GO:0016787'
      'GO:0008150'
      'GO:0016740'
      'GO:0016740'
      'GO:0016787'
      'GO:0016787'
      'GO:0016787'
      'GO:0006810'
      'GO:0006412'
      'GO:0004672'


 c1'=  % refer to children genes    
  'GO:0016740'
  'GO:0016787'
  'GO:0006810'
  'GO:0006412'
  'GO:0004672'
  'GO:0016779'
  'GO:0004386'
  'GO:0003774'
  'GO:0016298'
  'GO:0016192'
  'GO:0005215'
  'GO:0030533'

结果将是:Types =

  'GO:0016740'    [2]
  'GO:0006412'    [2]
  'GO:0016787'    [3]
  'GO:0004672'    [3]
  'GO:0016779'    [3]
  'GO:0005215'    [3]
  'GO:0006810'    [4]
  'GO:0004386'    [4]
  'GO:0003774'    [4]
  'GO:0016298'    [4]
  'GO:0030533'    [4]
  'GO:0016192'    [5]

你知道如何提高这段代码的速度吗?

4

2 回答 2

7

乍一看,我可以在您的代码中发现一些问题:

  1. 首先也是最重要的,Types并且type在循环内部动态增长。就执行时间而言,这在 MATLAB 中可能非常昂贵。相反,在循环之前预分配内存(即,使用预定的最终元素数量创建数组),您可能会看到性能的显着提升。

  2. 您正在使用循环。如果有矢量化解决方案(我还没有检查过),计算时间可能会大大减少。

  3. 您使用ij索引作为循环迭代器的变量名。这些变量已经有另一个目的:它们代表虚数单位sqrt(-1)。MATLAB 仍然允许将iandj用于变量名,但它为了找出正确的上下文而进行的变量名解析确实需要很小的成本。您应该选择其他名称,甚至iijj
    编辑:同样适用type,它已经是 MATLAB 中的保留函数名称

试试下面的优化版本,它应该运行速度至少快一个数量级:

Types = cell(numel(c1), 2);      % # Preallocate memory
type1 = level1_root;             % # ... or p1{1}
kk = [1, 2];                     % # Initialize indices
while ~isempty(type1)
    type_fc = cellfun(@(x)c1(strcmp(x, p1)), type1, 'Uniform', false);
    type1 = vertcat(type_fc{:});
    idx = kk(1):kk(1) + numel(type1) - 1;
    Types(idx, 1) = type1;
    Types(idx, 2) = {kk(2)};
    kk = kk + [numel(type1), 1]; % # Advance indices
end
Types = Types(1:kk(1) - 1, :);   % # Remove empty output cells
于 2012-12-19T09:09:18.283 回答
2

如果我没看错,那么该函数会将类型 1 中的值与 p1 中的父基因进行比较,在其中找到匹配项,然后从 c1 返回相应的子基因。这个对吗?

在这种情况下,矢量化解决方案使用strcmp来获取 type1(j) 和 p1 之间匹配的逻辑数组。

>> strcmp(type1(j),p1)

然后可以将其用于数组 c1 上的逻辑寻址,实际上它是您要提取的 c1 值的真值表。我假设您将这些作为单元格数组处理,在这种情况下,我认为这样的事情应该可以工作。

function type=type_fc(p1,c1,type1)
type={};
for j=1:length(type1)
    type=[type{:} c1(strcmp(type1(j),p1))'];
end

现在我不确定它是否让它更快,我希望你能测试它。这是我对“矢量化”解决方案的建议。

于 2012-12-19T09:47:07.467 回答