NeuralNetwork.Net é uma biblioteca .NET Standard 2.0 que implementa redes neurais sequenciais e de computação com camadas personalizáveis, construídas do zero com C#. Ele fornece APIs simples projetadas para prototipagem rápida para definir e treinar modelos usando descida de gradiente estocástica, bem como métodos para salvar/carregar um modelo de rede e seus metadados e muito mais. A biblioteca também expõe camadas aceleradas por CUDA com recursos mais avançados que aproveitam a GPU e o kit de ferramentas do CUDNN para aumentar bastante as performances ao treinar ou usar uma rede neural.
Isenção de responsabilidade: esta biblioteca é fornecida como está e não está mais sendo mantida ativamente. NeuralNetwork.net foi desenvolvido durante um curso universitário e não é para substituir outras estruturas de aprendizado de máquina bem conhecidas. Se você está procurando uma biblioteca de aprendizado de máquina para o .NET para usar na produção, recomendo experimentar o ML.NET ou o Tensorflow.net alternativamente.
Para instalar o neuralnetwork.net , execute o seguinte comando no console do gerenciador de pacotes
Install-Package NeuralNetwork.NET
Mais detalhes disponíveis aqui.
A biblioteca NeuralNetwork.net expõe classes e métodos fáceis de usar para criar uma nova rede neural, preparar os conjuntos de dados para usar e treinar a rede. Essas APIs são projetadas para prototipagem rápida, e esta seção fornece uma visão geral das etapas necessárias para começar.
O primeiro passo é criar uma estrutura de rede personalizada. Aqui está um exemplo com uma rede seqüencial (uma pilha de camadas):
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 ) ) ;
A próxima etapa é preparar os conjuntos de dados para usar, através das APIs na classe 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
} ) ;
Treinar uma rede neural é bem direta - basta usar os métodos na classe 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: Os métodos NetworkManager
também estão disponíveis como APIs assíncronas.
Ao executar em uma estrutura suportada (.NET Framework, Xamarin ou Mono), é possível usar uma implementação diferente das camadas disponíveis que aproveitam o kit de ferramentas do CUDNN e paraleliza a maior parte do trabalho no GPU disponível CUDA. Para fazer isso, basta usar as camadas da classe CuDnnNetworkLayers
ao criar uma rede.
Algumas das camadas movidas a CUDNN suportam opções adicionais que as camadas padrão. Aqui está um exemplo:
// 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
Essas instâncias LayerFactory
podem ser usadas para criar uma nova rede, como no exemplo da CPU.
Nota: Para usar esse recurso, os kits de ferramentas CUDA e CUDNN devem ser instalados no sistema atual, uma GPU Nvidia GeForce/Quadro habilitada para Cuda deve estar disponível e o pacote Alea Nuget deve ser instalado no aplicativo usando o neuralnetwork.net biblioteca também. Informações adicionais estão disponíveis aqui.
Algumas estruturas de rede complexas, como redes residuais ou módulos de início, não podem ser expressos como uma simples estrutura de rede seqüencial: é aí que as redes gráficas de computação entram em jogo. Em vez de encaminhar as entradas através de uma pilha linear de camadas, um gráfico de computação possui uma estrutura espacial específica que permite que diferentes nós sejam conectados. Por exemplo, é possível canalizar dados por meio de diferentes pipelines paralelos que são mesclados posteriormente no gráfico ou com classificadores auxiliares que contribuem para a retropacagação do gradiente durante a fase de treinamento.
As redes de gráficos de computação são criadas usando a API da rede NetworkManager.NewGraph
, aqui está um exemplo:
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 fornece várias configurações compartilhadas disponíveis na classe NetworkSettings
. Essa classe atua como um contêiner para verificar rapidamente e modificar qualquer configuração a qualquer momento, e essas configurações influenciarão o comportamento de qualquer instância existente INeuralNetwork
e da biblioteca em geral.
Por exemplo, é possível personalizar os critérios usados pelas redes para verificar seu desempenho durante o treinamento
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
Ao usar redes movidas a CUDA, às vezes a GPU em uso pode não ser capaz de processar todo o conjunto de dados de teste ou validação em um único passe, que é o comportamento padrão (esses conjuntos de dados não são divididos em lotes). Para evitar problemas de memória, é possível modificar esse comportamento:
NetworkSettings . MaximumBatchSize = 400 ; // This will apply to any test or validation dataset
A interface INeuralNetwork
expõe um método Save
que pode ser usado para serializar qualquer rede a qualquer momento. Para obter uma nova instância de rede de um arquivo ou fluxo salvo, basta usar o método NetworkLoader.TryLoad
.
Como vários tipos de camada têm implementações diferentes nas bibliotecas disponíveis, você pode especificar os provedores de camada para usar ao carregar uma rede salva. Por exemplo, veja como carregar uma rede usando as camadas CUDNN, quando possível:
FileInfo file = new FileInfo ( @"C:...MySavedNetwork.nnet" ) ;
INeuralNetwork network = NetworkLoader . TryLoad ( file , ExecutionModePreference . Cuda ) ;
NOTA: A opção ExecutionModePreference
Indica o tipo desejado de camadas para desfazer sempre que possível. Por exemplo, usando ExecutionModePreference.Cpu
, a rede carregada terá apenas camadas movidas a CPU, se suportadas.
Há também um método SaveMetadataAsJson
adicional para exportar os metadados de uma instância INeuralNetwork
.
O namespace NeuralNetworkNET.Datasets
inclui classes estáticas para carregar rapidamente um conjunto de dados popular e preparar uma instância IDataset
para usar com uma nova rede neural. Como exemplo, veja como obter o conjunto de dados MNIST:
ITrainingDataset trainingData = await Mnist . GetTrainingDatasetAsync ( 400 ) ; // Batches of 400 samples
ITestDataset testData = await Mnist . GetTestDatasetAsync ( p => .. . /* Optional callback */ ) ;
Cada API neste espaço de nome também suporta um CancellationToken
opcional para interromper o carregamento do conjunto de dados, pois os dados de origem são baixados da Internet e podem levar algum tempo para estar disponível, dependendo do conjunto de dados usado.
A biblioteca NeuralNetwork.NET requer suporte .NET Standard 2.0, por isso está disponível para segmentação de aplicativos:
Além das estruturas acima, você precisa de um IDE com suporte C# 7.3 para compilar a biblioteca no seu PC.