[PYTHON] Depuis que j'ai touché Tensorflow pendant 2 mois, j'ai expliqué le réseau de neurones convolutifs d'une manière facile à comprendre avec 95,04% d'identification «hiragana manuscrite».

Apparemment, il m'a fallu une journée pour écrire l'article après avoir combattu le binaire pendant 5 heures avec l'ensemble de données prêt. Il est difficile d'écrire un article avec soin. Ufufu ☆

Dernière fois: Je ne suis ni programmeur ni data scientist, mais j'ai touché Tensorflow pendant un mois, donc c'est super facile à comprendre Suite à cela, j'ai pensé expliquer l'édition experte de MNIST, mais comme c'était un gros problème, ce n'était pas un nombre, mais ** un ensemble de données hiragana ** tout en identifiant un total de 71 caractères ** une explication du "réseau neuronal convolutif" ** Je veux. Puisqu'il s'agit d'un réseau de neurones convolutifs en anglais, il est appelé ** CNN ** ci-dessous.

Le code provient principalement de l'expert en didacticiel de Tensorflow, je me demande donc s'il sera plus facile à comprendre après l'avoir lu.

1: ensemble de données

Je l'ai reçu de la Base de données de caractères manuscrits ETL publiée par AIST. (Anciennement: ETL (Electro Technical Laboratory) pour Densoken) Si vous osez le nommer, ce n'est pas l'ensemble de données MNIST ** MAIST ** (Mixed Advanced Industrial Science and Technology) maist.JPG

Les données réelles sont de 127 x 128, ce qui est volumineux, mais elles ont été réduites à 28 x 28 pour s'adapter au didacticiel Tensorflow.

2: Ce qui est important, ce sont les fonctionnalités et comment réduire les dimensions!

Eh bien, ceci est un tutoriel d'expert. Même si vous dites soudainement un nouveau mot tel que plier ou regrouper, n'est-ce pas vraiment chimpunkampun?

Parlons un peu plus pour nous connecter avec la dernière fois, non? Droite?

Dans le tutoriel pour débutants, le poids W: [784, 10] a été calculé dans une matrice pour réduire l'image à 10 dimensions et faire correspondre les réponses. Ce poids est en pixels, c'est celui qui dit: "La possibilité de 0 ici est de 0,3%, la possibilité de 1 est de 21,1% ... Honyahonya".

Cependant, si vous voyez un minuscule 0 ** qui est ** 0 mais qui est bien en dessous, il y a de fortes chances que l'image réduite en dimension avec ce poids dise "La réponse est 6!". Au moins, les chances d'obtenir une réponse «0» sont considérablement réduites. Ceci est dû au fait que l'évaluation du pixel autour du centre du poids "W" est "0 possibilité est" -0,23017341 "". Si vous êtes un humain, vous pouvez immédiatement juger qu'il est "0 car il est rond". Ce ** "parce que c'est rond" ** est en fait une ** caractéristique importante **.

Pour élaborer un peu plus, puisqu'il s'agit d'une image, il devrait y avoir une relation entre le pixel cible et les pixels environnants, mais si vous transformez le vecteur et réduisez les dimensions, cette relation (caractéristique) peut être perdue. En regardant en arrière le graphique vectoriel qui était l'image de "1" la dernière fois, je ne peux pas du tout comprendre la relation avec les pixels environnants à partir d'ici. mnist1.jpg

La réduction de ce vecteur de 784 dimensions à un vecteur de 10 dimensions est une réponse assez approximative.

En d'autres termes, on peut dire que la ** caractéristique de ** "rond" ** a été perdue dans le processus de réduction de dimension **.

Les hiragana manuscrits ne peuvent pas être reconnus avec le modèle du didacticiel pour débutants.

Dans le didacticiel Tensorflow, le taux de réponse correct est de 91% pour les débutants à 99,2% pour les experts, donc pour la personne moyenne, il se termine par «Hmm». (En fait, il semble évident aux gens du domaine scientifique que cette différence est si grande. Cela a également été dit dans Breaking Bad.)

