Как эффективно реализовать перекрестную проверку в Matlab с помощью parfor

Перекрестная проверка - одна из тех досадно параллельных проблем.

Допустим, вы хотите проверить модель линейной регрессии. Предположим, что матрица плана X имеет размеры n на p, а непрерывный результат y представляет собой вектор n на 1. Далее предположим, что foldMatrix является матрицей logicals размером n на k. Каждый столбец представляет собой раздел: где 1 указывает, что наблюдение используется для обучения, а 0 означает, что оно используется для проверки. Этот трюк с обучающей проверкой повторяется k раз, чтобы уменьшить дисперсию ошибки обобщения (GE ) оценить.

Мой (наивный?) Подход к параллельной перекрестной проверке в Matlab выглядел бы так:

matlabpool

GE = nan(k,1);  

parfor i = 1:k

   trainIndices = foldMatrix(:, i);
   b = X(trainIndices, :)\y(trainIndices, :);

   GE(i) = mean( (y(~trainIndices, :)  - X(~trainIndices, :)*b).^2 );

end

mspe = mean(GE);

Когда вы это сделаете, Matlab будет жаловаться, что «X проиндексирован, но не разрезан в цикле PARFOR. Это может привести к ненужным накладным расходам связи» (то же самое для y).

Мои вопросы:

  • РЕДАКТИРОВАТЬ: есть ли способ ускорить перекрестную проверку с помощью параллельной реализации в Matlab?
  • Есть ли эффективный / элегантный способ решить проблему, когда переменные X и y не разделяются?

Два «решения», которые мне не кажутся очень элегантными:

  1. Не обращайте внимания на ворчание. Для небольших проблем, скажем, p < 100, n < 3000 и k < 40, последовательная реализация выполняется быстрее, чем параллельная.

  2. Предварительно выделите разделы с проверкой поезда «явно» в массиве ячеек или трехмерной матрице. Результатом являются k полные копии данных (X и y).


person Jim    schedule 26.08.2015    source источник


Ответы (1)


Не обращайте внимания на ворчание.

Предупреждение анализатора кода просто для того, чтобы вы знали, что делаете. Многие параллельные задачи выполняют только одно действие с отдельными порциями данных, поэтому TMW хочет, чтобы вы знали, что вы повторно используете некоторые данные.

Подумайте об этом так: данные должны каким-то образом попасть на правильный процессор. Вы можете продублировать его в памяти или позволить процессору каждый раз запрашивать один и тот же фрагмент памяти. Однако это дублирование требует времени, которого мы не хотим.

Вот небольшой скрипт, который мы можем использовать, чтобы проверить это:

n = 20000;
p = 6;
k = 1000;

N = [30 * (1:9), 300 * (1:9), 3000 * (1:10)];

timing = nan(length(N), 2);

gcp;

for iN = 1:length(N)
    n = N(iN);

    X = rand(n, p);
    beta = rand(p, 1);
    y= X * beta;

    foldMatrix = logical(rand(n,k) > 0.5);

    GE = nan(k,1);

    tic;
    parfor i = 1:k
        trainIndices = foldMatrix(:, i);
        b = X(trainIndices, :)\y(trainIndices, :); %#ok<*PFBNS>

        GE(i) = mean( (y(~trainIndices, :)  - X(~trainIndices, :)*b).^2 );
    end
    timing(iN, 1) = toc;

    tic;
    X_rep = repmat(X, [1 1 k]);
    y_rep = repmat(y, [1 1 k]);
    parfor i = 1:k
        trainIndices = foldMatrix(:, i);
        b = X(trainIndices, :)\y(trainIndices, :);

        GE(i) = mean( (y(~trainIndices, :)  - X(~trainIndices, :)*b).^2 );
    end
    timing(iN, 2) = toc;
end

Если вы построите график времени против N, plot(N, timing):

n

Синяя линия - с предупреждением анализатора кода, оранжевая - с repmat. То же самое верно и для измерения k:

введите описание изображения здесь

Так что сохраните вычисления и просто игнорируйте предупреждение. Вы можете добавить %#ok<PFBNS> в конец строк, где оно появляется, или %#ok<*PFBNS> в любом месте файла, чтобы они перестали отображаться.

person David Kelley    schedule 26.08.2015