2016-05-24 3 views
1

У меня есть матрица X (100000 X 10) и вектор Y (100000 X 1). X строк категоричны и принимают значения от 1 до 5, а метки также категоричны (от 11 до 20);Назначение меток на основе данных примеров для большого набора данных эффективно

Строки X повторяются, и есть только ~ 25% уникальных строк, я хочу, чтобы Y имел статистический режим для всех меток для определенной уникальной строки.

И вот наступает другой набор данных P (90000 X 10), я хочу предсказать метки Q на основе предыдущего упражнения.

Я попытался найти уникальные строки X, используя уникальные в MATLAB, а затем назначить статистический режим каждой из этих меток для уникальных строк. Для P я могу использовать ismember и выполнять то же самое.

Вопрос относится к размеру набора данных и для завершения процесса требуется 1,5-2 часа. Возможна ли версия векторизации в MATLAB?

Вот мой код:

[X_unique,~,ic] = unique(X,'rows','stable'); 
labels=zeros(length(X_unique),1); 
for i=1:length(X_unique) 
    labels(i)=mode(Y(ic==i)); 
end 

Q=zeros(length(P),1); 
for j=1:length(X_unique) 
    Q(all(repmat(X_unique(j,:),length(P),1)==P,2))=label(j); 
end 
+0

, пожалуйста, напишите код, который занял 1,5-2 часа, чтобы мы могли его оптимизировать и понять, что вы делаете. – GameOfThrows

+0

Приведенный код для оптимизации – GKS

+0

Попробуйте [профилирование] (http://uk.mathworks.com/help/matlab/ref/profile.html). –

ответ

1

Вы сможете ускорить свой первый цикл очень много, если заменить его полностью с:

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.

+0

Можете ли вы объяснить уникальный трюк с помощью P один раз? Я не уверен, что такое IC: Q_full = Q_unique (IC); – GKS

+0

@GKS Я редактировал сообщение и добавил пример. Кроме того, я исправил опечатку, которую я сделал: 'IC' должен был быть' IC_P'. Надеюсь, что все станет понятнее :). –

+0

Это помогло. Теперь это занимает половину времени, чем раньше. – GKS

Смежные вопросы