Least squares Levenburg Marquardt with Apache commons - java

I'm using the non linear least squares Levenburg Marquardt algorithm in java to fit a number of exponential curves (A+Bexp(Cx)). Although the data is quite clean and has a good approximation to the model the algorithm is not able to model the majority of them even with a excessive number of iterations(5000-6000). For the curves it can model, it does so in about 150 iterations.
LeastSquaresProblem problem = new LeastSquaresBuilder()
.start(start).model(jac).target(dTarget)
.lazyEvaluation(false).maxEvaluations(5000)
.maxIterations(6000).build();
LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
LeastSquaresOptimizer.Optimum optimum = optimizer.optimize(problem);}
My question is how would I define a convergence criteria in apache commons in order to stop it hitting a max number of iterations?

I don't believe Java is your problem. Let's address the mathematics.
This problem is easier to solve if you change your function.
Your assumed equation is:
y = A + B*exp(C*x)
It'd be easier if you could do this:
y-A = B*exp(C*x)
Now A is just a constant that can be zero or whatever value you need to shift the curve up or down. Let's call that variable z:
z = B*exp(C*x)
Taking the natural log of both sides:
ln(z) = ln(B*exp(C*x))
We can simplify that right hand side to get the final result:
ln(z) = ln(B) + C*x
Transform your (x, y) data to (x, z) and you can use least squares fitting of a straight line where C is the slope in (x, z) space and ln(B) is the intercept. Lots of software available to do that.

Related

How to divide Array Length into arrays with lengths that are multiples of 3

