# Iris-鸢尾花分类

Iris 数据集是常用的分类实验数据集,由 Fisher, 1936 收集整理。Iris 也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集包含 150 个数据样本,分为3类,每类 50 个数据,每个数据包含 4 个属性。可通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。

Iris 数据集包含了 4 种属性,分别为:

  • Sepal.Length (花萼长度);
  • Sepal.Width (花萼宽度);
  • Petal.Length (花瓣长度);
  • Petal.Width (花瓣宽度);

上面四个属性对应三个分类,分别为:

  • Iris Setosa (山鸢尾);
  • Iris Versicolour (杂色鸢尾);
  • Iris Virginica (维吉尼亚鸢尾);

我们并不关注给定的数据到底属于哪个分类,因为数据集已经帮我们做了,所以本实例要做的就是在现有数据的基础之上,基于上述四个属性搜索表达式,最终能够为给定的属性数据划归正确的分类。

# 数据生成

Iris 数据集有专门的 CSV 文件,网上可以很方便找到,这里给出连接:Iris 数据集 (opens new window)

拿到数据以后,需要对数据做简单处理,我们假定数据已经被处理成了 shape[150, 5] 的数组,由于每条数据的最后一项为所属分类,我们按照机器学习中常用的方式对类别数据进行处理:

  • Setosa: [1, 0, 0];
  • Versicolour: [0, 1, 0];
  • Virginica: [0, 0, 1];

以上处理完成后,每一条数据就变成了 xdataydata 的映射,例如对于前 3 条数据,其映射结果为:

// 1. [5.1, 3.5, 1.4, 0.2] ==> [1, 0, 0]
// 2. [4.9, 3.0, 1.4, 0.2] ==> [1, 0, 0]
// 3. [4.7, 3.2, 1.3, 0.2] ==> [1, 0, 0]

然后,我们随机打乱所有的数据,然后取出其 2/3 作为训练数据,剩余 1/3 为测试数据。

import IrisData from 'iris.json';

/**
 * 对输入数组进行随机排序
 * @param indata 输入数组
 */
function createRandomData(indata: number[]) {
  let dataCopy = [...indata];
  let res: number[] = [];
  while(dataCopy.length) {
    const idx = Math.floor(Math.random() * dataCopy.length);
    res = res.concat(dataCopy.splice(idx, 1));
  }
  return res;
}
// 打乱原数据
const irisRandomArray = createRandomData(IrisData);
// 训练数据
const trainData = irisRandomArray.slice(0, 100);
// 测试数据
const testData = irisRandomArray.slice(100);

# 输入参数

模型接收 4 个入参,对应数据集中的四个属性。

符号 类型 说明 属性
a Number Sepal.Length 花萼长度
b Number Sepal.Width 花萼宽度
c Number Petal.Length 花瓣长度
d Number Sepal.Width 花瓣宽度

# 集合算子

符号 表达式
+ a + b
- a - b
* a * b
/ a / b
E 常数 E
Q sqrt
S sin
L log

使用 Operator 模块设置入参和算子:

import { Operator } from 'gepjs';

const operators = new Operator();
// 清空内建算子
operators.clear();

// 设置新算子
operators.setFunc('+', (a, b) => a + b);
operators.setFunc('-', (a, b) => a - b);
operators.setFunc('*', (a, b) => a * b);
operators.setFunc('/', (a, b) => a / b);
operators.setFunc('Q', Math.sqrt);
operators.setFunc('S', Math.sign);
operators.setFunc('L', Math.log);
// 设置入参变量
operators.setVars('a');
operators.setVars('b');
operators.setVars('c');
operators.setVars('d');

// 导出数组以便环境使用
const operSets = operators.toArray();

# 环境参数:

头部长度 突变率 混入率 修正因子
5 0.3 0.3 0.0001

# 遗传参数

由于环境参数中基因的头部长度只有 3 ,显的非常短,为了确保整个基因能顺利表达出系数 k ,我们将 Gene shape 设置为 [1, 5] ,这样可以增加基因的长度,有助于表达系数。

种群 染色体长度 Gene Shape 损失函数 激活函数 迭代数
50 3 [1, 5] Loss.categorical_disc Activation.tanh 500

# 可视化

点击下方开始按钮查看训练过程。

下方的三个统计图分别记录了 训练数据误差测试数据误差测试数据的回测准确率

表达式:

Click the "Start" button to start calculating the expression

点击下方按钮开始执行

开始训练