Вы сможете ускорить свой первый цикл очень много, если заменить его полностью с:
labels = accumarray(ic, Y, [], @(y) mode(y));
Второй цикл может быть ускорено с помощью all(bsxfun(@eq, X_unique(i,:), P), 2)
внутри Q(...)
. Это хороший векторный подход, предполагающий, что ваши массивы не являются чрезвычайно большими w.r.t. доступную память на вашем компьютере. Кроме того, чтобы сэкономить время, вы можете использовать unique
трюк вы сделали с X
на P
, запустить все сравнения в гораздо меньшем массиве:
[P_unique, ~, IC_P] = unique(P, 'rows', 'stable');
EDIT: вычислить Q_unique
следующим образом : , а затем преобразовать его обратно в полный массив с помощью:
Q_unique = zeros(length(P_unique),1);
for i = 1:length(X_unique)
Q_unique(all(bsxfun(@eq, X_unique(i,:), P_unique), 2)) = labels(i)
end
и преобразовать обратно в Q_full
, чтобы соответствовать оригинальному P
вход:
END EDIT
Наконец, если память является проблемой, в дополнение ко всему выше, вы можете использовать полу-векторизованную подход внутри второго цикла:
for i = 1:length(X_unique)
idx = true(length(P), 1);
for j = 1:size(X_unique,2)
idx = idx & (X_unique(i,j) == P(:,j));
end
Q(idx) = labels(i);
% Q(all(bsxfun(@eq, X_unique(i,:), P), 2)) = labels(i);
end
Это займет около больше по сравнению с bsxfun
, но если память ограничена, вы должны заплатить со скоростью.
ОЧЕРЕДНАЯ EDIT
В зависимости от версии Matlab, вы можете также использовать containers.Map
в ваших интересах, отображение текстовых представлений числовых последовательностей к расчетному labels
. См. Пример ниже.
% find unique members of X to work with a smaller array
[X_unique, ~, IC_X] = unique(X, 'rows', 'stable');
% compute labels
labels = accumarray(IC_X, Y, [], @(y) mode(y));
% convert X to cellstr -- textual representation of the number sequence
X_cellstr = cellstr(char(X_unique+48)); % 48 is ASCII for 0
% map each X to its label
X_map = containers.Map(X_cellstr, labels);
% find unique members of P to work with a smaller array
[P_unique, ~, IC_P] = unique(P, 'rows', 'stable');
% convert P to cellstr -- textual representation of the number sequence
P_cellstr = cellstr(char(P_unique+48)); % 48 is ASCII for 0
% --- EDIT --- avoiding error on missing keys in X_map --------------------
% find which P's exist in map
isInMapP = X_map.isKey(P_cellstr);
% pre-allocate Q_unique to the size of P_unique (can be any value you want)
Q_unique = nan(size(P_cellstr)); % NaN is safe to use since not a label
% find the labels for each P_unique that exists in X_map
Q_unique(isInMapP) = cell2mat(X_map.values(P_cellstr(isInMapP)));
% --- END EDIT ------------------------------------------------------------
% convert back to full Q array to match original P
Q_full = Q_unique(IC_P);
Это занимает около 15 секунд, чтобы работать на моем ноутбуке. Большая часть которого потребляется путем вычисления mode
.
, пожалуйста, напишите код, который занял 1,5-2 часа, чтобы мы могли его оптимизировать и понять, что вы делаете. – GameOfThrows
Приведенный код для оптимизации – GKS
Попробуйте [профилирование] (http://uk.mathworks.com/help/matlab/ref/profile.html). –