[PYTHON] J'ai réfléchi un peu à l'API grandissante de TensorFlow

Intro

Enfin, TensorFLow 1.0 a été annoncé lors du TensorFlow Dev Summit. Il est question d'une version de test du compilateur Graph XLA, mais personnellement, je me demandais quelle serait la configuration API (Application Programming Interface) de TensorFlow.

(Extrait du blog Google Developers "Announcing TensorFlow 1.0".)

  • Higher-level API modules tf.layers, tf.metrics, and tf.losses - brought over from tf.contrib.learn after incorporating skflow and TF Slim

Récemment, je m'attendais à ce que la version 1.0 voie comment l'API de haut niveau, qui montrait beaucoup de problèmes, serait organisée, alors j'ai un peu étudié la situation.

Code du modèle CNN ancien

Auparavant, lorsque je travaillais avec le modèle CNN (Convolutional Neural Network) dans une situation où il n'y avait pas beaucoup d'API de haut niveau, j'ai préparé ma propre classe et codé comme suit.

#   my_lib_nn.py
#Par exemple...  Convolution 2-D Layer
class Convolution2D(object):
    '''
      constructor's args:
          input     : input image (2D matrix)
          input_siz ; input image size
          in_ch     : number of incoming image channel
          out_ch    : number of outgoing image channel
          patch_siz : filter(patch) size
          weights   : (if input) (weights, bias)
    '''
    def __init__(self, input, input_siz, in_ch, out_ch, patch_siz, activation='relu'):
        self.input = input      
        self.rows = input_siz[0]
        self.cols = input_siz[1]
        self.in_ch = in_ch
        self.activation = activation
        
        wshape = [patch_siz[0], patch_siz[1], in_ch, out_ch]
                w_cv = tf.Variable(tf.truncated_normal(wshape, stddev=0.1), 
                            trainable=True)
        b_cv = tf.Variable(tf.constant(0.1, shape=[out_ch]), 
                            trainable=True)
        self.w = w_cv
        self.b = b_cv
        self.params = [self.w, self.b]
        
    def output(self):
        shape4D = [-1, self.rows, self.cols, self.in_ch]
        
        x_image = tf.reshape(self.input, shape4D)  # reshape to 4D tensor
        linout = tf.nn.conv2d(x_image, self.w, 
                  strides=[1, 1, 1, 1], padding='SAME') + self.b
        if self.activation == 'relu':
            self.output = tf.nn.relu(linout)
        elif self.activation == 'sigmoid':
            self.output = tf.sigmoid(linout)
        else:
            self.output = linout
        
        return self.output

La fonction de tf.nn.xxx () est utilisée comme bibliothèque de sous-traitance, mais c'est une méthode de création et d'utilisation d'un wrapper qui le rend facile à utiliser. Il est facile de personnaliser votre propre bibliothèque, mais vous devez effectuer vous-même la maintenance détaillée à cause de cela. (Ce n'est pas une grande bibliothèque, mais ...)

Après avoir connu ** Keras **, j'ai choisi «Dois-je utiliser Keras?», Mais en tenant compte de la familiarité, de la facilité de débogage détaillé et de la flexibilité, de nombreux styles de codage utilisaient directement la bibliothèque TensorFlow.

TensorFlow Slim vs. tf.layers

"Slim" était au centre de l'attention du point de vue du "Wapper Tensor Flow mince". Il semble que certains cas aient été repris à Qiita. Le code pour classer MNIST à l'aide de ceci est le suivant.

import numpy as np
import tensorflow as tf
import tensorflow.contrib.slim as slim
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("../MNIST_data/", one_hot=True)

# Create the model
def my_nn(images, keep_prob):
   net = slim.layers.conv2d(images, 32, [5,5], scope='conv1')
   net = slim.layers.max_pool2d(net, [2,2], scope='pool1')
   net = slim.layers.conv2d(net, 64, [5,5], scope='conv2')
   net = slim.layers.max_pool2d(net, [2,2], scope='pool2')
   net = slim.layers.flatten(net, scope='flatten3')
   net = slim.layers.fully_connected(net, 1024, scope='fully_connected4')
   net = slim.layers.dropout(net, keep_prob)
   net = slim.layers.fully_connected(net, 10, activation_fn=None, 
                                        scope='fully_connected5')
   return net

def inference(x, y_, keep_prob):
    x_image = tf.reshape(x, [-1, 28, 28, 1])
    y_pred = my_nn(x_image, keep_prob)

    slim.losses.softmax_cross_entropy(y_pred, y_)
    total_loss = slim.losses.get_total_loss()
    correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.argmax(y_, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    
    return total_loss, accuracy, y_pred

Le modèle de réseau Nueral peut être écrit dans un code court d'une manière facile à comprendre. De plus, comme utilisé dans la fonction "inférence", la fonction de perte pourrait être écrite avec l'API slim. J'ai eu l'impression que c'était assez simple d'utilisation.

Ensuite, cette fois, j'ai examiné le module ** tf.layers ** préparé par TensorFlow 1.0. Il y avait une bonne explication dans le document API, donc j'ai codé en référence.

** De la Fig. Document de l'API TensorFlow (extrait de l'image) ** Module_tf_layers.png

