Intel MKL Несоответствие результатов LAPACKE_dgesvd - PullRequest
0 голосов
/ 01 апреля 2020

В моем коде есть вызов функции LAPACKE_dgesvd. Этот код покрыт автотестом. После миграции компилятора мы решили обновить MKL с 11.3.4 до 2019.0.5.

И тесты стали красными. После глубокого изучения я обнаружил, что эта функция больше не возвращает те же матрицы U & V.

Я извлек код и запустил его в отдельном env / проекте и в том же наблюдении. наблюдение - это первый столбец U, а первый ряд V имеет противоположный знак

Не могли бы вы сказать, что я делаю там неправильно? или как мне использовать новую версию, чтобы получить старые результаты?

Я сделал простой проект, позволяющий легко воспроизвести проблему. Вот код:

// MKL.cpp : This file contains the 'main' function. Program execution begins and ends there
#include <iostream>
#include <algorithm>
#include <mkl.h>

int main()
{
    const int rows(3), cols(3);
    double covarMatrix[rows*cols] = { 0.9992441421012894, -0.6088405718211041, -0.4935146797825398,
                            -0.6088405718211041, 0.9992441421012869, -0.3357678733652218, 
                            -0.4935146797825398, -0.3357678733652218, 0.9992441421012761};
    double U[rows*rows] = { -1,-1,-1,
                    -1,-1,-1,
                    -1,-1,-1 };
    double V[cols*cols] = { -1,-1,-1,
                    -1,-1,-1,
                    -1,-1,-1 };
    double superb[std::min(rows, cols) - 1];
    double eigenValues[std::max(rows, cols)];

    MKL_INT info = LAPACKE_dgesvd(LAPACK_ROW_MAJOR, 'A', 'A',
        rows, cols, covarMatrix, cols, eigenValues, U, rows, V, cols, superb);

    if (info > 0)
        std::cout << "not converged!\n";

    std::cout << "U\n";
    for (int row(0); row < rows; ++row)
    {
        for (int col(0); col < rows; ++col)
            std::cout << U[row * rows + col] << " ";
        std::cout << std::endl;
    }

    std::cout << "V\n";
    for (int row(0); row < cols; ++row)
    {
        for (int col(0); col < cols; ++col)
            std::cout << V[row * rows + col] << " ";
        std::cout << std::endl;
    }

    std::cout << "Converged!\n";
}

Вот более числовые объяснения:

A = 0,9992441421012894, -0.6088405718211041, -0,4935146797825398, -0.6088405718211041, 0,99244, 216786767867132533525130525525130525330525330525370525525525525525525525867837678376783713253783713283783713283783713283783713214824833283734883783714823783714823793783793793793793793793793793793793793793793793793793792523792528052500000000000000000000000000000000000000000000000000000000000000000000 Железобода фото Хохот 0.9992441421012761

Результаты по:

11.3.4 2019.0.5 & 2020.1.216

U

-0.765774 -0.13397 0.629 0.765774 -0.13397 0.629 0.575268 - 0.579935 0,576838 0,576838 -0,575268 -0,579935 0,2875 0,803572 0,521168 0,803572 0,521168 -0,2875

* * В тысяче двадцать пять * * -0,765774 тысячи двадцать-семь 0,575268 0,765774 0,2875 -0,2875 -0,13397 -0,575268 -0,579935 0,803572 -0,13397 0,803572 -0,579935 0,629 0,576838 0,521168 0,629 0.576838 0.521168

Я тестировал с использованием scipy, и результат такой же, как и в версии 11.3.4.

from scipy import linalg
from numpy import array

A = array([[0.9992441421012894, -0.6088405718211041, -0.4935146797825398], [-0.6088405718211041, 0.9992441421012869, -0.3357678733652218], [-0.4935146797825398, -0.3357678733652218, 0.9992441421012761]])
print(A)
u,s,vt,info = linalg.lapack.dgesvd(A)
print(u)
print(s)
print(vt)
print(info)

Спасибо за вашу помощь и наилучшие пожелания

Мохтар

1 Ответ

0 голосов
/ 04 апреля 2020

Разложение в единственном числе не является уникальным. Например, если у нас есть декомпозиция SVD (например, набор матриц U, S, V), так что A = U * S * V ^ T, то набор матриц (-U, S, -V) также является SVD разложение, потому что (-U) S (- V ^ T) = U S V ^ T = A. Более того, если D - диагональная матрица, диагональные элементы которой равны -1 или 1, то набор матриц U D, S, V D также является разложением SVD, потому что (U D) S D V ^ T = U S * V ^ T = A.

С тех пор не стоит проверять декомпозицию SVD путем сравнения двух наборов матриц. Руководство пользователя LAPACK, как и многие другие публикации, рекомендует проверить следующие условия для вычисленной декомпозиции SVD: 1. || A V - U S || / || || должно быть достаточно маленьким 2. || U ^ T * U - I || близко к нулю 3. || V ^ T * V - я || близко к нулю 4. все диагональные элементы диагонали S должны быть положительными и отсортированы в порядке убывания. Границы ошибок для всех приведенных выше выражений можно найти в https://www.netlib.org/lapack/lug/node97.html

Таким образом, обе версии MKL, упомянутые в пост-возврате сингулярных значений и сингулярных векторов, которые удовлетворяли всем 4 границам ошибок , Поскольку это и потому, что SVD не является уникальным, оба результата верны. Смена знака в первых сингулярных векторах произошла из-за того, что для очень маленьких матриц начал использоваться другой, более быстрый метод приведения к двухдиагональной форме.

...