2015-04-16 3 views
3

Я хочу попробовать svm-классификатор с использованием ядра пересечения гистограммы, для набора данных из 153 изображений, но это занимает много времени. Это мой код:Оптимизация ядра пересечения гистограммы в MATLAB

a = load('...'); %vectors 
b = load('...'); %labels 
g = dataset(a,b); 

error = crossval(g,libsvc([],proxm([],'ih'),100),10,10); 
error1 = crossval(g,libsvc([],proxm([],'ih'),10),10,10); 
error2 = crossval(g,libsvc([],proxm([],'ih'),1),10,10); 

Моя реализация ядра внутри функции proxm является:

... 
case {'dist_histint','ih'} 
    [m,d]=size(A); 
    [n,d1]=size(B); 
    if (d ~= d1) 
     error('column length of A (%d) != column length of B (%d)\n',d,d1); 
    end 

    % With the MATLAB JIT compiler the trivial implementation turns out 
    % to be the fastest, especially for large matrices. 
    D = zeros(m,n); 
    for i=1:m % m is number of samples of A 
     if (0==mod(i,1000)) fprintf('.'); end 
     for j=1:n % n is number of samples of B 
      D(i,j) = sum(min([A(i,:);B(j,:)]));%./max(A(:,i),B(:,j))); 
     end    
    end 

мне нужна оптимизация MatLab для этого кода!

ответ

3

Вы можете избавиться от этого цикла ядра для расчета D с этим bsxfun на основе vectorized подхода -

D = squeeze(sum(bsxfun(@min,A,permute(B,[3 2 1])),2)) 

Или избежать squeeze с этой модификации -

D = sum(bsxfun(@min,permute(A,[1 3 2]),permute(B,[3 1 2])),3) 

Если расчеты D связаны с max вместо min, просто замените @min на @max.


Объяснение: Путь bsxfun работы является то, что он делает расширение на одноэлементных размеров и выполняет операцию, как указано с @ внутри его вызова. Теперь это расширение в основном состоит в том, как можно получить векторизованные решения, которые заменяют for-loops. В singleton dimensions в массивах мы имеем в виду размеры 1.

Во многих случаях размеры синглтона еще не присутствуют и для векторизации с bsxfun нам необходимо создать singleton dimensions. Один из инструментов для этого - permute. Это в основном все о том, как будет работать ранее примененный векторизованный подход.

Таким образом, ваш код ядра -

... 
case {'dist_histint','ih'} 
    [m,d]=size(A); 
    [n,d1]=size(B); 
    if (d ~= d1) 
     error('column length of A (%d) != column length of B (%d)\n',d,d1); 
    end 

    % With the MATLAB JIT compiler the trivial implementation turns out 
    % to be the fastest, especially for large matrices. 
    D = zeros(m,n); 
    for i=1:m % m is number of samples of A 
     if (0==mod(i,1000)) fprintf('.'); end 
     for j=1:n % n is number of samples of B 
      D(i,j) = sum(min([A(i,:);B(j,:)]));%./max(A(:,i),B(:,j))); 
     end    
    end 

сводится к -

... 
case {'dist_histint','ih'} 
    [m,d]=size(A); 
    [n,d1]=size(B); 
    if (d ~= d1) 
     error('column length of A (%d) != column length of B (%d)\n',d,d1); 
    end 
    D = squeeze(sum(bsxfun(@min,A,permute(B,[3 2 1])),2)) 
    %// OR D = sum(bsxfun(@min,permute(A,[1 3 2]),permute(B,[3 1 2])),3) 

Я предполагаю, что линия: if (0==mod(i,1000)) fprintf('.'); end не важно для расчетов, как это делает печать какого-то сообщения.

+0

Я не мог удалить петлю, но используя [bsxfun] (http://in.mathworks.com/help/matlab/ref/bsxfun.html), чтобы вычислить минуты, получилось значительное улучшение. finaly: D (i, j) = sum (bsxfun (@ min, a (i, :), b (j, :))). спасибо – jperezmartin

+0

@ user3799302 Что значит, вы не могли удалить петлю? Код, посланный в этом ответе для вычисления D, является заменой двух вложенных циклов, которые у вас есть в ядре, с: 'для i = 1: m' и' для j = 1: n', являющимися двумя циклами. – Divakar

+0

@ user3799302 Имел ли смысл мой предыдущий комментарий? – Divakar