J'ai essayé le tutoriel TensorFlow (MNIST pour les débutants) dans Cloud9-Classification des images manuscrites- pour implémenter l'apprentissage automatique simple. J'ai fait. Ensuite, j'ai essayé "[Deep MNIST for Experts] de TensorFlow (https://www.tensorflow.org/get_started/mnist/pros)". Comme il est écrit pour les professionnels, diverses méthodes sont utilisées, mais elles sont plus faciles à comprendre lorsque vous écrivez le code. Ici, nous allons implémenter un réseau de neurones convolutifs (CNN) éprouvé lors de la classification des images.
L'environnement est le même que la dernière fois. Cloud9 Python 2.7.6 Sample Codes : GitHub La construction de l'environnement est «Utiliser TensorFlow dans l'environnement de développement intégré au cloud Cloud9 ~ GetStarted ~» L’utilisation de base de TesorFlow est «Utilisation de TensorFlow dans l’environnement de développement intégré au cloud Cloud9 - Principes d’utilisation-» Voir
Comme la dernière fois, il est divisé en deux par le code de traitement d'apprentissage et le code de prédiction de données manuscrites. Regardons d'abord le code du processus d'apprentissage.
nist_neural_train.py
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
# Define method
def weight_variable(shape, name):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial, name=name)
def bias_variable(shape, name):
initial= tf.constant(0.1, shape=shape)
return tf.Variable(initial, name=name)
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')
# Download gz files to MNIST_data directory
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# Initializing
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, shape=[None, 28*28])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])
W_conv1 = weight_variable([5, 5, 1, 32], name="W_conv1")
b_conv1 = bias_variable([32], name="b_conv1")
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
W_conv2 = weight_variable([5, 5, 32, 64], name="W_conv2")
b_conv2 = bias_variable([64], name="b_conv2")
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
W_fc1 = weight_variable([7 * 7 * 64, 1024], name="W_fc1")
b_fc1 = bias_variable([1024], name="b_fc1")
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)
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
W_fc2 = weight_variable([1024, 10], name="W_fc2")
b_fc2 = bias_variable([10], name="b_fc2")
y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
# Making model
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_conv, y_))
# Training
train_step = tf.train.GradientDescentOptimizer(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, tf.float32))
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})
# Evaluating
#print("test accuracy %g" %accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
# Save train data
saver = tf.train.Saver()
saver.save(sess, 'param/neural.param')
Le flux de base est le même que la dernière fois, mais je vais expliquer la différence.
def weight_variable(shape, name):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial, name=name)
def bias_variable(shape, name):
initial= tf.constant(0.1, shape=shape)
return tf.Variable(initial, name=name)
Définition du processus d'initialisation des paramètres. La dernière fois, il était en fait initialisé avec 0, mais il semble préférable de ne pas être à 0. J'utilise une fonction appelée ReLU, qui est une fonction spéciale avec une pente de 1 lorsqu'il s'agit d'une valeur positive et de 0 lorsqu'il s'agit d'une valeur négative, et pour cette raison, ceux qui ont une petite valeur positive comme valeur initiale Semble être bon.
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')
Convolution (conv2d) et pooling (max_pool_2x2), qui sont les origines du nom du réseau neuronal de convolution. Le traitement détaillé est expliqué ci-dessous.
W_conv1 = weight_variable([5, 5, 1, 32], name="W_conv1")
b_conv1 = bias_variable([32], name="b_conv1")
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
C'est une couche pliante. Parmi les [5, 5, 1, 32] de W_conv1, 5 * 5 représente le patch. Un calque pour capturer les caractéristiques d'une image, qui prend une partie de l'image (5 * 5) et calcule le statut de correspondance avec cette partie pour l'image. Ce faisant, vous pouvez capturer les caractéristiques de l'image. 1 est une entrée et représente une donnée d'image à entrer. 32 est la sortie, et 32 types de patchs captureront les caractéristiques des données d'image.
Le relu de h_conv1 est la fonction ReLU. S'il s'agit d'une valeur négative, c'est 0, si c'est une valeur positive, la pente est 1, c'est-à-dire que c'est une fonction qui utilise la valeur d'entrée telle quelle. Puisque l'inclinaison est de 1, cela empêche la situation où l'inclinaison devient trop petite ou 0 et vous ne pouvez pas apprendre.
h_pool1 est appelé la couche de pooling, et c'est un processus qui agrège la valeur maximale de 4 carrés de 2 * 2 dans l'image en 1 carré. L'image était à l'origine 28 * 28, soit un quart de 14 * 14. Même si les données d'image sont légèrement désalignées, ce sera différent, mais je pense que l'écart peut être absorbé par agrégation par mise en commun. (Je m'excuse si je me trompe)
W_conv2 = weight_variable([5, 5, 32, 64], name="W_conv2")
b_conv2 = bias_variable([64], name="b_conv2")
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
W_fc1 = weight_variable([7 * 7 * 64, 1024], name="W_fc1")
b_fc1 = bias_variable([1024], name="b_fc1")
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)
conv2 ne fait que réimplémenter la couche convolutive décrite ci-dessus. fc1 est juste le même calcul que la dernière fois. Cependant, à h_pool2_flat, le tableau multidimensionnel est converti en une dimension afin que fc1 puisse être calculé.
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
L'abandon signifie que certaines données ne sont pas utilisées avec la probabilité définie par keep_prob. Ce faisant, vous pouvez éviter le surapprentissage (une situation où la précision est élevée dans les données d'entraînement mais pas dans les données de test). J'ai défini la valeur de keep_prob pendant le traitement, mais j'utilise 0,5 pendant l'entraînement et 1,0 (sans abandon) pour la validation avec les données de test.
#print("test accuracy %g" %accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
C'est une partie de vérification avec des données de test, mais elle est commentée. En effet, cloud9 semble manquer de mémoire et une erreur se produit ici. La suppression keep_prob décrite ci-dessus est définie sur 1.0.
Vous pouvez comprendre le traitement ultérieur à partir du contenu expliqué la dernière fois. Lorsque j'ai effectué la formation, cloud9 prenait beaucoup de temps car il était gratuit et avait un processeur et une mémoire insuffisants. Cela prend de quelques heures à une demi-journée. Les paramètres étant sauvegardés, les données suivantes peuvent être prédites immédiatement, mais c'était difficile lorsque l'apprentissage a dû être refait.
Quand j'ai essayé de prédire mes données manuscrites comme avant, c'était 50%. À l'origine, la précision devrait augmenter, mais au contraire, elle diminue. .. .. Je ne sais pas si les données manuscrites sont 1 et 0, ou s'il n'y a que 10 données manuscrites, donc je ne sais pas si cela s'est avéré être éteint, mais j'ai l'impression que ce n'est pas assez bon. ⇒ Un prétraitement était nécessaire pour prédire les données manuscrites. Pour plus de détails, reportez-vous à l'article Prédire vos données manuscrites avec TensorFlow.
mnist_neural.py
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import sys
import numpy as np
import parsebmp as pb
# Define method
def weight_variable(shape, name):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial, name=name)
def bias_variable(shape, name):
initial= tf.constant(0.1, shape=shape)
return tf.Variable(initial, name=name)
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')
def whatisit(file, sess):
print("File name is %s" % file)
data = pb.parse_bmp(file)
# Show bmp data
for i in range(len(data)):
sys.stdout.write(str(int(data[i])))
if (i+1) % 28 == 0:
print("")
# Predicting
d = np.array([data])
x_image = tf.reshape(d, [-1, 28, 28, 1])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
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)
h_fc1_drop = tf.nn.dropout(h_fc1, 1.0)
y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
result = sess.run(y_conv)
# Show result
print(result)
print(np.argmax(result, 1))
if __name__ == "__main__":
# Restore parameters
W = tf.Variable(tf.zeros([28*28, 10]), name="W")
b = tf.Variable(tf.zeros([10]), name="b")
W_conv1 = weight_variable([5, 5, 1, 32], name="W_conv1")
b_conv1 = bias_variable([32], name="b_conv1")
W_conv2 = weight_variable([5, 5, 32, 64], name="W_conv2")
b_conv2 = bias_variable([64], name="b_conv2")
W_fc1 = weight_variable([7 * 7 * 64, 1024], name="W_fc1")
b_fc1 = bias_variable([1024], name="b_fc1")
W_fc2 = weight_variable([1024, 10], name="W_fc2")
b_fc2 = bias_variable([10], name="b_fc2")
sess = tf.InteractiveSession()
saver = tf.train.Saver()
saver.restore(sess, 'param/neural.param')
# My data
whatisit("My_data/0.bmp", sess)
whatisit("My_data/1.bmp", sess)
whatisit("My_data/2.bmp", sess)
whatisit("My_data/3.bmp", sess)
whatisit("My_data/4.bmp", sess)
whatisit("My_data/5.bmp", sess)
whatisit("My_data/6.bmp", sess)
whatisit("My_data/7.bmp", sess)
whatisit("My_data/8.bmp", sess)
whatisit("My_data/9.bmp", sess)
Au début, je ne pouvais pas du tout comprendre, mais j'ai approfondi ma compréhension en étudiant dans divers livres et sur le Web et en implémentant du code. Ensuite, j'aimerais réfléchir au réseau et le mettre en œuvre moi-même.
--2018 / 06/12: Ajout de la prédiction des données manuscrites --2017 / 03/28: Nouveau poste