Two-Layer Neural Net — NO TRAINING

This is a work in progress. I will add training and demonstrate that as my final project.

Implementation

static final String IRIS_DATASET_FILENAME = "iris.json";

// Keys used at the top level of the JSON dictionary
static final String DATA_KEY = "data";

// Keys used in each iris data record
static final String SEPAL_LENGTH_KEY = "sepalLength";
static final String SEPAL_WIDTH_KEY = "sepalWidth";
static final String PETAL_LENGTH_KEY = "petalLength";
static final String PETAL_WIDTH_KEY = "petalWidth";
static final String SPECIES_KEY = "species";

// The allowed values for species:
static final String[] ALLOWED_SPECIES = {"setosa", "versicolor", "virginica"};

interface IsAnInputSource {
  // To be an input source for something that requires an input source,
  // an object must be able to compute outputs
  float getOutput(int index) throws InputSourceNotSetException;
  // It must also be able to report its size
  int getSize();
}

interface RequiresAnInputSource {
  // An object that requires an input source will throw an exception if it hasn't had an input source set
  // It will also throw an exception if the input source is the wrong size.
  void setInputSource(IsAnInputSource inputSource) throws InputSourceSizeMismatchException;
}

class InputSourceNotSetException extends Exception {
}

class InputSourceSizeMismatchException extends Exception {
}

class Layer implements IsAnInputSource, RequiresAnInputSource {
  Neuron[] neurons;
  IsAnInputSource inputSource = null;

  Layer(int inputsPerNeuron, int neuronsCount) {
    neurons = new Neuron[neuronsCount];
    for (int i = 0; i < neuronsCount; ++i) {
      neurons[i] = new Neuron(inputsPerNeuron + 1);
    }
  }

  void setInputSource(IsAnInputSource inputSource_) throws InputSourceSizeMismatchException {
    if (inputSource_.getSize() != neurons.length * (neurons[0].weights.length - 1)) {
      println("inputSource_.getSize() is " + inputSource_.getSize());
      println("neurons.length is " + neurons.length);
      println("neurons[0].weights.length - 1 " + (neurons[0].weights.length - 1));
  
      throw new InputSourceSizeMismatchException();
    }
    inputSource = inputSource_;
  }

  float getOutput(int index) throws InputSourceNotSetException {
    if (inputSource == null) {
      throw new InputSourceNotSetException();
    }
    return neurons[index].feedForward();
  }

  int getSize() {
    return neurons.length;
  }
}

class TwoLayerNeuralNet implements IsAnInputSource, RequiresAnInputSource {

  Layer inputLayer;
  Layer outputLayer;

  TwoLayerNeuralNet(int inputsCount, int outputsCount) throws InputSourceSizeMismatchException {
    inputLayer = new Layer(inputsCount, outputsCount);
    outputLayer = new Layer(outputsCount, 1);
    outputLayer.setInputSource(inputLayer);
  }

  void setInputSource(IsAnInputSource inputSource_) throws InputSourceSizeMismatchException {
    inputLayer.setInputSource(inputSource_);
  }

  float getOutput(int index) throws InputSourceNotSetException {
    return outputLayer.getOutput(index);
  }

  int getSize() {
    return outputLayer.getSize();
  }

  float[] softMax() throws InputSourceNotSetException {
    float[] values = new float[getSize()];
    float sum = 0.0;
    for (int i = 0; i < values.length; ++i) {
      values[i] = exp(getOutput(i));
      sum += values[i];
    }
    for (int i = 0; i < values.length; ++i) {
      values[i] /= sum;
    }
    return values;
  }

  int classify() throws InputSourceNotSetException {
    float[] softMax = softMax();
    float biggest = softMax[0];
    int classification = 0;
    for (int i = 1; i < softMax.length; ++i) {
      if (softMax[i] > biggest) {
        biggest = softMax[i];
        classification = i;
      }
    }
    return classification;
  }
}

class Neuron implements RequiresAnInputSource {

  float[] weights;
  float learningRate = 0.01;
  IsAnInputSource inputSource = null;

  // Constructor. Takes one variable which is the number of
  // inputs. There is actually one more weight than the number
  // of inputs. The extra weight is for the bias.
  // Initializes the weights of the neuron randomly.
  // Later the weights will be trained.
  Neuron(int n) {
    weights = new float[n + 1];
    for (int i = 0; i <= n; ++i) {
      weights[i] = random(-1, 1);
    }
  }

  void setInputSource(IsAnInputSource inputSource_) throws InputSourceSizeMismatchException {
    if (inputSource_.getSize() != weights.length - 1) {
      throw new InputSourceSizeMismatchException();
    }
    inputSource = inputSource_;
  }

  float feedForward() throws InputSourceNotSetException {
    if (inputSource != null) {
      throw new InputSourceNotSetException();
    }
    float sum = 0.0;
    for (int i = 0; i < weights.length - 1; ++i) {
      sum += inputSource.getOutput(i) * weights[i];
    }
    sum += weights[weights.length - 1];
    float output = activate(sum);
    return output;
  }

  float activate(float sum) {
    // We use the classic sigmoid function for activation. See:
    // https://machinelearningmastery.com/a-gentle-introduction-to-sigmoid-function/
    return 1.0 / (1.0 + exp(-sum));
  }
}

abstract class FloatingPointDataset implements IsAnInputSource {
  float[][] records;
  int[] classifications;
  int recordPointer = 0;
  int recordCount = 0;

  float getOutput(int index) throws InputSourceNotSetException {
    return records[recordPointer][index];
  }

  int getClassification() {
    return classifications[recordPointer];
  }

  int getSize() {
    return records[0].length;
  }

  int recordPointer() {
    return recordPointer;
  }

  void setRecordPointer(int recordPointer_) {
    recordPointer = recordPointer_;
  }
}

class IrisDataset extends FloatingPointDataset {

  void configure(JSONObject json) {
    JSONArray data = json.getJSONArray(DATA_KEY);
    recordCount = data.size();
    classifications = new int[recordCount];
    // for convenience convert allowed species to an ArrayList
    ArrayList <String> allowedSpecies = new ArrayList <String>();
    for (String species : ALLOWED_SPECIES) {
      allowedSpecies.add(species);
    }
    records = new float[recordCount][4];
    for (int i = 0; i < recordCount; ++i) {
      JSONObject irisRecord = data.getJSONObject(i);
      String species = irisRecord.getString(SPECIES_KEY);
      int index = allowedSpecies.indexOf(species);
      classifications[i] = index;
      records[i][0] = irisRecord.getFloat(SEPAL_LENGTH_KEY);
      records[i][1] = irisRecord.getFloat(SEPAL_WIDTH_KEY);
      records[i][2] = irisRecord.getFloat(PETAL_LENGTH_KEY);
      records[i][3] = irisRecord.getFloat(PETAL_WIDTH_KEY);
    }
  }
}

TwoLayerNeuralNet neuralNet;
IrisDataset irisDataset;

void setup() {
  size(600, 400);
  frameRate(30);
  irisDataset = new IrisDataset();
  JSONObject json = loadJSONObject(IRIS_DATASET_FILENAME);
  irisDataset.configure(json);
  try {
    neuralNet = new TwoLayerNeuralNet(4, 3);
  } catch (InputSourceSizeMismatchException e) {
    e.printStackTrace(System.out);
  }
  try {
    neuralNet.setInputSource(irisDataset);
  } catch (InputSourceSizeMismatchException e) {
    e.printStackTrace(System.out);
  }
}

void draw() {
  int recordPointer = frameCount % irisDataset.recordCount;
  irisDataset.setRecordPointer(recordPointer);
  int classification = 0;
  try {
    classification = neuralNet.classify();
  } catch (InputSourceNotSetException e) {
    e.printStackTrace(System.out);
  }
  println("Record " + recordPointer + " is classified as " + ALLOWED_SPECIES[classification]);

}

The Iris Data Set

Save the json data below iris.json and add the file to the Processing sketch:

