# How can I implement tangent distance for k-nearest neighbor in python/scikit-learn?

My ultimate aim is to have a function which I can feed into scikit-learn's NearestNeighbor class as a custom metric parameter.

# Existing packages

I have been researching existing libraries for a while.

The only thing I found was this KMeans package, for python 2 and based on implementing a C library. I could neither load it in with ctypes nor convert it into an executable with gcc.

I also found this other C code and this Matlab script but with similar results.

# Implementation

I also looked into a few papers, to see if I can implement it by myself. For instance, based on this I understand that the main thing I need to do is to calculate the tangent matrix. But, I do not understand

• how do I define $$s(p, \alpha)$$ and especially
• how do I calculate the derivatives in python.

I would be glad for any help, comment, whatsoever.

# Update

As suggested, I raised the following related issues/requests:

# Update 2

@ComeOnGetMe rewrote his code so it can be used along the scikit-learn specifications (example code). Many thanks for that! Nonetheless, when I tried to use it in scikit-learn it underperformed and was very slow, so there is further work needed with that.

Since then I also found a more detailed explanation for code implementation, although based on the C code already mentioned.

I would just repeat my reply under the original issue in case anybody is looking for the answer here.

### The direct answer to the issue:

I can't really recall how I used this code 2 years ago. But I got it working with two steps:

1. Build the shared library with gcc -fPIC -shared st.c -o ts.so.
2. Change the .so path in tangentDistance.py to the absolute path of the ts.so file.

I have just updated the code so that you can run it directly after compiling the .so file in the root directory.

### A bit of comment on this repo:

Clearly this library is not well designed and filled with so much hardcodes. You can't really use it if you are not doing exactly the same task as I was doing: k-means clustering on MNIST dataset. If you want it to be more general and better fit your purposes just let me know.

• Great, many thanks for this! I try to build the shared library, but got another error message: gcc: error: st.c: No such file or directory // gcc: fatal error: no input files // compilation terminated. I suppose I would need to reinstall gcc for this? I continue to investigate and will get back if have some results. Dec 2 '18 at 21:43
• By 'root' I mean the root of the repository where the st.c file is located. Dec 2 '18 at 21:57
• BTW You don't need to compile it since I have pushed the .so file. Just pull from the repo and you are good to go. Dec 2 '18 at 21:58
• Thanks for this. I detailed my experiences on your KMeans package's github page. Dec 2 '18 at 23:35

ComOnGetMe's KMeans tangent distance metric looks good, if it didn't work for you initially you should fork it and work on the code. I would contact him directly, he probably would have insight for you. Scikit-learn doesn't have a distance metric for tangent distances but the documentation states you can call a user-defined distance (all be it with overhead).

Contributing code might be a good direction to go if you would want to contact scikit-learn's developers and there are a couple of researchers with published papers implementing tangent distance as a metric, so you could have luck there too.

• Thanks for this! I raised these issues as you suggested (see the links at the end), but to fork/contribute I still would need to understand how should I do it. [1]: github.com/ComeOnGetMe/… [2]: github.com/scikit-learn/scikit-learn/issues/12711 Dec 2 '18 at 10:07
• The paper I linked by some researchers who implemented it explains it pretty throughly. Basically it's a local linearity metric that scales using the jacobian determinant and uses a tangent transform. If you're familiar with manifold learning and take a look at [Tangent_space](en.wikipedia.org/wiki/Tangent_space) you can see the theoretical implications to distance metrics. Contributing to the code is more-or-less a process of studying it and getting it to work, which isn't something I can help out with on stackexchange, but I hope you do get it working! Dec 3 '18 at 17:54