Преобразовать вектор в логическую матрицу?

#matlab #octave

#matlab #октава

Вопрос:

У меня есть вектор y длиной n. y (i) — целое число в 1 ..m. Есть ли более простой способ преобразовать y в логическую матрицу yy из n x m, где yy (i, j) = 1, если y (i) = j, но 0 в противном случае? Вот как я это делал:

 % If m is known (m = 3 here), you could write it out all at once
yy = [y == 1; y== 2; y == 3];
yy = reshape(yy, n, 3);
  

или

 % if m is not known ahead of time
yy = [ y == 1 ];
for i = 2:m;
    yy = [ yy; y == i ];
end
yy = reshape(yy, n, m);
  

Комментарии:

1. Я нашел другой способ … не уверен, что это лучше… но, по крайней мере, это умещается в одной строке: yy = repmat(y,1,m) == repmat(1:m, n, 1);

2. bsxfun входит в число многопоточных функций Matlab. Таким образом, это, вероятно, будет быстрее, чем ваши решения.

Ответ №1:

Для этого вы можете использовать bsxfun

 yy = bsxfun(@eq,y(:),[1,2,3])
  

y преобразуется (при необходимости) в вектор-столбец, в то время как другой вектор является вектором-строкой. bsxfun неявно расширяет массивы m на 1 и 1 на n, так что результат становится m наn.

Ответ №2:

Если n * m достаточно велико (а m само по себе достаточно велико), это хорошая идея для создания yy в виде разреженной матрицы. Ваш y вектор — это действительно особый тип формата разреженной матрицы, но мы можем перевести его во встроенный формат разреженной матрицы, выполнив следующее.

 yy = sparse(1:length(y), y, 1);
  

Это сохранит объем вашего хранилища равным O (n). Это не принесет вам большой пользы, если вы используете yy для большого количества индексаций. Если это так, вам лучше использовать вашу исходную разреженную структуру (т.Е. y ).

Ответ №3:

Небольшая модификация вашего метода:

 % A n-dimensional vector y, with values in some range 1..m
m = 4;
n = 7;
y = randi([1 m], n, 1);

% Preallocating a n by m matrix of zeros
nXm = zeros(n, m);

% In each pass of this loop a single column of nXm is updated, where
% for each column index j in nXm, if y(i) = j then nXm(i,j) = 1
for j = 1:m;
    nXm(:,j) = (y == j);
end
  

Ответ №4:

Из машинного обучения на Coursera:

 yy = eye(m)(y, :)
  

Для этого требуется, чтобы список был диапазоном 1:m (как указано в OP). Для нерегулярного списка, например [2 3 5] , сделайте это

 yy = eye(m)(:, [2 3 5])(y, :)
  

Примечание: не тестировался в MATLAB.

Комментарии:

1. (Но я бы все равно предпочел способ @Jonas, очень аккуратный.)

Ответ №5:

В octave вы можете написать:

 yy = y' == (1:m); % or y == (1:m)' for transposed
[1 2 1 3 2] == [1 2 3]' % = [1 0 1 0 0; 0 1 0 0 1; 0 0 0 1 0]