2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Быстрая нормировкаматрицы на 1 в Matlab
Сообщение23.04.2014, 19:51 
В Matlabe часто нужно нормировать каждый столбец матрицы, что бы сумма элементов каждого столбца давала 1.
Я делаю это циклом по всем столбцам:
for i=1:D
M(:,i)=M(:,i)/sum(M(:,i));
end

Может быть кто-то может предложить более быстрый способ ? Может есть способ избежать цикла for или встроенная функция?

 
 
 
 Re: Быстрая нормировкаматрицы на 1 в Matlab
Сообщение24.04.2014, 01:49 
Аватара пользователя
Я попробовал следующие варианты:

Ваш способ:
Используется синтаксис Matlab M
tic, for iter=1:100 M=rand(1000,1000); for i=1:1000 M(:,i)=M(:,i)/sum(M(:,i)); end; end;toc
Elapsed time is 4.650408 seconds.


Векторный вариант, без циклов... (который описан еще и здесь:http://stackoverflow.com/questions/4521593/fast-technique-for-normalizing-a-matrix-in-matlab)

Используется синтаксис Matlab M
tic, for iter=1:100 M = rand(1000,1000); M=M./repmat(sum(M), [length(M), 1]); end; toc
Elapsed time is 9.929461 seconds.


Но, это все сделано в виртуальной машине, в Matlab 7.7.0 R2008b. Поэтому, возможно, что-то изменится на реальном железе?!

Есть еще в matlab функция normc, возможно ее функционал в последующих версиях изменился и она может выполнять такое преобразование матрицы.

 
 
 
 Re: Быстрая нормировкаматрицы на 1 в Matlab
Сообщение24.04.2014, 10:01 
Аватара пользователя
Вот как это работает у меня (8.3.0.532 (R2014a)).

Первый вариант:
Используется синтаксис Matlab M
tic, for iter=1:100 M=rand(1000,1000); for i=1:1000 M(:,i)=M(:,i)/sum(M(:,i)); end; end;toc
Elapsed time is 3.222425 seconds.


Второй вариант:
Используется синтаксис Matlab M
tic, for iter=1:100 M = rand(1000,1000); M=M./repmat(sum(M), [length(M), 1]); end; toc
Elapsed time is 3.023139 seconds.


Но я бы применил встроенную функцию bsxfun:
Используется синтаксис Matlab M
tic, for iter=1:100 M = rand(1000,1000); M = bsxfun(@rdivide,M,sum(M)); end; toc
Elapsed time is 2.814161 seconds.


Почитайте справку о функции bsxfun, она выполняет поэлементные бинарные операции между массивами. Никаких циклов, тривиальный код.

 
 
 
 Re: Быстрая нормировкаматрицы на 1 в Matlab
Сообщение24.04.2014, 12:04 
Используется синтаксис Matlab M
a=rand(3,4)
b=a/diag(sum(a))

Время не засекал.

-- Чт апр 24, 2014 13:08:57 --

А, ну засёк: Elapsed time is 0.137243 seconds для матрицы 1100*900 (время от запуска к запуску, естественно, немного плавает).

Т.е. оно плавает где-то в пределах 0.12 - 0.15 секунд. Время на собственно нормировку довольно стабильно чуть превышает 0.10 секунд.

 
 
 
 Re: Быстрая нормировкаматрицы на 1 в Matlab
Сообщение24.04.2014, 13:15 
Аватара пользователя
ewert
Ваш вариант:

Используется синтаксис Matlab M
tic, for iter=1:100 M = rand(1000,1000); M = M/diag(sum(M)); end; toc
Elapsed time is 13.386494 seconds.


довольно долгий, по сравнению с предыдущими... Впрочем, если ТС это нужно будет делать один раз, не в циклах, с небольшими матрицами, то какая разница...

 
 
 
 Re: Быстрая нормировкаматрицы на 1 в Matlab
Сообщение25.04.2014, 20:26 
Благодарю всех за ответы.

Я протестировал все варианты, работают примерно одинакового, но вариант с bsxfun немного лучше. Но на больших матрицах (больших для оперативной памяти) варианты с repmat diag выдавали out of memory, а другие варианты еще работали.

 
 
 
 Re: Быстрая нормировкаматрицы на 1 в Matlab
Сообщение26.04.2014, 10:16 
ShMaxG в сообщении #853830 писал(а):
довольно долгий, по сравнению с предыдущими...

Зато крайне короткий и без извращений. А долгий он, видимо, потому, что умножение на диагональную матрицу производится тупо именно как перемножение матриц. Если заменить его поэлементным умножением на произведение единичного столбца и строки сумм, то будет считать раз в семь быстрее (почему именно в семь -- не знаю).

 
 
 [ Сообщений: 7 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group