#[burn_tensor_testgen::testgen(cosine_similarity)]
mod tests {
use super::*;
use burn_tensor::TensorData;
use burn_tensor::linalg;
use burn_tensor::{ElementConversion, Tolerance, ops::FloatElem};
type FT = FloatElem<TestBackend>;
#[test]
fn test_cosine_similarity_basic() {
let x1 = TestTensor::<2>::from([[1.0, 2.0, 3.0], [0.5, 1.5, 2.5]]);
let x2 = TestTensor::<2>::from([[1.5, 2.5, 3.5], [0.7, 1.7, 2.7]]);
let expected = TestTensor::<2>::from([[0.99983203], [0.99987257]]).into_data();
linalg::cosine_similarity(x1.clone(), x2.clone(), 1, None)
.into_data()
.assert_approx_eq::<FT>(&expected, Tolerance::default());
linalg::cosine_similarity(x1.clone(), x2.clone(), 1, Some(1e-8.elem::<FT>()))
.into_data()
.assert_approx_eq::<FT>(&expected, Tolerance::default());
}
#[test]
fn test_cosine_similarity_orthogonal() {
let x1 = TestTensor::<2>::from([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]);
let x2 = TestTensor::<2>::from([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]);
let expected = TestTensor::<2>::from([[0.0], [0.0]]).into_data();
linalg::cosine_similarity(x1, x2, 1, None)
.into_data()
.assert_eq(&expected, true);
}
#[test]
fn test_cosine_similarity_parallel() {
let x1 = TestTensor::<2>::from([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]);
let x2 = TestTensor::<2>::from([[2.0, 4.0, 6.0], [8.0, 10.0, 12.0]]);
let expected = TestTensor::<2>::from([[1.0], [1.0]]).into_data();
linalg::cosine_similarity(x1, x2, 1, None)
.into_data()
.assert_approx_eq::<FT>(&expected, Tolerance::default());
}
#[test]
fn test_cosine_similarity_opposite() {
let x1 = TestTensor::<2>::from([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]);
let x2 = TestTensor::<2>::from([[-1.0, -2.0, -3.0], [-4.0, -5.0, -6.0]]);
let expected = TestTensor::<2>::from([[-1.0], [-1.0]]).into_data();
linalg::cosine_similarity(x1, x2, 1, None)
.into_data()
.assert_approx_eq::<FT>(&expected, Tolerance::default());
}
#[test]
fn test_cosine_similarity_different_dimension() {
let x1 = TestTensor::<3>::from([[[1.0, 2.0], [3.0, 4.0]], [[5.0, 6.0], [7.0, 8.0]]]);
let x2 = TestTensor::<3>::from([[[2.0, 3.0], [4.0, 5.0]], [[6.0, 7.0], [8.0, 9.0]]]);
let expected =
TestTensor::<3>::from([[[0.9959688], [0.9958376]], [[0.9955946], [0.9955169]]])
.into_data();
let tolerance = Tolerance::default().set_half_precision_relative(7e-3);
linalg::cosine_similarity(x1.clone(), x2.clone(), 2, None)
.into_data()
.assert_approx_eq::<FT>(&expected, tolerance);
linalg::cosine_similarity(x1.clone(), x2.clone(), -1, None)
.into_data()
.assert_approx_eq::<FT>(&expected, tolerance);
}
#[test]
fn test_cosine_similarity_near_zero() {
let x1 = TestTensor::<2>::from([[1e-10, 2e-10, 3e-10], [4e-10, 5e-10, 6e-10]]);
let x2 = TestTensor::<2>::from([[2e-10, 4e-10, 6e-10], [8e-10, 10e-10, 12e-10]]);
let expected = TestTensor::<2>::from([[0.0028], [0.0154]]).into_data();
let epsilon = Some(FT::from_elem(1e-2));
let tolerance = Tolerance::absolute(0.2);
linalg::cosine_similarity(x1, x2, 1, epsilon)
.into_data()
.assert_approx_eq::<FT>(&expected, tolerance);
}
}