Cette fois, Hiragana MAIST était donc une très bonne référence pour comparer les deux tutoriels.

MAIST-beginner.py


train_step = tf.train.GradientDescentOptimizer(1e-4).minimize(cross_entropy)
#Si le nombre d'apprentissages est important, il diverge, alors réglez le taux d'apprentissage sur 1e.-Changer en 4

for i in range(10000):                                                                                 
  batch = random_index(50) #load 50 examples                                                           
  train_step.run(feed_dict={x: train_image[batch], y_: train_label[batch]})                            
                                                                  
print accuracy.eval(feed_dict={x: test_image, y_: test_label})   

> simple_maist  10000 steps accuracy 0.287933  
> simple_maist  50000 steps accuracy 0.408602
> simple_maist 100000 steps accuracy 0.456392

Que voulez-vous dire ... Avec le code du tutoriel débutant que j'ai utilisé la dernière fois, même si je me suis entraîné 10 000 fois, c'était seulement ** 28,79% **. 40,86% même si formé 50 000 fois, 45,63% même s'il est formé 100 000 fois.

Vous pouvez voir à quel point il est effrayant de perdre des fonctionnalités en raison de la réduction des dimensions.

Les gens intelligents doivent avoir pensé cela. "Il faut une réduction de dimension pour répondre, mais je veux conserver les fonctionnalités."

Donc le modèle expert: ** CNN ** ** Détection de caractéristiques ** Convolution: Convolution ** Amélioration des fonctionnalités ** Activation: Activation ** Réduction de dimension ** Mise en commun: mise en commun ** Entièrement joint ** Couche connectée (cachée): couche cachée Apparaîtra.

3: Convolution: Convolution

Regardons maintenant le contenu dans l'ordre. Tout d'abord, l'explication du code

Détection des fonctionnalités.py


 x_image = tf.reshape(x, [-1,28,28,1])

def weight_variable(shape):                        
  initial = tf.truncated_normal(shape, stddev=0.1) 
  return tf.Variable(initial)  

def conv2d(x, W):                                                 
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

W_conv1 = weight_variable([5, 5, 1, 32])
Conv1 = conv2d(x_image, W_conv1)
                   

CNN ne traite pas l'image en tant que vecteur, mais la traite avec une matrice 28x28 qui conserve la signification des caractéristiques en tant qu'image. En termes de Tensorflow, x_image = tf.reshape (x, [-1,28,28,1]) renvoie ce qui était un vecteur à la forme de l'image d'origine.

Et la convolution de la détection des fonctionnalités. Le mot «plier» n'a pas de sens, et j'en ai parlé un peu la dernière fois, mais c'est aussi une variable de «poids», alors interprétons-le comme un filtre. La variable variable / Tensor [5, 5, 1, 32] ʻof Rank 4est contenue dansW_conv1. Ce Tensor W_conv1:estforme, mais la signification est [largeur, hauteur, entrée, filtres]`, et des filtres de taille 5x5 sont appliqués à chaque image.

La dernière fois, l'initialisation était tf.zeros (), mais cette fois l'initialisation est tf.truncated_normal () et un nombre aléatoire sera entré.

Puisqu'il s'agit d'un filtre, visualisons-le. Oui, non! w_step0.JPG

Eh bien, je ne sais pas! Ces filtres sont bien entendu appliqués à l'image avec conv2d (x_image, W_conv1). Image appliquée: Cliquez ici. Oui, non! conv_step0.JPG

Cela devient de plus en plus difficile à comprendre. Cela devrait être le cas, car ces filtres n'ont pas été optimisés en premier lieu.

Jetons un coup d'œil au filtre et à son image appliquée une fois l'apprentissage terminé. Filtrer après l'apprentissage: je n'ai pas l'impression que ça ressemble à une ligne. w_step10000.JPG

Image applicable une fois l'apprentissage terminé: (Zu): L'effet tridimensionnel est génial d'une manière ou d'une autre! J'ai l'impression que ça a augmenté conv_step10000.JPG

C'est un peu difficile pour les humains à interpréter ...

4: Activation: Activation

