Flutter遗传进化神经网络插件genetically_evolving_neural_network的应用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter遗传进化神经网络插件genetically_evolving_neural_network的应用

1. 插件概述

genetically_evolving_neural_network 是一个Flutter插件,它模拟了基因进化的过程,通过交叉繁殖和基因突变来优化神经网络。每个实体(Entity)由一个神经网络组成,其“DNA”可以视为神经网络的结构,而“基因”则是神经网络中的感知器(Perceptrons)。通过评估每个实体的表现并选择表现较好的实体进行繁殖,插件实现了进化的过程。

2. 工作原理

  • 初始种群生成:插件会生成一个随机的初始种群,每个实体包含一个随机生成的神经网络。
  • 适应度评分:每个神经网络都会根据自定义的 FitnessService 进行评估,获得一个适应度评分(fitness score),评分越高表示该神经网络的表现越好。
  • 繁殖与变异:表现较好的实体有更高的概率被选为父母,生成下一代实体。在繁殖过程中,父母的基因会被组合,并有一定概率发生突变。
  • 进化循环:这个过程会不断重复,逐渐优化种群中的神经网络。

3. 使用步骤

3.1 定义 FitnessService

FitnessService 是用来评估每个实体表现的关键部分。你需要根据具体的任务定义一个 FitnessService,例如判断一个数字是正数还是负数、预测下一步棋的走法等。

/// The inputs for this Neural Network, from -1 to 1 in increments of 0.1.
List<double> get inputs => List.generate(10, (index) => index * 0.1)
  ..addAll(List.generate(9, (index) => (index + 1) * -0.1));

/// The scoring function that will be used to evolve entities of a population
class PositiveNumberFitnessService extends GENNFitnessService {
  @override
  Future<double> gennScoringFunction({
    required GENNNeuralNetwork neuralNetwork,
  }) async {
    // Calculate how many correct guesses were made
    return inputs.fold(0, (previousValue, input) {
      final guess = neuralNetwork.guess(inputs: [input])[0];
      // Only add a point if the neural network guesses correctly
      if ((input > 0 && guess > 0) || (input <= 0 && guess == 0)) {
        return previousValue + 1;
      }
      return previousValue;
    }).toDouble();
  }
}
3.2 配置 GeneticEvolutionConfig

GeneticEvolutionConfig 用于定义种群的大小、突变率等参数。你可以根据任务的需求调整这些参数。

final config = GENNGeneticEvolutionConfig(
  numInitialInputs: 1, // 1 input into neural network
  numOutputs: 1, // 1 output from neural network
  layerMutationRate: 0.1, // 10% chance to add/remove layer to network
  perceptronMutationRate: 0.2, // 20% chance to add/remove perceptron to layer
  mutationRate: 0.05, // 5% chance to mutate an existing perceptron
);
3.3 创建 GENN 对象

使用 FitnessServiceGeneticEvolutionConfig 创建 GENN 对象,并开始进化过程。

final genn = GENN.create(
  config: config,
  fitnessService: PositiveNumberFitnessService(),
);

// 获取下一代实体
final nextGen = await genn.nextGeneration();

4. 示例代码

以下是一个完整的示例,展示了如何使用 genetically_evolving_neural_network 插件来构建一个简单的正负数分类器。

import 'package:flutter/material.dart';
import 'package:genetically_evolving_neural_network/genetically_evolving_neural_network.dart';

/// The inputs for this Neural Network, from -1 to 1 in increments of 0.1.
List<double> get inputs => List.generate(10, (index) => index * 0.1)
  ..addAll(List.generate(9, (index) => (index + 1) * -0.1));

/// The scoring function that will be used to evolve entities of a population
class PositiveNumberFitnessService extends GENNFitnessService {
  @override
  Future<double> gennScoringFunction({
    required GENNNeuralNetwork neuralNetwork,
  }) async {
    // Calculate how many correct guesses were made
    return inputs.fold(0, (previousValue, input) {
      final guess = neuralNetwork.guess(inputs: [input])[0];
      // Only add a point if the neural network guesses correctly
      if ((input > 0 && guess > 0) || (input <= 0 && guess == 0)) {
        return previousValue + 1;
      }
      return previousValue;
    }).toDouble();
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  /// Represents the FitnessService used to drive this GENN example.
  final GENNFitnessService fitnessService = PositiveNumberFitnessService();

  /// The current generation of Neural Networks.
  GENNGeneration? generation;

  /// The Genetically Evolving Neural Network object.
  late final GENN genn;

  @override
  void initState() {
    // Declare a config with specific mutation rates.
    final config = GENNGeneticEvolutionConfig(
      populationSize: 20,
      numOutputs: 1,
      mutationRate: 0.1,
      numInitialInputs: 1,
      layerMutationRate: 0.25,
      perceptronMutationRate: 0.4,
    );

    // Create the GENN object from the incoming config and fitness service.
    genn = GENN.create(
      config: config,
      fitnessService: fitnessService,
    );

    // Initialize the first generation
    genn.nextGeneration().then((value) {
      setState(() {
        generation = value;
      });
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final generation = this.generation;
    if (generation == null) {
      return const CircularProgressIndicator();
    }

    return MaterialApp(
      title: 'GENN Example',
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('代数: ${generation.wave.toString()}'),
              Text('最高得分: '
                  '${generation.population.topScoringEntity.fitnessScore} '
                  '总分: ${inputs.length}.01'),
              Text('最高得分实体的层数: '
                  '${generation.population.topScoringEntity.maxLayerNum + 1}'),
              Text('最高得分实体的感知器数量: '
                  '${generation.population.topScoringEntity.dna.genes.length}'),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton.extended(
          label: const Text('下一世代'),
          onPressed: () {
            // Set the next Generation to be displayed
            genn.nextGeneration().then((value) {
              setState(() {
                this.generation = value;
              });
            });
          },
        ),
      ),
    );
  }
}

5. 更复杂的示例

除了简单的正负数分类器,genetically_evolving_neural_network 还可以用于解决更复杂的问题,例如:

  • 逻辑异或(Logical XOR):判断输入是否满足逻辑异或条件,即只有一个输入为1.0,其他输入为0.0时返回正确结果。
  • 图像数字分类器:识别像素化图像所代表的数字(0-9)。
5.1 逻辑异或示例
/// This fitness service will be used to score a logical XOR calculator. The
/// Neural Network should only be rewarded for guessing "yes" when there is a
/// single input of 1.0 and both other inputs are 0.
class LogicalXORGENNVisualizationFitnessService extends GENNFitnessService {
  @override
  Future<double> gennScoringFunction({
    required GENNNeuralNetwork neuralNetwork,
  }) async {
    // Collect all the guesses from this NeuralNetwork
    final guesses = getNeuralNetworkGuesses(neuralNetwork: neuralNetwork);

    // Declare a variable to store the sum of all errors
    var errorSum = 0.0;

    // Cycle through each guess to check its validity
    for (int i = 0; i < guesses.length; i++) {
      // Calculate the error from this guess
      final error = (targetOutputsList[i] == guesses[i]) ? 0 : 1;

      // Add this error to the errorSum
      errorSum += error;
    }

    // Calculate the difference between a perfect score (8) and the total
    // errors. A perfect score would mean zero errors with 8 correct answers,
    // meaning a perfect score would be 8.
    final diff = inputList.length - errorSum;

    // To make the better performing Entities stand out more in this population,
    // use the following equation to calculate the FitnessScore.
    //
    // 4 to the power of diff
    return pow(4, diff).toDouble();
  }
}
5.2 图像数字分类器示例
/// This class will be used to score a Number Classifier in tandem with a
/// Neural Network.
class NumberClassifierFitnessService extends GENNFitnessService {
  @override
  Future<double> gennScoringFunction({
    required GENNNeuralNetwork neuralNetwork,
  }) async {
    // Collect all the guesses from this NeuralNetwork
    final guesses = getNeuralNetworkGuesses(neuralNetwork: neuralNetwork);

    // Declare a variable to store the sum of points scored
    int points = 0;

    // Cycle through each guess to check its validity
    for (int i = 0; i < guesses.length; i++) {
      final NaturalNumber targetOutput = targetOutputsList[i];
      final NaturalNumber guessOutput = guesses[i];

      if (targetOutput == guessOutput) {
        // Guessing correctly will give you a point.
        points++;
      }
    }

    // To make the better performing Entities stand out more in this population,
    // use the following equation to calculate the FitnessScore.
    //
    // 4 to the power of points
    return pow(4, points).toDouble();
  }
}

6. 文件解析

你还可以将特定的世代写入文件,并从文件中读取特定的世代。

  • 写入文件
genn.writeGenerationToFile();
  • 从文件加载
genn.loadGenerationFromFile(wave: 10);

更多关于Flutter遗传进化神经网络插件genetically_evolving_neural_network的应用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter遗传进化神经网络插件genetically_evolving_neural_network的应用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,虽然直接集成遗传进化神经网络(Genetically Evolving Neural Network, GENN)可能不是最常见的任务,但可以通过一些插件和原生代码桥接来实现这一功能。genetically_evolving_neural_network 并不是一个广泛认知的Flutter插件,因此假设你指的是一个自定义的或者类似功能的实现,我们可以探索如何使用Flutter与原生代码(如Dart调用C++或Python实现的遗传进化神经网络)进行交互。

由于Flutter主要使用Dart语言编写,而复杂的神经网络和遗传算法通常在性能更高的语言中实现(如C++或Python),我们可以利用Flutter的Platform Channels来与原生代码通信。

以下是一个简化的示例,展示了如何在Flutter中通过Platform Channels调用原生代码(假设我们在Android上使用Java/Kotlin实现了一个简单的遗传进化神经网络,iOS上类似)。

1. 设置Flutter项目

首先,创建一个新的Flutter项目:

flutter create genn_flutter_app
cd genn_flutter_app

2. 在Android端实现遗传进化神经网络

android/app/src/main/java/com/example/genn_flutter_app/目录下创建一个新的Java类,例如GeneticNeuralNetwork.java

package com.example.genn_flutter_app;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

// 假设的简单神经网络节点类
class NeuralNode implements Parcelable {
    double[] weights;

    protected NeuralNode(Parcel in) {
        weights = in.createDoubleArray();
    }

    public static final Creator<NeuralNode> CREATOR = new Creator<NeuralNode>() {
        @Override
        public NeuralNode createFromParcel(Parcel in) {
            return new NeuralNode(in);
        }

        @Override
        public NeuralNode[] newArray(int size) {
            return new NeuralNode[size];
        }
    };

    public NeuralNode(int numInputs) {
        weights = new double[numInputs];
        Random rand = new Random();
        for (int i = 0; i < numInputs; i++) {
            weights[i] = rand.nextDouble();
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeDoubleArray(weights);
    }
}

public class GeneticNeuralNetwork {
    // 简单的遗传算法示例,这里省略了详细的实现
    public List<NeuralNode> evolve(List<NeuralNode> population, int generations) {
        // 进化逻辑...
        // 这里只是简单地返回原始种群作为示例
        return population;
    }
}

3. 创建MethodChannel进行通信

MainActivity.java中设置MethodChannel:

package com.example.genn_flutter_app;

import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMessageCodec;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "com.example.genn_flutter_app/genn";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);

        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(
                        (call, result) -> {
                            if (call.method.equals("evolveNetwork")) {
                                List<Parcelable> populationList = call.argument("population");
                                int generations = call.argument("generations");

                                GeneticNeuralNetwork genn = new GeneticNeuralNetwork();
                                List<NeuralNode> evolvedPopulation = new ArrayList<>();
                                for (Parcelable p : populationList) {
                                    evolvedPopulation.add((NeuralNode) p);
                                }
                                evolvedPopulation = genn.evolve(evolvedPopulation, generations);

                                result.success(evolvedPopulation);
                            } else {
                                result.notImplemented();
                            }
                        }
                );
    }
}

