Mentions légales du service

Skip to content
Snippets Groups Projects
Commit aebf2f37 authored by hhakim's avatar hhakim
Browse files

Add a fourth notebook to demonstrate the use of FAµST API to write algorithms like OMP.

parent e23a5333
Branches
Tags
No related merge requests found
This diff is collapsed.
%% Cell type:markdown id: tags:
# Using the FAµST API in Algorithms
After the little tour we've done in the previous notebooks, about the creation of Faust objects, their manipulation and their use in factorization algorithms, we shall see in this fourth notebook how the FAµST API can be deployed seamlessly in algorithms.
Our example, already alluded in the second notebook, we'll be the Orthogonal Matching Pursuit algorithm (OMP).
This algorithm intervenes in the dictionary learning problem. Of course, I won't treat the theory behind but I assume the reader is already familiar to.
They're not so much to say so let's go straight in the code example.
%% Cell type:markdown id: tags:
### 1. The OMP Algorithm Implementation
%% Cell type:code id: tags:
``` python
from pyfaust import *
from numpy import zeros, copy, argmax
def omp(y, D, niter):
m,n = D.shape
x = zeros((n,1))
supp = []
res = copy(y)
i = 0
K = min(*D.shape)
while (len(supp) < K and i < niter):
j = argmax(abs(D.T*res))
supp += [j]
x[supp,:] = pinv(D[:,supp])*y
res = y-D[:,supp]*x[supp,:]
i += 1
return x
```
%% Cell type:markdown id: tags:
The most important point to notice in this code is that except the import part in the header, all the code seems to be a natural numpy implementation of OMP.
This is in fact the core philosophy of the FAµST API, as explained in previous notebooks and also in the API documentation, we have wanted a Faust to be seen as a numpy array (or rather as a numpy.matrix) hence this code is in fact totally compatible with the two APIs: the D function argument, which is the dictionary, can be indifferentially a pyfaust.Faust object or a numpy.matrix object.
In the next, we'll test this implementation in the both cases. But first, let's define a test case.
%% Cell type:markdown id: tags:
### 2. The Test Case Dictionary
%% Cell type:markdown id: tags:
For convenience, we shall set up a dictionary which garanties uniqueness of representations.
The dictionary will hence be the concatenation of an identity matrix and a Hadamard matrix, and because we work with Faust objects, this concatenation will be a Faust object.
Below is the block matrix of our dictionary:
$
D =
\left[
\begin{array}{c|c}
I_n & H_n \\
\end{array}
\right]
$
$I_n$ is the identity or dirac matrix and $H_n$ the hadamard matrix, with n being a power of two.
The condition on which the uniqueness of the representation $x$ of a vector $y$ is insured is defined by the following inequality:
$ \| x \|_0 < (1 + 1/\mu)/2 $ where $\mu$ denotes the coherence of the dictionary and in case of our specially crafted dictionary $\mu = {1 \over \sqrt n}$
So let's construct the Faust of D, compute y for a unique x and test our OMP implementation to find out if we effectively retrieve the unique x as we should according to this theorem.
Note that, for a better view and understanding you might consult this document: [Rémi Gribonval HDR](http://videos.rennes.inria.fr/hdr/gribonval/HDR2007.pdf).
%% Cell type:code id: tags:
``` python
from pyfaust import FaustFactory as FF
from numpy import log2
n = 128
log2n = log2(n)
FD = FF.eye(n).concatenate(FF.wht(log2n), axis=1)
D = FD.todense()
print(D)
```
%% Output
[[ 1. 0. 0. ..., 1. 1. 1.]
[ 0. 1. 0. ..., -1. 1. -1.]
[ 0. 0. 1. ..., 1. -1. -1.]
...,
[ 0. 0. 0. ..., 1. -1. 1.]
[ 0. 0. 0. ..., -1. 1. 1.]
[ 0. 0. 0. ..., 1. 1. -1.]]
%% Cell type:markdown id: tags:
Now that we have our dictionary both defined as a Faust and as a matrix, let's construct our sparsity satisfiying vector x, we'll call it $x_0$.
%% Cell type:code id: tags:
``` python
from numpy import zeros, count_nonzero
from numpy.random import randn
from random import randint
from math import floor, sqrt
x0 = zeros((FD.shape[1], 1))
nnz = max(1,randint(1,floor(.5*(1+sqrt(n)))))
nonzero_inds = []
while len(nonzero_inds) < nnz:
nonzero_inds += [ randint(0,n) for i in range(0,nnz) ]
nonzero_inds = list(set(nonzero_inds)) # set imposes id. uniqueness
# we got nz indices, now build the vector x0
x0[nonzero_inds,0] = [ randn()*50 for i in range(0,len(nonzero_inds)) ]
print("l0 norm of x0: ", count_nonzero(x0))
```
%% Output
l0 norm of x0: 1
%% Cell type:markdown id: tags:
It remains to compute $y$, normalizing FD and D before.
%% Cell type:code id: tags:
``` python
FD = FD.normalize()
D = FD.todense()
y = FD*x0
```
%% Cell type:markdown id: tags:
Our test case is complete, we are fully prepared to run our OMP algorithm using a well-defined dictionary as a Faust or as numpy array we should retrieve our $x_0$ from the vector y. Let's try!
%% Cell type:markdown id: tags:
### 3. Running the Algorithm
%% Cell type:code id: tags:
``` python
x = omp(y, FD, nnz)
from numpy import allclose
assert(allclose(x,x0))
print("We succeeded to retrieve x0, OMP works!")
```
%% Output
We succeeded to retrieve x0, OMP works!
%% Cell type:markdown id: tags:
We tested OMP on a Faust, go ahead and verify what I was aiming to in the first part of the notebook; is this OMP implementation really working as well on a Faust and on a numpy.matrix?
%% Cell type:code id: tags:
``` python
x = omp(y, D, nnz)
assert(allclose(x,x0))
print("We succeeded to retrieve x0, OMP works!")
```
%% Output
We succeeded to retrieve x0, OMP works!
%% Cell type:markdown id: tags:
We can conclude that the algorithm is indeed available to both numpy and Faust worlds, and we can imagine surely that other algorithms are reachable through the FAµST API. That's anyway in that purpose that the FAµST library will be extended in the future (starting from the latest version which is 2.5.1).
%% Cell type:markdown id: tags:
***The fourth notebook is ending here***, I hope you'll be interested to try yourself writing another algorithm with the FAµST API and maybe discover any current limitation. Don't hesitate to contact us in that case, we'll appreciate any feedback!
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment