// Worker thread
void SearchSolution()
{
// prepare learning data
double[][] input = new double[samples][];
double[][] output = new double[samples][];
for (int i = 0; i < samples; i++)
{
input[i] = new double[variables];
output[i] = new double[1];
// copy input
for (int j = 0; j < variables; j++)
input[i][j] = data[i, j];
// copy output
output[i][0] = classes[i];
}
// create perceptron
ActivationNetwork network = new ActivationNetwork(new ThresholdFunction(), variables, 1);
ActivationNeuron neuron = network.Layers[0].Neurons[0] as ActivationNeuron;
// create teacher
PerceptronLearning teacher = new PerceptronLearning(network);
// set learning rate
teacher.LearningRate = learningRate;
// iterations
int iteration = 1;
// statistic files
StreamWriter errorsFile = null;
StreamWriter weightsFile = null;
try
{
// check if we need to save statistics to files
if (saveStatisticsToFiles)
{
// open files
errorsFile = File.CreateText("errors.csv");
weightsFile = File.CreateText("weights.csv");
}
// erros list
ArrayList errorsList = new ArrayList();
// loop
while (!needToStop)
{
// save current weights
if (weightsFile != null)
{
for (int i = 0; i < variables; i++)
{
weightsFile.Write(neuron.Weights[i] + ",");
}
weightsFile.WriteLine(neuron.Threshold);
}
// run epoch of learning procedure
double error = teacher.RunEpoch(input, output);
errorsList.Add(error);
// show current iteration
SetText(iterationsBox, iteration.ToString());
// save current error
if (errorsFile != null)
{
errorsFile.WriteLine(error);
}
// show classifier in the case of 2 dimensional data
if ((neuron.InputsCount == 2) && (neuron.Weights[1] != 0))
{
double k = -neuron.Weights[0] / neuron.Weights[1];
double b = -neuron.Threshold / neuron.Weights[1];
double[,] classifier = new double[2, 2] {
{ chart.RangeX.Min, chart.RangeX.Min * k + b },
{ chart.RangeX.Max, chart.RangeX.Max * k + b }
};
// update chart
chart.UpdateDataSeries("classifier", classifier);
}
// stop if no error
if (error == 0)
break;
iteration++;
}
// show perceptron's weights
ListViewItem item = null;
ClearList(weightsList);
for (int i = 0; i < variables; i++)
{
item = AddListItem(weightsList, string.Format("Weight {0}", i + 1));
AddListSubitem(item, neuron.Weights[i].ToString("F6"));
}
item = AddListItem(weightsList, "Threshold");
AddListSubitem(item, neuron.Threshold.ToString("F6"));
// show error's dynamics
double[,] errors = new double[errorsList.Count, 2];
for (int i = 0, n = errorsList.Count; i < n; i++)
{
errors[i, 0] = i;
errors[i, 1] = (double)errorsList[i];
}
errorChart.RangeX = new Range(0, errorsList.Count - 1);
errorChart.RangeY = new Range(0, samples);
errorChart.UpdateDataSeries("error", errors);
}
catch (IOException)
{
MessageBox.Show("Failed writing file", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
// close files
if (errorsFile != null)
errorsFile.Close();
if (weightsFile != null)
weightsFile.Close();
}
// enable settings controls
EnableControls(true);
}