1
$\begingroup$

Has anyone ever tried to implement the geometric difference metric introduced in the Google's power of data paper? It is defined in Eq. 5.

enter image description here

My implementation of the metric is as follows.

def geometric_difference(kernel_1, kernel_2):
#     diff = -1
    diff = np.sqrt(np.linalg.norm( 
        np.matmul(np.matmul(np.sqrt(kernel_2), 
                            np.linalg.inv(kernel_1)), 
                  np.sqrt(kernel_2)), np.inf))
    
    return diff

I understand that when I compute the geometric difference of a kernel matrix with itself, it should give $1$.

However, I am getting $3.5425853205393496$ which is greater than $1$ for the following matrix.

M = np.array([[1.0, 0.9864463445333996, 0.9740668604480669, 0.9522423474912594, 0.9924537684077833, 0.8895864607254809, 0.8911800123689296, 0.9273022835638276, 0.9093065295855488, 0.942937484839194], [0.9864463445333996, 1.0, 0.9362292204642889, 0.9058183417109515, 0.9720042335801492, 0.8236054328646096, 0.8311148112692656, 0.873310656326527, 0.8563983095457245, 0.9095079241006527], [0.9740668604480669, 0.9362292204642889, 1.0, 0.9251948438121138, 0.9922213493721925, 0.9667491686359904, 0.9689939767213887, 0.9872801673373786, 0.9786773752322605, 0.9889003372198818], [0.9522423474912594, 0.9058183417109515, 0.9251948438121138, 1.0, 0.9299880514954331, 0.8633016543725155, 0.8480159549979944, 0.8846832119506772, 0.8549651220805452, 0.8625840477854568], [0.9924537684077833, 0.9720042335801492, 0.9922213493721925, 0.9299880514954331, 1.0, 0.9286669208701384, 0.9333471169337565, 0.9608763731749859, 0.9493255688093539, 0.9761062630584328], [0.8895864607254809, 0.8236054328646096, 0.9667491686359904, 0.8633016543725155, 0.9286669208701384, 1.0, 0.9980284463169727, 0.994348065667556, 0.993861166093055, 0.9695176223678753], [0.8911800123689296, 0.8311148112692656, 0.9689939767213887, 0.8480159549979944, 0.9333471169337565, 0.9980284463169727, 1.0, 0.9957851054969118, 0.9982181534658013, 0.9791400659545252], [0.9273022835638276, 0.873310656326527, 0.9872801673373786, 0.8846832119506772, 0.9608763731749859, 0.994348065667556, 0.9957851054969118, 1.0, 0.9978737256112197, 0.9885554512243394], [0.9093065295855488, 0.8563983095457245, 0.9786773752322605, 0.8549651220805452, 0.9493255688093539, 0.993861166093055, 0.9982181534658013, 0.9978737256112197, 1.0, 0.989447655967652], [0.942937484839194, 0.9095079241006527, 0.9889003372198818, 0.8625840477854568, 0.9761062630584328, 0.9695176223678753, 0.9791400659545252, 0.9885554512243394, 0.989447655967652, 1.0]])

Could anyone help me to understand what I am doing wrong?

$\endgroup$
3
$\begingroup$

This is because $\sqrt{K^2}$ is not the matrix whose entries are the square root of those of $K^2$, but the matrix such that $\left(\sqrt{K^2}\right)^2=K^2$. You can compute this matrix by, for instance, performing an SVD decomposition on your matrix using numpy, like this:

import numpy as np

def geometric_difference(kernel_1, kernel_2):
    u, s, v = np.linalg.svd(kernel_2, hermitian=True)
    sqrt_k2 = u @ np.diag(np.sqrt(s)) @ v
    return np.sqrt(np.linalg.norm(sqrt_k2 @ np.linalg.inv(kernel_1) @ sqrt_k2, np.inf))

Applying this function on the matrix you provided yields 1.0000000010916217. Note that it is also possible, and potentially faster, to compute $\sqrt{K^2}$ using the scipy.linalg.sqrtm function.

$\endgroup$
3
  • $\begingroup$ thanks a lot for your response. I was able to reproduce your number 1.0000000010916217. Out of curiosity, I normalized the input matrix using normalize(kernel_1, axis=1, norm='l1') before passing it into geometric_difference() and got 505.20041904170046 instead of ~1. Any idea why? $\endgroup$ Jun 16 at 15:25
  • $\begingroup$ I'm not sure what is meant by the normalize function here but its customary to rescale an $m\times m$ kernel matrix $K$ such that $\text{Tr}(K) = m$ (or $K_{ii}=1, i=1\dots m$); this is also the normalization the authors apply in the text. $\endgroup$
    – forky40
    Jun 16 at 18:38
  • $\begingroup$ @OmarShehab To add on @forky40's answer, your kernel is supposed to be Hermitian. You can look at the norm of M's columns with np.linalg.norm(M, 1, axis=1) which returns [9.46552209, 9.09443527, 9.7183133 , 9.02679358, 9.63498965, 9.42766494, 9.44382364, 9.61001504, 9.52807361, 9.60669685]. Thus, by applying the normalize function from sklearn, you won't divide each column by the same coefficient. Hence, the resulting matrix is not Hermitian anymore. If you really want to compute it despite this, remove the hermitian=True in the function, which returns 1.0284638009215255. $\endgroup$ Jun 17 at 6:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.