Certaines fonctionnalités sont significatives, tandis que d'autres sont des pixels blancs vierges sans signification. Je veux souligner uniquement les caractéristiques autant que possible avant de réduire les dimensions. C'est là qu'intervient la fonction d'activation Relu. (Le biais n'est plus (^ o ^) par défaut ...)

Activation.py


def bias_variable(shape):                       
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

b_conv1 = bias_variable([32])   
h_conv1 = tf.nn.relu(Conv + b_conv1)

Le biais b_conv1 est un Tensor rempli avec le nombre spécifié par tf.constant (). Cette fois, c'est "0,1".

L'activation est également facile à comprendre, il suffit de passer le précédent Conv à tf.nn.relu.

En termes de MAIST cette fois, la valeur numérique est faible dans la partie sombre de l'image, et elle n'est pas détectée comme une caractéristique par l'ordinateur, elle est donc dans un état (valeur numérique) que je ne veux pas trop considérer. Par conséquent, toutes les personnes inutiles sont rendues «0» grâce à la fonction d'activation. Bref, c'est une coupure. J'ai peur de la restructuration.

L'activation est comme ça.py


-> x
[  1.43326855 -10.14613152   2.10967159   6.07900429  -3.25419664  
-1.93730605  -8.57098293  10.21759605   1.16319525   2.90590048]

-> Relu(x)
[  1.43326855  0.   2.10967159   6.07900429   0.  
 0.  0.  10.21759605   1.16319525   2.90590048]

Ce qui se passe Image: (Z) le rend encore plus facile à comprendre. relu_step10000.JPG

Sauf pour la partie (blanche) où les traits restent forts, il est devenu noir. Wow, seules les fonctionnalités restent magnifiquement! Facile à comprendre ~! C'est comme ça?

5: Mise en commun: mise en commun

L'image pliée et activée est bien extraite des caractéristiques, il est donc temps de réduire les dimensions. Dans le cas de la mise en commun, cela peut être plus comme une compression.

Réduction de dimension.py


def max_pool_2x2(x): 
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],                 
                         strides=[1, 2, 2, 1], padding='SAME') 
h_pool1 = max_pool_2x2(h_conv1)

La mise en commun est un peu déroutante, mais ksize = [1, 2, 2, 1] crée une image de 2x2 pixels, et strides = [1, 2, 2, 1] déplace 2x2 pixels. Je vais continuer. Dans le cas de «tf.nn.max_pool», la plus grande valeur de la trame de la taille spécifiée par «ksize» est considérée comme 1 pixel après compression. Ce chiffre est facile à comprendre. Dans le cas de la figure, "6" pour rose, "8" pour vert, "3" pour jaune et "4" pour bleu sont générés sous forme d'images compressées.

En plus de tf.nn.max_pool, il y a aussi tf.nn.avg_pool qui prend la valeur moyenne dans le cadre. Les fonctionnalités tf.nn.avg_pool peuvent être meilleures si vous voulez compresser tel quel ou si la relation de position des blancs est significative plutôt que de compresser principalement.

Regardons maintenant le cas essentiel de MAIST. L'image activée ci-dessus: (Z) est une image 14x14 comme celle-ci par mise en commun. pool_step10000.JPG Il est devenu impossible pour les humains de juger visuellement, mais il semble que l'image est devenue plus petite alors que seules les caractéristiques sont restées bien.

Après cela, le même processus est répété une fois de plus, et l'image devient finalement [batch_num, 7, 7, 64].

Deuxième fois.py


W_conv2 = weight_variable([5, 5, 32, 64])                   
b_conv2 = bias_variable([64])                              
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)  
h_pool2 = max_pool_2x2(h_conv2)                           

Si vous y réfléchissez bien, la dimension de l'image a diminué, mais l'image cible est passée à 64 caractéristiques. Cette zone dépend du réglage du nombre de filtres, et si vous augmentez le nombre de filtres, le processus de calcul deviendra de plus en plus lourd, il semble donc que vous deviez l'ajuster en tenant compte des spécifications de l'ordinateur personnel et du nombre de données.

