遗传编程GP-拟合方程

一般都是用机器学习、梯度下降或sklearn、pytorch来做函数拟合运算,今天介绍遗传编程,或称基因编程/GP,来做这个计算

最终就是构造一棵树AST,来表示运算的先后、权重:

 

 

具体原理可以参考这篇文章:https://blog.csdn.net/ocd_with_naming/article/details/98901749 

我们的目标是拟合这个函数:

np.sin(x) + np.log(x)

 图像为:

 

 先来一段java代码,是加载训练数据的,x、y的一个list;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static List<Sample<Double>> load训练数据()
    {
        List<Sample<Double>> samples=new ArrayList<>();
        samples.add(new DoubleDataSample(new Double[]{ 1.0 , 0.8414709848078965 }));                  //第一个为x,第二个为y
        samples.add(new DoubleDataSample(new Double[]{ 1.1 , 0.9865175398657604 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.2000000000000002 , 1.1143606427611812 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.3000000000000003 , 1.2259224498846844 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.4000000000000004 , 1.3219219666096733 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.5000000000000004 , 1.4029600947122192 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.6000000000000005 , 1.4695772322872411 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.7000000000000006 , 1.5222930615146393 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.8000000000000007 , 1.5616342957803144 }));
        samples.add(new DoubleDataSample(new Double[]{ 1.9000000000000008 , 1.5881539738598094 }));        //省略很多x/y对
        return samples;
    }  

 

 下面就是整个算法的架子了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static void main(String[] args) {
        List<Op<Double>> terminals=new ArrayList<>();
        terminals.add(Var.of("x", 0));                  //由于只有1个自变量,所以这里只有x                                         //0代表第一个自变量                                         //如果是向量,则此处可以为x1/0, x2/1, x3/2  以此类推
 
        List<Sample<Double>> samples=load训练数据();
 
        final ISeq<Op<Double>> OPS = ISeq.of(MathOp.ADD, MathOp.SUB, MathOp.MUL, MathOp.SIN,MathOp.COS, MathOp.LOG);      //这些是算法允许使用的操作算子
        final ISeq<Op<Double>> TMS = ISeq.of(terminals);          //上面的自变量在此处挂接上
        final Regression<Double> REGRESSION =
                Regression.of(
                        Regression.codecOf(
                                OPS, TMS, 5,
                                t -> t.getGene().size() < 30
                        ),
                        Error.of(LossFunction::mse),             //MSE计算误差
                        samples
                );
 
        final Engine<ProgramGene<Double>, Double> engine = Engine
                .builder(REGRESSION)
                .minimizing()
                .alterers(
                        new SingleNodeCrossover<>(0.1),
                        new Mutator<>())
                .build();
 
        final EvolutionResult<ProgramGene<Double>, Double> er =
                engine.stream()
                        .limit(Limits.byExecutionTime(Duration.ofSeconds(5)))
                        .collect(EvolutionResult.toBestEvolutionResult());
 
        final ProgramGene<Double> program = er.getBestPhenotype()
                .getGenotype()
                .getGene();
 
        final TreeNode<Op<Double>> tree = program.toTreeNode();
        MathExpr.rewrite(tree);
        System.out.println("G: " + er.getTotalGenerations());
        System.out.println("F: " + new MathExpr(tree));
        System.out.println("E: " + REGRESSION.error(tree));
    }

  

 

 

posted @   McKay  阅读(1162)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示