Home > database >  Different function outputs without changing inputs in Python 3
Different function outputs without changing inputs in Python 3

Time:01-23

I have these inputs and functions

p = np.array([1., 0., 0.])
q = np.array([0., 0., 1.])
m = np.array([0.5, 0. , 0.5])

def kl(p, q):
    return np.sum(np.log2(np.divide(p, q, where=q!=0), where=p!=0))

def js(p, q):
    m = 1/2 * (p   q)
    return 1/2 * (kl(p, m)   kl(q, m))

I get these outputs:

>>> js(p, q)
3.0
>>> kl(p, m)
2.0
>>> kl(p, m)
1.0

I was expecting:

>>> js(p, q)
1.0
>>> kl(p, m)
1.0
>>> kl(p, m)
1.0

Why are the outputs wrong? I have tried breaking it up as follows:

def kl(j, m):
  s = np.divide(j, m, where=m!=0)
  t = np.log2(s, where=j!=0)
  return np.sum(t)

But I still get the wrong output. Only when I break up the code by adding a print() do I get the correct result:

def kl(j, m):
  s = np.divide(j, m, where=m!=0)
  print(s)
  t = np.log2(s, where=j!=0)
  return np.sum(t)

>>> js(p, q)
[2. 0. 0.]
[0. 0. 2.]
1.0

CodePudding user response:

Focusing just on the divide. Without the where:

In [10]: p/q
C:\Users\paul\AppData\Local\Temp\ipykernel_1128\1155702164.py:1: RuntimeWarning: divide by zero encountered in divide
  p/q
C:\Users\paul\AppData\Local\Temp\ipykernel_1128\1155702164.py:1: RuntimeWarning: invalid value encountered in divide
  p/q
Out[10]: array([inf, nan,  0.])

With the where, only the last term is calculated. The rest are "random" (as in the sense of np.empty(3):

In [11]: np.divide(p, q, where=q!=0)
Out[11]: array([1.04756264e-311, 0.00000000e 000, 0.00000000e 000])

But we can define an out array:

In [12]: res = np.zeros_like(p)    
In [13]: np.divide(p, q, where=q!=0, out=res)
Out[13]: array([0., 0., 0.])

Or to make it a bit more obvious:

In [15]: res = np.ones_like(p)

In [16]: res
Out[16]: array([1., 1., 1.])    
In [17]: np.divide(p, q, where=q!=0, out=res)
Out[17]: array([1., 1., 0.])

It's up to you to choose the correct out for both the divide and the log.

  • Related