Comme mentionné dans l'extrait de l'annonce Google ci-dessus, ** tf.contrib.layers ** est également mentionné dans le document, mais cette fois ** tf.layers ** est différent, alors soyez prudent.

Ce qui suit est le code CNN utilisant ** tf.layers **.

import tensorflow as tf
from tensorflow.python.layers import layers
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("../MNIST_data/", one_hot=True)

# Create the model
def my_nn(images, drop_rate):
   net = tf.layers.conv2d(images, 32, [5,5], padding='same', 
                                activation=tf.nn.relu, name='conv1')
   net = tf.layers.max_pooling2d(net, pool_size=[2,2], strides=[2,2], 
                                name='pool1')
   net = tf.layers.conv2d(net, 64, [5,5], padding='same', 
                                activation=tf.nn.relu, name='conv2')
   net = tf.layers.max_pooling2d(net, pool_size=[2,2], strides=[2,2], 
                                name='pool2')
   net = tf.reshape(net, [-1, 7*7*64])
   net = tf.layers.dense(net, 1024, activation=tf.nn.relu, name='dense1')
   net = tf.layers.dropout(net, rate=drop_rate)
   net = tf.layers.dense(net, 10, activation=None, name='dense2')
   return net

def inference(x, y_, keep_prob):
    x_image = tf.reshape(x, [-1, 28, 28, 1])
    drop_rate = 1.0 - keep_prob
    y_pred = my_nn(x_image, drop_rate)
    
    loss = tf.losses.softmax_cross_entropy(y_, y_pred)
    correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.argmax(y_, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    
    return loss, accuracy, y_pred
 

Au début, j'ai commencé avec le code slim avec le préjugé que ce serait quelque chose comme slim, mais j'étais confus car il y avait une différence surprenante dans les spécifications des fonctions. (Faites attention au code de la fonction "my_nn ()".)

En supposant que différents noms de fonction (max_pool2d <-> max_ Covoiturage2d, Fully_connected <-> dense) sont acceptés comme "communs", des ajustements fins étaient nécessaires, tels que différents mots-clés d'argument et différentes valeurs par défaut d'argument. .. Comme point particulièrement préoccupant (impardonnable), en tant que paramètre Dropout, la spécification qui donne le rapport "keep_prob" qui laisse l'influence de l'unité après le traitement a été modifiée en spécification qui donne le rapport pour omettre (supprimer) l'effet. C'est le point. (En guise de contre-mesure, j'ai mis une ligne de drop_rate = 1.0 --keep_prob.) C'est peut-être un point qui est divisé selon la" préférence "du programmeur, mais je voulais que vous considériez la compatibilité avec le passé ...

Cela ne signifiait pas que l'API TensorFlow était organisée et ordonnée, et j'avais l'impression que les spécifications actuelles étaient un peu décevantes.

Que devrais-je faire?

Compte tenu de la situation ci-dessus, je vais vous donner quelques options.

--Attendez ** Keras2 ** en préparation. Étant donné que le nombre d'utilisateurs est important, on s'attend à ce que la sophistication de l'API soit continuellement améliorée. Compte tenu du fait qu'il vient d'apparaître, nous prévoyons que ** tf.layers **, ** tf.metrics **, ** tf.losses ** seront plus complets à l'avenir. (Parce qu'il est open source, il est préférable de dire activement "c'est mieux" sur GitHub.)

Puisque les «préférences» sont souvent reflétées dans des détails tels que les paramètres d'abandon (rapport restant ou taux de rejet), je pense qu'il est inévitable de trop s'inquiéter de «quelle est la meilleure API». Cette fois, je me suis concentré sur les fonctions CNN qui gèrent les images, mais compte tenu des capacités de modélisation flexibles du Deep Learning (par exemple, RNN et modèles de génération), je ne me souciais pas des détails de l'API (le cas échéant). Il peut être plus constructif de suivre un large éventail de contenus techniques (tout en les utilisant correctement).

(Si vous avez des opinions ou des conseils, veuillez commenter.) (L'environnement de programmation au moment de la rédaction est le suivant: Python 3.5.2, TensorFlow 1.0.0)

Références, site Web

Recommended Posts

J'ai réfléchi un peu à l'API grandissante de TensorFlow
Un peu plus sur le FIFO
J'ai pensé à un cours pour débutants sur Python basé sur des jeux blockchain
J'ai une question sur les blancs
Après avoir fait des recherches sur la bibliothèque Python, j'ai un peu compris egg.info.
J'ai créé une API Web
[PyTorch] J'étais un peu perdu dans torch.max ()
J'ai fait un peu de recherche sur la classe
Création du wrapper d'API Qiita Python "qiipy"
J'ai réfléchi à la raison pour laquelle Python self est nécessaire avec le sentiment d'un interpréteur Python
Un peu d'informations addictives sur Cliff, le framework CLI
Dessine un graphique avec Julia ... j'ai essayé une petite analyse
J'ai réfléchi à la façon d'apprendre la programmation gratuitement.
[python] [Gracenote Web API] Une petite personnalisation de pygn
Une note de ce que j'ai appris quand j'ai pensé à utiliser pyenv ou virtualenv sous Windows
J'ai réfléchi un peu car Trace Plot du paramètre de stan est difficile à voir
TensorFlow change-t-il l'image de l'apprentissage profond? Ce que j'ai pensé après avoir touché un peu