Getting a gradient of a bi-variant function - java

I'm doing some video processing, for each frame I need to get a gradient of a bi-variate function.
The function is represented as a two dimensional array of doubles. Where the domain is the rows and columns indices and the range is the double value of the corresponding indices values. Or more simply put, the function f is defined for double[][] matrix as such:
f(x,y)=matrix[x][y]
I'm trying to use the Apache Commons Math library for it:
SmoothingPolynomialBicubicSplineInterpolator iterpolator = new SmoothingPolynomialBicubicSplineInterpolator();
BicubicSplineInterpolatingFunction f = iterpolator.interpolate(xs, ys, matrix.getData());
for (int i = 0; i < ans.length; i++) {
for (int j = 0; j < ans[0].length; j++) {
ans[i][j] = f.partialDerivativeY(i, j);
}
}
with xs, as a sorted array of the x indices (0,1,...,matrix.getRowDimension() - 1)
ys the same on the columns dimension (0,1,...,matrix.getColumnDimension() - 1)
The problem is that for a typical matrix in the size of 150X80 it takes as much as 1.4 seconds to run, which renders it completely irrelevant for my needs. So, as a novice user of this library, and programmatic numeric analysis in general, I want to know:
Am I doing something wrong?
Is there another, faster, way I can accomplish this task with?
Is there another open source library (preferably maven-friendly) that offers a solution?