Même si vous utilisez un filtre et que c'est [batch_num, 7, 7, 1], vous pouvez toujours apprendre. Bien sûr, c'est moins précis, mais c'est quand même meilleur que le modèle du débutant. Environ deux fois.

6: Couche cachée: Couche cachée

La réponse approche. La couche cachée ne fait que des opérations matricielles, donc ce n'est pas si difficile.

Couche cachée cachée.py


h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])             
W_fc1 = weight_variable([3136, 1024]) #[7*7*64, 1024]3136 est la taille de Tensor,1024 est approprié. Surtout 1024 ou 1024 dans l'industrie*Il semble être un multiple de n.
b_fc1 = bias_variable([1024])                               
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) 
#Dropout                                    
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) 

Plein de fonctionnalités ☆ Uhauha Tensor h_pool2: [batch_num, 7, 7, 64] Tout d'abord, renvoyez ceci à un vecteur avec tf.reshape (h_pool2, [-1, 7 * 7 * 64]). Il ne reste plus qu'à effectuer une opération matricielle avec le poids W_fc1: [3136, 1024], ajouter un biais, et l'activer.

La raison pour laquelle nous n'effectuons pas de calcul matriciel jusqu'au nombre de réponses à la fois est que nous voulons nous rapprocher de la correspondance des réponses tout en laissant autant que possible les fonctionnalités, et cela semble éviter le surapprentissage qui ne s'adapte qu'aux données de formation.

La raison pour laquelle vous ne pouvez pas donner une bonne réponse si vous écrasez trop les dimensions / Le rôle du calque caché est Voir ** "Topologie et classification" ** dans Qiita: Réseaux de neurones, variantes, topologies traduit par @KojiOhki.

L'analyse de régression est difficile lorsque la corrélation des caractéristiques entre les données de différentes classes est forte ou couverte, lorsqu'elle ne peut pas être bien séparée par réduction de dimension, ou lorsque le déterminant se trouve à un endroit différent. Je me demande si tel est le cas. Déterminez la taille de vos seins à partir de votre visage uniquement Cela peut être le cas. Au contraire, la taille des seins peut être connue de la voix. C'est pourquoi c'est un apprentissage profond amusant à essayer.

Concernant le surapprentissage, c'est la partie de h_fc1_drop = tf.nn.dropout (h_fc1, keep_prob), mais il sera décrit plus tard après le résultat d'apprentissage.

7: Résultat d'apprentissage

Avec ce réseau, la précision était de ** 87,15% ** à 10000 pas. C'était 28,79% dans le modèle du débutant, donc je suppose que j'ai dit CNN.

10000steps.py


simple_maist 10000 steps accuracy 0.287933        

now MAIST-CNN...                                         
i 0, training accuracy 0 cross_entropy 1200.03     
i 100, training accuracy 0.02 cross_entropy 212.827
i 200, training accuracy 0.14 cross_entropy 202.12 
i 300, training accuracy 0.02 cross_entropy 199.995
i 400, training accuracy 0.14 cross_entropy 194.412
i 500, training accuracy 0.1 cross_entropy 192.861 
i 600, training accuracy 0.14 cross_entropy 189.393
i 700, training accuracy 0.16 cross_entropy 174.141
i 800, training accuracy 0.24 cross_entropy 168.601
i 900, training accuracy 0.3 cross_entropy 152.631 
...                   
i 9000, training accuracy 0.96 cross_entropy 8.65753         
i 9100, training accuracy 0.96 cross_entropy 11.4614         
i 9200, training accuracy 0.98 cross_entropy 6.01312         
i 9300, training accuracy 0.96 cross_entropy 10.5093         
i 9400, training accuracy 0.98 cross_entropy 6.48081         
i 9500, training accuracy 0.98 cross_entropy 6.87556         
i 9600, training accuracy 1 cross_entropy 7.201              
i 9700, training accuracy 0.98 cross_entropy 11.6251         
i 9800, training accuracy 0.98 cross_entropy 6.81862         
i 9900, training accuracy 1 cross_entropy 4.18039            
test accuracy 0.871565                                       

