Monday, December 10, 2007

Monday Morning Algorithm Part 6: The Fast Johnson-Lindenstrauss Transform

Last year, Nir Ailon and Bernard Chazelle described a new algorithm that improves the ability to perform the Johnson-Lindenstrauss transform. It is presented in Approximate Nearest Neighbors and the Fast Johnson-Lindenstrauss Transform (slides (ppt) are here). The summary can be described in the Fast Johnson-Lindenstrauss Transform Lemma:

Fix any set X of n vectors in R^d, epsilon < 1, and p is either 1 or 2. Let phi be the FJLT. With probability at least 2/3, we have for all x element of X: (1 + epsilon) * alpha_p * ||x||_2 < || Phi x||_p < (1 + epsilon) * alpha_p * ||x||_2 This dimension reduction technique improves a classic algorithm by Johnson and Lindenstrauss from the mid 80’s. Their technique is the first to offer an asymptotic improvement, and has already been used in design of efficient algorithms for nearest neighbor searching and high dimensional linear algebraic numerical computations. A better technique has recently surfaced as well. A good description of this new technique can be found in this presentation by Edo Liberty.

I have implemented a version of it by following the instructions on the paper but I am not convinced I have done the right implementation as the results are not so sharp to me. I haven't had much time to debug it so here it is, if you find a mistake please let me know:

clear
% Fast Johnson-Lindenstrauss Transform
% as described by Nir Ailon and Bernard Chazelle
% in their paper:
% "Approximate Nearest Neighbors and the Fast Johnson-Lindenstrauss
% Transform"
% The algorithm uses the PHD transform of paragraph 2
% The transform is a k x d projection
% for every set S of n points in R^d
% Let us define an example case
% All columns of G are sets of points
% i.e. we have 1000 points of dimension 128
n = 1000;
d = 256;
% let us examine a reduction from d = 256 to k = 150
%
k = 150;
G = 180 * rand(d,n);
% k = O(epsilon^(-2) * log(n))
epsilon = sqrt(log(n)/k)
%
% epsilon is really O( sqrt(log(n)/k) )
%
%
% Projection in dim k << d % let us take d = 2^w w = log2(d); % % % Defining P (k x d) % first define q % q = min((log(n))^2/d,1); % P = rand(k,d); P = (P < q); P1 = 1/q * randn(k,d); P = P1 .* P; % % Defining H (d x d) H = [1]; for i=1:w H = [ H H;H -H]; end H = 1/d^(0.5)* H; % % Defining D ( d x d) vec1=rand(d,1); v1 = ((vec1 > 0.5) - 1*(vec1<=0.5)); D = diag(v1); % % % FJLT = P * H * D; u = FJLT * G(:,5); v = FJLT * G(:,36); norm(G(:,5)-G(:,36))^2 * k * (1-epsilon) norm( u - v)^2 norm(G(:,5)-G(:,36))^2 * k * (1+epsilon)

9 comments:

Unknown said...

Hi
Just wondering how you evaluated the FJLT algorithm - Did you compare it with, say, taking a random matrix of the same size?
Thanks,
Nir Ailon

Unknown said...

Hi
Just wondering how you evaluated the FJLT algorithm - Did you compare it with, say, taking a random matrix of the same size?
Thanks,
Nir Ailon

Douglas Sellers said...

Hi,

I have tried this implementation as well and found it to be very lacking. I tried it against two identical images where a Gaussian blur was applied to one of them. I also tried applying an image against a random matrix of the same size and the results between the random matrix and the Gauusian blur were very similar.

Were you ever able to determine what was wrong with this implementation?

Igor said...

Hello Douglas,

I just noticed Nir's comment of a year ago !

To answer your question, no I have never looked back at this implementation. I thought I had followed as closely as possible the paper for its implementation, so I am a little surprised at:
- the results
- the fact that I did not implement the transform well.

I am all ear on making it better and I will mention it prominently in the blog if there is a better implementation (I have screwed up before and mentioned it prominently in the blog before so this is not a new exercise :) ).

Cheers,

Igor.

Unknown said...

Does anyone have a Matlab code or a Psuedocode for the Johnson Lindenstrauss Lemma for dot product?

Unknown said...

I have read through the The Fast Johnson-Lindenstrauss Transform. I even copied and pasted the code to ran and see what it does, but i don't think it is working. The aft hand side is always greater than the middle. I am just looking for a basic Johnson-Lindenstrauss lemma. Can anyone point me to a psuedocode i can use to implement it. I want to understand it. If i have a code like the one pasted here fpr the basic Johnson-Lindenstrauss lemma would also be great.

Unknown said...

Hi
Can you send me the code?
can you tell me what exactly you are trying to do?

in order to implement a JL transform (without the "fast"), you just need to draw a random plus/minus 1 matrix. Can you try, as a sanity check, to see if there is a difference between the results using your fast JL implementation and the naive JL implementation I just mentioned?

Igor said...

Unknown,

Everything that is needed is here. If you want me to do something for you then we need to get This written in a contract.

Cheers,

Igor.

Unknown said...

Hi,
I am trying to implement The Johnson-Lindenstrauss lemma using this prove here:
http://tcs.nju.edu.cn/wiki/index.php/%E9%9A%8F%E6%9C%BA%E7%AE%97%E6%B3%95_%28Fall_2011%29/Johnson-Lindenstrauss_Theorem
I don't know if i have implemented it correctly or not. Can you please check my code for me and advice me as to the correct matlab implementation.

clear
clc
n = 2;
d = 4;
% let us examine a reduction from d = 256 to k = 150
%
k = 2;
G = rand(n,d);

epsilon = sqrt(log(n)/k);

% Projection in dim k << d

% Defining P (k x d)
P = randn(k,d);


% Projecting down to k-dim
proj = P.*G;
u = proj(:,1);
v = proj(:,2);
% u = P * G(:,5);
% v = P * G(:,36);
norm(G(:,1)-G(:,2))^2 * k * (1-epsilon);
norm(u - v)^2;
norm(G(:,1)-G(:,2))^2 * k * (1+epsilon);

Printfriendly