// Worker thread
void SearchSolution()
{
bool reducedNetwork = ((classesCount == 2) && (useOneNeuronForTwoClasses));
// 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[neuronsCount];
// set input
for (int j = 0; j < variables; j++)
input[i][j] = data[i, j];
// set output
if (reducedNetwork)
{
output[i][0] = classes[i];
}
else
{
output[i][classes[i]] = 1;
}
}
// create perceptron
ActivationNetwork network = new ActivationNetwork(
new SigmoidFunction(sigmoidAlphaValue), variables, neuronsCount);
ActivationLayer layer = network.Layers[0] as ActivationLayer;
// create teacher
DeltaRuleLearning teacher = new DeltaRuleLearning(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 < neuronsCount; i++)
{
weightsFile.Write("neuron" + i + ",");
for (int j = 0; j < variables; j++)
weightsFile.Write(layer.Neurons[i].Weights[j] + ",");
weightsFile.WriteLine(((ActivationNeuron)layer.Neurons[i]).Threshold);
}
}
// run epoch of learning procedure
double error = teacher.RunEpoch(input, output) / samples;
errorsList.Add(error);
// save current error
if (errorsFile != null)
{
errorsFile.WriteLine(error);
}
// show current iteration & error
SetText(currentIterationBox, iteration.ToString());
SetText(currentErrorBox, error.ToString());
iteration++;
// check if we need to stop
if ((useErrorLimit) && (error <= learningErrorLimit))
break;
if ((!useErrorLimit) && (iterationLimit != 0) && (iteration > iterationLimit))
break;
}
// show perceptron's weights
ClearList(weightsList);
for (int i = 0; i < neuronsCount; i++)
{
string neuronName = string.Format("Neuron {0}", i + 1);
ListViewItem item = null;
// add all weights
for (int j = 0; j < variables; j++)
{
item = AddListItem(weightsList, neuronName);
AddListSubitem(item, string.Format("Weight {0}", j + 1));
AddListSubitem(item, layer.Neurons[i].Weights[0].ToString("F6"));
}
// threshold
item = AddListItem(weightsList, neuronName);
AddListSubitem(item, "Threshold");
AddListSubitem(item, ((ActivationNeuron)layer.Neurons[i]).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.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);
}