Curve fitting of Hyperbola and finding its parameters associated [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Assuming General formula of hyperbola to be y = 1 / (a*x + b), and we are provided with 100 data points out of which 99 points exactly fits a hyperbola and one data point is doesn't fits in it (unknown), from this information we need to find approximate values of a and b parameters for the hyperbola that will be formed from correct data points which are provided.
The approach which I took was by using scipy.optimize.curve_fit method as "parameters, _ = optimize.curve_fit(test, x_data ,y_data) "
where my "test" function was "def test(x, a, b): return 1 / (a*x + b)" using this method provides me perfect solution is my data points are all in first quadrant but if the data is distributed in more than one quadrant then this approach fails and I get wrong values of a and b.
Code:
import numpy as np
from scipy import optimize
x_data = np.linspace(-5,1, num=99)
y_data = 1 / (5 * x_data + 4) # value of original value of a = 5 & b = 4
np.random.seed(0)
# adding wrong point at 36th position
x_data = np.insert(x_data, 36 , 7)
y_data = np.insert(y_data, 36, 5)
def test(x, a, b):
return 1 / (a*x + b)
parameters, _ = optimize.curve_fit(test, x_data ,y_data)
[a,b] = parameters
a = 146.83956808191303
b = 148.78257639384725
# which is too wrong
Solution for above will certainly be appreciated.

Your problem is easy if the given points "exactly fit the hyperbola," and you need only two data points.
Your equation y = 1 / (ax + b) can be transformed into
(x*y) * a + (y) * b = 1
That is a linear equation in a and b. Use two data points to find the corresponding values of x * y and y and you end up with two linear equations in two variables (though in a and b rather than x and y). Then solve those two linear equations. This can easily be automated. This also does not depend on the quadrants of your two given points.
This does not work if your given points only approximate a hyperbola, of course.
In your last edit, you added the statement that only 99 of the points fit on the hyperbola, and one does not. This can be handled by choosing three pairs of your points (six distinct points), and finding the hyperbola that goes through each pair of points. That means calculating three hyperbolas (equivalently, calculating three values of a and b). If those three pairs of a and b all agree with small precision, the non-matching point was not in the chosen sample of three pairs of points and you have your hyperbola. If only two of them agree within precision, use that hyperbola. If no pair of the hyperbolas agree, some mistake was made and you should raise an exception.

Related

Closed Form Ridge Regression

I am having trouble understanding the output of my function to implement multiple-ridge regression. I am doing this from scratch in Python for the closed form of the method. This closed form is shown below:
I have a training set X that is 100 rows x 10 columns and a vector y that is 100x1.
My attempt is as follows:
def ridgeRegression(xMatrix, yVector, lambdaRange):
wList = []
for i in range(1, lambdaRange+1):
lambVal = i
# compute the inner values (X.T X + lambda I)
xTranspose = np.transpose(x)
xTx = xTranspose # x
lamb_I = lambVal * np.eye(xTx.shape[0])
# invert inner, e.g. (inner)**(-1)
inner_matInv = np.linalg.inv(xTx + lamb_I)
# compute outer (X.T y)
outer_xTy = np.dot(xTranspose, y)
# multiply together
w = inner_matInv # outer_xTy
wList.append(w)
print(wList)
For testing, I am running it with the first 5 lambda values.
wList becomes 5 numpy.arrays each of length 10 (I'm assuming for the 10 coefficients).
Here is the first of those 5 arrays:
array([ 0.29686755, 1.48420319, 0.36388528, 0.70324668, -0.51604451,
2.39045735, 1.45295857, 2.21437745, 0.98222546, 0.86124358])
My question, and clarification:
Shouldn't there be 11 coefficients, (1 for the y-intercept + 10 slopes)?
How do I get the Minimum Square Error from this computation?
What comes next if I wanted to plot this line?
I think I am just really confused as to what I'm looking at, since I'm still working on my linear-algebra.
Thanks!
First, I would modify your ridge regression to look like the following:
import numpy as np
def ridgeRegression(X, y, lambdaRange):
wList = []
# Get normal form of `X`
A = X.T # X
# Get Identity matrix
I = np.eye(A.shape[0])
# Get right hand side
c = X.T # y
for lambVal in range(1, lambdaRange+1):
# Set up equations Bw = c
lamb_I = lambVal * I
B = A + lamb_I
# Solve for w
w = np.linalg.solve(B,c)
wList.append(w)
return wList
Notice that I replaced your inv call to compute the matrix inverse with an implicit solve. This is much more numerically stable, which is an important consideration for these types of problems especially.
I've also taken the A=X.T#X computation, identity matrix I generation, and right hand side vector c=X.T#y computation out of the loop--these don't change within the loop and are relatively expensive to compute.
As was pointed out by #qwr, the number of columns of X will determine the number of coefficients you have. You have not described your model, so it's not clear how the underlying domain, x, is structured into X.
Traditionally, one might use polynomial regression, in which case X is the Vandermonde Matrix. In that case, the first coefficient would be associated with the y-intercept. However, based on the context of your question, you seem to be interested in multivariate linear regression. In any case, the model needs to be clearly defined. Once it is, then the returned weights may be used to further analyze your data.
Typically to make notation more compact, the matrix X contains a column of ones for an intercept, so if you have p predictors, the matrix is dimensions n by p+1. See Wikipedia article on linear regression for an example.
To compute in-sample MSE, use the definition for MSE: the average of squared residuals. To compute generalization error, you need cross-validation.
Also, you shouldn't take lambVal as an integer. It can be small (close to 0) if the aim is just to avoid numerical error when xTx is ill-conditionned.
I would advise you to use a logarithmic range instead of a linear one, starting from 0.001 and going up to 100 or more if you want to. For instance you can change your code to that:
powerMin = -3
powerMax = 3
for i in range(powerMin, powerMax):
lambVal = 10**i
print(lambVal)
And then you can try a smaller range or a linear range once you figure out what is the correct order of lambVal with your data from cross-validation.

Least square on linear N-way-equal problem

Suppose I want to find the "intersection point" of 2 arbitrary high-dimensional lines. The two lines won't actually intersect, but I still want to find the most intersect point (i.e. a point that is as close to all lines as possible).
Suppose those lines have direction vectors A, B and initial points C, D,
I can find the most intersect point by simply set up a linear least square problem: converting the line-intersection equation
Ax + C = By + D
to least-square form
[A, -B] # [[x, y]] = D - C
where # standards for matrix times vector, and then I can use e.g. np.linalg.lstsq to solve it.
But how can I find the "most intersect point" of 3 or more arbitrary lines? If I follow the same rule, I now have
Ax + D = By + E = Cz + F
The only way I can think of is decomposing this into three equations:
Ax + D = By + E
Ax + D = Cz + F
By + E = Cz + F
and converting them to least-square form
[A, -B, 0] [E - D]
[A, 0, -C] # [[x, y, z]] = [F - D]
[0, B, -C] [F - E]
The problem is the size of the least-square problem increases quadraticly about the number of lines. I'm wondering are there more efficient way to solve n-way-equal least-square linear problem?
I was thinking about the necessity of By + E = Cz + F above providing the other two terms. But since this problem do not have exact solution (i.e. they don't actually intersect), I believe doing so will create more "weight" on some variable?
Thank you for your help!
EDIT
I just tested pairing the first term with all other terms in the n-way-equality (and no other pairs) using the following code
def lineIntersect(k, b):
"k, b: N-by-D matrices describing N D-dimensional lines: k[i] * x + b[i]"
# Convert the problem to least-square form `Ax = B`
# A is temporarily defined 3-dimensional for convenience
A = np.zeros((len(k)-1, k.shape[1], len(k)), k.dtype)
A[:,:,0] = k[0]
A[range(len(k)-1),:,range(1,len(k))] = -k[1:]
# Convert to 2-dimensional matrix by flattening first two dimensions
A = A.reshape(-1, len(k))
# B should be 1-dimensional vector
B = (b[1:] - b[0]).ravel()
x = np.linalg.lstsq(A, B, None)[0]
return (x[:,None] * k + b).mean(0)
The result below indicates doing so is not correct because the first term in the n-way-equality is "weighted differently".
The first output is difference between the regular result and the result of different input order (line order should not matter) where the first term did not change.
The second output is the same with the first term did change.
k = np.random.rand(10, 100)
b = np.random.rand(10, 100)
print(np.linalg.norm(lineIntersect(k, b) - lineIntersect(np.r_[k[:1],k[:0:-1]], np.r_[b[:1],b[:0:-1]])))
print(np.linalg.norm(lineIntersect(k, b) - lineIntersect(k[::-1], b[::-1])))
results in
7.889616961715915e-16
0.10702479853076755
Another criterion for the 'almost intersection point' would be a point x such that the sum of the squares of the distances of x to the lines is as small as possible. Like your criterion, if the lines actually do intersect then the almost intersection point will be the actual intersection point. However I think the sum of distances squared criterion makes it straightforward to compute the point in question:
Suppose we represent a line by a point and a unit vector along the line. So if a line is represented by p,t then the points on the line are of the form
p + l*t for scalar l
The distance-squared of a point x from a line p,t is
(x-p)'*(x-p) - square( t'*(x-p))
If we have N lines p[i],t[i] then the sum of the distances squared from a point x is
Sum { (x-p[i])'*(x-p[i]) - square( t[i]'*(x[i]-p[i]))}
Expanding this out I get the above to be
x'*S*x - 2*x'*V + K
where
S = N*I - Sum{ t[i]*t[i]'}
V = Sum{ p[i] - (t[i]'*p[i])*t[i] }
and K does not depend on x
Unless all the lines are parallel, S will be (strictly) positive definite and hence invertible, and in that case our sum of distances squared is
(x-inv(S)*V)'*S*(x-inv(S)*V) + K - V'*inv(S)*V
Thus the minimising x is
inv(S)*V
So the drill is: normalise your 'direction vectors' (and scale each point by the same factor as used to scale the direction), form S and V as above, solve
S*x = V for x
This question might be better suited for the math stackexchange. Also, does anyone have a good way of formatting math here? Sorry that it's hard to read, I did my best with unicode.
EDIT: I misinterpreted what #ZisIsNotZis meant by the lines Ax+C so what disregard the next paragraph.
I'm not convinced that your method is stated correctly. Would you mind posting your code and a small example of the output (maybe in 2d with 3 or 4 lines so we can plot it)? When you're trying to find the intersection of two lines shouldn't you do Ax+C = Bx+D? If you do Ax+C=By+D you can pick some x on the first line and some y on the second line and satisfy both equations exactly. Because here x and y should be the same size as A and B which is the dimension of the space rather than scalars.
There are many ways to understand the problem of finding a point that is as close to all lines as possible. I think the most natural one is that the sum of squares of euclidian distance to each line is minimized.
Suppose we have a line in R^n: c^Tz + d = 0 (where c is unit length) and another point x. Then the shortest vector from x to the line is: (I-cc^T)(x-d) so the square of the distance from x to the line is ║(I-cc^T)(x-d)║^2. We can find the closest point to the line by minimizing this distance. Note that this is a standard least squares problem of the form min_x ║b-Ax║_2.
Now, suppose we have lines given by c_iz+d_i for i=1,...,m. The squared distance d_i^2 from a point x to the i-th line is d_i^2 = ║(I-cc^T)(x-d)║_2^2. We now want to solve the problem of min_x \sum_{i=1}^{m} d_i^2.
In matrix form we have:
║ ⎡ (I-c_1 c_1^T)(x-d_1) ⎤ ║
║ | (I-c_2 c_2^T)(x-d_2) | ║
min_x ║ | ... | ║
║ ⎣ (I-c_n c_n^T)(x-d_n) ⎦ ║_2
This is again in the form min_x ║b - Ax║_2 so there are good solvers available.
Each block has size n (dimension of the space) and there are m blocks (number of lines). So the system is mn byn. In particular, it is linear in the number of lines and quadratic in the dimension of the space.
It also has the advantage that if you add a line you simply add another block to the least squares system. This also offers the possibility of updating solutions iteratively as you add lines.
I'm not sure if there are special solvers for this type of least squares system. Note that each block is the identity minus a rank one matrix, so that might give some additional structure which can be used to speed things up. That said, I think using existing solvers will almost always work better than writing your own, unless you have quite a bit of background in numerical analysis or have a very specialized class of systems to solve.
Not a solution, some thoughts:
If line in nD space has parametric equation (with unit Dir vector)
L(t) = Base + Dir * t
then squared distance from point P to this line is
W = P - Base
Dist^2 = (W - (W.dot.Dir) * Dir)^2
If it is possible to write Min(Sum(Dist[i]^2)) in form suitable for LSQ method (make partial derivatives by every point coordinate), so resulting system might be solved for (x1..xn) coordinate vector.
(Situation resembles reversal of many points and single line of usual LSQ)
You say that you have two "high-dimensional" lines. This implies that the matrix indicating the lines has many more columns than rows.
If this is the case and you can efficiently find a low-rank decomposition such that A=LRᵀ, then you can rewrite the solution of the least squares problem min ||Ax-y||₂ as x=(Rᵀ RLᵀ L)⁻¹ Lᵀ y.
If m is the number of lines and n the dimension of the lines, then this reduces the least-squares time complexity from O(mn²+nʷ) to O(nr²+mr²) where r=min(m,n).
The problem then is to find such a decomposition.

Calculating Mean Square Displacement for a single particle in 1d [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a particle trajectory in 1D, j=[] and for the time=np.arange(0, 10 + dt, dt) where dt is the time step. I have calculate the MSD according to this article.
I have searched in google as well as here for 1d MSD in python but did not find any suitable one as my python knowledge is very beginner level. I have written one code and it is working without any error but I am not sure that it represent the same thing according to the given article. Here is my code,
j_i = np.array(j)
MSD=[]
diff_i=[]
tau_i=[]
for l in range(0,len(time)):
tau=l*dt
tau_i.append(tau)
for i in range(0,(len(time)-l)):
diff=(j_i[l+i]-j_i[i])**2
diff_i.append(diff)
MSD_j=np.sum(diff_i)/np.max(time)
MSD.append(MSD_j)
Can anyone please check verify the code and give suggestion if it is wrong.
The code is mostly correct, here is a modified version where:
I simplified some expressions (e.g. range)
I corrected the average, directly using np.mean because the MSD is a squared displacement [L^2], not a ratio [L^2] / [T].
Final code:
j_i = np.array(j)
MSD = []
diff_i = []
tau_i = []
for l in range(len(time)):
tau = l*dt
tau_i.append(tau)
for i in range(len(time)-l):
diff = (j_i[l+i]-j_i[i])**2
diff_i.append(diff)
MSD_j = np.mean(diff_i)
MSD.append(MSD_j)
EDIT: I realized I forgot to mention it because I was focusing on the code, but the ensemble average denoted by <.> in the paper should, as the name implies, be performed over several particles, preferentially comparing the initial position of each particle with its new position after a time tau, and not as you did with a kind of time-running average
EDIT 2: here is a code that shows how to do a proper ensemble average to implement exactly the formula in the article
js = # an array of shape (N, M), with N the number of particles and
# M the number of time points
MSD_i = np.zeros((N, M))
taus = []
for l in range(len(time)):
taus.append(l*dt) # store the values of tau
# compute all squared displacements at current tau
MSD_i[:, l] = np.square(js[:, 0] - js[:, l])
# then, compute the ensemble average for each tau (over the N particles)
MSD = np.mean(MSD_i, axis=0)
And now you can plot MSD versus taus and Bob's your uncle

Rotated Paraboloid Surface Fitting

I have a set of experimentally determined (x, y, z) points which correspond to a parabola. Unfortunately, the data is not aligned along any particular axis, and hence corresponds to a rotated parabola.
I have the following general surface:
Ax^2 + By^2 + Cz^2 + Dxy + Gyz + Hzx + Ix + Jy + Kz + L = 0
I need to produce a model that can represent the parabola accurately using (I'm assuming) least squares fitting. I cannot seem to figure out how this works. I have though of rotating the parabola until its central axis lines up with z-axis but I do not know what this axis is. Matlab's cftool only seems to fit equations of the form z = f(x, y) and I am not aware of anything in python that can solve this.
I also tried solving for the parameters numerically. When I tried making this into a matrix equation and solving by least squares, the matrix turned out to be invertible and hence my parameters were just all zero. I also am stuck on this and any help would be appreciated. I don't really mind the method as I am familiar with matlab, python and linear algebra if need be.
Thanks
Dont use any toolboxes, GUIs or special functions for this problem. Your problem is very common and the equation you provided may be solved in a very straight-forward manner. The solution to the linear least squares problem can be outlined as:
The basis of the vector space is x^2, y^2, z^2, xy, yz, zx, x, y, z, 1. Therefore your vector has 10 dimensions.
Your problem may be expressed as Ap=b, where p = [A B C D E F G H I J K L]^T is the vector containing your parameters. The right hand side b should be all zeros, but will contain some residual due to model errors, uncertainty in the data or for numerical reasons. This residual has to be minimized.
The matrix A has a dimension of N by 10, where N denotes the number of known points on surface of the parabola.
A = [x(1)^2 y(1)^2 ... y(1) z(1) 1
...
x(N)^2 y(N)^2 ... y(N) z(N) 1]
Solve the overdetermined system of linear equations by computing p = A\b.
Do you have enough data points to fit all 10 parameters - you will need at least 10?
I also suspect that 10 parameters are to many to describe a general paraboloid, meaning that some of the parameters are dependent. My fealing is that a translated and rotated paraboloid needs 7 parameters (although I'm not really sure)

python implementation of 3D rigid body translation and rotation

I've been trying to work out how to solve the following problem using python:
We have points a, b, c, d which form a rigid body
Some unknown 3D translation and rotation is applied to the rigid body
We now know the coordinates for a, b, c
We want to calculate coordinates for d
What I know so far:
Trying to do this with "straightforward" Euler angle calculations seems like a bad idea due to gimbal lock etc.
Step 4 will therefore involve a transformation matrix, and once you know the rotation and translation matrix it looks like this step is easy using one of these:
http://www.lfd.uci.edu/~gohlke/code/transformations.py.html
https://pypi.python.org/pypi/euclid/0.01
What I can't work out is how I can calculate the rotation and translation matrices given the "new" coordinates of a, b, c.
I can see that in the general case (non-rigid body) the rotation part of this is Wahba's problem, but I think that for rigid bodies there should be some faster way of calculating it directly by working out a set of orthogonal unit vectors using the points.
For a set of corresponding points that you're trying to match (with possible perturbation) I've used SVD (singular value decomposition), which appears to exist in numpy.
An example of this technique (in Python even) can be found here, but I haven't evaluated it for correctness.
What you're going for is a "basis transform" or "change of basis" which will be represented as a transformation matrix. Assuming your 3 known points are not collinear, you can create your initial basis by:
Computing the vectors: x=(b-a) and y=(c-a)
Normalize x (x = x / magnitude(x))
Project y onto x (proj_y = x DOT y * x)
Subtract the projection from y (y = y - proj_y)
Normalize y
Compute z = x CROSS y
That gives you an initial x,y,z coordinate basis A. Do the same for your new points, and you get a second basis B. Now you want to find transform T which will take a point in A and convert it to B (change of basis). That part is easy. You can invert A to transform the points back to the Normal basis, then use B to transform into the second one. Since A is orthonormal, you can just transpose A to get the inverse. So the "new d" is equal to d * inverse(A) * B. (Though depending on your representation, you may need to use B * inverse(A) * d.)
You need to have some familiarity with matrices to get all that. Your representation of vectors and matrices will inform you as to which order to multiply the matrices to get T (T is either inverse(A)*B or B*inverse(A)).
To compute your basis matrix from your vectors x=(x1,x2,x3), y=(y1,y2,y3), z=(z1,z2,z3) you populate it as:
| x1 y1 z1 |
| x2 y2 z2 |
| x3 y3 z3 |

Categories

Resources