10

I am trying to create a cosine similarity function and then display the results in a HTML element. I have written the following:

function cosinesim(A,B){
        var dotproduct=0;
        var mA=0;
        var mB=0;
        for(i = 0; i < A.length;){
            dotproduct += (A[i] * B[i]);
            mA += (A[i]*A[i]);
            mB += (B[i]*B[i]);
        }
        mA = Math.sqrt(mA);
        mB = Math.sqrt(mB);
        var similarity = (dotproduct)/(mA)*(mB)
        return similarity;
    }

//.....

var array1 = [1,0,0,1];
var array2 = [1,0,0,0];

var p = cosinesim(array1,array2);
document.getElementById("sim").innerHTML = String(p);

I have tested and both the arrays I am inputting are the same length, however when my code runs to this bit it crashes and I cant seem to find what is wrong.

Any help is appreciated, thanks.

Future
  • 191
  • 2
  • 13

4 Answers4

10
function cosinesim(A, B) {
    var dotproduct = 0;
    var mA = 0;
    var mB = 0;

    for(var i = 0; i < A.length; i++) {
        dotproduct += A[i] * B[i];
        mA += A[i] * A[i];
        mB += B[i] * B[i];
    }

    mA = Math.sqrt(mA);
    mB = Math.sqrt(mB);
    var similarity = dotproduct / (mA * mB);

    return similarity;
}


var array1 = [1, 0, 0, 1];
var array2 = [1, 0, 0, 0];

var p = cosinesim(array1, array2);

console.log(p);

This should give the actual cosine similarity. You were missing:

  1. The var i and i++ in your for loop, as mentioned before.
  2. Extra brackets around (mA * mB) in this line: var similarity = dotproduct / (mA * mB); Without them, the division is done before the multiplication.
Vivasvan Patel
  • 2,458
  • 1
  • 9
  • 14
DiffXP
  • 101
  • 1
  • 2
4

Using the map and reduce the functionality of javascript

function dotp(x, y) {
  function dotp_sum(a, b) {
    return a + b;
  }
  function dotp_times(a, i) {
    return x[i] * y[i];
  }
  return x.map(dotp_times).reduce(dotp_sum, 0);
}

function cosineSimilarity(A,B){
  var similarity = dotp(A, B) / (Math.sqrt(dotp(A,A)) * Math.sqrt(dotp(B,B)));
  return similarity;
}


var array1 = [1,2,2,1];
var array2 = [1,3,2,0];

var p = cosineSimilarity(array1,array2);

console.log(p);

Hope this helps!! Happy coding!!

sriesow
  • 51
  • 2
3

you missed i++ in your loop which leads to an endless one

replacing for(i = 0; i < A.length;) to for(i = 0; i < A.length;i++) fixed the issue

user3003238
  • 1,517
  • 10
  • 17
  • 1
    Serious mistake also here: (dotproduct)/(mA)*(mB) is wrong because of operator precedence.. Use (dotproduct)/(mA * mB) instead, otherwise the score will not be in [0,1] – hymloth Jul 02 '19 at 11:23
0

function cosinesim(A,B){
        var dotproduct=0;
        var mA=0;
        var mB=0;
        for(i = 0; i < A.length; i++){
            dotproduct += (A[i] * B[i]);
            mA += (A[i]*A[i]);
            mB += (B[i]*B[i]);
        }
        mA = Math.sqrt(mA);
        mB = Math.sqrt(mB);
        var similarity = (dotproduct)/(mA)*(mB)
        return similarity;
    }


var array1 = [1,0,0,1];
var array2 = [1,0,0,0];

var p = cosinesim(array1,array2);

console.log(p);
Hardik Shah
  • 4,042
  • 2
  • 20
  • 41
  • 1
    It can go above `1` while it should be between `-1` an `1` I think. It gives e.g. `2` if I compare `[1,1,0,0]` and `[1,1,0,0]`. – gazdagergo Feb 15 '19 at 14:35
  • 1
    @gazdagergo n@HardikShah There are problems with floats and math in JS; is that maybe why it doesn't work as good as in Python? – leeand00 Apr 13 '22 at 21:46