/// <summary> /// Visualizes the full neural network for the most recently executed input. /// </summary> /// <param name="network">The neural network to draw.</param> /// <param name="input">Input image that was fed into the network.</param> /// <returns>An object that can be assigned directly to an ImageControl's Source property.</returns> public static ImageSource DrawNetworkSingle(NeuralNetwork network, float[,] input) { int inputWidth = input.GetLength(0); int inputHeight = input.GetLength(1); const int inputScaleFact = 2; int networkMaxNeurons = network.LayerSizes.Skip(1).Max(); int lastWeightsCount = network.LayerSizes[network.LayerCount - 2]; int lastWeightsWidth = (network.LayerCount == 2 ? inputWidth : lastWeightsCount); int lastWeightsHeight = lastWeightsCount / lastWeightsWidth; int width = /*inputWidth * inputScaleFact + * sectionPadding +*/(network.LayerCount - 1) * neuronFullSize + sectionPadding + lastWeightsWidth; int height = Math.Max(Math.Max(inputHeight * inputScaleFact, networkMaxNeurons * neuronFullSize), network.LayerSizes.Last() * (lastWeightsHeight + neuronPadding)); var output = new WriteableBitmap(width, height, 96.0, 96.0, PixelFormats.Rgb24, null); byte[] bytes = new byte[width * height * 3]; int baseX = 0; // Draw input image, scaled by a factor 2 /*drawInput(input, bytes, inputScaleFact, baseX, 0, width); * baseX += inputWidth * inputScaleFact + sectionPadding;*/ // Draw neuron values (except input) for (int k = 1; k < network.LayerCount; k++) { for (int i = 0; i < network.LayerSizes[k]; i++) { int baseY = i * neuronFullSize; float value = Truncate1(network.Layers[k][i]); // force in interval [0, 1] byte r = (byte)Truncate255(128.0f + value * 128.0f); byte g = (byte)Truncate255(value * 256.0f); byte b = (byte)Truncate255(value * 64.0f); for (int y = baseY; y < baseY + neuronSize; y++) { for (int x = baseX; x < baseX + neuronSize; x++) { bytes[(x + y * width) * 3] = r; bytes[(x + y * width) * 3 + 1] = g; bytes[(x + y * width) * 3 + 2] = b; } } } baseX += neuronFullSize; } baseX += sectionPadding; // Draw weights of last two layers var lastWeights = network.Weights.Last(); for (int j = 0; j < network.LayerSizes[network.LayerCount - 1]; j++) { int baseY = j * (lastWeightsHeight + neuronPadding); for (int i = 0; i < network.LayerSizes[network.LayerCount - 2]; i++) { int y = baseY + (i / lastWeightsWidth); int x = baseX + (i % lastWeightsWidth); float value = Truncate1((lastWeights[i, j] + 1.0f) / 2.0f); // force in interval [0, 1] byte r = (byte)Truncate255(128.0f + value * 128.0f); byte g = (byte)Truncate255(value * 256.0f); byte b = (byte)Truncate255(value * 64.0f); bytes[(x + y * width) * 3] = r; bytes[(x + y * width) * 3 + 1] = g; bytes[(x + y * width) * 3 + 2] = b; } } output.WritePixels(new Int32Rect(0, 0, width, height), bytes, width * 3, 0); return(output); }
public BackpropNetworkTrainer(NeuralNetwork network, float learningRate) { Network = network; LearningRate = learningRate; }