注意:由于NeuralNode实现了Parcelable,我们可以通过MethodCall传递这些对象。然而,这里有一个限制,即Parcelable不能直接在Dart中使用,你可能需要在Dart端定义一个对应的类,并在传递数据时进行适当的序列化和反序列化。

4. 在Dart端调用原生方法

lib/main.dart中:

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class NeuralNode {
  List<double> weights;

  NeuralNode({required this.weights});

  factory NeuralNode.fromMap(Map<String, dynamic> map) {
    return NeuralNode(weights: List<double>.from(map['weights']!));
  }

  Map<String, dynamic> toMap() {
    return {'weights': weights};
  }
}

void main() {
  const MethodChannel _channel = MethodChannel('com.example.genn_flutter_app/genn');

  List<NeuralNode> createInitialPopulation() {
    // 创建初始种群...
    return [NeuralNode(weights: [0.1, 0.2, 0.3]), NeuralNode(weights: [0.4, 0.5, 0.6])];
  }

  void evolveNetwork() async {
    List<NeuralNode> population = createInitialPopulation();
    List<Map<String, dynamic>> populationMap = population.map((node) => node.toMap()).toList();

    try {
      final List<dynamic> result = await _channel.invokeMethod('evolveNetwork', {
        'population': populationMap,
        'generations': 10,
      });

      // 处理返回的结果...
      print(result);
    } on PlatformException catch (e) {
      print("Failed to invoke: '${e.message}'.");
    }
  }

  runApp(MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Genetic Evolving Neural Network'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: evolveNetwork,
          child: Text('Evolve Network'),
        ),
      ),
    ),
  ));
}

注意:上面的Dart代码尝试直接传递NeuralNode的映射到原生代码,但由于Parcelable的限制,你可能需要实现一个更复杂的数据转换逻辑,比如将NeuralNode转换为JSON或其他可以在Dart和原生代码之间安全传输的格式。

结论

这个示例提供了一个框架,展示了如何在Flutter应用中通过Platform Channels与原生代码进行交互,以实现遗传进化神经网络的功能。然而,实际的实现将涉及更多细节,如数据序列化和反序列化、性能优化、错误处理等。根据具体的神经网络和遗传算法实现,你可能需要对上述代码进行大量修改和扩展。

回到顶部