Tutoriel traduit pour Débutant et utilisé TensorFlow dans précédent et précédent J'ai fait du machine learning. Cette fois, j'ai traduit le tutoriel pour Expert.
Deep MNIST for Experts TensorFlow est une bibliothèque puissante pour effectuer des calculs numériques à grande échelle. L'une des meilleures tâches est la formation et l'exécution de réseaux de neurones profonds. Dans ce didacticiel, nous allons apprendre les composants de base du modèle TensorFlow tout en créant un classificateur MNIST à convolution profonde.
Cette introduction suppose que vous êtes familiarisé avec les réseaux de neurones et les jeux de données MNIST. Si vous ne pouvez pas avoir ces antécédents, consultez l'introduction pour les débutants (https://www.tensorflow.org/versions/master/tutorials/mnist/beginners/index.html). Veillez à installer TensorFlow avant de commencer.
Setup Avant de créer notre modèle, nous chargeons d'abord le jeu de données MNIST, puis démarrons une session TensorFlow.
Load MNIST Data Pour votre commodité, nous téléchargeons et importons automatiquement l'ensemble de données MNIST [Script](https://tensorflow.googlesource.com/tensorflow/+/master/tensorflow/examples/tutorials/mnist/input_data .py) est inclus. Cela crée un répertoire "MNIST_data" pour stocker les fichiers de données.
import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
Cette mnist est une classe légère qui stocke un ensemble d'entraînement, de validation et de test sous forme de tableau de NumPy. Il fournit également une fonction qui itère dans un mini-lot de données, que nous utilisons ci-dessous.
Start TensorFlow InteractiveSession TensorFlow s'appuie sur un backend C ++ très efficace pour ses calculs. La connexion à ce backend s'appelle une session. L'utilisation habituelle du programme TensorFlow consiste à créer d'abord un graphique, puis à le démarrer dans une session.
Ici, nous utilisons à la place la classe pratique InteractiveSession, qui rend TensorFlow plus flexible sur la façon de créer votre code. Cela vous permet de démarrer le graphe et de connecter le processus de construction du graphe de calcul (https://www.tensorflow.org/versions/master/get_started/basic_usage.html#the-computation-graph) À. Ceci est particulièrement utile lorsque vous travaillez dans un contexte bidirectionnel comme iPython. Si vous n'utilisez pas InteractiveSession, vous démarrez la session et démarrez le graphique (https://www.tensorflow.org/versions/master/get_started/basic_usage.html#launching-the-graph-in -a-session) Vous devriez construire le graphe de calcul complet avant.
import tensorflow as tf
sess = tf.InteractiveSession()
Pour des calculs numériques efficaces en Python, nous utilisons généralement du code très efficace implémenté dans d'autres langages, comme NumPy, qui effectue un traitement élevé comme la multiplication de matrice en dehors de Python. La bibliothèque est utilisée. Malheureusement, le passage à l'ensemble du traitement de Python entraînera encore beaucoup de surcharge. Cette surcharge est particulièrement mauvaise si vous souhaitez calculer sur un GPU ou d'une manière distribuée qui coûterait cher pour transférer des données.
TensorFlow effectue également sa tâche difficile en dehors de Python, mais prend des mesures supplémentaires pour éviter cette surcharge. Au lieu d'exécuter un processus coûteux indépendant de Python, TensorFlow décrit un graphique de processus en interaction qui s'exécute entièrement en dehors de Python. Cette approche est similaire à l'utilisation de Theano ou Torch.
Le rôle du code Python est donc de construire ce graphe de calcul externe et de dicter quelle partie du graphe de calcul doit être exécutée. Pour plus de détails, voir Calculation Graph dans Basic Usage. Consultez la section /get_started/basic_usage.html#the-computation-graph).
Dans cette section, nous construisons un modèle de régression softmax pour une seule couche linéaire. Dans la section suivante, nous étendons cela dans le cas de la régression softmax des réseaux de convolution multicouches.
Placeholders Nous commençons à créer des graphiques informatiques en créant des nœuds pour les entrées d'image et les classes de sortie d'intérêt.
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])
Ces «x» et «y_» ne sont pas des valeurs spéciales. Ce sont plutôt des espaces réservés, les valeurs que nous saisissons lorsque nous demandons à TensorFlow d'exécuter des calculs, respectivement.
L'image d'entrée «x» est constituée d'un tenseur 2D à virgule flottante. Ici, nous lui attribuons la forme [Aucun, 784]. 783 est le nombre de dimensions de l'image MNIST parallèles à une ligne, indiquant que la première dimension, Aucune, peut être de n'importe quelle taille, correspondant à la taille du lot. La classe de sortie «y_» d'intérêt se compose également d'un tenseur 2D. Chaque colonne est un vecteur unique à 10 dimensions montrant les nombres correspondant à l'image MNIST.
L'argument de forme d'espace réservé est facultatif, mais il vous permet de détecter automatiquement les bogues résultant de formes tensorielles qui ne correspondent pas à TensorFlow.
Variables Nous définissons maintenant les poids «W» et le biais «b» pour notre modèle. Nous pouvons imaginer les traiter comme des entrées supplémentaires, mais TensorFlow a une meilleure façon de les gérer. C'est variable. La variable est une valeur qui existe dans le graphique de calcul TensorFlow. Dans les applications d'apprentissage automatique, les paramètres du modèle sont généralement variables.
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
Nous transmettons les valeurs initiales de ces paramètres en appelant tf.Variable
.
Dans ce cas, nous initialisons à la fois "W" et "b" comme un tenseur de tous les zéros.
«W» est une matrice de 784x10 (car nous avons 784 caractéristiques d'entrée et 10 sorties) et «b» est un vecteur à 10 dimensions (car nous avons 10 classes).
Avant que les variables ne soient utilisées dans une session, elles doivent être initialisées à l'aide de la session. Dans cette étape, nous prenons les valeurs initiales que nous avons déjà clarifiées (pour tous les tenseurs nuls) et leur attribuons leurs Variables respectives. Cela peut être fait pour toutes les variables en une seule fois.
sess.run(tf.initialize_all_variables())
Nous pouvons maintenant implémenter notre modèle de régression. C'est juste une ligne! Nous multiplions l'image d'entrée vectorisée «x» par la matrice de poids «W», ajoutons le biais «b» et calculons les probabilités softmax attribuées à chaque classe.
y = tf.nn.softmax(tf.matmul(x,W) + b)
La fonction de coût minimisée pendant la formation est brièvement décrite. Notre fonction de coût est l'entropie croisée entre l'objet et la prédiction du modèle.
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
Notez que tf.reduce_sum
additionne toutes les classes ainsi que toutes les images dans un mini-lot.
Nous calculons l'entropie croisée pour l'ensemble du mini-lot.
Maintenant que nous avons défini notre modèle et notre fonction de coût de formation, la formation avec TensorFlow est simple. Parce que TensorFlow connaît tous les graphes de calcul et utilise l'auto-identification pour trouver le gradient de coût pour chaque variable. TensorFlow a divers algorithmes d'optimisation installés. Par exemple, nous prenons des pas de 0,01 longueur et utilisons la descente la plus raide pour descendre l'entropie croisée.
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
Ce que TensorFlow a réellement fait dans cette ligne était d'ajouter un nouveau traitement au graphe de calcul. Le processus, y compris ceux qui calculent ces gradients, calcule les étapes de mise à jour des paramètres et applique les étapes mises à jour aux paramètres.
Le processus retourné train_step
applique une descente de gradient qui met à jour les paramètres lors de son exécution.
La formation du modèle sera donc efficace en effectuant plusieurs fois train_step
.
for i in range(1000):
batch = mnist.train.next_batch(50)
train_step.run(feed_dict={x: batch[0], y_: batch[1]})
Dans chaque itération d'entraînement, nous lisons 50 échantillons d'apprentissage.
Nous utilisons ensuite feed_dict
pour remplacer le x
et le _y
du tenseur placeholder
par la nuance d'entraînement et exécutons le processus train_step
.
Notez que vous pouvez utiliser feed_dict
pour échanger n'importe quel tenseur dans le graphe de calcul d'Atana. Pas seulement limité à «placeholder».
Comment améliorer notre modèle?
Nous calculons d'abord où nous avons prédit l'étiquette correcte.
tf.argmax
est une fonction très utile qui donne l'indice d'entrée le plus élevé dans un tenseur le long d'un axe.
Par exemple, tf.argmax (_y, 1)
est la vraie étiquette, tandis que tf.argmax (y, 1)
est l'étiquette la plus similaire pour chaque entrée que notre modèle considère.
Nous pouvons utiliser tf.equal
pour voir si nos prédictions correspondent à la vérité.
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
Cela donne une liste de booléens. Pour déterminer si la pièce est correcte, nous la convertissons en virgule flottante puis prenons la moyenne. Par exemple, «[True, False, True, True]» devient «[1,0,1,1]» et devient «0,75».
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
Enfin, nous évaluons notre précision avec des données de test. Cela devrait être correct à environ 91%.
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
Il n'est pas bon d'obtenir une précision d'environ 91% avec MNIST. C'est presque déroutant. Dans cette section, nous le corrigeons et passons d'un modèle très simple à quelque chose de raisonnablement sophistiqué, un petit réseau de neurones convolutifs. Cela donne une précision d'environ 99,2%. Pas de pointe, mais simple.
Pour créer ce modèle, nous devons créer de nombreux poids et biais. On initialise généralement les poids avec un faible bruit dû à la rupture de symétrie, empêchant le gradient de devenir nul. Puisque nous avons utilisé des neurones à fonction linéaire normalisée (ReLU), il est recommandé de les initialiser avec un biais initial légèrement positif pour éviter la mort des neurones. Au lieu de répéter cela pendant que nous construisons le modèle, créons deux fonctions faciles à utiliser qui le font pour nous.
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
Convolution and pooling TensorFlow nous offre également une grande flexibilité dans la convolution et l'échantillonnage partiel. Comment bien gérer les frontières? Quelle est la taille de notre foulée? Dans cet exemple, nous choisissons toujours la version médiocre. Notre convolution utilise une foulée et est complétée à 0 afin que la sortie ait la même taille que l'entrée. Notre échantillonnage partiel est un ancien plan d'échantillonnage partiel maximal (couche) qui dépasse 2x2 blocs. Pour garder notre code propre, faisons fonctionner ces processus abstraits.
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1], padding='SAME')
Nous pouvons maintenant implémenter notre première couche. Il consiste en une convolution et se produit après le pooling max. La convolution calcule 32 fonctionnalités pour un patch 5x5. Son tenseur de poids a la forme «[5, 5, 1, 32]». Les deux premières dimensions sont la taille du patch, puis le nombre de canaux d'entrée et enfin les canaux de sortie. Nous avons également un vecteur de biais avec des éléments pour chaque canal de sortie.
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
Pour appliquer aux calques, nous traduisons d'abord «x» en un tenseur 4D avec une deuxième et une troisième dimension correspondant à la largeur et à la hauteur de l'image et une dimension finale correspondant au nombre de canaux de couleur. Refaire.
x_image = tf.reshape(x, [-1,28,28,1])
Nous faisons ensuite une convolution de x_image
et du tenseur de poids, le biaisons, appliquons la fonction ReLU, et enfin calculons le pool max.
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
Au lieu de construire un réseau profond, nous empilons plusieurs couches de ce type. La deuxième couche a 64 fonctionnalités pour chaque patch 5x5.
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)
Maintenant que la taille de l'image a été réduite à 7x7, nous ajoutons une couche entièrement connectée avec 1024 neurones qui permettent le traitement de toutes les images. Nous transformons le tenseur d'une couche d'échantillonnage partiel en un lot de vecteurs, le multiplions par une matrice de poids, ajoutons un biais et appliquons ReLU.
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
Dropout
Pour réduire la sur-application, nous appliquons une suppression avant la couche de lecture.
Nous faisons un «espace réservé» pour la probabilité de conserver la sortie du neurone pendant la déconnexion.
Cela nous permet d'abandonner pendant l'entraînement et d'arrêter de courir pendant les tests.
L'opération tf.nn.dropout
de TensorFlow met automatiquement à l'échelle la sortie neuronale en plus de les masquer, et la suppression s'exécute sans mise à l'échelle supplémentaire.
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
Enfin, nous ajoutons une couche softmax ainsi qu'une couche de régression softmax ci-dessus.
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
Quelle est la qualité de ce modèle? Pour la formation et l'évaluation, nous utilisons presque le même code qu'une couche du réseau Softmax simple ci-dessus. Les différences sont les suivantes. Nous transformons le programme d'optimisation de descente le plus raide en un programme d'optimisation ADAM plus sophistiqué. Nous incluons un paramètre supplémentaire «keep_prob» dans «deed_dict» pour contrôler le taux d'abandon. Et nous ajoutons une journalisation toutes les 100 itérations du processus de formation.
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
sess.run(tf.initialize_all_variables())
for i in range(20000):
batch = mnist.train.next_batch(50)
if i%100 == 0:
train_accuracy = accuracy.eval(feed_dict={
x:batch[0], y_: batch[1], keep_prob: 1.0})
print("step %d, training accuracy %g"%(i, train_accuracy))
train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
print("test accuracy %g"%accuracy.eval(feed_dict={
x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
La précision de l'ensemble de test final après l'exécution de ce code doit être d'environ 99,2%.
Nous avons appris à créer, former et évaluer un modèle d'apprentissage en profondeur assez sophistiqué avec TensorFlow, rapidement et facilement.
C'est tout pour la traduction. C'est plus compliqué que le tutoriel du débutant, mais c'est similaire en ce que chaque couche est pondérée, biaisée et la fonction appliquée. Ensuite, j'aimerais réellement exécuter le code tout en comprenant mieux ce contenu.
Recommended Posts