在 java 中使用曲线拟合计算出一个点
Working out a point using curve fitting in java
以下代码生成一条曲线,该曲线应适合点
1, 1
150, 250
10000, 500
100000, 750
100000, 1000
我根据文档 here 构建了此代码,但是,我不完全确定如何正确使用数据进行进一步计算以及 PolynomialCurveFitter.create(3)
是否会影响这些未来计算的答案.
例如,如果 y
值为 200
,我将如何使用输出的数据来计算什么是 x
值,如果我有 PolynomialCurveFitter.create(2)
而不是 PolynomialCurveFitter.create(3)
?
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
public class MyFuncFitter {
public static void main(String[] args) {
ArrayList<Integer> keyPoints = new ArrayList<Integer>();
keyPoints.add(1);
keyPoints.add(150);
keyPoints.add(10000);
keyPoints.add(100000);
keyPoints.add(1000000);
WeightedObservedPoints obs = new WeightedObservedPoints();
if(keyPoints != null && keyPoints.size() != 1) {
int size = keyPoints.size();
int sectionSize = (int) (1000 / (size - 1));
for(int i = 0; i < size; i++) {
if(i != 0)
obs.add(keyPoints.get(i), i * sectionSize);
else
obs.add(keyPoints.get(0), 1);
}
} else if(keyPoints.size() == 1 && keyPoints.get(0) >= 1) {
obs.add(1, 1);
obs.add(keyPoints.get(0), 1000);
}
PolynomialCurveFitter fitter = PolynomialCurveFitter.create(3);
fitter.withStartPoint(new double[] {keyPoints.get(0), 1});
double[] coeff = fitter.fit(obs.toList());
System.out.println(Arrays.toString(coeff));
}
}
关于改变 d 对你的函数有什么影响
PolynomialCurveFitter.create
取多项式的次数作为参数。
非常(非常)粗略地说,多项式的次数将描述你想要拟合的曲线的"complexity"。 low-level 度将产生简单的曲线(对于 d=2 只是抛物线),而更高的度将产生更复杂的曲线,有很多峰谷,大小变化很大,因此更能够完美 "fit" 你所有的数据点,以不一定是所有其他值的好 "prediction" 为代价。
喜欢这张图上的蓝色曲线:
您可以看到直线会更好 "approximation",但不能正确拟合数据点。
如何为计算函数中的任何 y 值计算 x
你"simply"需要解多项式!使用完全相同的库。将反转的 y 值添加到系数列表中,并找到它的根。
假设您选择了 2 度。
您的系数数组 coeffs
将包含 3 个因子 {a0, a1, a2}
,它们描述了方程式:
如果你想解决一个特定的值,比如 y=600,你需要解决:
所以,基本上,
所以,只需将 600 减去 a0:
coeffs[0] -= 600
并使用专用函数求多项式的根:
PolynomialFunction polynomial = new PolynomialFunction(coeffs);
LaguerreSolver laguerreSolver = new LaguerreSolver();
double x = laguerreSolver.solve(100, polynomial, 0, 1000000);
System.out.println("For y = 600, we found x = " + x);
以下代码生成一条曲线,该曲线应适合点
1, 1
150, 250
10000, 500
100000, 750
100000, 1000
我根据文档 here 构建了此代码,但是,我不完全确定如何正确使用数据进行进一步计算以及 PolynomialCurveFitter.create(3)
是否会影响这些未来计算的答案.
例如,如果 y
值为 200
,我将如何使用输出的数据来计算什么是 x
值,如果我有 PolynomialCurveFitter.create(2)
而不是 PolynomialCurveFitter.create(3)
?
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
public class MyFuncFitter {
public static void main(String[] args) {
ArrayList<Integer> keyPoints = new ArrayList<Integer>();
keyPoints.add(1);
keyPoints.add(150);
keyPoints.add(10000);
keyPoints.add(100000);
keyPoints.add(1000000);
WeightedObservedPoints obs = new WeightedObservedPoints();
if(keyPoints != null && keyPoints.size() != 1) {
int size = keyPoints.size();
int sectionSize = (int) (1000 / (size - 1));
for(int i = 0; i < size; i++) {
if(i != 0)
obs.add(keyPoints.get(i), i * sectionSize);
else
obs.add(keyPoints.get(0), 1);
}
} else if(keyPoints.size() == 1 && keyPoints.get(0) >= 1) {
obs.add(1, 1);
obs.add(keyPoints.get(0), 1000);
}
PolynomialCurveFitter fitter = PolynomialCurveFitter.create(3);
fitter.withStartPoint(new double[] {keyPoints.get(0), 1});
double[] coeff = fitter.fit(obs.toList());
System.out.println(Arrays.toString(coeff));
}
}
关于改变 d 对你的函数有什么影响
PolynomialCurveFitter.create
取多项式的次数作为参数。
非常(非常)粗略地说,多项式的次数将描述你想要拟合的曲线的"complexity"。 low-level 度将产生简单的曲线(对于 d=2 只是抛物线),而更高的度将产生更复杂的曲线,有很多峰谷,大小变化很大,因此更能够完美 "fit" 你所有的数据点,以不一定是所有其他值的好 "prediction" 为代价。
喜欢这张图上的蓝色曲线:
您可以看到直线会更好 "approximation",但不能正确拟合数据点。
如何为计算函数中的任何 y 值计算 x
你"simply"需要解多项式!使用完全相同的库。将反转的 y 值添加到系数列表中,并找到它的根。
假设您选择了 2 度。
您的系数数组 coeffs
将包含 3 个因子 {a0, a1, a2}
,它们描述了方程式:
如果你想解决一个特定的值,比如 y=600,你需要解决:
所以,基本上,
所以,只需将 600 减去 a0:
coeffs[0] -= 600
并使用专用函数求多项式的根:
PolynomialFunction polynomial = new PolynomialFunction(coeffs);
LaguerreSolver laguerreSolver = new LaguerreSolver();
double x = laguerreSolver.solve(100, polynomial, 0, 1000000);
System.out.println("For y = 600, we found x = " + x);