У меня есть матрица X
с десятками строк и тысячами столбцов, все элементы являются категориальными и реорганизованы в индексную матрицу. Например, столбец ith
X(:,i) = [-1,-1,0,2,1,2]'
преобразуется в X2(:,i) = ic
из [x,ia,ic] = unique(X(:,i))
для удобства использования функции accumarray
. Я случайным образом выбрал подматрицу из матрицы и подсчитал количество уникальных значений каждого столбца подматрицы. Я проделал эту процедуру 10000 раз. Я знаю несколько методов подсчета количества уникальных значений в столбце, быстрый способ, который я нашел до сих пор, показан ниже:
mx = max(X);
for iter = 1:numperm
for j = 1:ny
ky = yrand(:,iter)==uy(j);
% select submatrix from X where all rows correspond to rows in y that y equals to uy(j)
Xk = X(ky,:);
% specify the sites where to put the number of each unique value
mxj = mx*(j-1);
mxi = mxj+1;
mxk = max(Xk)+mxj;
% iteration to count number of unique values in each column of the submatrix
for i = 1:c
pxs(mxi(i):mxk(i),i) = accumarray(Xk(:,i),1);
end
end
end
Это способ выполнить тест случайной перестановки для расчета прироста информации между матрицей данных X
размера n by c
и категориальной переменной y
, при которой y
переставляется случайным образом. В приведенных выше кодах все случайно переставленные y
хранятся в матрице yrand
, а количество перестановок равно numperm
. Уникальные значения y
хранятся в uy
, а уникальный номер — ny
. В каждой итерации 1:numperm
подматрица Xk
выбирается в соответствии с уникальным элементом y
, и количество уникальных элементов в каждом столбце этой подматрицы подсчитывается и сохраняется в матрице pxs
.
Наиболее затратный по времени раздел в приведенном выше коде — это итерации i = 1:c
для больших c
.
Можно ли выполнить функцию accumarray
матричным способом, чтобы избежать цикла for
? Как еще я могу улучшить приведенный выше код?
-------
В соответствии с запросом предоставляется упрощенная функция тестирования, включающая приведенные выше коды.
%% test
function test(x,y)
[r,c] = size(x);
x2 = x;
numperm = 1000;
% convert the original matrix to index matrix for suitable and fast use of accumarray function
for i = 1:c
[~,~,ic] = unique(x(:,i));
x2(:,i) = ic;
end
% get 'numperm' rand permutations of y
yrand(r, numperm) = 0;
for i = 1:numperm
yrand(:,i) = y(randperm(r));
end
% get statistic of y
uy = unique(y);
nuy = numel(uy);
% main iterations
mx = max(x2);
pxs(max(mx),c) = 0;
for iter = 1:numperm
for j = 1:nuy
ky = yrand(:,iter)==uy(j);
xk = x2(ky,:);
mxj = mx*(j-1);
mxk = max(xk)+mxj;
mxi = mxj+1;
for i = 1:c
pxs(mxi(i):mxk(i),i) = accumarray(xk(:,i),1);
end
end
end
И тестовые данные
x = round(randn(60,3000));
y = [ones(30,1);ones(30,1)*-1];
Проверьте функцию
tic; test(x,y); toc
вернуть Elapsed time is 15.391628 seconds.
на мой компьютер. В тестовой функции установлено 1000 перестановок. Поэтому, если я выполняю 10 000 перестановок и выполняю некоторые дополнительные вычисления (незначительные по сравнению с приведенным выше кодом), ожидается время более 150 s
. Я думаю, можно ли улучшить код. Интуитивно понятно, что выполнение accumarray
в виде матрицы может сэкономить много времени. Могу я?
rng(42528955)
иrandi
), и показывает ожидаемый вывод (< href="https://stackoverflow.com/help/minimal-reproducible-example">минимальный воспроизводимый пример)? Вопросы, связанные с улучшением существующего кода, на мой взгляд, должны иметь какой-то функционирующий базовый код. - person Dev-iL   schedule 01.03.2017hist
илиhistcount
. Предположим, у меня есть массив 5 * 5, и я хочу найти счетчик каждого столбца.a=randi(10,5,5);h=hist(a,1:10)
- person rahnema1   schedule 01.03.2017for i = 1:c
заменить одной строкойpxs(mmx*(j-1)+1:mmx*j,:)=hist(x2(ky,:), xbin)
, гдеxbin=(0.5:1:max(mx)-0.5)'
. Спасибо. - person Elkan   schedule 01.03.2017for i=1:c;...; end
на одну строкуpxs(mmx*(j-1)+1:mmx*j,:)=hist(x2(ky,:), xbin)
. Новое обновление использует функциюhistc
. Я не знаю, достаточно ли этого, чтобы показать ответ. - person Elkan   schedule 03.03.2017