首先了解下Iris鸢尾花数据集:
Iris数据集(https://en.wikipedia.org/wiki/Iris_flower_data_set)是常用的分类实验数据集,由Fisher,1936收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集包含150个数据集,分为3类,每类50个数据,每个数据包含4个属性。可通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。
iris以鸢尾花的特征作为数据来源,常用在分类操作中。该数据集由3种不同类型的鸢尾花的50个样本数据构成。其中的一个种类与另外两个种类是线性可分离的,后两个种类是非线性可分离的。
该数据集包含了4个属性:
Sepal.Length(花萼长度),单位是cm;
Sepal.Width(花萼宽度),单位是cm;
Petal.Length(花瓣长度),单位是cm;
Petal.Width(花瓣宽度),单位是cm;
种类:Iris Setosa(1.山鸢尾)、Iris Versicolour(2.杂色鸢尾),以及Iris Virginica(3.维吉尼亚鸢尾)。
Iris Setosa(1.山鸢尾)
Iris Versicolour(2.杂色鸢尾)
Iris Virginica(3.维吉尼亚鸢尾)
百闻不如一见:
贴一下使用最多的:
5.1 3.5 1.4 0.2 1
4.9 3 1.4 0.2 1
4.7 3.2 1.3 0.2 1
4.6 3.1 1.5 0.2 1
5 3.6 1.4 0.2 1
5.4 3.9 1.7 0.4 1
4.6 3.4 1.4 0.3 1
5 3.4 1.5 0.2 1
4.4 2.9 1.4 0.2 1
4.9 3.1 1.5 0.1 1
5.4 3.7 1.5 0.2 1
4.8 3.4 1.6 0.2 1
4.8 3 1.4 0.1 1
4.3 3 1.1 0.1 1
5.8 4 1.2 0.2 1
5.7 4.4 1.5 0.4 1
5.4 3.9 1.3 0.4 1
5.1 3.5 1.4 0.3 1
5.7 3.8 1.7 0.3 1
5.1 3.8 1.5 0.3 1
5.4 3.4 1.7 0.2 1
5.1 3.7 1.5 0.4 1
4.6 3.6 1 0.2 1
5.1 3.3 1.7 0.5 1
4.8 3.4 1.9 0.2 1
5 3 1.6 0.2 1
5 3.4 1.6 0.4 1
5.2 3.5 1.5 0.2 1
5.2 3.4 1.4 0.2 1
4.7 3.2 1.6 0.2 1
4.8 3.1 1.6 0.2 1
5.4 3.4 1.5 0.4 1
5.2 4.1 1.5 0.1 1
5.5 4.2 1.4 0.2 1
4.9 3.1 1.5 0.2 1
5 3.2 1.2 0.2 1
5.5 3.5 1.3 0.2 1
4.9 3.6 1.4 0.1 1
4.4 3 1.3 0.2 1
5.1 3.4 1.5 0.2 1
5 3.5 1.3 0.3 1
4.5 2.3 1.3 0.3 1
4.4 3.2 1.3 0.2 1
5 3.5 1.6 0.6 1
5.1 3.8 1.9 0.4 1
4.8 3 1.4 0.3 1
5.1 3.8 1.6 0.2 1
4.6 3.2 1.4 0.2 1
5.3 3.7 1.5 0.2 1
5 3.3 1.4 0.2 1
7 3.2 4.7 1.4 2
6.4 3.2 4.5 1.5 2
6.9 3.1 4.9 1.5 2
5.5 2.3 4 1.3 2
6.5 2.8 4.6 1.5 2
5.7 2.8 4.5 1.3 2
6.3 3.3 4.7 1.6 2
4.9 2.4 3.3 1 2
6.6 2.9 4.6 1.3 2
5.2 2.7 3.9 1.4 2
5 2 3.5 1 2
5.9 3 4.2 1.5 2
6 2.2 4 1 2
6.1 2.9 4.7 1.4 2
5.6 2.9 3.6 1.3 2
6.7 3.1 4.4 1.4 2
5.6 3 4.5 1.5 2
5.8 2.7 4.1 1 2
6.2 2.2 4.5 1.5 2
5.6 2.5 3.9 1.1 2
5.9 3.2 4.8 1.8 2
6.1 2.8 4 1.3 2
6.3 2.5 4.9 1.5 2
6.1 2.8 4.7 1.2 2
6.4 2.9 4.3 1.3 2
6.6 3 4.4 1.4 2
6.8 2.8 4.8 1.4 2
6.7 3 5 1.7 2
6 2.9 4.5 1.5 2
5.7 2.6 3.5 1 2
5.5 2.4 3.8 1.1 2
5.5 2.4 3.7 1 2
5.8 2.7 3.9 1.2 2
6 2.7 5.1 1.6 2
5.4 3 4.5 1.5 2
6 3.4 4.5 1.6 2
6.7 3.1 4.7 1.5 2
6.3 2.3 4.4 1.3 2
5.6 3 4.1 1.3 2
5.5 2.5 4 1.3 2
5.5 2.6 4.4 1.2 2
6.1 3 4.6 1.4 2
5.8 2.6 4 1.2 2
5 2.3 3.3 1 2
5.6 2.7 4.2 1.3 2
5.7 3 4.2 1.2 2
5.7 2.9 4.2 1.3 2
6.2 2.9 4.3 1.3 2
5.1 2.5 3 1.1 2
5.7 2.8 4.1 1.3 2
6.3 3.3 6 2.5 3
5.8 2.7 5.1 1.9 3
7.1 3 5.9 2.1 3
6.3 2.9 5.6 1.8 3
6.5 3 5.8 2.2 3
7.6 3 6.6 2.1 3
4.9 2.5 4.5 1.7 3
7.3 2.9 6.3 1.8 3
6.7 2.5 5.8 1.8 3
7.2 3.6 6.1 2.5 3
6.5 3.2 5.1 2 3
6.4 2.7 5.3 1.9 3
6.8 3 5.5 2.1 3
5.7 2.5 5 2 3
5.8 2.8 5.1 2.4 3
6.4 3.2 5.3 2.3 3
6.5 3 5.5 1.8 3
7.7 3.8 6.7 2.2 3
7.7 2.6 6.9 2.3 3
6 2.2 5 1.5 3
6.9 3.2 5.7 2.3 3
5.6 2.8 4.9 2 3
7.7 2.8 6.7 2 3
6.3 2.7 4.9 1.8 3
6.7 3.3 5.7 2.1 3
7.2 3.2 6 1.8 3
6.2 2.8 4.8 1.8 3
6.1 3 4.9 1.8 3
6.4 2.8 5.6 2.1 3
7.2 3 5.8 1.6 3
7.4 2.8 6.1 1.9 3
7.9 3.8 6.4 2 3
6.4 2.8 5.6 2.2 3
6.3 2.8 5.1 1.5 3
6.1 2.6 5.6 1.4 3
7.7 3 6.1 2.3 3
6.3 3.4 5.6 2.4 3
6.4 3.1 5.5 1.8 3
6 3 4.8 1.8 3
6.9 3.1 5.4 2.1 3
6.7 3.1 5.6 2.4 3
6.9 3.1 5.1 2.3 3
5.8 2.7 5.1 1.9 3
6.8 3.2 5.9 2.3 3
6.7 3.3 5.7 2.5 3
6.7 3 5.2 2.3 3
6.3 2.5 5 1.9 3
6.5 3 5.2 2 3
6.2 3.4 5.4 2.3 3
5.9 3 5.1 1.8 3
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using AForge;
using AForge.Neuro;
using AForge.Neuro.Learning;
using AForge.Controls;
//BPann反向传播神经网络
//进行鸢(yuan)尾花分类
namespace bpannIris
{
class Program
{
private static double premnmx( double num , double min , double max )//归一化1
{
if (num > max)
num = max;
if (num < min)
num = min;
return 2*(num - min) / (max - min) - 1;
}
private static double premnmx1(double num, double min, double max)//归一化2
{
if (num > max)
num = max;
if (num < min)
num = min;
return (num - min) / (max - min);
}
//主程序入口
static void Main(string[] args)
{
int trainNum = 75 ; //训练数据个数
int testNum = 75 ; //测试数据个数
double[][] trainInput = new double[trainNum][];
double[][] trainOutput = new double[trainNum][];
double[] max = new double[4];
double[] min = new double[4];
for (int i = 0; i < 4; ++i)
{
min[i] = double.MaxValue;//注意赋值,不能弄反了,目的找出每个属性的范围,做归一下用
max[i] = double.MinValue;
}
// 读取训练数据
StreamReader reader = new StreamReader("trainData.txt");
for (int i = 0; i < trainNum; ++i)
{
string value = reader.ReadLine();//读取一行
string[] temp = value.Split('\t');//分割出字段
trainInput[i] = new double[4];//4个属性Sepal length, Sepal width, Petal length, Petal width
trainOutput[i] = new double[3];//分3种类别Iris setosa, Iris versicolor, Iris virginica
for (int j = 0; j < 4; ++j)//属性
{
trainInput[i][j] = double.Parse(temp[j]);
if (trainInput[i][j] > max[j])
{
max[j] = trainInput[i][j];
}
if (trainInput[i][j] < min[j])
{
min[j] = trainInput[i][j];
}
}
for (int j = 0; j < 3; ++j)
{
trainOutput[i][j] = 0;//初始化分类为0
}
trainOutput[i][int.Parse(temp[4])-1] = 1;
}
// 归一化
for (int i = 0; i < trainNum; ++i)
{
for (int j = 0; j < 4; ++j)
{
trainInput[i][j] = premnmx(trainInput[i][j], min[j], max[j]);
}
}
//训练网络
// create multi-layer neural network
ActivationNetwork network = new ActivationNetwork( new SigmoidFunction(3), 4, 5, 3 );
// create teacher 反向传播算法
BackPropagationLearning teacher = new BackPropagationLearning(network);
// set learning rate and momentum
teacher.LearningRate = 0.1;//学习率
teacher.Momentum = 0;//动量参数
int iteration = 1 ;//训练轮数
while( iteration < 500 )
{
teacher.RunEpoch( trainInput, trainOutput );
++iteration;
}
// 读取测试数据
double[][] testInput = new double[testNum][];
double[] testOutput = new double[testNum];
StreamReader reader1 = new StreamReader("testData.txt");
for (int i = 0; i < testNum; ++i)
{
string value = reader1.ReadLine();//读取行
string[] temp = value.Split('\t');//分割字段
testInput[i] = new double[4];
for (int j = 0; j < 4; ++j)//4个属性
{
testInput[i][j] = double.Parse(temp[j]);
}
testOutput[i] = int.Parse(temp[4]);//分类结果
}
// 对测试数据进行分类, 并统计正确率
int hitNum = 0 ;
for( int i = 0 ; i < testNum ; ++i )
{
double[] inp = new double[4]{ testInput[i][0], testInput[i][1], testInput[i][2], testInput[i][3] } ;
for (int j = 0; j < 4; ++j)
{
inp[j] = premnmx(inp[j], min[j], max[j]);//归一化
}
double[] t = { inp[0], inp[1], inp[2], inp[3] };
// 使用已训练的网络对测试样本计算输出
double[] result = network.Compute(t) ;
int m = 0;
for (int j = 0; j < 3; ++j)
{
if (result[j] > result[m])//选出概率最大的分类
{
m = j;
}
}
if (m + 1 == testOutput[i])//转成测试集分类标签
{
++hitNum;//统计命中个数
}
}
System.Console.WriteLine("分类正确率为 {0}% ", 100.0 * hitNum / testNum );
System.Console.Read();//读取输入,暂停
}
}
}