Numerical differentiation is an entire topic unto itself, a simple google should bring up enough material for you to work with (just the wiki might be sufficient). There are parameters of your problem that I cannot know, so I can only speak broadly here, but there are direct methods of determining the gradient at a given point, i.e. ones that don't require an interpolation. See the wikipedia for the formulae (ranging from the simple f(x+1)-f(x), which is where h=1, to the higher order ones). Calculating the partial derivatives is then a simple O(NM) loop with an uber easy formula inside (no interpolation required).
The specifics can get gritty:
The higher order formulae need to be reduced for the edges, or
discarded altogether.
Your precise speed requirements might render more complex formulae useless (depending on the platform sometimes the lookup times for higher order formulae make them too slow; again, it depends on the cache etc.). This is easy to test, the formulae are simple; code them and benchmark.
The specific implementation is also dependent on your error requirements. The theory provides error bounds, so that will play a role in what formula you need; but again, there's a trade-off with speed requirements. The in turn can be practically lowered if you know specifics about the types of matrices you'll be processing, if such a thing is known.
The implementation can be made even easier (and maybe faster) if you have existing convolution tools, since this method is really just a convolution of the matrix (note; technically it's called a cross-correlation).

Related

Unit testing a discrete Fourier transformation

Several months ago I had to implement a two-dimensional Fourier transformation in Java. While the results seemed sane for a few manual checks I wondered how a good test-driven approach would look like.
Basically what I did was that I looked at reasonable values of the DC components and compared the AC components if they roughly match the Mathematica output.
My question is: Which unit tests would you implement for a discrete Fourier transformation? How would you validate results returned by your calculation?
As for other unit-tests, you should consider small fixed input test-vectors for which results can easily be computed manually and compared against. For the more involved input test-vectors, a direct DFT implementation should be easy enough to implement and used to cross-validate results (possibly on top of your own manual computations).
As far as specific test vectors for one-dimensional FFT, you can start with the following from dsprelated, which they selected to exercise common flaws:
Single FFT tests - N inputs and N outputs
Input random data
Inputs are all zeros
Inputs are all ones (or some other nonzero value)
Inputs alternate between +1 and -1.
Input is e^(8*j*2*pi*i/N) for i = 0,1,2, ...,N-1. (j = sqrt(-1))
Input is cos(8*2*pi*i/N) for i = 0,1,2, ...,N-1.
Input is e^((43/7)*j*2*pi*i/N) for i = 0,1,2, ...,N-1. (j sqrt(-1))
Input is cos((43/7)*2*pi*i/N) for i = 0,1,2, ...,N-1.
Multi FFT tests - run continuous sets of random data
Data sets start at times 0, N, 2N, 3N, 4N, ....
Data sets start at times 0, N+1, 2N+2, 3N+3, 4N+4, ....
For two-dimensional FFT, you can then build on the above. The first three cases are still directly applicable (random data, all zeros, all ones). Others require a bit more work but are still manageable for small input sizes.
Finally google searches should yield some reference images (before and after transform) for a few common cases such as black & white squares, rectangle, circles which are can be used as reference (see for example http://www.fmwconcepts.com/misc_tests/FFT_tests/).
99.9% of the numerical and coding issues you will likely find will be found by testing with a random complex vectors and comparing with a direct DFT to a tolerance on the order of floating point precision.
Zero, constant, or sinusoidal vectors may help understand a failure by allowing your eye to catch issues like initialization, clipping, folding, scaling. But they will not typically find anything that the random case does not.
My kissfft library does a few extra tests related to fixed point issues -- not an issue if you are working in floating point.

Matrix library vs for loops for element-wise operations in Java

I'm looking to do some some element-wise operations (addition, multiplication, sqrt, etc.) on floating point arrays that are ~800x300 elements in size.
How much of a speedup (if any) would I get from doing this with matrix libraries (JAMA, EJML, etc.) over just doing the element-wise operations in for loops?
For loops look more appealing because my equations can get kind of complicated, and for loops would mean I could keep all my equations as is -- in plain old infix notation. Since java doesn't support operator overloading, using a matrix library wouldn't be as simple. So, I only want to use a matrix library if it's going to mean a real speedup. (Speed will be important here.)
I would suggest you to use some of the matrix libraries for that. In most cases it should run as fast as simple for loops. But it also can run faster. So, what you will get for free: API & the equal or better perfromance. It also saves a bit of your time while writing element-wise operations.
As the author of la4j library I can say that using third-party library gives you an opportunity to get faster and faster code from new releases. For example. You can choise la4j for you needs. It is currenlty (version 0.4.0-0.4.5) uses simple for loops calculations for element-wise operations. So, it won't be faster then hand-written code. But, I'm now on the middle of developing a new parallel engine for la4j, that allows to run a code in parallel mode without any significant changes in API. Like this:
Matrix a = new Basic2DMatrix(...); // simple 2D array matrix
Matrix b = new Basic2DMatrix(...); // that is too
Matrix c = a.multiply(b); // a * b in sequental mode
Matrix c = a.par().multiply(b); // a * b in parallel mode
So, all you need to do is change a one piece of the code. All these advantages you'll get for free with libraries like la4j. Just let the libraries do their job and spend your solving real problems.

Calculate exact area under curve in Java

Are there any methods which do that? I have an application where I need the area under the curve, and I am given the formula, so if I can do the integration on hand, I should be able to do it programatically? I can't find the name of the method I'm referring to, but this image demonstrates it: http://www.mathwords.com/a/a_assets/area%20under%20curve%20ex1work.gif
Edit: to everyone replying, I have already implemented rectangular, trapezoidal and Simpson's rule. However, they take like 10k+ stripes to be accurate, and should I not be able to find programatically the integrated version of a function? If not, there must be a bloody good reason for that.
Numerical integration
There are multiple methods, which can be used. For description, have a look in Numerical Recipes: The Art of Scientific Computing.
For Java there is Apace Commons library, which can be used. Integration routines are in Numerical Analysis section.
Symbolic integration
Check out jScience. Functions module "provides support for fairly simple symbolic math analysis (to solve algebraic equations, integrate, differentiate, calculate expressions, and so on)".
If type of function is given, it can be possible to integrate faster in that specific case than when using some standard library.
To compute it exactly, you would need a computer algebra system library of some sort to perform symbolic manipulations. Such systems are rather complicated to implement, and I am not familiar with any high quality, open source libraries for Java. An alternative, though, assuming it meets your requirements, would be to estimate the area under the curve using the trapezoidal rule. Depending on how accurate you require your result to be, you can vary the size of the subdivisions accordingly.
I would recommend using Simpsons rule or the trapezium rule, because it could be excessively complicated to integrate every single type of graph.
See Numerical analysis specifically numerical integration. How about using the Riemann sum method?
You can use numerical integration, using some rule, like already mentioned Simpsons, Trapezoidal, or Monte-Carlo simulation. It uses pseudo random generator.
You can try some libraries for symbolic integration, but I'm not sure that you can get symbolic representation of every integral.
Here's a simple but efficient approach:
public static double area(DoubleFunction<Double> f, double start, double end, int intervals) {
double deltaX = (end - start)/intervals;
double area = 0.0;
double effectiveStart = start + (deltaX / 2);
for (int i=0; i<intervals; ++i) {
area += f.apply(effectiveStart + (i * deltaX));
}
return deltaX * area;
}
This is a Riemann sum using the midpoint rule, which is a variation of the trapezoidal rule, except instead of calculating the area of a trapezoid, I use a rectangle from f(x) at the middle of the interval. This is faster and gives a better result. This is why my effective starting value of x is at the middle of the first interval. And by looping over an integer, I avoid any round-off problems.
I also improve performance by waiting till the end of the loop before multiplying by deltaX. I could have written the loop like this:
for (int i=0; i<intervals; ++i) {
area += deltaX * f.apply(effectiveStart + (i * deltaX)); // this is x * y for each rectangle
}
But deltaX is constant, so it's faster to wait till the loop is finished.
One of the most popular forms of numeric integration is the Runge-Kutta order 4 (RK4) technique. It's implementations is as follows:
double dx, //step size
y ; //initial value
for(i=0;i<number_of_iterations;i++){
double k1=f(y);
double k2=f(y+dx/2*k1);
double k3=f(y+dx/2*k2);
double k4=f(y+dx*k3);
y+= dx/6*(k1+2*k2+2*k3+k4);
}
and will converge much faster than rectangle, trapezoids, and Simpson's rule. It is one of the more commonly used techniques for integration in physics simulations.

How to generate MFCC Algorithm's triangular windows and how to use them?

I am implementing MFCC algorithm in Java.
There is a sample code here: http://www.ee.columbia.edu/~dpwe/muscontent/practical/mfcc.m at Matlab. However I have some problems with mel filter banking process. How to generate triangular windows and how to use them?
PS1: An article which has a part that describes MFCC: http://arxiv.org/pdf/1003.4083
PS2: If there is a document about MFCC algorithms steps basically, it will be good.
PS3: My main question is related to that: MFCC with Java Linear and Logarithmic Filters some implementations use both linear and logarithmic filter and some of them not. What is that filters and what is the center frequent concept. I follow that code:MFCC Java , what is the difference of it between that code: MFCC Matlab
Triangular windows as frequency band filters aren't hard to implement. You basically want to integrate the FFT data within each band (defined as the frequency space between center frequency i-1 and center frequency i+1).
You're basically looking for something like,
for(int bandIdx = 0; bandIdx < numBands; bandIdx++) {
int startFreqIdx = centerFreqs[bandIdx-1];
int centerFreqIdx = centerFreqs[bandIdx];
int stopFreqIdx = centerFreqs[bandIdx+1];
for(int freq = startFreqIdx; i < centerFreqIdx; i++) {
magnitudeScale = centerFreqIdx-startFreqIdx;
bandData[bandIdx] += fftData[freq]*(i-startFreqIdx)/magnitudeScale;
}
for(int freq = centerFreqIdx; i <= stopFreqIdx; i++) {
magnitudeScale = centerFreqIdx-stopFreqIdx;
bandData[bandIdx] += fftData[freq]*(i-stopFreqIdx)/magnitudeScale;
}
}
If you do not understand the concept of a "center frequency" or a "band" or a "filter," pick up an elementary signals textbook--you shouldn't be implementing this algorithm without understanding what it does.
As for what the exact center frequencies are, it's up to you. Experiment and pick (or find in publications) values that capture the information you want to isolate from the data. The reason that there are no definitive values, or even scale for values, is because this algorithm tries to approximate a human ear, which is a very complicated listening device. Whereas one scale may work better for, say, speech, another may work better for music, etc. It's up to you to choose what is appropriate.
Answer for the second PS: I found this tutorial that really helped me computing the MFCCs.
As for the triangular windows and the filterbanks, from what I understood, they do overlap, they do not extend to negative frequences and the whole process of computing them from the FFT spectrum and applying them back to it goes something like this:
Choose a minimum and a maximum frequency for the filters (for example, min freq = 300Hz - the minimum voice frequency and max frequency = your sample rate / 2. Maybe this is where you should choose the 1000Hz limit you were talking about)
Compute the mel values from the min and max chosen frequences. Formula here.
Compute N equally distanced values between these two mel values. (I've seen examples of different values for N, you can even find a efficiency comparison for different of values in this work, for my tests I've picked 26)
Convert these values back to Hz. (you can find the formula on the same wiki page) => array of N + 2 filter values
Compute a filterbank (filter triangle) for each three consecutive values, either how Thomas suggested above (being careful with the indexes) or like in the turorial recommended at the beginning of this post) => an array of arrays, size NxM, asuming your FFT returned 2*M values and you only use M.
Pass the whole power spectrum (M values obtained from FFT) through each triangular filter to get a "filterbank energy" for each filter (for each filterbank (N loop), multiply each magnitude obtained after FFT to each value in the corresponding filterbank (M loop) and add the M obtained values) => N-sized array of energies.
These are your filterbank energies that you can further apply a log to, apply the DCT and extract the MFCCs...

Static Typing and Writing a Simple Matrix Library

Aye it's been done a million times before, but damnit I want to do it again. I'm writing a simple Matrix Library for C++ with the intention of doing it right. I've come across something that's fairly obvious in mathematics, but not so obvious to a strongly typed system -- the fact that a 1x1 matrix is just a number. To avoid this, I started walking down the hairy path of matrices as a composition of vectors, but also stumbled upon the fact that two vectors multiplied together could either be a number or a dyad, depending on the orientation of the two.
My question is, what is the right way to deal with this situation in a strongly typed language like C++ or Java?
something that's fairly obvious in
mathematics, but not so obvious to a
strongly typed system -- the fact that
a 1x1 matrix is just a number.
That's arguable. A hardcore mathematician (I'm not) would probably argue against it, he would say that a 1x1 matrix can be regarded as isomorphic (or something like that) to a scalar, but they are conceptually different things. Only in some informal sense "a 1x1 matrix is a scalar" (similar, though stronger, that a complex number without an imaginary part "is a real").
I don't think that that correspondence should be reflected in a strong typed language. And I dont' think it is, in typical implementations (of complex or matrix), eg. Java Apache Commons Math. For example, a Complex with zero imaginary part is not a Number (from the type POV - they cannot be casted one into another).
In the case of matrices, the correspondence is even more disputable. Should we be able to multiply two matrices of sizes (4x3) x (1x1) ? If we regard the second as a scalar, it's valid, but not as a matrix, since it violates the restriction on matrix dimensions for multiplication. And I believe Commons sticks to that.
In a weakly typed language (eg Matlab) it would be another story.
If you aren't worried about SIMD optimisations and the like then I would have thought the best way would be to set up a templated tensor. Choose your maximum tensor dimensions and then you can do things like this:
typedef Tensor3D< float, 4, 1, 1 > Vector4;
And so forth. The mathematics, if implemented correctly, will just work with all forms of "matrix" and "vector". Both are, afterall, just special cases of tensors.
Edit: knowing the size of a template is actually pretty easy. Add in a GetRows() etc function and you can return the value you pass into the template at instantiation.
ie
template< typename T, int rows, int cols > class Tensor2D
{
public:
int GetRows() { return rows; }
int GetCols() { return cols; }
};
My advice? Don't worry about the 1x1 case and sleep at night. You shouldn't be worried about any uses suddenly deciding to use your library to model a bunch of numbers as 1x1 matricies and complaining about your implementation.
No one who solves these problems will be so foolish. If you're smart enough to use matricies, you're smart enough to use them properly.
As for all the permutations that scalars introduce, I'd say that you must account for them. As a matrix library user, I'd expect to be able to multiply two matricies together to get another matrix, a matrix by a (column or row) vector get a vector result, and a scalar times a matrix to get another matrix.
If I multiply two vectors I can get a scalar (inner product) or a matrix (outer product). Your library had better give them to me.
It's not trivial. It's been done "right" by others, but kudos to working it through for yourself.

Categories