Как выполнить для более быстрого в Matlab - PullRequest
0 голосов
/ 07 декабря 2018

Я должен выполнить это для цикла:

load('Y');
X_test = ...;
Y_test = ...;
X_train = ...;
Y_train = ...;

    for i=1:length(Y.Y)
        if Y.Y(i,1) == l
            current_test_data = [current_test_data; X_test(i,:)];
            current_test_labes = [current_test_labes; Y_test(i,:)];
        else
            current_train_data = [current_train_data; X_train(i,:)];
            current_train_labes = [current_train_labes; Y_train(i,:)];            
        end
    end

Но длина (ГГ) равна 2300250, поэтому это выполнение занимает много времени.Есть более быстрый способ сделать это?

1 Ответ

0 голосов
/ 07 декабря 2018

То, что вы делаете, действительно не очень хорошо с точки зрения производительности.

Первая проблема - это цикл.Matlab не справляется с ними очень быстро;когда это возможно, векторизованные операции должны быть предпочтительными, поскольку они хорошо оптимизированы.Например, гораздо быстрее выполнить A=B.*C, чем for ii=1:length(B), A(ii)=B(ii)*C(ii);end

Вторая проблема заключается в том, что вы объединяете массивы в цикле.current_test_data начинается с небольшого массива, который растет со временем.Каждый раз, когда некоторые данные добавляются, память должна быть перераспределена.Данные могут быть перемещены в другое место в памяти.Поскольку Matlab хранит данные в главном порядке столбцов, добавление дополнительной строки также означает, что все выборки, кроме первого столбца, должны быть перемещены (при добавлении дополнительного столбца просто добавляются данные в конце).Все это сговорилось сделать ужасное представление.С небольшими массивами это может быть незаметно;но когда вы начнете перемещать мегабайты или больше данных в памяти на каждой итерации, производительность будет падать

Обычное решение, когда известен окончательный размер массива, заключается в предварительном выделении массивов, например current_test_data = zeros(expected_rows,expected_columns); и сразу же поместите данные туда, где они должны быть: current_test_data(jj,:) = some_matrix(ii,:);.Больше не нужно выделять память, не нужно больше перемещать память, больше не нужно перемешивать выборки.

Но тогда, в вашем конкретном случае, решение заключается в первом пункте: использование векторизованной записи является решением.Он будет предварительно распределять массивы до нужного размера и эффективно копировать данные.

sel = Y.Y(:,1)==1; % Builds a logical vector
% Selects data based on logical vector
current_test_data =  X_test(sel,:);
current_test_labes = Y_test(sel,:);
current_train_data = X_train(~sel,:);
current_train_labes = Y_train(~sel,:);  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...