So I have a fairly large array that contains xyz coordinates, where array[0] = x0, array[1] = y0, array[2] = z0, array[3] = x1, array[4] = y1... and so on.
I'm running an algorithm on this array that is taking longer than I would like it to, and I want to split the work amongst threads. I have my threads set up, but I am not sure how to divide this array properly so I can distribute this work across 3 threads.
Even though I have an array length that is divisible by 3, this won't work, because splitting into 3 can split an xyz coordinate (for instance, if my array was size 15, dividing it by 3 will give me arrays of size 5, which means I'm splitting an XYZ coordinate.
How can I split this array (it doesn't have to necessarily be equal in size) so that I can distribute the work? (for instance, in the previous example, I would like to have two arrays of size 6 and one of size 3).
Note: The size of the array is variable, but is always divisible by 3.
EDIT: Sorry, should have mentioned that I'm working in Java. My algorithm iterates through a collection of coordinates and determines which coordinates lie inside of a particular 3d shape (such as an ellipsoid). It saves these coordinates and I perform other tasks with these coordinates (I'm working on a computer graphics app).
EDIT2: I'm going to elaborate on the algorithm a bit more.
Basically, I am working in Android OpenGL-ES-3.0. I have complex 3D-object with somewhere around 230000 vertices and close to a million triangles.
In the app, the user moves either a ellipsoid or box (they choose which one) to a location close to or on the object. After moving it, they click a button, which runs my algorithm.
The purpose of the algorithm is to determine which points from my object lie inside of the ellipsoid or box. These points are subsequently changed to a different color. To add to the complexity, however, is the fact that I have transformation matrices applied to both the points of the object and the points of the ellipsoid/box.
My current algorithm begins by iterating through all the points of the object. For those of you unclear on my iteration, this is my loop.
for(int i = 0; i < numberOfVertices*3;)
{
pointX = vertices[i];
i++;
pointY = vertices[i];
i++;
pointZ = vertices[i];
i++;
//consider transformations, then run algorithm
}
I perform the necessary steps to consider all my transformations, and after that is finished, I have a point from my object and the location of my ellipsoid/box centroid.
Then, depending on the shape, one of the following algorithms is used:
Ellipsoid: I use the centroid of the ellipse and apply the formula
(x−c)T RT A R(x−c) (sorry I don't know how to format that, I'll explain the formula). x is a column vector describing the xyz point from my object that I am on in my iteration. c is a column vector describing the xyz point of my centroid. T is supposed to mean transpose. R is my rotation matrix. A is a diagonal matrix with entries with entries (1/a^2, 1/b^2, 1/c^2), and I have values for a b and c. If this formula is > 1, then x lies outside of my ellipsoid and is not a valid point. If it is <=1, then I save x.
Box: I simply check if the point falls within a range. If the point of the object lies a certain distance in the X-direction, Y-direction, and Z-direction from the centroid, I save it.
These algorithms are accurate, and work as intended. The issue, is obviously efficiency. I don't seem to have a good understanding of what makes my app strain and what doesn't. I thought multi-threading would work, and I tried some of the techniques described but they didn't have a significant improvement on performance. If anyone has ideas on filtering out my search so I'm not iterating through all these points, it would help.
May I suggest a slightly different way to handle it. I know this isn't a direct answer to your question, but please consider it.
This could be easier to see if you implemented it as coordinate Objects, each with x, y and z values. Your "array" would now be 1/3 as long. You might think this would be less efficient--and you might be right--but you'd be surprised at how well java can optimize things. Often Java optimizes for the cases people use the most and your manually manipulating this array as you suggest is possibly even slower than using objects. Until you've proven the most readable design too slow you shouldn't optimize it.
Now you have a collection of coordinate objects. Java has queues that multiple threads can pull from efficiently. Dump all your objects into a queue and have each of your threads pull one and work on it by processing it and putting it in a "Completed" queue. Note that this gives you the ability to add or remove threads easily, without effecting your code except for 1 number. How would you take the array based solution to 4 or 6 threads?
Good luck
Here is a demo of the work explained below.
Observations
Each coordinate is 3 indexes.
You have 3 threads.
Let's say you have 17 coordinates, that's 51 indexes. You want to split the 17 coordinates among your 3 threads.
var arraySize = 51;
var numberOfThreads = 3;
var numberOfIndexesPerCoordinate = 3;
var numberOfCoordinates = arraySize / numberOfIndexesPerCoordinate; //17 coordinates
Now split that 17 coordinates among your threads.
var coordinatesPerThread = numberOfCoordinates / numberOfThreads; //5.6667
This isn't an even number, so you need to distribute unevenly. We can use Math.floor and modulo to distribute.
var floored = Math.floor(coordinatesPerThread); //5 - every thread gets at least 5.
var modulod = numberOfCoordinates % floored; // 2 - there will be 2 left that need to be placed sequentially into your thread pool
This should give you all the information you need. Without knowing what language you are using, I don't want to give any real code samples.
I see you edited your question to specify Java as your language. I'm not going to do the threading work for you, but I'll give a rough idea.
float[] coordinates = new float[17 * 3]; //17 coordinates with 3 indexes each.
int numberOfThreads = 3;
int numberOfIndexesPerCoordinate = 3;
int numberOfCoordinates = coordinates.length / numberOfIndexesPerCoordinate ; //coordinates * 3 indexes each = 17
//Every thread has this many coordinates
int coordinatesPerThread = Math.floor(numberOfCoordinates / numberOfThreads);
//This is the number of coordinates remaining that couldn't evenly be split.
int remainingCoordinates = numberOfCoordinates % coordinatesPerThread
//To make things easier, I'm just going to track the offset in the original array. It could probably be computed instead, but its just an int.
int offset = 0;
for (int i = 0; i < numberOfThreads; i++) {
int numberOfIndexes = coordinatesPerThread * numberOfIndexesPerCoordinate;
//If this index is one of the remainders, then increase by 1 coordinate (3 indexes).
if (i < remainingCoordinates)
numberOfIndexes += numberOfIndexesPerCoordinate ;
float[] dest = new float[numberOfIndexes];
System.arraycopy(coordinates, offset, dest, 0, numberOfIndexes);
offset += numberOfIndexes;
//Put the dest array of indexes into your threads.
}
Another, potentially better option would be to use a Concurrent Deque that has all of your coordinates, and have each thread pull from it as they need a new coordinate to work with. For this solution, you'd need to create Coordinate objects.
Declare a Coordinate object
public static class Coordinate {
protected float x;
protected float y;
protected float z;
public Coordinate(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
Declare a task to do your work, and pass it your concurrent deque.
public static class CoordinateTask implements Runnable {
private final Deque<Coordinate> deque;
public CoordinateTask(Deque<Coordinate> deque) {
this.deque = deque;
}
public void run() {
Coordinate coordinate;
while ((coordinate = this.deque.poll()) != null) {
//Do your processing here.
System.out.println(String.format("Proccessing coordinate <%f, %f, %f>.",
coordinate.x,
coordinate.y,
coordinate.z));
}
}
}
Here's the main method showing the example in action
public static void main(String []args){
Coordinate[] coordinates = new Coordinate[17];
for (int i = 0; i < coordinates.length; i++)
coordinates[i] = new Coordinate(i, i + 1, i + 2);
final Deque<Coordinate> deque = new ConcurrentLinkedDeque<Coordinate>(Arrays.asList(coordinates));
Thread t1 = new Thread(new CoordinateTask(deque));
Thread t2 = new Thread(new CoordinateTask(deque));
Thread t3 = new Thread(new CoordinateTask(deque));
t1.start();
t2.start();
t3.start();
}
See this demo.
Before trying to optimize with concurrency, try to minimize the amount of points you need to test, and minimize the cost of those tests, by using the most efficient collision detection methods at your disposal.
Some general suggestions:
Consider normalizing everything to a common frame of reference before running through your calculations. For example, instead of applying transformations to each point, transform the selection box/ellipsoid into the shape's coordinate system so you can perform your collision detection without the transformations within each iteration.
You may also be able to combine some or all of your transformations (rotation, translation, etc.) into a single matrix calculation, but that won't gain you much unless you're performing a lot of transformations, which you should try to avoid.
Generally speaking it's beneficial to keep the transformation pipeline as streamlined as possible, and keep all coordinate calculations in the same space to avoid transformations as much as possible.
Try to minimize the number of points you need to perform your slowest calculations on. The most accurate collision test should only be necessary for points that you can't rule out as being inside the shape by faster means, using an approximation of the shape, such as a collection of spheres, or the shape's convex hull. Simplifying the shape allows you to limit the slowest calculations to only those points that lie very close to your shape's actual bounds.
In my own 2D work in the past I found that even calculating the convex hulls for hundreds of complex animated shapes in real time was faster than doing collision detection directly without using their convex hulls, because they enable much faster collision calculations.
Consider calculating/storing additional information about the shape, such as an inner and outer collision sphere (one sphere inside all points, and one outside all points) which you can use as a fast initial filter. Anything inside the smaller sphere is guaranteed to be inside your shape, anything outside the outer sphere is known to be outside your shape. You might even want to store a simplified version of your shape, (or its convex hull), which you could calculate in advance and use to aid collision detection.
Similarly, consider using one or more spheres to approximate your ellipsoid in initial calculations, to minimize which points you need to test for collision.
Instead of calculating actual distances, calculate the squared distances and use those for comparison. However, prefer using faster tests for collision if possible. For example, for convex polygons you can use the Separating Axis Theorem, which projects vertices onto a common axis/plane to permit very quick overlap calculations.

How to generate some identically distributed pseudo-random vectors with a fixed length r in a programming language?

For example, for the dimension d=2, it means that we could generate a random angle 0<=a<2*pi, and then we could just use
(x_1,x_2)=(r*cos(a),r*sin(a)) as the random vector.
However, for the dimension d>=3, we could not just generate an angle and use it to represent the vector. Then how could we generate such a vector (x_1,...,x_d), which is identically distributed on x_1^2+x_2^2+...+x_d^2=r^2?
I have just come up with a new idea, that we could generate a vector (x_1,...,x_d) such that -r<=x_i<r for all i, normalize it if x_1^2+x_2^2+...+x_d^2<=r^2 and abondon it if x_1^2+x_2^2+...+x_d^2>r^2.
However, there is a drawback that the probability that x_1^2+x_2^2+...+x_d^2<=r^2 would become very small if d is very large. Does there exist some better solutions?
Generate random variables (X_1, X_2, ... X_d) that are independent and have standard normal distributions, and then normalize by dividing by sqrt(X_1^2+...+X_d^2)/r.
That the joint distribution of independent normal distributions is rotationally symmetric is not just true, it characterizes normal distributions.
You can generate pairs of independent variables with a standard normal distribution efficiently from uniform random variables using the Box-Muller transform.
I see two ways around it.
The straightforward way is, in pseudo-code:
1. build n-dimensional vector x[0] through x[n-1] with random components
2. find radius
3. go to step 1 if radius > r; otherwise, normalize to radius r
This is non-deterministic, because there is no way to know how many times you will need to cycle before you find an acceptable sphere. Additionally, the probability of finding a bad point goes up with the number of dimensions.
To understand why (thanks commenters!), imagine a 1x1 square. Add a r=1 circle inside. Fill the square with random points. All the points between the center and the circle are evenly distributed when projected on the circle. All the points between the circle and the square's border are not - because there's too many at, say, 45º; and none at, say, 90º.
The non-straightforward version is a generalization of your 2-dimensional approach:
1. assume that we are on an n-sphere; generate angles phi[0], ...phi[n-2]
for a polar-coordinates point
2. convert to cartesian coordinates x[0] through x[n-1]
According to the n-sphere page in wikipedia, the formula is
x[0] = r*cos(phi[0]);
x[1] = r*sin(phi[0])*cos(phi[1]);
x[2] = r*sin(phi[0])*sin(phi[1]);
...
x[n-2] = r*sin(phi[0])*sin(phi[1])* /*...*/ sin(phi[n-3])*sin(phi[n-2])
x[n-1] = r*sin(phi[0])*cos(phi[1])* /*...*/ sin(phi[n-3])*cos(phi[n-2])
The actual algorithm can be implemented a lot more efficiently (sin(phi[0]) is getting calculated a lot, for example)
To avoid non-determinism, I recommend the second approach.
Edit
The recommended approach, not listed above, is in Douglas's answer and many reference sites:
https://mathoverflow.net/questions/136314/what-is-a-good-method-to-find-random-points-on-the-n-sphere-when-n-is-large
http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
http://mathworld.wolfram.com/HyperspherePointPicking.html

How to move along sinus function at constant speed

I have a Java program that moves an object according to a sinus function asin(bx).
The object moves at a certain speed by changing the x parameter by the time interval x the speed. However, this only moves the object at a constant speed along the x axis.
What I want to do is move the object at a constant tangential speed along the curve of the function. Could someone please help me? Thanks.
Let's say you have a function f(x) that describes a curve in the xy plane. The problem consists in moving a point along this curve at a constant speed S (i.e., at a constant tangential speed, as you put it.)
So, let's start at an instant t and a position x. The point has coordinates (x, f(x)). An instant later, say, at t + dt the point has moved to (x + dx, f(x + dx)).
The distance between these two locations is:
dist = sqrt((x + dx - dx)2 + (f(x+dx) - f(x))2) = sqrt(dx2 + (f(x+dx) - f(x))2)
Now, let's factor out dx to the right. We get:
dist = sqrt(1 + f'(x)2) dx
where f'(x) is the derivative (f(x+dx) - f(x)) /dx.
If we now divide by the time elapsed dt we get
dist/dt = sqrt(1 + f'(x)2) dx/dt.
But dist/dt is the speed at which the point moves along the curve, so it is the constant S. Then
S = sqrt(1 + f'(x)2) dx/dt
Solving for dx
dx = S / sqrt(1 + f'(x)2) dt
which gives you how much you have to move the x-coordinate of the point after dt units of time.
The arc length on a sine curve as a function of x is an elliptic integral of the second kind. To determine the x coordinate after you move a particular distance (or a particular time with a given speed) you would need to invert this elliptic integral. This is not an elementary function.
There are ways to approximate the inverse of the elliptic integral that are much simpler than you might expect. You could combine a good numerical integration algorithm such as Simpson's rule with either Newton's method or binary search to find a numerical root of arc length(x) = kt. Whether this is too computationally expensive depends on how accurate you need it to be and how often you need to update it. The error will decrease dramatically if you estimate the length of one period once, and then reduce t mod the arc length on one period.
Another approach you might try is to use a different curve than a sine curve with a more tractable arc length parametrization. Unfortunately, there are few of those, which is why the arc length exercises in calculus books repeat the same types of curves over and over. Another possibility is to accept a speed that isn't constant but doesn't go too far above or below a specified constant, which you can get with some Fourier analysis.
Another approach is to recognize the arc length parametrization as a solution to a 2-dimensional ordinary differential equation. A first order numerical approximation (Euler's method) might suffice, and I think that's what Leandro Caniglia's answer suggests. If you find that the round off errors are too large, you can use a higher order method such as Runge-Kutta.

Weighted Linear Regression in Java

Does anyone know of a scientific/mathematical library in Java that has a straightforward implementation of weighted linear regression? Something along the lines of a function that takes 3 arguments and returns the corresponding coefficients:
linearRegression(x,y,weights)
This seems fairly straightforward, so I imagine it exists somewhere.
PS) I've tried Flannigan's library: http://www.ee.ucl.ac.uk/~mflanaga/java/Regression.html, it has the right idea but seems to crash sporadically and complain out my degrees of freedom?
Not a library, but the code is posted: http://www.codeproject.com/KB/recipes/LinReg.aspx
(and includes the mathematical explanation for the code, which is a huge plus).
Also, it seems that there is another implementation of the same algorithm here: http://sin-memories.blogspot.com/2009/04/weighted-linear-regression-in-java-and.html
Finally, there is a lib from a University in New Zealand that seems to have it implemented: http://www.cs.waikato.ac.nz/~ml/weka/ (pretty decent javadocs). The specific method is described here:
http://weka.sourceforge.net/doc/weka/classifiers/functions/LinearRegression.html
I was also searching for this, but I couldn't find anything. The reason might be that you can simplify the problem to the standard regression as follows:
The weighted linear regression without residual can be represented as
diag(sqrt(weights))y = diag(sqrt(weights))Xb where diag(sqrt(weights))T basically means multiplying each row of the T matrix by a different square rooted weight. Therefore, the translation between weighted and unweighted regressions without residual is trivial.
To translate a regression with residual y=Xb+u into a regression without residual y=Xb, you add an additional column to X - a new column with only ones.
Now that you know how to simplify the problem, you can use any library to solve the standard linear regression.
Here's an example, using Apache Commons Math:
void linearRegression(double[] xUnweighted, double[] yUnweighted, double[] weights) {
double[] y = new double[yUnweighted.length];
double[][] x = new double[xUnweighted.length][2];
for (int i = 0; i < y.length; i++) {
y[i] = Math.sqrt(weights[i]) * yUnweighted[i];
x[i][0] = Math.sqrt(weights[i]) * xUnweighted[i];
x[i][1] = Math.sqrt(weights[i]);
}
OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
regression.setNoIntercept(true);
regression.newSampleData(y, x);
double[] regressionParameters = regression.estimateRegressionParameters();
double slope = regressionParameters[0];
double intercept = regressionParameters[1];
System.out.println("y = " + slope + "*x + " + intercept);
}
This can be explained intuitively by the fact that in linear regression with u=0, if you take any point (x,y) and convert it to (xC,yC), the error for the new point will also get multiplied by C. In other words, linear regression already applies higher weight to points with higher x. We are minimizing the squared error, that's why we extract the roots of the weights.
I personally used org.apache.commons.math.stat.regression.SimpleRegression Class of the Apache Math library.
I also found a more lightweight class from Princeton university but didn't test it:
http://introcs.cs.princeton.edu/java/97data/LinearRegression.java.html
Here's a direct Java port of the C# code for weighted linear regression from the first link in Aleadam's answer:
https://github.com/lukehutch/WeightedLinearRegression.java

Best way to find Quadratic Regression Curve in Java

I've three sets of data such as:
x y
4 0
6 60
8 0
Does anyone know any (efficient) Java codes that can give me back the values of a, b, and c (the coefficients)?
I assume you want the formula in this form:
y = a * x^2 + b*x + c
If you have only three points you can describe the quadratic curve that goes through all three points with the formula:
y = ((x-x2) * (x-x3)) / ((x1-x2) * (x1-x3)) * y1 +
((x-x1) * (x-x3)) / ((x2-x1) * (x2-x3)) * y2 +
((x-x1) * (x-x2)) / ((x3-x1) * (x3-x2)) * y3
In your example:
x1 = 4, y1 = 0, x2 = 6, y2 = 60, x3 = 8, y3 = 0
To get the coefficients a, b, c in terms of x1, x2, x3, y1, y2 and y3 you just need to multiply the formula out and then collect the terms. It's not difficult, and it will run very fast but it will be quite a lot of code to type in. It would probably be better to look for a package that already does this for you, but if you want to do it yourself, this is how you could do it.
The fact that two of the y terms are zero in your example makes the formula a lot simpler, and you might be able to take advantage of that. But if that was just a coincidence and not a general rule, then you need the full formula.
The LaGrange interpolation is probably the most 'efficient' (how do you measure that?) solution you are going to find. So I'll suggest a completely general code. You did want code, right? This code can go linear, quadratic, cubic, .... for any number of points.
I didn't actually try to compile it, so I don't if the source code is up to date. You know how online demos go. Yet the applet from the associated web page is fully functional. The jar file will run standalone. With a resizable window, you really don't need to customize it.
It depends on exactly what you are looking for: Are you looking for the unique polynomial which is defined by those three points, or are you looking for a library which will generate a polynomial which passes through all points?
If you are looking at the first, the best technique is to construct the coefficient matrix(That is, the set of three linear equations which uniquely constrain this quadratic equation)and apply Gaussian Elimination to get your result. This can be done by hand the most efficiently, but you can also use The Apache Commons Math Library's Real Matrix solve methods. (EDIT Thanks for the correction--I speak before I think sometimes ;)
If you are looking at the second, this is specific case of a general class of problems called Interpolation by Polynomials, and there are several ways of solving--Splines are my personal favorite, but all have their strengths and weaknesses. Luckily, Apache Commons Math implements several such methods. I would look at the SplineInterpolator class. Splines use cubics instead of quadratics, but they tend to be very good approximations. They also don't fail if one point is a linear multiple of another.
For just three points, both methods should be about equal in performance characteristics. If you are doing more than three points, however, I would strongly recommend using interpolation, as using Guassian Elimination scales incredibly poorly( O(n^3)), and Splines(Or another interpolation technique) are less likely to fail.

Categories