# 'Geometric difference' in Google's 'Power of data in quantum machine learning' paper

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.

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?

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.

• 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? Jun 16 at 15:25
• 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. Jun 16 at 18:38
• @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. Jun 17 at 6:58