Java通过坐标点进行拟合函数

15 篇文章 0 订阅

今天来记录一下通过数据拟合函数的代码,这里用到了commons-math3工具包进行拟合。

参考内容:https://blog.csdn.net/wufeiwua/article/details/109004452

首先导入依赖

        <dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-math3</artifactId>
			<version>3.6.1</version>
		</dependency>

 因为博主大学数据全都还给了老师,在同事的帮助下才实现如下代码:


import com.adc.devp.function.bean.Point;
import org.apache.commons.math3.analysis.ParametricUnivariateFunction;
import org.apache.commons.math3.fitting.SimpleCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 极化曲线拟合函数
 *
 * @author: 刘朋
 * <br/>date:
 */
class PolarizationFunction implements ParametricUnivariateFunction {

    private double[] parameters;

    /**
     * 定义公式
     * V = v0 - b * Math.log10(i) - r * i
     *
     * @param i
     * @param parameters
     * @return
     */
    @Override
    public double value(double i, double... parameters) {
        double v0 = parameters[0];
        double b = parameters[1];
        double r = parameters[2];
        // 自定义函数
        return v0 - b * Math.log10(i) - r * i;
    }

    @Override
    public double[] gradient(double i, double... parameters) {
        double[] gradients = new double[3];
        // 对 v0 求导
        gradients[0] = 1;
        // 对 b 求导
        gradients[1] = -Math.log10(i);
        // 对 r 求导
        gradients[2] = -i;

        return gradients;
    }

    /**
     * 拟合代码逻辑
     *
     * @param points 待拟合的数据
     * @return
     */
    public PolarizationFunction fitting(List<Point> points) {
        ParametricUnivariateFunction function = new PolarizationFunction();/*多项式函数*/
        /*猜测值 依次为 v0 b r 。必须和 gradient 方法返回数组对应*/
        double[] guess = {250, 0.1, 0.1};

        // 初始化拟合
        SimpleCurveFitter curveFitter = SimpleCurveFitter.create(function, guess);

        // 添加数据点。带权重的点,我的理解这个点权重越大,拟合出来的曲线会更靠近这个点
        WeightedObservedPoints observedPoints = new WeightedObservedPoints();
        for (Point point : points) {
            observedPoints.add(point.getX(), point.getY());
        }
        /*
         * best 为拟合结果 对应 v0 b r
         * 可能会出现无法拟合的情况
         * 需要合理设置初始值
         * */
        double[] best = curveFitter.fit(observedPoints.toList());
        System.out.println(Arrays.toString(best));
        parameters = best;

        return this;
    }

    /**
     * @param x
     * @return
     */
    public double caleY(double x) {
        if (Objects.isNull(parameters)) {
            throw new RuntimeException("参数为空,请先进行拟合操作");
        }
        return this.value(x, parameters);
    }

}
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serializable;


@Data
@EqualsAndHashCode
public class Point implements Serializable {

    private static final long serialVersionUID = 3256087124347421878L;

    private double x;

    private double y;

    public Point() {
    }

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

}

在此感谢我的同事晋津对我的帮助!

最小二乘法是一种常用的数据拟合方法,Java中也提供了相应的实现方法。对于曲线拟合,可以使用最小二乘法来求解拟合曲线的参数。在Java中,可以使用Apache Commons Math库提供的类来实现最小二乘法。 具体实现方法如下: 1. 引入Apache Commons Math库,导入依赖。 2. 准备数据:需要提供待拟合的数据坐标(x,y),将其存储在数组或者List中。 3. 构造拟合函数:根据拟合曲线的类型(比如直线、二次曲线等),构造对应的函数。 4. 定义误差函数:误差函数用于评估拟合曲线与原始数据之间的偏差。 5. 求解最小二乘解:使用LevenbergMarquardtOptimizer类来求解最小二乘解,该类是一个适用于非线性最小二乘问题的实现。 以下是一个简单的Java代码示例: ``` import org.apache.commons.math3.fitting.leastsquares.*; import org.apache.commons.math3.fitting.WeightedObservedPoints; public class CurveFitting { public static void main(String[] args) { // 准备数据 double[] xValues = new double[]{0, 1, 2, 3, 4, 5}; double[] yValues = new double[]{1, 2, 3, 4, 5, 6}; // 构造拟合函数 ParametricUnivariateFunction function = new ParametricUnivariateFunction() { @Override public double value(double x, double... parameters) throws DimensionMismatchException { double a = parameters; double b = parameters; return a * x + b; } @Override public double[] gradient(double x, double... parameters) throws DimensionMismatchException { double a = parameters; double b = parameters; return new double[]{x, 1}; } }; // 定义误差函数 WeightedObservedPoints obs = new WeightedObservedPoints(); for (int i = 0; i < xValues.length; i++) { obs.add(xValues[i], yValues[i]); } AbstractCurveFitter fitter = new LevenbergMarquardtCurveFitter(function); double[] initialGuess = new double[]{0.5, 0.5}; double[] bestFitParameters = fitter.fit(obs.toList(), initialGuess); // 输出结果 System.out.println("a: " + bestFitParameters); System.out.println("b: " + bestFitParameters); } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值