Строка-нормализует разреженную матрицу в нулевое среднее в Matlab

У меня есть большая m *n разреженная матрица Y. Я хотел бы нормализовать каждую строку Y, чтобы каждая строка имела нулевое среднее значение.

Я впервые попробовал это. Но среднее значение каждой строки также вычитается из нулевых записей, а это не то, что я хочу.

Ynorm = bsxfun(@minus, Y, Ymean); 

Тогда я попробовал это.

[m, n] = size(Y);
nonZeroNum = nnz(Y); 
Ynorm = spalloc(m,n,nonZeroNum); 
for i = 1:m
    Ynorm(i, :) = spfun(@(x)(x - Ymean(i)), Y(i, :));
end

Однако это не векторизованное решение слишком медленное.

Я также думал о комбинировании bsxfun и spfun, но не смог.

У кого-нибудь есть векторизованное решение?

1 ответ

Решение

Очень просто.

Случайная разреженная матрица.

A = sprand(100,100,.05);

Грести значит. Если в строке нет ненулевых элементов, мы ожидаем, что 0/0 = NaN, но следующий шаг никогда не затронет эту строку.

rowmeans = sum(A,2)./sum(A~=0,2);

Извлечь ненулевые.

[i,j.a] = find(A);

И восстановить массив, значит вычесть.

[n,m] = size(A);
B = sparse(i,j,a - rowmeans(i),n,m);

Теперь проверь это. Не забывайте, что здесь применяется арифметика с плавающей запятой, поэтому значение строки не будет точно нулевым, только порядка eps.

min(mean(B,2))
ans =
   (1,1)     -1.5543e-17

max(mean(B,2))
ans =
   (1,1)      1.1657e-17

Кажется, правильно и полностью векторизовано. Чтобы убедить вас, что результат действительно скудный и нулевые элементы не были повреждены, вот результат шпиона.

spy(B)

spyplot.jpg

Другие вопросы по тегам