Prefácio
No aprendizado de máquina, as redes neurais convolucionais são redes neurais artificiais profundas que foram aplicadas com sucesso ao reconhecimento de imagem. Atualmente, muitos reconhecimento de número de placas, reconhecimento de rosto etc. Use redes neurais convolucionais. Pode -se dizer que as redes neurais convolucionais alcançaram grande sucesso no reconhecimento de imagens. Existem muitas estruturas de aprendizado profundo de código aberto, como Caffe, Tensorflow, Torch etc. Essas estruturas de aprendizado profundo incluem a implementação de redes neurais convolucionais completas. Então, por que ainda temos que escrever redes neurais convolucionais? É melhor usar essas estruturas de aprendizado profundo de código aberto diretamente, que são rápidas e fáceis de lidar, têm bom desempenho e poucos bugs. Sim, se você usar apenas redes neurais convolucionais para fazer alguns aplicativos e não se importa com seu princípio de trabalho, não precisará trabalhar duro para escrever redes neurais convolucionais. Mas se você deseja dominar completamente o princípio de trabalho das redes neurais convolucionais, os antigos disseram: O que você obtém no papel é sempre superficial e você deve praticar a conscientização neste momento. Portanto, é muito necessário que você implemente a rede neural convolucional para aprofundar sua compreensão.
O que é cupcnn
Cupcnn é uma rede neural convolucional escrita em Java. Além do trabalho, percebi isso para aprofundar minha compreensão das redes neurais convolucionais. É simples o suficiente e tem um bom desempenho, tornando -o muito adequado para os iniciantes se referirem. Seu código -fonte pode ser baixado do github: cupcnn
Você não precisa se preocupar com as limitações de seu protocolo ou algo assim. Você pode usá -lo para fazer qualquer coisa e modificá -lo arbitrariamente. Se puder ajudá -lo, espero que possa lhe dar uma estrela! ! !
^-^^-^^-^^-^
Idéias de design
Espero que seja uma rede neural que seja simples o suficiente para ajudar os iniciantes a aprender. Por isso, não implementei essas coisas de aceleração simultânea, o que garante a natureza introdutória do código. Ao projetar, dividi a rede neural convolucional em quatro módulos: rede (perda de blob de camada ativa), que pode ser vista no nome do pacote. Camada, perda e ativo todos têm uma classe base, e a programação de toda a rede neural é orientada para a classe base. A rede é o centro que integra esses quatro módulos, coordena e despacha recursos. Cada camada terá uma instância da rede, para que vários dados possam ser facilmente obtidos através da rede, como a obtenção da saída de cada camada, difft etc.
O diagrama de blocos de design é o seguinte:
Salvar parâmetros é muito simples para Java. A implementação da interface serializável pode implementar rapidamente a serialização e a desserialização dos parâmetros. O Cupcnn implementa apenas a interface serializável para blob e blobparams no diretório de dados, e todos os parâmetros são implementados por esses dois.
Desempenho atual
Rede neural totalmente conectada
Atualmente, no conjunto de dados MNIST, uma rede neural totalmente conectada (conexão completa (100) + conexão completa (30) + conexão completa (10) + softmax) é treinada com 30 EPOs, com uma taxa de precisão de 96,76
Rede neural convolucional
Rede neural convolucional (6 recursos) + Pooling máximo + convolução (6 recursos) + conexão completa (512) + conexão completa (30) + conexão completa (10) + softmax), quando a taxa de aprendizado é 0,2, 30 EPOs são treinados, a taxa de precisão é 97,79. Acredito que, após um ajuste adicional de parâmetros, a taxa de precisão pode ser maior sob treinamento suficiente.
O instantâneo de treinamento da rede neural convolucional é a seguinte:
Comece o trem
Epoe: 0 LossValue: 2.3019369891560455 LR: 0,2 precisão é 0,13
Epoe: 0 LESTVALUE: 2.0722489482105195 LR: 0,2 precisão é 0,44
Epoe: 0 LossValue: 1.2423286194012682 LR: 0,2 precisão é 0,72
Epoe: 0 LESTVALUE: 0,7860529560675255 LR: 0,2 precisão é 0,79
Epoe: 0 LossValue: 0,6272194196176664 LR: 0,2 precisão é 0,87
Epoe: 0 LESTVALUE: 0,5240051326725808 LR: 0,2 precisão é 0,84
Epoe: 0 LESTVALUE: 0,27637563581928026 LR: 0,2 precisão é 0,95
Epoe: 0 LESTVALUE: 0,35585388987055083 LR: 0,2 precisão é 0,92
Epoe: 0 PerdValue: 0,441971528417802 LR: 0,2 precisão é 0,92
Epoe: 0 LESTVALUE: 0,25637710325999674 LR: 0,2 precisão é 0,95
Epoe: 0 LESTVALUE: 0,39872273532502 LR: 0,2 precisão é 0,9
EPOE: 1 LESTVALUE: 0,264085484522027 LR: 0,160000000000000000003 A precisão é 0,91
Epoe: 1 LESTVALUE: 0,22754066024803088 LR: 0,16000000000000000000003 A precisão é 0,96
Epoe: 1 LESTVALUE: 0.30256420975577103 LR: 0,16000000000000000000003 A precisão é 0,96
Epoe: 1 LESTVALUE: 0,18149648622985948 LR: 0,16000000000000000003 A precisão é 0,99
Epoe: 1 LESTVALUE: 0,177239938748327 LR: 0,16000000000000000000003 A precisão é 0,96
Epoe: 1 LESTVALUE: 0.150419930097774443 LR: 0,16000000000000000000003 A precisão é 0,98
Epoe: 1 LESTVALUE: 0,107595457526665524 LR: 0,1600000000000000000003 A precisão é 1.0
O uso de cupcnn
Atualmente, o Cupcnn implementa testes no conjunto de dados MNIST. Em SRC/teste, o MnistTest é a entrada da função principal e a rede neural específica é construída na classe MnistNetwork. Na classe MnistNetwork, BuildConvNetwork e BuildFCNetwork implementam respectivamente a construção de redes neurais convolucionais e a construção de redes neurais totalmente conectadas. Graças às boas propriedades de plataforma cruzada de Java, depois de baixar o código-fonte do Cupcnn, use o Eclipse para abrir o projeto e executá-lo diretamente, você poderá começar a treinar e testar no conjunto de dados MNIST.
Construindo uma rede neural
public void BuildNetwork () {// primeiro construa o objeto de rede neural e defina a rede de parâmetros = new Network (); Network.setBatch (100); Network.setLoss (novo logLikeHoodLoss ()); //network.setloss(new crossEntropyloss ()); otimizer = novo sgDoptimizer (0,2); Network.setOtimizer (otimizador); // buildfcNetwork (); BuildConvNetwork (); Network.Prepare (); } A função setBatch () define quantas imagens estão em um lote.
setLoss () define a função de perda a ser usada. O Cupcnn implementa a função de perda de entropia cruzada e a função de perda de log-probabilidade.
SetOptimizer () deve ser usado para definir o otimizador. A cupcnn implementa apenas o otimizador SGD. Se você implementar um melhor otimizador e estiver disposto a enviá -lo ao Cupcnn, gostaria de recebê -lo profundamente.
Construa uma rede neural totalmente conectada
private void BuildfcNetwork () {// Adicione a camada de rede à camada de entrada de rede de entrada1 = new inputLayer (rede, new BlobParams (Network.getBatch (), 1,28,28)); Network.addlayer (camada1); FullConnectionLayer Layer2 = new FullConnectionLayer (Rede, New BlobParams (Network.getBatch (), 784,1,1)); camada2.SetActivationFunc (new ReluativationFunc ()); Network.addlayer (camada2); FullConnectionLayer Layer3 = new FullConnectionLayer (Rede, New BlobParams (Network.getBatch (), 100,1,1)); camada3.SetActivationFunc (new ReluativationFunc ()); Network.addlayer (camada3); FullConnectionLayer Layer4 = new FullConnectionLayer (Rede, New BlobParams (Network.getBatch (), 30,1,1)); Layer4.SetActivationFunc (new SigmodActivationFunc ()); Network.addlayer (Layer4); FullConnectionLayer Layer5 = new FullConnectionLayer (Rede, New BlobParams (Network.getBatch (), 10,1,1)); camada5.SetActivationFunc (new ReluativationFunc ()); Network.addlayer (camada5); Softmaxlayer sflayer = new Softmaxlayer (rede, new BlobParams (network.getBatch (), 10,1,1)); Network.addlayer (Sflayer); }Conforme mostrado no código acima, cada camada precisa de uma rede, que é uma instância da rede. A rede é o administrador global e o despachante de recursos. Com a referência da rede, podemos obter facilmente os dados de saída, erros de saída etc. de cada camada. Além disso, cada camada precisa de um parâmetro que especifique o tamanho do bloco de dados de saída da camada atual, que informa a uma certa camada quanto dados você precisa para produzir. Por exemplo, a última camada de uma rede neural é o Softmaxlayer, cujo número precisa ser emitido. Esse número é representado por um vetor de comprimento 10, como o número 7, portanto, o SoftmaxLayer deve gerar o valor do 8º elemento para ser 1 e o valor de outros elementos a ser 0. A camada de convolução e a camada de agrupamento requerem mais parâmetros porque ambos têm um kernel. Para a camada de convolução, é chamado de núcleo de convolução. O passo de cada direção da camada de convolução é 1, que ainda tem espaço para melhorias. Para a camada de pool, além de passar nos parâmetros do núcleo de pool, você também precisa passar nas etapas horizontais e verticais, o que é necessário.
Treinamento e teste
Após a criação de uma rede neural, você precisa ligar para o método Network.Prepare (), que criará blocos de dados de saída e blocos de dados de erro com base nos parâmetros de dados de cada camada. Portanto, a chamada para esse método é necessária.
Public Void Train (List <GitiTimage> imglist, int epoes) {System.out.println ("Begin Train"); int batch = Network.getBatch (); duplo loclalr = otimizer.getlr (); for (int e = 0; e <epoes; e ++) {collection.Shuffle (imglist); for (int i = 0; i <imglist.size ()-lote; i+= em lote) {list <blob> inputandlabel = buildblobbyImagelist (imglist, i, lote, 1,28,28); Double PerdValue = Network.Train (inputAndlabel.get (0), inputAndlabel.get (1)); if (i> lote && i/lote%50 == 0) {System.out.print ("Epoe:"+e+"LESTVALUE:"+LESTVALUE+""+"LR:"+otimizer.getlr ()+""); testInner (inputAndlabel.get (0), inputandlabel.get (1)); }} if (loclalr> 0,001) {loclalr*= 0.8; otimizer.setlr (loclalr); }}} public void test (list <GitiTimage> imglist) {System.out.println ("BEGIN TEST"); int batch = Network.getBatch (); int corretoCount = 0; int i = 0; for (i = 0; i <imglist.size ()-lote; i+= em lote) {list <blob> inputandlabel = BuildBlobbyImagelist (imglist, i, lote, 1,28,28); BLOB output = Network.Predict (inputAndlabel.get (0)); int [] caloutlabels = getBatchOutputLabel (output.getData ()); int [] realLabels = getBatchOutputLabel (inputAndlabel.get (1) .getData ()); for (int kk = 0; kk <caloutlabels.length; kk ++) {if (caloutlabels [kk] == reallabels [kk]) {corretoCount ++; }}} precisão dupla = corretoCount/(1.0*i+lote); System.out.println ("precisão do teste é"+precisão+"corretoCount"+correto); }Como mencionado acima, você pode treinar ligando para o trem da rede e pode testar chamando o método Predict da rede.
Salvar e carregar parâmetros
public void Savemodel (Nome da String) {Network.SaveModel (Nome); } public void loadModel (nome da string) {rede = new Network (); Network.LoadModel (nome); Network.Prepare (); }Chamar o Savemodel e o LoadModel da rede podem respectivamente salvar e carregar parâmetros. Você só precisa passar em um nome de arquivo. Quando criamos uma rede neural por meio de parâmetros salvos, precisamos primeiro uma nova rede e ligar para o LoadModel dessa rede para carregar os parâmetros salvos e, em seguida, não se esqueça de chamar o método de preparação para criar blocos de dados de saída e blocos de dados de erro para cada camada.
Status de conclusão atual e planos futuros
Atualmente, as camadas implementadas incluem: conexão completa, convolução, camada máxima de agrupamento, camada média de pool e camada softmax. As funções de ativação implementadas são: Sigmod, Tanh, Relu.
As funções de perda implementadas são: entropia cruzada, Log-Likelinco. A otimização implementada é: SGD. Os parâmetros já podem salvar e carregar. Em seguida, a camada de abandono será adicionada e os exemplos no CIFAR-10 serão adicionados.
Além disso, escreverei alguns artigos para revisar meus pensamentos e perguntas durante o processo de redação do Cupcnn para referência por iniciantes. Por favor, faça um desvio. Aqueles que estão interessados podem continuar prestando atenção. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.