#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]