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

У меня есть 2 вектора с 11 измерениями.

a <- c(-0.012813841, -0.024518383, -0.002765056,  0.079496744,  0.063928973,
        0.476156960,  0.122111977,  0.322930189,  0.400701256,  0.454048860,
        0.525526219)

b <- c(0.64175768,  0.54625694,  0.40728261,  0.24819750,  0.09406221, 
       0.16681692, -0.04211932, -0.07130129, -0.08182200, -0.08266852,
       -0.07215885)

cosine_sim <- cosine(a,b)

который возвращает:

-0.05397935

Я использовал cosine() из пакета lsa.

для некоторых значений я получаю отрицательный cosine_sim, как данный. Я не уверен, как сходство может быть отрицательным. Он должен быть между 0 и 1.

Может ли кто-нибудь объяснить, что здесь происходит.


person Robin    schedule 06.07.2011    source источник
comment
взгляните на ссылку в Википедии для косинусного подобия (en.wikipedia.org/wiki/Cosine_similarity ). в нем четко указано, что значения лежат между -1 и 1, где -1 указывает на полное несходство, а 1 указывает на полное сходство.   -  person Ramnath    schedule 06.07.2011
comment
Подсказка в названии. Функция тригометрического косинуса может принимать значения от -1 до 1, так что можно ожидать, что и эта функция тоже.   -  person Richie Cotton    schedule 06.07.2011
comment
Тот же вопрос о CrossValidated: Можно ли получить отрицательное косинусное сходство с использованием LSA?   -  person smci    schedule 30.03.2017


Ответы (4)


Преимущество R в том, что вы часто можете копаться в функциях и сами видеть, что происходит. Если вы введете cosine (без каких-либо скобок, аргументов и т. д.), то R распечатает тело функции. Поковырявшись в ней (что требует некоторой практики), можно увидеть, что есть куча машин для вычисления попарного сходства столбцов матрицы (т.е. бит, завернутый в условие if (is.matrix(x) && is.null(y)), но ключевая строка функции

crossprod(x, y)/sqrt(crossprod(x) * crossprod(y))

Давайте вытащим это и применим к вашему примеру:

> crossprod(a,b)/sqrt(crossprod(a)*crossprod(b))
            [,1]
[1,] -0.05397935
> crossprod(a)
     [,1]
[1,]    1
> crossprod(b)
     [,1]
[1,]    1

Итак, вы используете уже нормализованные векторы, так что у вас есть только crossprod для просмотра. В вашем случае это эквивалентно

> sum(a*b)
[1] -0.05397935

(для реальных матричных операций crossprod намного эффективнее, чем построение эквивалентной операции вручную).

Как говорится в ответе @Jack Maney, скалярное произведение двух векторов (длина (a) * длина (b) * cos (a, b)) может быть отрицательным...

Для чего бы это ни стоило, я подозреваю, что функция cosine в lsa может быть более легко/эффективно реализована для аргументов матрицы как as.dist(crossprod(x))...

редактировать: в комментариях к уже удаленному ответу ниже я предположил, что квадрат меры косинусного расстояния может быть подходящим, если кто-то хочет получить меру сходства на [0, 1] -- это было бы аналогично использованию коэффициента детерминации (r^2), а не коэффициента корреляции (r) -- но, возможно, стоит вернуться и более тщательно обдумать цель/значение подобия меры, которые следует использовать...

person Ben Bolker    schedule 06.07.2011

Функция cosine возвращает

crossprod(a, b)/sqrt(crossprod(a) * crossprod(b))

В этом случае оба члена в знаменателе равны 1, но crossprod(a, b) равно -0,05.

person Richie Cotton    schedule 06.07.2011

функция косинуса может принимать отрицательные значения.

person Community    schedule 06.07.2011

В то время как косинус двух векторов может принимать любое значение от -1 до +1, косинус сходство (при поиске документа) используется для получения значений из интервала [0,1]. Причина проста: в матрице WordxDocument нет отрицательных значений, поэтому максимальный угол двух векторов равен 90 градусов, для которого косинус равен 0.

person Surjan    schedule 13.01.2017