{
	"source": "https://www.kaggle.com/datasets/rtatman/iris-dataset-json-version?resource=download",
	"citation": "Fisher, R. A. (1936) The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.",
	"data": [
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.5,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.9,
			"sepalWidth": 3.0,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.7,
			"sepalWidth": 3.2,
			"petalLength": 1.3,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.6,
			"sepalWidth": 3.1,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.6,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.4,
			"sepalWidth": 3.9,
			"petalLength": 1.7,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 4.6,
			"sepalWidth": 3.4,
			"petalLength": 1.4,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.4,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.4,
			"sepalWidth": 2.9,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.9,
			"sepalWidth": 3.1,
			"petalLength": 1.5,
			"petalWidth": 0.1,
			"species": "setosa"
		},
		{
			"sepalLength": 5.4,
			"sepalWidth": 3.7,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.8,
			"sepalWidth": 3.4,
			"petalLength": 1.6,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.8,
			"sepalWidth": 3.0,
			"petalLength": 1.4,
			"petalWidth": 0.1,
			"species": "setosa"
		},
		{
			"sepalLength": 4.3,
			"sepalWidth": 3.0,
			"petalLength": 1.1,
			"petalWidth": 0.1,
			"species": "setosa"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 4.0,
			"petalLength": 1.2,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 4.4,
			"petalLength": 1.5,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 5.4,
			"sepalWidth": 3.9,
			"petalLength": 1.3,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.5,
			"petalLength": 1.4,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 3.8,
			"petalLength": 1.7,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.8,
			"petalLength": 1.5,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 5.4,
			"sepalWidth": 3.4,
			"petalLength": 1.7,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.7,
			"petalLength": 1.5,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 4.6,
			"sepalWidth": 3.6,
			"petalLength": 1.0,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.3,
			"petalLength": 1.7,
			"petalWidth": 0.5,
			"species": "setosa"
		},
		{
			"sepalLength": 4.8,
			"sepalWidth": 3.4,
			"petalLength": 1.9,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.0,
			"petalLength": 1.6,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.4,
			"petalLength": 1.6,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 5.2,
			"sepalWidth": 3.5,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.2,
			"sepalWidth": 3.4,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.7,
			"sepalWidth": 3.2,
			"petalLength": 1.6,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.8,
			"sepalWidth": 3.1,
			"petalLength": 1.6,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.4,
			"sepalWidth": 3.4,
			"petalLength": 1.5,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 5.2,
			"sepalWidth": 4.1,
			"petalLength": 1.5,
			"petalWidth": 0.1,
			"species": "setosa"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 4.2,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.9,
			"sepalWidth": 3.1,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.2,
			"petalLength": 1.2,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 3.5,
			"petalLength": 1.3,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.9,
			"sepalWidth": 3.6,
			"petalLength": 1.4,
			"petalWidth": 0.1,
			"species": "setosa"
		},
		{
			"sepalLength": 4.4,
			"sepalWidth": 3.0,
			"petalLength": 1.3,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.4,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.5,
			"petalLength": 1.3,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 4.5,
			"sepalWidth": 2.3,
			"petalLength": 1.3,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 4.4,
			"sepalWidth": 3.2,
			"petalLength": 1.3,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.5,
			"petalLength": 1.6,
			"petalWidth": 0.6,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.8,
			"petalLength": 1.9,
			"petalWidth": 0.4,
			"species": "setosa"
		},
		{
			"sepalLength": 4.8,
			"sepalWidth": 3.0,
			"petalLength": 1.4,
			"petalWidth": 0.3,
			"species": "setosa"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 3.8,
			"petalLength": 1.6,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 4.6,
			"sepalWidth": 3.2,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.3,
			"sepalWidth": 3.7,
			"petalLength": 1.5,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 3.3,
			"petalLength": 1.4,
			"petalWidth": 0.2,
			"species": "setosa"
		},
		{
			"sepalLength": 7.0,
			"sepalWidth": 3.2,
			"petalLength": 4.7,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 3.2,
			"petalLength": 4.5,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.9,
			"sepalWidth": 3.1,
			"petalLength": 4.9,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 2.3,
			"petalLength": 4.0,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.5,
			"sepalWidth": 2.8,
			"petalLength": 4.6,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 2.8,
			"petalLength": 4.5,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 3.3,
			"petalLength": 4.7,
			"petalWidth": 1.6,
			"species": "versicolor"
		},
		{
			"sepalLength": 4.9,
			"sepalWidth": 2.4,
			"petalLength": 3.3,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.6,
			"sepalWidth": 2.9,
			"petalLength": 4.6,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.2,
			"sepalWidth": 2.7,
			"petalLength": 3.9,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 2.0,
			"petalLength": 3.5,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.9,
			"sepalWidth": 3.0,
			"petalLength": 4.2,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.0,
			"sepalWidth": 2.2,
			"petalLength": 4.0,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.1,
			"sepalWidth": 2.9,
			"petalLength": 4.7,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.6,
			"sepalWidth": 2.9,
			"petalLength": 3.6,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.1,
			"petalLength": 4.4,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.6,
			"sepalWidth": 3.0,
			"petalLength": 4.5,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 2.7,
			"petalLength": 4.1,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.2,
			"sepalWidth": 2.2,
			"petalLength": 4.5,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.6,
			"sepalWidth": 2.5,
			"petalLength": 3.9,
			"petalWidth": 1.1,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.9,
			"sepalWidth": 3.2,
			"petalLength": 4.8,
			"petalWidth": 1.8,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.1,
			"sepalWidth": 2.8,
			"petalLength": 4.0,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 2.5,
			"petalLength": 4.9,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.1,
			"sepalWidth": 2.8,
			"petalLength": 4.7,
			"petalWidth": 1.2,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 2.9,
			"petalLength": 4.3,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.6,
			"sepalWidth": 3.0,
			"petalLength": 4.4,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.8,
			"sepalWidth": 2.8,
			"petalLength": 4.8,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.0,
			"petalLength": 5.0,
			"petalWidth": 1.7,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.0,
			"sepalWidth": 2.9,
			"petalLength": 4.5,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 2.6,
			"petalLength": 3.5,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 2.4,
			"petalLength": 3.8,
			"petalWidth": 1.1,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 2.4,
			"petalLength": 3.7,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 2.7,
			"petalLength": 3.9,
			"petalWidth": 1.2,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.0,
			"sepalWidth": 2.7,
			"petalLength": 5.1,
			"petalWidth": 1.6,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.4,
			"sepalWidth": 3.0,
			"petalLength": 4.5,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.0,
			"sepalWidth": 3.4,
			"petalLength": 4.5,
			"petalWidth": 1.6,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.1,
			"petalLength": 4.7,
			"petalWidth": 1.5,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 2.3,
			"petalLength": 4.4,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.6,
			"sepalWidth": 3.0,
			"petalLength": 4.1,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 2.5,
			"petalLength": 4.0,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.5,
			"sepalWidth": 2.6,
			"petalLength": 4.4,
			"petalWidth": 1.2,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.1,
			"sepalWidth": 3.0,
			"petalLength": 4.6,
			"petalWidth": 1.4,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 2.6,
			"petalLength": 4.0,
			"petalWidth": 1.2,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.0,
			"sepalWidth": 2.3,
			"petalLength": 3.3,
			"petalWidth": 1.0,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.6,
			"sepalWidth": 2.7,
			"petalLength": 4.2,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 3.0,
			"petalLength": 4.2,
			"petalWidth": 1.2,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 2.9,
			"petalLength": 4.2,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.2,
			"sepalWidth": 2.9,
			"petalLength": 4.3,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.1,
			"sepalWidth": 2.5,
			"petalLength": 3.0,
			"petalWidth": 1.1,
			"species": "versicolor"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 2.8,
			"petalLength": 4.1,
			"petalWidth": 1.3,
			"species": "versicolor"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 3.3,
			"petalLength": 6.0,
			"petalWidth": 2.5,
			"species": "virginica"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 2.7,
			"petalLength": 5.1,
			"petalWidth": 1.9,
			"species": "virginica"
		},
		{
			"sepalLength": 7.1,
			"sepalWidth": 3.0,
			"petalLength": 5.9,
			"petalWidth": 2.1,
			"species": "virginica"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 2.9,
			"petalLength": 5.6,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.5,
			"sepalWidth": 3.0,
			"petalLength": 5.8,
			"petalWidth": 2.2,
			"species": "virginica"
		},
		{
			"sepalLength": 7.6,
			"sepalWidth": 3.0,
			"petalLength": 6.6,
			"petalWidth": 2.1,
			"species": "virginica"
		},
		{
			"sepalLength": 4.9,
			"sepalWidth": 2.5,
			"petalLength": 4.5,
			"petalWidth": 1.7,
			"species": "virginica"
		},
		{
			"sepalLength": 7.3,
			"sepalWidth": 2.9,
			"petalLength": 6.3,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 2.5,
			"petalLength": 5.8,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 7.2,
			"sepalWidth": 3.6,
			"petalLength": 6.1,
			"petalWidth": 2.5,
			"species": "virginica"
		},
		{
			"sepalLength": 6.5,
			"sepalWidth": 3.2,
			"petalLength": 5.1,
			"petalWidth": 2.0,
			"species": "virginica"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 2.7,
			"petalLength": 5.3,
			"petalWidth": 1.9,
			"species": "virginica"
		},
		{
			"sepalLength": 6.8,
			"sepalWidth": 3.0,
			"petalLength": 5.5,
			"petalWidth": 2.1,
			"species": "virginica"
		},
		{
			"sepalLength": 5.7,
			"sepalWidth": 2.5,
			"petalLength": 5.0,
			"petalWidth": 2.0,
			"species": "virginica"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 2.8,
			"petalLength": 5.1,
			"petalWidth": 2.4,
			"species": "virginica"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 3.2,
			"petalLength": 5.3,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 6.5,
			"sepalWidth": 3.0,
			"petalLength": 5.5,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 7.7,
			"sepalWidth": 3.8,
			"petalLength": 6.7,
			"petalWidth": 2.2,
			"species": "virginica"
		},
		{
			"sepalLength": 7.7,
			"sepalWidth": 2.6,
			"petalLength": 6.9,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 6.0,
			"sepalWidth": 2.2,
			"petalLength": 5.0,
			"petalWidth": 1.5,
			"species": "virginica"
		},
		{
			"sepalLength": 6.9,
			"sepalWidth": 3.2,
			"petalLength": 5.7,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 5.6,
			"sepalWidth": 2.8,
			"petalLength": 4.9,
			"petalWidth": 2.0,
			"species": "virginica"
		},
		{
			"sepalLength": 7.7,
			"sepalWidth": 2.8,
			"petalLength": 6.7,
			"petalWidth": 2.0,
			"species": "virginica"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 2.7,
			"petalLength": 4.9,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.3,
			"petalLength": 5.7,
			"petalWidth": 2.1,
			"species": "virginica"
		},
		{
			"sepalLength": 7.2,
			"sepalWidth": 3.2,
			"petalLength": 6.0,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.2,
			"sepalWidth": 2.8,
			"petalLength": 4.8,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.1,
			"sepalWidth": 3.0,
			"petalLength": 4.9,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 2.8,
			"petalLength": 5.6,
			"petalWidth": 2.1,
			"species": "virginica"
		},
		{
			"sepalLength": 7.2,
			"sepalWidth": 3.0,
			"petalLength": 5.8,
			"petalWidth": 1.6,
			"species": "virginica"
		},
		{
			"sepalLength": 7.4,
			"sepalWidth": 2.8,
			"petalLength": 6.1,
			"petalWidth": 1.9,
			"species": "virginica"
		},
		{
			"sepalLength": 7.9,
			"sepalWidth": 3.8,
			"petalLength": 6.4,
			"petalWidth": 2.0,
			"species": "virginica"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 2.8,
			"petalLength": 5.6,
			"petalWidth": 2.2,
			"species": "virginica"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 2.8,
			"petalLength": 5.1,
			"petalWidth": 1.5,
			"species": "virginica"
		},
		{
			"sepalLength": 6.1,
			"sepalWidth": 2.6,
			"petalLength": 5.6,
			"petalWidth": 1.4,
			"species": "virginica"
		},
		{
			"sepalLength": 7.7,
			"sepalWidth": 3.0,
			"petalLength": 6.1,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 3.4,
			"petalLength": 5.6,
			"petalWidth": 2.4,
			"species": "virginica"
		},
		{
			"sepalLength": 6.4,
			"sepalWidth": 3.1,
			"petalLength": 5.5,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.0,
			"sepalWidth": 3.0,
			"petalLength": 4.8,
			"petalWidth": 1.8,
			"species": "virginica"
		},
		{
			"sepalLength": 6.9,
			"sepalWidth": 3.1,
			"petalLength": 5.4,
			"petalWidth": 2.1,
			"species": "virginica"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.1,
			"petalLength": 5.6,
			"petalWidth": 2.4,
			"species": "virginica"
		},
		{
			"sepalLength": 6.9,
			"sepalWidth": 3.1,
			"petalLength": 5.1,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 5.8,
			"sepalWidth": 2.7,
			"petalLength": 5.1,
			"petalWidth": 1.9,
			"species": "virginica"
		},
		{
			"sepalLength": 6.8,
			"sepalWidth": 3.2,
			"petalLength": 5.9,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.3,
			"petalLength": 5.7,
			"petalWidth": 2.5,
			"species": "virginica"
		},
		{
			"sepalLength": 6.7,
			"sepalWidth": 3.0,
			"petalLength": 5.2,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 6.3,
			"sepalWidth": 2.5,
			"petalLength": 5.0,
			"petalWidth": 1.9,
			"species": "virginica"
		},
		{
			"sepalLength": 6.5,
			"sepalWidth": 3.0,
			"petalLength": 5.2,
			"petalWidth": 2.0,
			"species": "virginica"
		},
		{
			"sepalLength": 6.2,
			"sepalWidth": 3.4,
			"petalLength": 5.4,
			"petalWidth": 2.3,
			"species": "virginica"
		},
		{
			"sepalLength": 5.9,
			"sepalWidth": 3.0,
			"petalLength": 5.1,
			"petalWidth": 1.8,
			"species": "virginica"
		}
	]
}