NeuralNetwork.net es una biblioteca .NET Standard 2.0 que implementa redes neuronales secuenciales y de cálculo con capas personalizables, construidas desde cero con C#. Proporciona API simples diseñadas para prototipos rápidos para definir y entrenar modelos utilizando descenso de gradiente estocástico, así como métodos para guardar/cargar un modelo de red y sus metadatos y más. La biblioteca también expone capas aceleradas con CUDA con características más avanzadas que aprovechan la GPU y el Cudnn Toolkit para aumentar en gran medida las actuaciones al entrenar o usar una red neuronal.
Descargo de responsabilidad: esta biblioteca se proporciona tal como está, y ya no se mantiene activamente. Neuralnetwork.net se desarrolló durante un curso universitario y no está destinado a ser un reemplazo para otros marcos de aprendizaje automático bien conocidos. Si está buscando una biblioteca de aprendizaje automático para .NET para usar en producción, le recomiendo probar ml.net o alternativamente tensorflow.net.
Para instalar neuralnetwork.net , ejecute el siguiente comando en la consola del administrador de paquetes
Install-Package NeuralNetwork.NET
Más detalles disponibles aquí.
La biblioteca NeuralNetwork.net expone clases y métodos fáciles de usar para crear una nueva red neuronal, prepare los conjuntos de datos para usar y capacitar a la red. Estas API están diseñadas para prototipos rápidos, y esta sección proporciona una visión general de los pasos requeridos para comenzar.
El primer paso es crear una estructura de red personalizada. Aquí hay un ejemplo con una red secuencial (una pila de capas):
INeuralNetwork network = NetworkManager . NewSequential ( TensorInfo . Image < Alpha8 > ( 28 , 28 ) ,
NetworkLayers . Convolutional ( ( 5 , 5 ) , 20 , ActivationType . Identity ) ,
NetworkLayers . Pooling ( ActivationType . LeakyReLU ) ,
NetworkLayers . Convolutional ( ( 3 , 3 ) , 40 , ActivationType . Identity ) ,
NetworkLayers . Pooling ( ActivationType . LeakyReLU ) ,
NetworkLayers . FullyConnected ( 125 , ActivationType . LeakyReLU ) ,
NetworkLayers . FullyConnected ( 64 , ActivationType . LeakyReLU ) ,
NetworkLayers . Softmax ( 10 ) ) ;
El siguiente paso es preparar los conjuntos de datos para usar, a través de las API en la clase DatasetLoader
:
// A training dataset with a batch size of 100
IEnumerable < ( float [ ] x , float [ ] u ) > data = .. . // Your own dataset parsing routine
ITrainingDataset dataset = DatasetLoader . Training ( data , 100 ) ;
// An optional test dataset with a callback to monitor the progress
ITestDataset test = DatasetLoader . Test ( .. . , p =>
{
Console . WriteLine ( $" Epoch { p . Iteration } , cost: { p . Cost } , accuracy: { p . Accuracy } " ) ; // Progress report
} ) ;
Entrenar una red neuronal es bastante sencilla: solo use los métodos en la clase NetworkManager
:
// Train the network using Adadelta and 0.5 dropout probability
TrainingSessionResult result = NetworkManager . TrainNetwork (
network , // The network instance to train
dataset , // The ITrainingDataset instance
TrainingAlgorithms . AdaDelta ( ) , // The training algorithm to use
60 , // The expected number of training epochs to run
0.5f , // Dropout probability
p => .. . , // Optional training epoch progress callback
null , // Optional callback to monitor the training dataset accuracy
null , // Optional validation dataset
test , // Test dataset
token ) ; // Cancellation token for the training
Nota: Los métodos NetworkManager
también están disponibles como API asincrónicas.
Cuando se ejecuta en un marco compatible (.NET Framework, xamarin o mono), es posible utilizar una implementación diferente de las capas disponibles que aprovecha el kit de herramientas CUDNN y paraleliza la mayor parte del trabajo en la GPU habilitada para CUDA disponible. Para hacer eso, solo use las capas de la clase CuDnnNetworkLayers
al crear una red.
Algunas de las capas impulsadas por CUDNN admiten opciones adicionales que las capas predeterminadas. Aquí hay un ejemplo:
// A cuDNN convolutional layer, with custom mode, padding and stride
LayerFactory convolutional = CuDnnNetworkLayers . Convolutional (
ConvolutionInfo . New ( ConvolutionMode . CrossCorrelation , 3 , 3 , 2 , 2 ) ,
( 7 , 7 ) , 20 , ActivationType . ReLU ) ;
// An inception module, from the design of the GoogLeNet network
LayerFactory inception = CuDnnNetworkLayers . Inception ( InceptionInfo . New (
10 , // 1x1 convolution kernels
20 , 10 , // 1x1 + 3x3 convolution pipeline kernels
20 , 10 , // 1x1 + 5x5 convolution pipeline kernels
PoolingMode . AverageExcludingPadding , 10 ) ) ; // Pooling mode and 1x1 convolution kernels
Estas instancias LayerFactory
se pueden usar para crear una nueva red al igual que en el ejemplo de CPU.
Nota: Para usar esta función, los kits de herramientas CUDA y CUDNN deben instalarse en el sistema actual, debe estar disponible una GPU NVIDIA GeForce/Quadro habilitada para CUDA y el paquete Alea Nuget debe instalarse en la aplicación utilizando el NeuralNet.net.net.net. Biblioteca también. Hay información adicional disponible aquí.
Algunas estructuras de red complejas, como las redes residuales o los módulos de inicio, no pueden expresarse como una estructura de red secuencial simple: aquí es donde entran en juego las redes de gráficos de cálculo. En lugar de reenviar las entradas a través de una pila lineal de capas, un gráfico de cálculo tiene una estructura espacial específica que permite conectarse diferentes nodos. Por ejemplo, es posible canalizar los datos a través de diferentes tuberías paralelas que se fusionan más adelante en el gráfico, o tener clasificadores auxiliares que contribuyen a la respaldo de gradiente durante la fase de entrenamiento.
Las redes de gráficos de cálculo se crean utilizando la API NetworkManager.NewGraph
, aquí hay un ejemplo:
INeuralNetwork network = NetworkManager . NewGraph ( TensorInfo . Image < Rgb24 > ( 32 , 32 ) , root =>
{
var conv1 = root . Layer ( CuDnnNetworkLayers . Convolutional ( ( 5 , 5 ) , 20 , ActivationType . Identity ) ) ;
var pool1 = conv1 . Layer ( CuDnnNetworkLayers . Pooling ( ActivationType . ReLU ) ) ;
var conv2 = pool1 . Pipeline (
CuDnnNetworkLayers . Convolutional ( ( 1 , 1 ) , 20 , ActivationType . ReLU ) ,
CuDnnNetworkLayers . Convolutional ( ConvolutionInfo . Same ( ) , ( 5 , 5 ) , 40 , ActivationType . ReLU ) ,
CuDnnNetworkLayers . Convolutional ( ( 1 , 1 ) , 20 , ActivationType . ReLU ) ) ;
var sum = conv2 + pool1 ;
var fc1 = sum . Layer ( CuDnnNetworkLayers . FullyConnected ( 250 , ActivationType . LeCunTanh ) ) ;
var fc2 = fc1 . Layer ( CuDnnNetworkLayers . FullyConnected ( 125 , ActivationType . LeCunTanh ) ) ;
_ = fc2 . Layer ( CuDnnNetworkLayers . Softmax ( 10 ) ) ;
} ) ;
NeuralNetwork.net proporciona varias configuraciones compartidas disponibles a través de la clase NetworkSettings
. Esta clase actúa como un contenedor para verificar y modificar rápidamente cualquier configuración en cualquier momento, y estas configuraciones influirán en el comportamiento de cualquier instancia de INeuralNetwork
y la biblioteca existente en general.
Por ejemplo, es posible personalizar los criterios utilizados por las redes para verificar su rendimiento durante la capacitación
NetworkSettings . AccuracyTester = AccuracyTesters . Argmax ( ) ; // The default mode (mutually-exclusive classes)
// Other testers are available too
NetworkSettings . AccuracyTester = AccuracyTesters . Threshold ( ) ; // Useful for overlapping classes
NetworkSettings . AccuracyTester = AccuracyTesters . Distance ( 0.2f ) ; // Distance between results and expected outputs
Cuando se usa redes con cuda, a veces la GPU en uso podría no ser capaz de procesar la prueba completa o los conjuntos de datos de validación en un solo pase, que es el comportamiento predeterminado (estos conjuntos de datos no se dividen en lotes). Para evitar problemas de memoria, es posible modificar este comportamiento:
NetworkSettings . MaximumBatchSize = 400 ; // This will apply to any test or validation dataset
La interfaz INeuralNetwork
expone un método Save
que se puede utilizar para serializar cualquier red en un momento dado. Para obtener una nueva instancia de red de un archivo o transmisión guardado, simplemente use el método NetworkLoader.TryLoad
.
Como los tipos de múltiples capas tienen diferentes implementaciones en las bibliotecas disponibles, puede especificar que los proveedores de capa usen al cargar una red guardada. Por ejemplo, aquí le mostramos cómo cargar una red utilizando las capas Cudnn, cuando sea posible:
FileInfo file = new FileInfo ( @"C:...MySavedNetwork.nnet" ) ;
INeuralNetwork network = NetworkLoader . TryLoad ( file , ExecutionModePreference . Cuda ) ;
Nota: La opción ExecutionModePreference
indica el tipo de capas deseado para deserializar siempre que sea posible. Por ejemplo, utilizando ExecutionModePreference.Cpu
, la red cargada solo tendrá capas con CPU, si se admite.
También hay un método adicional SaveMetadataAsJson
para exportar los metadatos de una instancia INeuralNetwork
.
El espacio de nombres NeuralNetworkNET.Datasets
incluye clases estáticas para cargar rápidamente un conjunto de datos popular y obtener una instancia IDataset
lista para usar con una nueva red neuronal. Como ejemplo, aquí le mostramos cómo obtener el conjunto de datos MNIST:
ITrainingDataset trainingData = await Mnist . GetTrainingDatasetAsync ( 400 ) ; // Batches of 400 samples
ITestDataset testData = await Mnist . GetTestDatasetAsync ( p => .. . /* Optional callback */ ) ;
Cada API en este espacio de nombres también es compatible con una CancellationToken
opcional para detener la carga del conjunto de datos, ya que los datos de origen se descargan de Internet y pueden tomar algún tiempo disponible, dependiendo del conjunto de datos que se utiliza.
La biblioteca NeuralNetwork.NET requiere soporte .NET Standard 2.0, por lo que está disponible para aplicaciones de orientación:
Además de los marcos anteriores, necesita un IDE con soporte C# 7.3 para compilar la biblioteca en su PC.