Dans quelle mesure le secteur du Deep Learning trouve-t-il désormais des fonctionnalités et réduit-il les dimensions? Il peut être possible de devenir assez célèbre en maîtrisant.

twitter.JPG

8: (Réglage fin) Divergence d'apprentissage et prévention du surapprentissage

Une divergence d'apprentissage qui vous fait perdre la trace du modèle CNN intelligent

Pour Hiragana MAIST cette fois, si le nombre d'apprentissage est fixé à 20000 comme dans le tutoriel expert, la précision du taux de réponse correct pour les données d'apprentissage chutera à environ 2% à la fois d'environ 15000. Je ne connais pas le mécanisme détaillé des raisons pour lesquelles il diverge soudainement, mais si je ne baisse pas le taux d'apprentissage au fur et à mesure que l'apprentissage progresse, Gradient explosera probablement lorsque quelque chose comme Cross Entropy atteindra 0 ou moins. Je m'attends à ce que cela arrive.

La mesure préventive est-elle comme ça?

Prévention de la divergence d'apprentissage.py


L =  1e-3 #Taux d'apprentissage
train_step = tf.train.AdamOptimizer(L).minimize(cross_entropy)                                                             
for i in range(20000):                                               
  batch = random_index(50)                                           
  if i == 1000:   
    L = 1e-4      
  if i == 5000:   
    L = 1e-5      
  if i == 10000:  
    L = 1e-6      


...
i 19800, training accuracy 1 cross_entropy 6.3539e-05
i 19900, training accuracy 1 cross_entropy 0.00904318
test accuracy 0.919952         

Lors de l'apprentissage 20000 fois, la précision est de 91,99%. Eh bien, est-ce quelque chose comme ça? J'ai juste regardé cross_entropy environ toutes les 100 fois d'apprentissage et mis une étape appropriée. En réalité, ce taux d'apprentissage peut être ajusté automatiquement, mais si vous visez une super précision, vous pourrez peut-être le faire manuellement.

