J'essaie de convertir un réseau que j'utilise en utilisant conv2d de tf-slim en utilisant tf.layers.conv2d, car il semble que tf.layers soit l'option la plus prise en charge et la plus évolutive. Les signatures de fonction sont assez similaires, mais y a-t-il quelque chose d'algorithmiquement différent entre les deux? Je reçois des dimensions de tenseur de sortie différentes de celles attendues.
x = tf.layers.conv2d(inputs=x,
filters=256,
kernel_size=[3,3],
trainable=True)
Par opposition à ceci:
x = slim.conv2d(x, 256, 3)
Je reçois des dimensions de tenseur de sortie différentes de celles attendues.
Cela est dû au fait que, par défaut, slim.conv2d utilise le même remplissage alors que tf.layers.conv2d utilise un remplissage valide.
Si vous souhaitez reproduire exactement le même comportement, voici l'implémentation correcte:
x = tf.layers.conv2d(x, 256, 3, padding='same')
Le description du tf.slim
package jette un peu plus de lumière sur les différences: Plus précisément, si vous regardez sous "Calques", les éléments suivants peuvent être trouvés:
Couches
Alors que l'ensemble des opérations TensorFlow est assez étendu, les développeurs de réseaux de neurones pensent généralement aux modèles en termes de concepts de niveau supérieur tels que "couches", "pertes", "métriques" et "réseaux". Une couche, telle qu'une couche convolutionnelle, une couche entièrement connectée ou une couche BatchNorm est plus abstraite qu'une seule opération TensorFlow et implique généralement plusieurs opérations. De plus, une couche est généralement (mais pas toujours) associée à des variables (paramètres ajustables), contrairement aux opérations plus primitives. Par exemple, une couche convolutionnelle dans un réseau de neurones est composée de plusieurs opérations de bas niveau:
- Création des variables de poids et de biais
- Convolution des poids avec l'entrée de la couche précédente
- Ajout des biais au résultat de la convolution.
- Appliquer une fonction d'activation.
En utilisant uniquement du code TensorFlow simple, cela peut être plutôt laborieux:
input = ... with tf.name_scope('conv1_1') as scope: kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32, stddev=1e-1), name='weights') conv = tf.nn.conv2d(input, kernel, [1, 1, 1, 1], padding='SAME') biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32), trainable=True, name='biases') bias = tf.nn.bias_add(conv, biases) conv1 = tf.nn.relu(bias, name=scope)
Pour réduire le besoin de dupliquer ce code à plusieurs reprises, TF-Slim fournit un certain nombre d'opérations pratiques définies au niveau plus abstrait des couches de réseau neuronal. Par exemple, comparez le code ci-dessus à une invocation du code TF-Slim correspondant:
input = ... net = slim.conv2d(input, 128, [3, 3], scope='conv1_1')
En bref, les opérateurs slim
font des abstractions soignées pour vous afin que vous n'ayez pas à vous soucier de tous les détails de TensorFlow - un ajout intéressant si vous me le demandez. Il semble cependant que ce soit encore en développement actif, je voudrais donc en lire un peu plus avant de l'utiliser activement dans le développement (à l'épreuve du temps).