Y at-il un avantage à utiliser tf.nn.*
plus de tf.layers.*
?
La plupart des exemples de la doc utilisent tf.nn.conv2d
_, par exemple, mais on ne comprend pas pourquoi.
Pour la convolution, ce sont les mêmes. Plus précisément, tf.layers.conv2d
(En réalité _Conv
) Utilise tf.nn.convolution
Comme serveur principal. Vous pouvez suivre la chaîne d’appel de: tf.layers.conv2d>Conv2D>Conv2D.apply()>_Conv>_Conv.apply()>_Layer.apply()>_Layer.\__call__()>_Conv.call()>nn.convolution()...
Comme mentionné par GBY, ils utilisent la même implémentation.
Il y a une légère différence dans les paramètres.
Pour tf.nn.conv2d:
filter: A Tensor. Must have the same type as input. A 4-D tensor of shape [filter_height, filter_width, in_channels, out_channels]
Pour tf.layers.conv2d:
filters: Integer, the dimensionality of the output space (i.e. the number of filters in the convolution).
J'utiliserais tf.nn.conv2d lors du chargement d'un modèle pré-entraîné (exemple de code: https://github.com/ry/tensorflow-vgg16 ), et tf.layers.conv2d pour un modèle formé à partir de rayure.
Comme d'autres l'ont mentionné, les paramètres sont différents, en particulier le "filtre (s)". tf.nn.conv2d prend un tenseur comme filtre, ce qui signifie que vous pouvez spécifier la décroissance du poids (ou peut-être d’autres propriétés) comme ci-dessous dans code cifar1 . (Si vous voulez/avez besoin d'une décroissance du poids dans la couche de conv est une autre question.)
kernel = _variable_with_weight_decay('weights',
shape=[5, 5, 3, 64],
stddev=5e-2,
wd=0.0)
conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')
Je ne suis pas tout à fait sûr de savoir comment définir la décroissance du poids dans tf.layers.conv2d car il ne prend qu'un entier comme filtre. Peut-être en utilisant kernel_constraint
?
D'autre part, tf.layers.conv2d gère l'activation et le biais automatiquement tandis que vous devez écrire des codes supplémentaires pour ceux-ci si vous utilisez tf.nn.conv2d.
Toutes ces autres réponses expliquent en quoi les paramètres sont différents, mais en réalité, la principale différence entre tf.nn et tf.layers conv2d est que, pour tf.nn, vous devez créer votre propre tenseur de filtre et le transmettre. Ce filtre doit avoir la taille de: [kernel_height, kernel_width, in_channels, num_filters]
Jetez un coup d'œil ici: tensorflow> tf.layers.conv2d
et ici: tensorflow> conv2d
Comme vous pouvez le voir, les arguments de la version des couches sont:
tf.layers.conv2d (entrées, filtres, taille du noyau, strides = (1, 1), padding = 'valide', data_format = 'channel_last', dilation_rate = (1, 1), activation = Aucune, use_bias = True, kernel_initializer = Aucune, polarisation_initialiseur = tf.zeros_initializer (), kernel_regularizer = Aucune, polarisation_d'autoriseur = None, activity_regularizer = Aucune, formatable = Vrai, nom = Aucune, réutilisation = Aucune)
et la version nn:
tf.nn.conv2d (entrée, filtre, enjambées, remplissage, use_cudnn_on_gpu = None, data_format = None, name = None)
Je pense que vous pouvez choisir celui avec les options que vous voulez/avez besoin/aimez!
DIFFERENCES DE PARAMETRE:
Utiliser tf.layer * dans un code:
# Convolution Layer with 32 filters and a kernel size of 5
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu)
# Max Pooling (down-sampling) with strides of 2 and kernel size of 2
conv1 = tf.layers.max_pooling2d(conv1, 2, 2)
Utilisation de tf.nn * dans un code: (Notez que nous devons passer les pondérations et les biais en plus en tant que paramètres)
strides = 1
# Weights matrix looks like: [kernel_size(=5), kernel_size(=5), input_channels (=3), filters (= 32)]
# Similarly bias = looks like [filters (=32)]
out = tf.nn.conv2d(input, weights, padding="SAME", strides = [1, strides, strides, 1])
out = tf.nn.bias_add(out, bias)
out = tf.nn.relu(out)