Le score dans les données d'évaluation est mauvais, n'est-ce pas? (`・ Ω ・ ´) [Prévention du surapprentissage]

Le code h_fc1_drop = tf.nn.dropout (h_fc1, keep_prob) qui était sur le calque caché Il semble très important d'éviter le surapprentissage. C'est ce qui s'est produit lorsque je l'ai mis plus loin avec la prévention de la divergence d'apprentissage.

Prévention du surapprentissage.py


for i in range(20000):
  batch = random_index(50)
#tune the learning rate
  if i == 1000: 
    L = 1e-4    
  if i == 3000: 
    L = 1e-5    
  if i == 7000: 
    L = 1e-6    
  if i == 10000:
    L = 1e-7    
  if i == 14000:
    L = 1e-8    
  if i == 19000:
    L = 1e-9    

#tune the dropout
  if i < 3000:                                                                                
    train_step.run(feed_dict={x: train_image[batch], y_: train_label[batch], keep_prob: 1})   
  elif i >= 3000 and i < 10000:                                                               
    train_step.run(feed_dict={x: train_image[batch], y_: train_label[batch], keep_prob: 0.3}) 
  elif i >= 10000 and i < 15000:                                                              
    train_step.run(feed_dict={x: train_image[batch], y_: train_label[batch], keep_prob: 0.1}) 
  elif i >= 15000 and i < 19000:                                                              
    train_step.run(feed_dict={x: train_image[batch], y_: train_label[batch], keep_prob: 0.05})
  else:                                                                                       
    train_step.run(feed_dict={x: train_image[batch], y_: train_label[batch], keep_prob: 0.8}) 

...
i 19900, training accuracy 1 cross_entropy 0.0656946
test accuracy 0.950418

** 95,04% ** dans les données d'évaluation C'est une bonne idée d'augmenter le nombre d'apprentissages tant que l'apprentissage ne diverge pas, mais si vous essayez d'en faire un format qui vous fait oublier d'un coup du début à juste avant la fin, vous pouvez atteindre ce niveau de précision.

Du premier ** 87,15% ** au ** 95,04% **, je pense que c'était un assez bon ajustement. Si le modèle fonctionne, il peut s'agir de l'artisanat à partir de là.

S'il y a beaucoup de traitement de calcul, cela prendra du temps, donc si la précision des données d'évaluation peut être améliorée, il est préférable de regarder toutes les 1000 étapes d'apprentissage afin que le surapprentissage puisse être détecté immédiatement. De manière inattendue, la précision d'apprentissage du modèle que j'ai créé était de 80%, mais les données d'évaluation étaient de 20%. Cela dépend cependant du nombre de classes que vous classez.

Résumé et la prochaine fois ...?

Si l'apprentissage ne se déroule pas bien avec CNN, la visualisation facilite la compréhension des problèmes structurels. La visualisation peut être faite facilement en recevant le contenu de Tensor avec sess.run et en utilisant matplotlib.

Le site suivant est recommandé pour ceux qui souhaitent voir la visualisation MNIST et le traitement détaillé. Quelle folie d'implémenter le deep learning avec JavaScript ConvNetJS - http://cs.stanford.edu/people/karpathy/convnetjs/demo/mnist.html

La prochaine fois, si possible, j'aimerais expliquer word2vec, qui est la base de LSTM, qui est la base de la prédiction de recherche, mais quand le sera-t-il? word2vec est un algorithme amusant que les entreprises Web (ou toutes) peuvent facilement appliquer à l'analyse de données.

Cependant, je pense que plus les modèles sont sophistiqués et la grande quantité de données, plus il faut de temps aux individus pour le faire sur leur propre ordinateur personnel, et la limite ** est atteinte. Je voudrais vous expliquer Google Inception, qui est le modèle de reconnaissance d'image le plus puissant, mais je me demande s'il est difficile pour moi, qui manque vraiment d'argent, d'utiliser le Tensorflow distribué dans un environnement cloud!

C'est tout pour le côté.

Les actions, tweets, likes, haines, commentaires, etc. sont tous encourageants, alors s'il vous plaît.

Si la méthode de bourdonnement dépasse le temps précédent, faisons-le la prochaine fois. Ouais, faisons ça.

Recommended Posts

Depuis que j'ai touché Tensorflow pendant 2 mois, j'ai expliqué le réseau de neurones convolutifs d'une manière facile à comprendre avec 95,04% d'identification «hiragana manuscrite».
[Pour les débutants] Je souhaite expliquer le nombre d’apprentissage d’une manière facile à comprendre.
J'ai essayé un réseau de neurones convolutifs (CNN) avec un tutoriel TensorFlow sur Cloud9-Classification des images manuscrites-
J'ai couru le tutoriel TensorFlow avec des commentaires (premier réseau de neurones: le début du problème de classification)
J'ai essayé de comprendre l'apprentissage supervisé de l'apprentissage automatique d'une manière facile à comprendre, même pour les ingénieurs serveurs 1
J'ai essayé de comprendre l'apprentissage supervisé de l'apprentissage automatique d'une manière facile à comprendre, même pour les ingénieurs serveurs 2
[Python] J'ai essayé de résumer le type collectif (ensemble) d'une manière facile à comprendre.
Créez un classificateur avec un taux de reconnaissance de l'écriture manuscrite de 99,2% à l'aide du réseau neuronal convolutif TensorFlow
Comparer la grammaire de base de Python et Go d'une manière facile à comprendre
J'ai essayé d'expliquer comment obtenir le contenu de l'article avec l'API MediaWiki d'une manière facile à comprendre avec des exemples (Python 3)
Introduction au Deep Learning (1) --Chainer est expliqué d'une manière facile à comprendre pour les débutants-
Affichez les journaux d'une manière facile à comprendre avec Ansible
J'ai essayé le tutoriel MNIST de tensorflow pour les débutants.
[Deep Learning from scratch] J'ai essayé d'expliquer la confirmation du gradient d'une manière facile à comprendre.
Exécutons Fusion 360 avec Python Partie 11 Puisqu'il n'y a aucun point le long du chemin dans l'API, j'ai pensé à une alternative