UNPKG

2.17 kBJavaScriptView Raw
1import { factory } from '../../utils/factory.js';
2var name = 'kldivergence';
3var dependencies = ['typed', 'matrix', 'divide', 'sum', 'multiply', 'dotDivide', 'log', 'isNumeric'];
4export var createKldivergence = /* #__PURE__ */factory(name, dependencies, (_ref) => {
5 var {
6 typed,
7 matrix,
8 divide,
9 sum,
10 multiply,
11 dotDivide,
12 log,
13 isNumeric
14 } = _ref;
15
16 /**
17 * Calculate the Kullback-Leibler (KL) divergence between two distributions
18 *
19 * Syntax:
20 *
21 * math.kldivergence(x, y)
22 *
23 * Examples:
24 *
25 * math.kldivergence([0.7,0.5,0.4], [0.2,0.9,0.5]) //returns 0.24376698773121153
26 *
27 *
28 * @param {Array | Matrix} q First vector
29 * @param {Array | Matrix} p Second vector
30 * @return {number} Returns distance between q and p
31 */
32 return typed(name, {
33 'Array, Array': function ArrayArray(q, p) {
34 return _kldiv(matrix(q), matrix(p));
35 },
36 'Matrix, Array': function MatrixArray(q, p) {
37 return _kldiv(q, matrix(p));
38 },
39 'Array, Matrix': function ArrayMatrix(q, p) {
40 return _kldiv(matrix(q), p);
41 },
42 'Matrix, Matrix': function MatrixMatrix(q, p) {
43 return _kldiv(q, p);
44 }
45 });
46
47 function _kldiv(q, p) {
48 var plength = p.size().length;
49 var qlength = q.size().length;
50
51 if (plength > 1) {
52 throw new Error('first object must be one dimensional');
53 }
54
55 if (qlength > 1) {
56 throw new Error('second object must be one dimensional');
57 }
58
59 if (plength !== qlength) {
60 throw new Error('Length of two vectors must be equal');
61 } // Before calculation, apply normalization
62
63
64 var sumq = sum(q);
65
66 if (sumq === 0) {
67 throw new Error('Sum of elements in first object must be non zero');
68 }
69
70 var sump = sum(p);
71
72 if (sump === 0) {
73 throw new Error('Sum of elements in second object must be non zero');
74 }
75
76 var qnorm = divide(q, sum(q));
77 var pnorm = divide(p, sum(p));
78 var result = sum(multiply(qnorm, log(dotDivide(qnorm, pnorm))));
79
80 if (isNumeric(result)) {
81 return result;
82 } else {
83 return Number.NaN;
84 }
85 }
86});
\No newline at end of file