Одни и те же матричные операции возвращают разные результаты в Matlab

У меня небольшая проблема с Matlab, я думаю, это связано с точностью Matlab, но я бы очень хотел ее решить. У меня есть три матрицы, одна называется f размером 296x3118, другая называется mapping.mean размером 1x3118 и последняя называется mapping.M размером 3118x100.
Результатом следующих операций должна быть единица, но это не так. Полученные матрицы f_s_1 и f_s_2 имеют значения, которые отличаются только в диапазоне 10^-12. Кто-нибудь знает, почему или как это исправить?

f_s_1 = ((f(1:296,:)-repmat(mapping.mean,296,1))*mapping.M)';
f_s_2 = ((f(1:295,:)-repmat(mapping.mean,295,1))*mapping.M)';
isequal(f_s_1(:,1:295),f_s_2)

ans =

 0

person SwatchPuppy    schedule 02.07.2012    source источник


Ответы (1)


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

Поскольку ваш компьютер использует только небольшое количество битов для представления вашего числа (в вашей версии Matlab он, вероятно, использует 64 бита), у вас часто будет небольшая часть десятичного числа, которая обрезается при выполнении операций. На самом деле, когда вы добавляете очень большое число к очень маленькому числу, компьютер может вернуть в результате только очень большое число, потому что «больше нет места» для представления меньшего числа.

Например, попробуйте запустить следующий код:

mybase = 1e17;

sum1 = mybase + sum(1e-4*ones(2^14,1)) - mybase
sum2 = mybase - mybase + sum(1e-4*ones(2^14,1))

Вы должны получить:

sum1 =

     0


sum2 =

    1.6384

хотя суммы просто переставлены, они дают разные числа. Если вы поиграете с этим, вы обнаружите, что MATLAB складывает числа слева направо, и когда числа сильно различаются по величине, начинают возникать проблемы. Поскольку 1,6384 — это такая маленькая доля от 1e17, мы могли бы считать это вообще не настоящей ошибкой... но ясно, что ответ неверен, и все из-за порядка нашей суммы.

Почему это актуально здесь? Как мы отмечали ранее, если MATLAB решит распараллелить операцию, то каждая часть задачи будет вычисляться одновременно, а затем объединяться. Фрагменты могут добавляться в другом порядке в зависимости от многих факторов (размер задачи, другие действия компьютера и т. д.). Это означает, что результат будет немного другим. Если вы установите матрицы одинакового размера в моей версии (R2012a), вы можете получить тот же ответ... а можете и нет. Кроме того, это будет зависеть от размера.

Это поведение является «функцией», и я получил тот же ответ даже при использовании maxNumCompThreads(1)

person Steve    schedule 02.07.2012