private static void ExecuteNeuralNet( string name, TestNet net, int batchSize, int totalSets, int iterations) { var inputs = CreateSampleSets(net, batchSize, totalSets); var stopWatch = new Stopwatch(); Console.WriteLine($"- {name} ------"); stopWatch.Restart(); var trainer = new SgdTrainer(net); trainer.LearningRate = 0.01; trainer.Momentum = 0.5; trainer.BatchSize = batchSize; for (var i = 0; i < iterations; i++) { foreach (var set in inputs) { trainer.Train(set.Inputs[0], set.Outputs); } } stopWatch.Stop(); Console.WriteLine(" total: {0:0.000}ms", stopWatch.ElapsedMilliseconds); Console.WriteLine(" forward: {0:0.000}ms", trainer.ForwardTimeMs); Console.WriteLine(" backward: {0:0.000}ms", trainer.BackwardTimeMs); Console.WriteLine(" update: {0:0.000}ms", trainer.UpdateWeightsTimeMs); }
double learnFromTuple(double[] s0, int a0, float r0, double[] s1, int a1) { // want: Q(s,a) = r + gamma * max_a' Q(s',a') // compute the target Q value double[] tmat = forwardQ(s1); double qmax = r0 + gamma * tmat[maxi(tmat)]; // now predict double[] pred = forwardQ(s0); //double tderror = pred[a0] - qmax; double tderror = qmax - pred[a0]; if (Mathf.Abs((float)tderror) > clamp) { // huber loss to robustify if (tderror > clamp) { tderror = clamp; } if (tderror < -clamp) { tderror = -clamp; } } trainer.Train(new Volume(s0), tderror, a0); return(tderror); }
private Tuple<double[], double[], double[]> TrainModel(ModelSettings settings) { var data = GetConvNetSharpData(); _images = data.Item1; _labels = data.Item2; var confusionMatrix = new int[settings.NoEpochs, 4, 4]; var validationConfusionMatrix = new int[settings.NoEpochs, 4, 4]; var threshold = (int)Math.Floor(0.9*_images.Count); for (var k = 0; k < settings.NoEpochs; k++) { for (var i = 0; i < threshold; i++) { var image = _images[i]; var vol = BuilderInstance.Volume.From(_labels[i], new Shape(1, 1, 4, 1)); try { _trainer.Train(BuilderInstance.Volume.From(image, new Shape(80, 60, 1)), vol); } catch(ArgumentException) { } var prediction = _trainer.Net.GetPrediction()[0]; confusionMatrix[k, LabelFromOneHot(_labels[i]), prediction]++; } for (var i = threshold; i < _images.Count; i++) { var image = _images[i]; _trainer.Net.Forward(BuilderInstance.Volume.From(image, new Shape(80, 60, 1))); var prediction = _trainer.Net.GetPrediction()[0]; validationConfusionMatrix[k, LabelFromOneHot(_labels[i]), prediction]++; } } return GetEpochsAndAccuracies(confusionMatrix, settings.NoEpochs, validationConfusionMatrix, threshold); }
/// <summary> /// Train network /// </summary> /// <param name="val1">The first value.</param> /// <param name="val2">The second value.</param> /// <param name="val3">The third value.</param> /// <param name="val4">The fourth value.</param> internal void TrainNetwork(double val1, double val2, double val3, double val4) { var trainer = new SgdTrainer(_net) { LearningRate = 0.3, L2Decay = -0.5 }; trainer.Train(_trainResult, BuilderInstance <double> .Volume?.From(new[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, new Shape((int)val1, (int)val2, (int)val3, (int)val4))); }
private static void Main(string[] args) { var logger = new ConsoleLogger(); try { var dataFolder = GetDataFolder(args); if (string.IsNullOrEmpty(dataFolder)) { return; } Control.UseNativeMKL(); var(trainX, trainY, devX, devY) = LoadData(dataFolder, logger); bool repeat; do { var randomSeed = 13; var network = NetworkBuilder.Build(28 * 28, new LayerOptions(10, new Sigmoid()), new[] { new LayerOptions(30, new Sigmoid()), //new LayerOptions(30, new Sigmoid()), //new LayerOptions(30, new Sigmoid()), }, randomSeed); var trainer = new SgdTrainer(30, 10, 3.0, new QuadraticCostFunction(), logger, randomSeed); var(randomTrainX, randomTrainY) = Shuffler.Shuffle(randomSeed, trainX, trainY); PrintDataHistograms(trainY, devY, logger); trainer.Train(network, randomTrainX, randomTrainY, 0.95); DisplayTestPrecision(devX, devY, network, logger); logger.Log("Press key to exit. \"r\" to repeat..."); var answer = Console.ReadKey(); repeat = answer.KeyChar == 'r'; } while (repeat); } catch (Exception e) { logger.Log(e.Message); } }
/// <summary> /// This sample shows how to serialize and deserialize a ConvNetSharp.Core network /// 1) Network creation /// 2) Dummy Training (only use a single data point) /// 3) Serialization /// 4) Deserialization /// </summary> private static void Main() { // 1) Network creation var net = new Net <double>(); net.AddLayer(new InputLayer(1, 1, 2)); net.AddLayer(new FullyConnLayer(20)); net.AddLayer(new ReluLayer()); net.AddLayer(new FullyConnLayer(10)); net.AddLayer(new SoftmaxLayer(10)); // 2) Dummy Training (only use a single data point) var x = BuilderInstance.Volume.From(new[] { 0.3, -0.5 }, new Shape(2)); var y = BuilderInstance.Volume.From(new[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, new Shape(10)); var count = 0; var trainer = new SgdTrainer(net) { LearningRate = 0.01 }; do { trainer.Train(x, y); // train the network, specifying that x is class zero Console.WriteLine($"Loss: {trainer.Loss}"); count++; } while (trainer.Loss > 1e-2); Console.WriteLine($"{count}"); // Forward pass with original network var prob1 = net.Forward(x); Console.WriteLine("probability that x is class 0: " + prob1.Get(0)); // 3) Serialization var json = net.ToJson(); // 4) Deserialization var deserialized = SerializationExtensions.FromJson <double>(json); // Forward pass with deserialized network var prob2 = deserialized.Forward(x); Console.WriteLine("probability that x is class 0: " + prob2.Get(0)); // This should give exactly the same result as previous network evaluation Console.ReadLine(); }
private static void Main() { // species a 2-layer neural network with one hidden layer of 20 neurons var net = new Net <double>(); // input layer declares size of input. here: 2-D data // ConvNetJS works on 3-Dimensional volumes (width, height, depth), but if you're not dealing with images // then the first two dimensions (width, height) will always be kept at size 1 net.AddLayer(new InputLayer(1, 1, 2)); // declare 20 neurons net.AddLayer(new FullyConnLayer(20)); // declare a ReLU (rectified linear unit non-linearity) net.AddLayer(new ReluLayer()); // declare a fully connected layer that will be used by the softmax layer net.AddLayer(new FullyConnLayer(10)); // declare the linear classifier on top of the previous hidden layer net.AddLayer(new SoftmaxLayer(10)); // forward a random data point through the network var x = BuilderInstance.Volume.From(new[] { 0.3, -0.5 }, new Shape(2)); var prob = net.Forward(x); // prob is a Volume. Volumes have a property Weights that stores the raw data, and WeightGradients that stores gradients Console.WriteLine("probability that x is class 0: " + prob.Get(0)); // prints e.g. 0.50101 var trainer = new SgdTrainer(net) { LearningRate = 0.01, L2Decay = 0.001 }; trainer.Train(x, BuilderInstance.Volume.From(new[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, new Shape(1, 1, 10, 1))); // train the network, specifying that x is class zero var prob2 = net.Forward(x); Console.WriteLine("probability that x is class 0: " + prob2.Get(0)); // now prints 0.50374, slightly higher than previous 0.50101: the networks // weights have been adjusted by the Trainer to give a higher probability to // the class we trained the network with (zero) }
public void ExperienceReplay() { var miniBatch = new List <State>(); for (int i = 0; i < batchSize; i++) { miniBatch.Add(stateMemory[random.Next(0, stateMemory.Count)]); } miniBatch.Shuffle(); var inputList = miniBatch.Select(x => x.state).ToList(); var nextInputList = miniBatch.Select(x => x.next_state).ToList(); var inputVol = ToVolume(inputList, true); var nextInputVol = ToVolume(nextInputList, true); var result = mainNet.Forward(inputVol); var nextResult = targetNet.Forward(nextInputVol); var value = GetAction(result); var nextValue = GetAction(nextResult); for (int i = 0; i < batchSize; i++) { var _index = Convert.ToInt32(value[i][0]); value[i][1] += gamma * nextValue[i][1]; result.Set(0, 0, _index, i, value[i][1]); } trainer.Train(inputVol, result); averageLossMemory.Add(trainer.Loss); if (epsilon > epsilonMin) { epsilon *= epsilonDecay; } age++; lossWriter.AppendLine($"{age},{trainer.Loss}"); }
private void Train(int iterations = 50) { var samples = new Volume(trainingData, new Shape(windowSize, windowSize, 1, numOfSamples)); var labels = new Volume(trainingLabels, new Shape(1, 1, 2, numOfSamples)); var start = DateTime.Now; double avloss = 0.0; for (int i = 0; i < iterations; i++) { trainer.Train(samples, labels); avloss += trainer.Loss; } avloss /= iterations; visualisation.AddLoss(avloss); Console.WriteLine($"Loss: {avloss} Step took: {DateTime.Now - start}."); }
double learnFromTuple(double[] s0, int a0, float r0, double[] s1, int a1) { // want: Q(s,a) = r + gamma * max_a' Q(s',a') // compute the target Q value double[] tmat = forwardQ(s1); double qmax = r0 + gamma * tmat[maxi(tmat)]; // now predict double[] pred = forwardQ(s0); Debug.Log("s1:"); printArrayDouble(tmat); Debug.Log("qmax: " + qmax); Debug.Log("s2:"); printArrayDouble(pred); double tderror = pred[a0] - qmax; Debug.Log("tderror: " + tderror + " a0: " + a0); if (Mathf.Abs((float)tderror) > clamp) { // huber loss to robustify if (tderror > clamp) { tderror = clamp; } if (tderror < -clamp) { tderror = -clamp; } } trainer.Train(new Volume(s0), tderror, a0); return(tderror); }
public void Train(List <JumpyReflexData> frameInput, bool goodJob) { foreach (var reflex in frameInput) { var resp = new double[2]; if (goodJob) { if (reflex.Jump) { resp = new[] { 1.0, 0.0 }; } else { resp = new[] { 0.0, 1.0 }; } } else { if (reflex.Jump) { resp = new[] { 0.0, 1.0 }; } else { resp = new[] { 1.0, 0.0 }; } } if (reflex.AllfeaturesEmpty) { continue; } NetTrainer.Train(new Volume(reflex.Features, new Shape(TrainerConfig.InputNodesCount)), new Volume(resp, new Shape(1, 1, 2))); } }
private static void Main(string[] args) { // Load data var min_count = 10; var polarity_cutoff = 0.1; var labels = File.ReadAllLines("../../../../Data/labels.txt"); var reviews = File.ReadAllLines("../../../../Data/reviews.txt"); // Count words var vocab = new Dictionary <string, int>(); var positive_counts = new Dictionary <string, int>(); var negative_counts = new Dictionary <string, int>(); var pos_neg_ratios = new Dictionary <string, double>(); foreach (var pair in reviews.Zip(labels, (review, label) => new { review, label })) { var review = pair.review; var label = pair.label; foreach (var word in review.ToLower().Split(' ')) { vocab.TryGetValue(word, out var count); vocab[word] = count + 1; var dico = label == "positive" ? positive_counts : negative_counts; dico.TryGetValue(word, out count); dico[word] = count + 1; var otherDico = label == "positive" ? negative_counts : positive_counts; otherDico.TryGetValue(word, out count); otherDico[word] = count; // This is used to set count to 0 words that appear only on one side } } // Compute ratios foreach (var word in vocab.Keys) { if (vocab[word] > 50) { var ratio = positive_counts[word] / (negative_counts[word] + 1.0); if (ratio > 1.0) { pos_neg_ratios[word] = Math.Log(ratio); } else { pos_neg_ratios[word] = -Math.Log(1.0 / (ratio + 0.01)); } } else { pos_neg_ratios[word] = 0.0; } } var review_vocab = vocab.Where(o => o.Value > min_count && Math.Abs(pos_neg_ratios[o.Key]) > polarity_cutoff).Select(o => o.Key).ToList(); // Create word to index map var wordToIndex = review_vocab.Select((word, index) => new { word, index }).ToDictionary(o => o.word, o => o.index); // Build network var network = new Net <double>(); network.AddLayer(new InputLayer(1, 1, review_vocab.Count)); network.AddLayer(new FullyConnLayer(10)); network.AddLayer(new FullyConnLayer(1)); network.AddLayer(new RegressionLayer()); // Training var trainer = new SgdTrainer(network) { LearningRate = 0.005 }; var input = BuilderInstance.Volume.SameAs(new Shape(1, 1, review_vocab.Count)); var output = BuilderInstance.Volume.SameAs(new Shape(1, 1, 1)); var i = 0; var correct = 0; for (var epoch = 0; epoch < 3; epoch++) { Console.WriteLine($"Epoch #{epoch}"); foreach (var pair in reviews.Zip(labels, (review, label) => new { review, label })) { var review = pair.review; var label = pair.label; FillVolume(input, review, wordToIndex); output.Set(0, 0, 0, pair.label == "positive" ? 1.0 : 0.0); var test = network.Forward(input); if (test > 0.5 && label == "positive" || test < 0.5 && label == "negative") { correct++; } trainer.Train(input, output); if (i % 100 == 0) { Console.WriteLine($"Accuracy: {Math.Round(correct / (double)i * 100.0, 2)}%"); Console.WriteLine($"{i}/{reviews.Length}"); } i++; if (Console.KeyAvailable) { break; } } } // Save Network File.WriteAllText(@"../../../../Model/sentiment.json", network.ToJson()); }
public void CompareCoreVsFlow() { var inputWidth = 28; var inputHeigth = 28; var inputDepth = 3; var batchSize = 20; #region Flow network var netFlow = new Net <T>(); netFlow.AddLayer(new InputLayer <T>()); var convLayerFlow1 = new ConvLayer <T>(5, 5, 8) { BiasPref = (T)Convert.ChangeType(0.1, typeof(T)), Stride = 1, Pad = 2 }; netFlow.AddLayer(convLayerFlow1); netFlow.AddLayer(new ReluLayer <T>()); netFlow.AddLayer(new PoolLayer <T>(2, 2) { Stride = 2 }); var fullyConnLayerFlow = new FullyConnLayer <T>(10); netFlow.AddLayer(fullyConnLayerFlow); netFlow.AddLayer(new SoftmaxLayer <T>()); var trainerFlow = new SgdTrainer <T>(netFlow, (T)Convert.ChangeType(0.01f, typeof(T))) { BatchSize = batchSize }; #endregion #region Core network var netCore = new Core.Net <T>(); netCore.AddLayer(new Core.Layers.InputLayer <T>(inputWidth, inputHeigth, inputDepth)); var convLayerCore1 = new Core.Layers.ConvLayer <T>(5, 5, 8) { BiasPref = (T)Convert.ChangeType(0.1, typeof(T)), Stride = 1, Pad = 2 }; netCore.AddLayer(convLayerCore1); netCore.AddLayer(new Core.Layers.ReluLayer <T>()); netCore.AddLayer(new Core.Layers.PoolLayer <T>(2, 2) { Stride = 2 }); var fullyConnLayerCore = new Core.Layers.FullyConnLayer <T>(10); netCore.AddLayer(fullyConnLayerCore); netCore.AddLayer(new Core.Layers.SoftmaxLayer <T>(10)); var trainerCore = new Core.Training.SgdTrainer <T>(netCore) { LearningRate = (T)Convert.ChangeType(0.01f, typeof(T)), BatchSize = batchSize }; #endregion // Same weights var convfilterCore1 = netFlow.Session.GetVariableByName(netFlow.Op, (convLayerFlow1.Filter as IPersistable <T>).Name); convfilterCore1.Result = BuilderInstance <T> .Volume.SameAs(convLayerCore1.Filters.ToArray(), convLayerCore1.Filters.Shape); var fullyfilterCore = netFlow.Session.GetVariableByName(netFlow.Op, (fullyConnLayerFlow.Filter as IPersistable <T>).Name); fullyfilterCore.Result = BuilderInstance <T> .Volume.SameAs(fullyConnLayerCore.Filters.ToArray(), fullyConnLayerCore.Filters.Shape); // Create input var xStorage = new double[inputWidth * inputHeigth * inputDepth * batchSize].Populate(1.0); var x = NewVolume(xStorage, Volume.Shape.From(inputWidth, inputHeigth, inputDepth, batchSize)); // Create output var yStorage = new double[10 * batchSize]; var y = NewVolume(yStorage, Volume.Shape.From(1, 1, 10, batchSize)); for (var i = 0; i < batchSize; i++) { y.Set(0, 0, i % 10, i, Ops <T> .One); } for (var k = 0; k < 10; k++) { xStorage = new double[inputWidth * inputHeigth * inputDepth * batchSize].Populate(1.0 + k); x = NewVolume(xStorage, Volume.Shape.From(inputWidth, inputHeigth, inputDepth, batchSize)); var flowResult = netFlow.Forward(x); var coreResult = netCore.Forward(x); var sum1 = BuilderInstance <T> .Volume.SameAs(new Shape(1)); flowResult.DoSum(sum1); var sum2 = BuilderInstance <T> .Volume.SameAs(new Shape(1)); coreResult.DoSum(sum2); var diff = Ops <T> .Subtract(sum1.Get(0), sum2.Get(0)); Console.WriteLine(diff); AssertNumber.AreSequenceEqual(flowResult.ToArray(), coreResult.ToArray(), 1e-6); trainerCore.Train(x, y); trainerFlow.Train(x, y); } }
public void TrainWithExperienceReplay(int numGames, int batchSize, float initialRandomChance, bool degradeRandomChance = true, string saveToFile = null) { var gamma = 0.975f; var buffer = batchSize * 2; var h = 0; //# Stores tuples of (S, A, R, S') var replay = new List <object[]>(); _trainer = new SgdTrainer(Net) { LearningRate = 0.01, Momentum = 0.0, BatchSize = batchSize, L2Decay = 0.001 }; var startTime = DateTime.Now; var batches = 0; for (var i = 0; i < numGames; i++) { World = GridWorld.RandomPlayerState(); var gameMoves = 0; double updatedReward; var gameRunning = true; while (gameRunning) { //# We are in state S //# Let's run our Q function on S to get Q values for all possible actions var state = GetInputs(); var qVal = Net.Forward(state); var action = 0; if (Util.Rnd.NextDouble() < initialRandomChance) { //# Choose random action action = Util.Rnd.Next(NumActions); } else { //# Choose best action from Q(s,a) values action = MaxValueIndex(qVal); } //# Take action, observe new state S' World.MovePlayer(action); gameMoves++; TotalTrainingMoves++; var newState = GetInputs(); //# Observe reward, limit turns var reward = World.GetReward(); gameRunning = !World.GameOver(); //# Experience replay storage if (replay.Count < buffer) { replay.Add(new[] { state, (object)action, (object)reward, newState }); } else { h = (h < buffer - 1) ? h + 1 : 0; replay[h] = new[] { state, (object)action, (object)reward, newState }; batches++; var batchInputValues = new Volume[batchSize]; var batchOutputValues = new List <double>(); //# Randomly sample our experience replay memory for (var b = 0; b < batchSize; b++) { var memory = replay[Util.Rnd.Next(buffer)]; var oldState = (Volume)memory[0]; var oldAction = (int)memory[1]; var oldReward = (int)memory[2]; var oldNewState = (Volume)memory[3]; //# Get max_Q(S',a) var newQ = Net.Forward(oldNewState); var y = GetValues(newQ); var maxQ = MaxValue(newQ); if (oldReward == GridWorld.ProgressScore) { //# Non-terminal state updatedReward = (oldReward + (gamma * maxQ)); } else { //# Terminal state updatedReward = oldReward; } //# Target output y[action] = updatedReward; //# Store batched states batchInputValues[b] = oldState; batchOutputValues.AddRange(y); } Console.Write("."); //# Train in batches with multiple scores and actions _trainer.Train(batchOutputValues.ToArray(), batchInputValues); TotalLoss += _trainer.Loss; } } Console.WriteLine($"{(World.GetReward() == GridWorld.WinScore ? " WON!" : string.Empty)}"); Console.Write($"Game: {i + 1}"); TotalTrainingGames++; // Save every 10 games... if (!string.IsNullOrEmpty(saveToFile) && (i % 10 == 0)) { Util.SaveBrainToFile(this, saveToFile); } //# Optinoally: slowly reduce the chance of choosing a random action if (degradeRandomChance && initialRandomChance > 0.05f) { initialRandomChance -= (1f / numGames); } } var duration = (DateTime.Now - startTime); LastLoss = _trainer.Loss; TrainingTime += duration; if (!string.IsNullOrEmpty(saveToFile)) { Util.SaveBrainToFile(this, saveToFile); } Console.WriteLine($"\nAvg loss: {TotalLoss / TotalTrainingMoves}. Last: {LastLoss}"); Console.WriteLine($"Training duration: {duration}. Total: {TrainingTime}"); }
public void Train(int numGames, float initialRandomChance) { var gamma = 0.9f; _trainer = new SgdTrainer(Net) { LearningRate = 0.01, Momentum = 0.0, BatchSize = 1, L2Decay = 0.001 }; var startTime = DateTime.Now; for (var i = 0; i < numGames; i++) { World = GridWorld.StandardState(); double updatedReward; var gameRunning = true; var gameMoves = 0; while (gameRunning) { //# We are in state S //# Let's run our Q function on S to get Q values for all possible actions var state = GetInputs(); var qVal = Net.Forward(state); var action = 0; if (Util.Rnd.NextDouble() < initialRandomChance) { //# Choose random action action = Util.Rnd.Next(NumActions); } else { //# Choose best action from Q(s,a) values action = MaxValueIndex(qVal); } //# Take action, observe new state S' World.MovePlayer(action); gameMoves++; TotalTrainingMoves++; var newState = GetInputs(); //# Observe reward var reward = World.GetReward(); gameRunning = !World.GameOver(); //# Get max_Q(S',a) var newQ = Net.Forward(newState); var y = GetValues(newQ); var maxQ = MaxValue(newQ); if (gameRunning) { //# Non-terminal state updatedReward = (reward + (gamma * maxQ)); } else { //# Terminal state updatedReward = reward; TotalTrainingGames++; Console.WriteLine($"Game: {TotalTrainingGames}. Moves: {gameMoves}. {(reward == 10 ? "WIN!" : "")}"); } //# Target output y[action] = updatedReward; //# Feedback what the score would be for this action _trainer.Train(state, y); TotalLoss += _trainer.Loss; } //# Slowly reduce the chance of choosing a random action if (initialRandomChance > 0.05f) { initialRandomChance -= (1f / numGames); } } var duration = (DateTime.Now - startTime); LastLoss = _trainer.Loss; TrainingTime += duration; Console.WriteLine($"Avg loss: {TotalLoss / TotalTrainingMoves}. Last: {LastLoss}"); Console.WriteLine($"Training duration: {duration}. Total: {TrainingTime}"); }
public Net <double> XOR() { var network = new Net <double>(); network.AddLayer(new InputLayer(1, 1, 2)); network.AddLayer(new FullyConnLayer(6)); network.AddLayer(new ReluLayer()); network.AddLayer(new FullyConnLayer(2)); network.AddLayer(new ReluLayer()); network.AddLayer(new RegressionLayer()); List <int[]> data = new List <int[]>(); List <int> label = new List <int>(); data.Add(new int[] { 0, 0 }); label.Add(0); data.Add(new[] { 0, 1 }); label.Add(1); data.Add(new[] { 1, 0 }); label.Add(1); data.Add(new[] { 1, 1 }); label.Add(0); var n = label.Count; var trainer = new SgdTrainer <double>(network) { LearningRate = 0.01, BatchSize = n }; var x = BuilderInstance.Volume.SameAs(new Shape(1, 1, 2, n)); var y = BuilderInstance.Volume.SameAs(new Shape(1, 1, 2, n)); for (var i = 0; i < n; i++) { y.Set(0, 0, 0, i, label[i]); x.Set(0, 0, 0, i, data[i][0]); x.Set(0, 0, 1, i, data[i][1]); } do { var avloss = 0.0; trainer.Train(x, y); avloss = trainer.Loss; //avloss /= 50.0; Console.WriteLine(" Loss:" + avloss); } while (!Console.KeyAvailable); var input = BuilderInstance.Volume.SameAs(new Shape(1, 1, 2, n)); for (var i = 0; i < n; i++) { for (var i2 = 0; i2 < 2; i2++) { input.Set(0, 0, i2, i, data[i][i2]); } } var result = network.Forward(input); for (int i = 0; i < n; i++) { Console.WriteLine("{0} XOR {1} = {2}", data[i][0], data[i][1], result.Get(0, 0, 0, i)); } return(network); }