Skip to content

Commit 8e43974

Browse files
authored
Merge pull request #76 from Sergio0694/dev
Computation graph and new APIs
2 parents 884ff28 + cf6febf commit 8e43974

File tree

65 files changed

+3504
-1064
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+3504
-1064
lines changed

NeuralNetwork.NET/APIs/CuDnnNetworkLayers.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ public static class CuDnnNetworkLayers
2020
/// </summary>
2121
public static bool IsCudaSupportAvailable
2222
{
23-
[Pure]
2423
get
2524
{
2625
try
@@ -63,6 +62,20 @@ public static LayerFactory Softmax(
6362
WeightsInitializationMode weightsMode = WeightsInitializationMode.GlorotUniform, BiasInitializationMode biasMode = BiasInitializationMode.Zero)
6463
=> input => new CuDnnSoftmaxLayer(input, outputs, weightsMode, biasMode);
6564

65+
/// <summary>
66+
/// Creates a convolutional layer with the desired number of kernels
67+
/// </summary>
68+
/// <param name="kernel">The volume information of the kernels used in the layer</param>
69+
/// <param name="kernels">The number of convolution kernels to apply to the input volume</param>
70+
/// <param name="activation">The desired activation function to use in the network layer</param>
71+
/// <param name="biasMode">Indicates the desired initialization mode to use for the layer bias values</param>
72+
[PublicAPI]
73+
[Pure, NotNull]
74+
public static LayerFactory Convolutional(
75+
(int X, int Y) kernel, int kernels, ActivationFunctionType activation,
76+
BiasInitializationMode biasMode = BiasInitializationMode.Zero)
77+
=> input => new CuDnnConvolutionalLayer(input, ConvolutionInfo.Default, kernel, kernels, activation, biasMode);
78+
6679
/// <summary>
6780
/// Creates a convolutional layer with the desired number of kernels
6881
/// </summary>
@@ -81,6 +94,14 @@ public static LayerFactory Convolutional(
8194
/// <summary>
8295
/// Creates a pooling layer with a window of size 2 and a stride of 2
8396
/// </summary>
97+
/// <param name="activation">The desired activation function to use in the network layer</param>
98+
[PublicAPI]
99+
[Pure, NotNull]
100+
public static LayerFactory Pooling(ActivationFunctionType activation) => input => new CuDnnPoolingLayer(input, PoolingInfo.Default, activation);
101+
102+
/// <summary>
103+
/// Creates a pooling layer with a custom mode, window size and stride
104+
/// </summary>
84105
/// <param name="info">The info on the pooling operation to perform</param>
85106
/// <param name="activation">The desired activation function to use in the network layer</param>
86107
[PublicAPI]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace NeuralNetworkNET.APIs.Enums
2+
{
3+
/// <summary>
4+
/// An <see langword="enum"/> that indicates the type of a node in a graph network
5+
/// </summary>
6+
public enum ComputationGraphNodeType : byte
7+
{
8+
/// <summary>
9+
/// The root node for a computation graph, that forwards the network inputs through the computation pipeline(s)
10+
/// </summary>
11+
Input,
12+
13+
/// <summary>
14+
/// A computation graph node with an associated <see cref="Interfaces.INetworkLayer"/> that processes an input <see cref="Structs.Tensor"/>
15+
/// </summary>
16+
Processing,
17+
18+
/// <summary>
19+
/// The root node for a training sub-graph, a secondary training branch used during backpropagation to inject partial gradients
20+
/// </summary>
21+
TrainingBranch,
22+
23+
/// <summary>
24+
/// A computation graph node that merges a series of inputs by stacking them along the depth axis
25+
/// </summary>
26+
DepthConcatenation,
27+
28+
/// <summary>
29+
/// A computation graph node that merges a series of inputs by summing their values together
30+
/// </summary>
31+
Sum
32+
}
33+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace NeuralNetworkNET.APIs.Enums
2+
{
3+
/// <summary>
4+
/// Indicates the preferred mode of execution for all expensive operations in the library
5+
/// </summary>
6+
public enum ExecutionModePreference
7+
{
8+
/// <summary>
9+
/// Only CPU-powered functions are executed. This means that network layers are deserialized through the <see cref="NetworkLayers"/> class,
10+
/// and that all other computations will only be scheduled on the CPU.
11+
/// </summary>
12+
Cpu,
13+
14+
/// <summary>
15+
/// CUDA-powered functions are supported. When using this mode, network layers are deserialized through the <see cref="CuDnnNetworkLayers"/> class,
16+
/// and all other available operations will be scheduled on the GPU.
17+
/// </summary>
18+
Cuda
19+
}
20+
}

NeuralNetwork.NET/APIs/Enums/LayersLoadingPreference.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

NeuralNetwork.NET/APIs/Enums/NetworkType.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ public enum NetworkType : byte
88
/// <summary>
99
/// The classic network model, consisting in a linear stack of connected layers
1010
/// </summary>
11-
Sequential
11+
Sequential,
12+
13+
/// <summary>
14+
/// A network with a custom computation graph used to process its inputs
15+
/// </summary>
16+
ComputationGraph
1217
}
1318
}

NeuralNetwork.NET/APIs/Interfaces/Data/ITrainingDataset.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using JetBrains.Annotations;
33
using NeuralNetworkNET.SupervisedLearning.Progress;
4+
using SixLabors.ImageSharp;
5+
using SixLabors.ImageSharp.PixelFormats;
46

57
namespace NeuralNetworkNET.APIs.Interfaces.Data
68
{
@@ -19,6 +21,39 @@ public interface ITrainingDataset : IDataset
1921
/// </summary>
2022
int BatchesCount { get; }
2123

24+
/// <summary>
25+
/// Artificially expands the current dataset applying the input transformation to each sample to create new ones
26+
/// </summary>
27+
/// <param name="factories">The list of functions to use to generate new samples from each one in the dataset</param>
28+
void Expand([NotNull, ItemNotNull] params Func<float[], float[]>[] factories);
29+
30+
/// <summary>
31+
/// Artificially expands the current dataset by reinterpreting each sample as an image of the specified type and applying the input transformation to each sample to create new ones
32+
/// </summary>
33+
/// <typeparam name="TPixel">The type of image pixels. It must be either <see cref="Alpha8"/>, <see cref="Rgb24"/> or <see cref="Argb32"/></typeparam>
34+
/// <param name="width">The width of each sample image</param>
35+
/// <param name="height">The height of each sample image</param>
36+
/// <param name="factories">The list of functions to use to process the images and generate new samples</param>
37+
void Expand<TPixel>(int width, int height, [NotNull, ItemNotNull] params Action<IImageProcessingContext<TPixel>>[] factories) where TPixel : struct, IPixel<TPixel>;
38+
39+
/// <summary>
40+
/// Removes a specified fraction of samples from the current instance and returns a new <see cref="ITestDataset"/>
41+
/// </summary>
42+
/// <param name="ratio">The ratio of samples to include in the returned <see cref="ITrainingDataset"/></param>
43+
/// <param name="progress">The optional progress callback to use</param>
44+
[Pure, NotNull]
45+
ITestDataset ExtractTest(float ratio, [CanBeNull] Action<TrainingProgressEventArgs> progress = null);
46+
47+
/// <summary>
48+
/// Returns a pair of new datasets, where the first is an <see cref="ITrainingDataset"/> with the specified fraction of samples and
49+
/// the second is an <see cref="IValidationDataset"/> with the remaining number of samples from the current dataset
50+
/// </summary>
51+
/// <param name="ratio">The ratio of samples to include in the returned <see cref="ITrainingDataset"/></param>
52+
/// <param name="tolerance">The desired tolerance to test the network for convergence</param>
53+
/// <param name="epochs">The epochs interval to consider when testing the network for convergence</param>
54+
[Pure, NotNull]
55+
IValidationDataset ExtractValidation(float ratio, float tolerance = 1e-2f, int epochs = 5);
56+
2257
/// <summary>
2358
/// Returns a pair of new datasets, where the first is an <see cref="ITrainingDataset"/> with the specified fraction of samples and
2459
/// the second is an <see cref="ITestDataset"/> with the remaining number of samples from the current dataset
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using JetBrains.Annotations;
4+
using NeuralNetworkNET.APIs.Enums;
5+
6+
namespace NeuralNetworkNET.APIs.Interfaces
7+
{
8+
/// <summary>
9+
/// The base <see langword="interface"/> for the various types of nodes in a graph network
10+
/// </summary>
11+
public interface IComputationGraphNode : IEquatable<IComputationGraphNode>
12+
{
13+
/// <summary>
14+
/// Indicates the type of the current node
15+
/// </summary>
16+
ComputationGraphNodeType Type { get; }
17+
18+
/// <summary>
19+
/// Gets the collection of child nodes for the current computation graph node
20+
/// </summary>
21+
[NotNull, ItemNotNull]
22+
IReadOnlyList<IComputationGraphNode> Children { get; }
23+
}
24+
}

NeuralNetwork.NET/APIs/Interfaces/INeuralNetwork.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using JetBrains.Annotations;
55
using NeuralNetworkNET.APIs.Enums;
6+
using NeuralNetworkNET.APIs.Interfaces.Data;
67
using NeuralNetworkNET.APIs.Structs;
78

89
namespace NeuralNetworkNET.APIs.Interfaces
@@ -35,11 +36,21 @@ public interface INeuralNetwork : IEquatable<INeuralNetwork>, IClonable<INeuralN
3536
[NotNull, ItemNotNull]
3637
IReadOnlyList<INetworkLayer> Layers { get; }
3738

39+
/// <summary>
40+
/// Gets the number of units in the current network (layers or graph nodes)
41+
/// </summary>
42+
int Size { get; }
43+
3844
/// <summary>
3945
/// Gets the total number of parameters in the current network layer
4046
/// </summary>
4147
int Parameters { get; }
4248

49+
/// <summary>
50+
/// Gets whether or not a numeric overflow has occurred in the network
51+
/// </summary>
52+
bool IsInNumericOverflow { get; }
53+
4354
#endregion
4455

4556
#region Methods
@@ -96,6 +107,12 @@ public interface INeuralNetwork : IEquatable<INeuralNetwork>, IClonable<INeuralN
96107
[CollectionAccess(CollectionAccessType.Read)]
97108
float CalculateCost([NotNull] float[,] x, [NotNull] float[,] y);
98109

110+
/// <summary>
111+
/// Calculates the current network performances with the given dataset
112+
/// </summary>
113+
/// <param name="dataset">The <see cref="IDataset"/> instance to evaluate</param>
114+
(float Cost, int Classified, float Accuracy) Evaluate([NotNull] IDataset dataset);
115+
99116
#endregion
100117

101118
#region Serialization

NeuralNetwork.NET/APIs/NetworkLoader.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,18 @@ public static class NetworkLoader
2929
/// <returns>The deserialized network, or <see langword="null"/> if the operation fails</returns>
3030
[PublicAPI]
3131
[Pure, CanBeNull]
32-
public static INeuralNetwork TryLoad([NotNull] FileInfo file, LayersLoadingPreference preference)
32+
public static INeuralNetwork TryLoad([NotNull] FileInfo file, ExecutionModePreference preference)
3333
{
34-
using (FileStream stream = file.OpenRead())
35-
return TryLoad(stream, preference);
34+
try
35+
{
36+
using (FileStream stream = file.OpenRead())
37+
return TryLoad(stream, preference);
38+
}
39+
catch (FileNotFoundException)
40+
{
41+
// Just keep going
42+
return null;
43+
}
3644
}
3745

3846
/// <summary>
@@ -43,7 +51,7 @@ public static INeuralNetwork TryLoad([NotNull] FileInfo file, LayersLoadingPrefe
4351
/// <returns>The deserialized network, or <see langword="null"/> if the operation fails</returns>
4452
[PublicAPI]
4553
[Pure, CanBeNull]
46-
public static INeuralNetwork TryLoad([NotNull] Stream stream, LayersLoadingPreference preference)
54+
public static INeuralNetwork TryLoad([NotNull] Stream stream, ExecutionModePreference preference)
4755
{
4856
try
4957
{
@@ -53,6 +61,7 @@ public static INeuralNetwork TryLoad([NotNull] Stream stream, LayersLoadingPrefe
5361
switch (model)
5462
{
5563
case NetworkType.Sequential: return SequentialNetwork.Deserialize(gzip, preference);
64+
case NetworkType.ComputationGraph: return ComputationGraphNetwork.Deserialize(gzip, preference);
5665
default: return null;
5766
}
5867
}

NeuralNetwork.NET/APIs/NetworkManager.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using NeuralNetworkNET.APIs.Results;
1111
using NeuralNetworkNET.APIs.Structs;
1212
using NeuralNetworkNET.Extensions;
13+
using NeuralNetworkNET.Networks.Graph;
1314
using NeuralNetworkNET.Networks.Implementations;
1415
using NeuralNetworkNET.SupervisedLearning.Data;
1516
using NeuralNetworkNET.SupervisedLearning.Optimization;
@@ -41,6 +42,21 @@ public static INeuralNetwork NewSequential(TensorInfo input, [NotNull, ItemNotNu
4142
}).ToArray());
4243
}
4344

45+
/// <summary>
46+
/// Creates a computational graph network with a custom structure
47+
/// </summary>
48+
/// <param name="input">The input <see cref="TensorInfo"/> description</param>
49+
/// <param name="builder">An <see cref="Action{T}"/> used to build the graph from the input <see cref="NodeBuilder"/> node</param>
50+
[PublicAPI]
51+
[Pure, NotNull]
52+
public static INeuralNetwork NewGraph(TensorInfo input, [NotNull] Action<NodeBuilder> builder)
53+
{
54+
NodeBuilder root = NodeBuilder.Input();
55+
builder(root);
56+
ComputationGraph graph = ComputationGraph.New(input, root);
57+
return new ComputationGraphNetwork(graph);
58+
}
59+
4460
#region Training APIs
4561

4662
/// <summary>
@@ -126,7 +142,7 @@ private static TrainingSessionResult TrainNetworkCore(
126142

127143
// Start the training
128144
return NetworkTrainer.TrainNetwork(
129-
network as SequentialNetwork ?? throw new ArgumentException("The input network instance isn't valid", nameof(network)),
145+
network as NeuralNetworkBase ?? throw new ArgumentException("The input network instance isn't valid", nameof(network)),
130146
dataset as BatchesCollection ?? throw new ArgumentException("The input dataset instance isn't valid", nameof(dataset)),
131147
epochs, dropout, algorithm, batchProgress, trainingProgress,
132148
validationDataset as ValidationDataset,

0 commit comments

Comments
 (0)