Правильный способ вычислить косинусное сходство между двумя массивами?

Я работаю над проектом, который определяет некоторые особенности двух входных изображений (рукописные подписи) и сравнивает эти две функции с использованием косинусного сходства. Здесь, когда я имею в виду два входных изображения, одно - исходное изображение, а другое - дублированное изображение. Скажем, я извлекаю 15 таких функций из одного изображения (исходного изображения) и сохраняю их в одном массиве (скажем, Array_ORG), а функции другого изображения сохраняются в Array_DUP аналогичным образом. Теперь я пытаюсь вычислить косинусное сходство между этими двумя массивами. Эти массивы имеют двойной тип данных.

Я перечисляю два метода, которым я следовал:

1) Ручной расчет косинусного подобия:

main(){

for(int i=0;i<15;i++)
    sum_org += (Array_org[i]*Array_org[i]);
for(int i=0;i<15;i++)
    sum_dup += (Array_dup[i]*Array_dup[i]);
double magnitude = sqrt(sum_org +sum_dup );
double cosine_similarity = dot_product(Array_org, Array_dup, sizeof(Array_org)/sizeof(Array_org[0]))/magnitude;
}

double dot_product(double *a, double* b, size_t n){
double sum = 0;
    size_t i;

    for (i = 0; i < n; i++) {
            sum += a[i] * b[i];
    }

    return sum;
}

2) Сохранение значений в Mat и вызов функции точки:

Mat A = Mat(1,15,CV_32FC1,&Array_org);
Mat B = Mat(1,15,CV_32FC1,&Array_dup);
double similarity = cal_theta(A,B);

double cal_theta(Mat A, Mat B){
double ab = A.dot(B);
double aa = A.dot(A);
double bb = B.dot(B);
return -ab / sqrt(aa*bb);
}

Я читал, что значение подобия косинуса колеблется от -1 до 1, где -1 означает, что оба они точно противоположны, а 1 означает, что оба они равны. Но первая функция дает мне значения в 1000, а вторая функция дает мне значения больше 1.
Пожалуйста, объясните мне, какой процесс правильный и почему? Также как мне сделать вывод о сходстве, если значения схожести косинуса больше 1?


person Shruthi Kodi    schedule 22.05.2015    source источник


Ответы (2)


Правильное определение косинусного подобия:

введите описание изображения здесь

Ваш код не вычисляет знаменатель, следовательно, значения неверны.

double cosine_similarity(double *A, double *B, unsigned int Vector_Length)
{
    double dot = 0.0, denom_a = 0.0, denom_b = 0.0 ;
     for(unsigned int i = 0u; i < Vector_Length; ++i) {
        dot += A[i] * B[i] ;
        denom_a += A[i] * A[i] ;
        denom_b += B[i] * B[i] ;
    }
    return dot / (sqrt(denom_a) * sqrt(denom_b)) ;
}
person a_pradhan    schedule 22.05.2015
comment
Извините, похоже, это опечатка, я делю dot_product только по величине. Я изменил имена переменных для лучшего понимания при публикации, и произошла опечатка. - person Shruthi Kodi; 22.05.2015
comment
Охк, пройдите мой модифицированный код. Вы неправильно рассчитываете знаменатель! Это должно быть sqrt(sum_org*sum_dup). Вы прибавляли, а не умножали. - person a_pradhan; 22.05.2015
comment
Спасибо! Получил ошибку :) Оба метода дают один и тот же ответ, но знаете ли вы, как я могу сделать вывод о сходстве, если значение больше 1? - person Shruthi Kodi; 22.05.2015
comment
@ShruthiKodi величина значения не может быть больше 1, т.к. |AB|^2 <= norm(A)norm(B) (неравенство Коши-Шварца) - person vsoftco; 22.05.2015
comment
@vsoftco, именно так! Это меня беспокоит. Приведенный выше код дает мне значение типа 2.6821e + 006. Я серьезно не понимаю, что мне следует понимать под этим значением? Любые подсказки будут полезны. - person Shruthi Kodi; 22.05.2015
comment
@ShruthiKodi убедитесь, что вы не выходите за границы, так как он не может дать вам значение больше 1 - person vsoftco; 22.05.2015
comment
Как сказал @vsoftco, функция не может возвращать ничего больше 1,0 или меньше 0,0. Итак, проверьте, к чему вы получаете доступ. - person a_pradhan; 22.05.2015
comment
Спасибо. Код еще раз проверю. Спасибо за вклад. :) - person Shruthi Kodi; 22.05.2015

Просто добавив метод, который с Opencv (C ++) вычисляет косинусное сходство векторов функций:

float cosSim = f1.dot(f2) / (cv::norm(f1) * cv::norm(f2));

где f1 и f2 являются одномерными cv::Mat с размером (1, xx).

person Hu Xixi    schedule 05.11.2020