Préface
Dans l'apprentissage automatique, les réseaux de neurones convolutionnels sont des réseaux de neurones artificiels profonds à force qui ont été appliqués avec succès à la reconnaissance d'image. À l'heure actuelle, de nombreux numéros de plaque d'immatriculation, reconnaissance du visage, etc. Utilisent des réseaux de neurones convolutionnels. On peut dire que les réseaux de neurones convolutionnels ont connu un grand succès dans la reconnaissance de l'image. Il existe de nombreux cadres d'apprentissage en profondeur open source, tels que Caffe, TensorFlow, Torch, etc. Alors, pourquoi devons-nous encore écrire nous-mêmes des réseaux de neurones convolutionnels? Il est préférable d'utiliser directement ces frameworks d'apprentissage en profondeur open source, qui sont rapides et faciles à gérer, ont de bonnes performances et peu de bogues. Oui, si vous utilisez simplement des réseaux de neurones convolutionnels pour faire des applications et ne vous souciez pas de son principe de travail, vous n'avez pas à travailler dur pour rédiger des réseaux de neurones convolutionnels. Mais si vous voulez maîtriser pleinement le principe de travail des réseaux de neurones convolutionnels, les anciens ont dit: Ce que vous obtenez sur papier est toujours superficiel et vous devez pratiquer la sensibilisation à ce moment. Par conséquent, il vous est très nécessaire de mettre en œuvre vous-même le réseau neuronal convolutionnel pour approfondir votre compréhension.
Qu'est-ce que CupCnn
CupCnn est un réseau neuronal convolutionnel écrit en Java. En plus du travail, je l'ai réalisé afin d'approfondir ma compréhension des réseaux de neurones convolutionnels. Il est assez simple et fonctionne bien, ce qui le rend très adapté aux débutants. Son code source peut être téléchargé à partir de GitHub: CupCnn
Vous n'avez pas à vous soucier des limites de son protocole ou quelque chose. Vous pouvez l'utiliser pour faire n'importe quoi et le modifier arbitrairement. Si cela peut vous aider, j'espère que cela pourra vous donner une étoile! ! !
^ - ^^ - ^^ - ^^ - ^
Idées de conception
J'espère que c'est un réseau neuronal assez simple pour aider les débutants à apprendre. Je n'ai donc pas mis en œuvre ces trucs d'accélération simultanés, ce qui garantit la nature d'introduction du code. Lors de la conception, j'ai divisé le réseau neuronal convolutionnel en quatre modules: réseau (couche Blob Loss active), qui peut être vue à partir du nom du package. La couche, la perte et les actifs ont tous une classe de base, et la programmation de l'ensemble du réseau neuronal est orientée vers la classe de base. Le réseau est le centre qui intègre ces quatre modules, coordonne et dépasse les ressources. Chaque couche aura une instance du réseau, de sorte que diverses données peuvent être facilement obtenues via le réseau, comme l'obtention de la sortie de chaque couche, diff, etc.
Le diagramme de bloc de conception est le suivant:
Les paramètres de sauvegarde sont très simples pour Java. La mise en œuvre de l'interface sérialisable peut rapidement implémenter la sérialisation et la désérialisation des paramètres. CupCNN implémente uniquement l'interface sérialisable pour Blob et BlobParams dans le répertoire de données, et tous les paramètres sont implémentés par ces deux.
Performance actuelle
Réseau neuronal entièrement connecté
Actuellement, sur l'ensemble de données MNIST, un réseau neuronal entièrement connecté (connexion complète (100) + connexion complète (30) + connexion complète (10) + softmax) est formé avec 30 EPOES, avec un taux de précision de 96,76
Réseau neuronal convolutionnel
Réseau neuronal convolutionnel (6 caractéristiques) + pool maximum + convolution (6 caractéristiques) + connexion complète (512) + connexion complète (30) + connexion complète (10) + softmax), lorsque le taux d'apprentissage est de 0,2, 30 époques sont formés, le taux de précision est de 97,79. Je crois qu'après un autre réglage des paramètres, le taux de précision peut être plus élevé sous une formation suffisante.
L'instantané de formation du réseau neuronal convolutionnel est le suivant:
commencer à s'entraîner
EPOE: 0 LossValue: 2.3019369891560455 LR: 0,2 La précision est de 0,13
EPOE: 0 LossValue: 2.0722489482105195 LR: 0,2 La précision est de 0,44
EPOE: 0 LossValue: 1.2423286194012682 LR: 0,2 La précision est de 0,72
EPOE: 0 LossValue: 0,7860529560675255 LR: 0,2 La précision est de 0,79
EPOE: 0 LossValue: 0,6272194196176664 LR: 0,2 La précision est de 0,87
EPOE: 0 LossValue: 0,5240051326725808 LR: 0,2 La précision est de 0,84
EPOE: 0 LossValue: 0,27637563581928026 LR: 0,2 La précision est de 0,95
EPOE: 0 LossValue: 0,35585388987055083 LR: 0,2 La précision est de 0,92
EPOE: 0 LossValue: 0,441971528417802 LR: 0,2 La précision est de 0,92
EPOE: 0 LossValue: 0,25637710325999674 LR: 0,2 La précision est de 0,95
EPOE: 0 LossValue: 0,39872273532502 LR: 0,2 La précision est de 0,9
EPOE: 1 LossValue: 0,264085484522027 LR: 0,160000000000000000003 La précision est de 0,91
EPOE: 1 LossValue: 0,22754066024803088 LR: 0,160000000000000000003 La précision est de 0,96
EPOE: 1 LossValue: 0,30256420975577103 LR: 0,160000000000000000003 La précision est de 0,96
EPOE: 1 LossValue: 0,18149648622985948 LR: 0,16000000000000000003 La précision est de 0,99
EPOE: 1 LossValue: 0,177239938748327 LR: 0,160000000000000000003 La précision est de 0,96
EPOE: 1 LossValue: 0,15041993009777443 LR: 0,160000000000000000003 La précision est de 0,98
EPOE: 1 LossValue: 0.10759545752665524 LR: 0,1600000000000000000003 La précision est de 1,0
L'utilisation de CupCnn
À l'heure actuelle, CupCNN met en œuvre des tests sur l'ensemble de données MNIST. Sous SRC / Test, MNISTTest est l'entrée de la fonction principale, et le réseau neuronal spécifique est construit dans la classe MNISTNetwork. Dans la classe MNISTNETWORD, BuildConvNetwork et BuildFCNetwork mettent respectivement la construction de réseaux de neurones convolutionnels et la construction de réseaux de neurones entièrement connectés. Grâce aux bonnes propriétés multiplateformes de Java, après avoir téléchargé le code source de CupCNN, utiliser Eclipse pour ouvrir le projet, puis l'exécuter directement, vous devriez pouvoir commencer à s'entraîner et à tester sur le jeu de données MNIST.
Construire un réseau de neurones
public void buildNetwork () {// construire d'abord l'objet de réseau neuronal et définir les paramètres Network = new Network (); Network.SetBatch (100); Network.Setloss (new LogLIGLOHNOLOSS ()); //network.setloss(New CrossentRopyloss ()); Optimizer = new sgdoptimizer (0,2); Network.SetOptimizer (Optimizer); // buildfcnetwork (); buildConvNetwork (); network.prepare (); } La fonction setBatch () définit le nombre d'images dans un lot.
setloss () définit la fonction de perte à utiliser. CupCnn implémente la fonction de perte d'entropie croisée et la fonction de perte de vérification logarithmique.
SetOptimizer () doit être utilisé pour définir l'optimiseur. CupCNN implémente uniquement l'optimiseur SGD. Si vous implémentez un meilleur optimiseur et que vous êtes prêt à le soumettre à CupCNN, je voudrais l'accueillir profondément.
Construire un réseau neuronal entièrement connecté
private void buildfcnetwork () {// ajouter la couche réseau au réseau InputLayer couche1 = new inputLayer (réseau, new BlobParams (réseau.getBatch (), 1,28,28)); Network.Addlayer (couche1); FullConnectionLayer Layer2 = new FullConnectionLaYer (réseau, nouveau BlobParams (réseau.GetBatch (), 784,1,1)); couche2.SetActivationFunc (new ReluactivationFunc ()); Network.Addlayer (couche2); FullConnectionLaYer Layer3 = new FullConnectionlayer (réseau, nouveau BlobParams (réseau.GetBatch (), 100,1,1)); couche3.SetActivationFunc (new ReluactivationFunc ()); Network.Addlayer (couche3); FullConnectionLayer Layer4 = new FullConnectionlayer (réseau, nouveau BlobParams (réseau.GetBatch (), 30,1,1)); couche4.SetActivationFunc (new SigmodActivationFunc ()); Network.Addlayer (couche4); FullConnectionLayer Layer5 = new FullConnectionlayer (réseau, nouveau BlobParams (réseau.GetBatch (), 10,1,1)); couche5.SetActivationFunc (new ReluactivationFunc ()); Network.Addlayer (couche5); SoftMaxLayer sfLayer = new softMaxlayer (réseau, nouveau blobParams (réseau.getBatch (), 10,1,1)); Network.Addlayer (SfLayer); }Comme le montre le code ci-dessus, chaque couche a besoin d'un réseau, qui est une instance du réseau. Le réseau est l'administrateur mondial et le répartiteur des ressources. Avec la référence du réseau, nous pouvons facilement obtenir les données de sortie, les erreurs de sortie, etc. de chaque couche. De plus, chaque couche a besoin d'un paramètre qui spécifie la taille du bloc de données de sortie de la couche actuelle, qui indique une certaine couche dont vous avez besoin de données. Par exemple, la dernière couche d'un réseau neuronal est SoftMaxLayer, quel nombre doit être sorti. Ce nombre est représenté par un vecteur de longueur 10, comme le nombre 7, de sorte que SoftMaxLayer devrait produire la valeur du 8ème élément pour être 1 et la valeur des autres éléments à 0. La couche de convolution et la couche de pool nécessitent plus de paramètres car ils ont tous les deux un noyau. Pour la couche de convolution, elle est appelée noyau de convolution. La foulée de chaque direction de la couche de convolution est de 1, ce qui est toujours la place d'amélioration. Pour la couche de mise en commun, en plus de passer les paramètres du noyau de mise en commun, vous devez également passer par les étapes horizontales et verticales, ce qui est nécessaire.
Formation et tests
Après avoir construit un réseau neuronal, vous devez appeler la méthode Network.Prepare (), qui créera des blocs de données de sortie et des blocs de données d'erreur basés sur les paramètres de données de chaque couche. Par conséquent, l'appel à cette méthode est nécessaire.
Public Void Train (List <Gitimage> imglist, int epoes) {System.out.println ("Begin Train"); int batch = network.getBatch (); double loclalr = optimizer.getlr (); pour (int e = 0; e <epoes; e ++) {Collection.Shuffle (imglist); pour (int i = 0; i <imglist.size () - lot; i + = lot) {list <blob> inputAndLabel = buildBlobByImageList (imglist, i, lot, 1,28,28); Double LossValue = Network.Train (InputAndLabel.get (0), InputAndLabel.get (1)); if (i> lot && i / lot% 50 == 0) {System.out.print ("epoe:" + e + "LossValue:" + LossValue + "" + "lr:" + optimizer.getlr () + ""); Testinner (inputAndLabel.get (0), inputAndLabel.get (1)); }} if (loclalr> 0,001) {loclalr * = 0,8; Optimizer.setlr (loclalr); }}} Public Void Test (List <Gitimage> imglist) {System.out.println ("Begin Test"); int batch = network.getBatch (); int correctCount = 0; int i = 0; pour (i = 0; i <imglist.size () - lot; i + = lot) {list <blob> inputAndLabel = BuildBlobByImageList (imglist, i, lot, 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]) {correctCount ++; }}} double précision = correctCount / (1.0 * i + lot); System.out.println ("La précision du test est" + précision + "correctCount" + correctCount); }Comme mentionné ci-dessus, vous pouvez vous entraîner en appelant le train du réseau et vous pouvez tester en appelant la méthode de prédiction du réseau.
Enregistrer et charger les paramètres
public void SAVEMODEL (String Name) {Network.SaveModel (name); } public void lodModel (nom de chaîne) {Network = new Network (); Network.LoadModel (nom); network.prepare (); }L'appel de SaveModel et LoadModel du réseau peut respectivement enregistrer et charger les paramètres. Vous n'avez qu'à passer un nom de fichier. Lorsque nous créons un réseau de neurones via des paramètres enregistrés, nous devons d'abord d'abord appeler un réseau, puis appeler le chargeur de chargement de ce réseau pour charger les paramètres enregistrés, puis n'oubliez pas d'appeler la méthode de préparation pour créer des blocs de données de sortie et des blocs de données d'erreur pour chaque couche.
Statut d'achèvement actuel et plans futurs
Actuellement, les couches implémentées comprennent: Connexion complète, convolution, couche de pool maximale, couche de pool moyenne et couche Softmax. Les fonctions d'activation implémentées sont: Sigmod, Tanh, Relu.
Les fonctions de perte implémentées sont: l'entropie croisée, le journal logarithmique. L'optimisation implémentée est: SGD. Les paramètres peuvent déjà enregistrer et se charger. Ensuite, la couche d'abandon sera ajoutée et les exemples sur CIFAR-10 seront ajoutés.
De plus, j'écrirai quelques articles pour passer en revue mes pensées et mes questions pendant le processus d'écriture CupCnn pour référence par les débutants. Veuillez prendre un détour. Ceux qui sont intéressés peuvent continuer à faire attention. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.