Existe-t-il une fonction native TensorFlow qui désutilise les réseaux déconvolutionnels?
J'ai écrit cela en python normal, mais cela devient compliqué lorsque vous voulez le traduire en TensorFlow car ses objets ne prennent même pas en charge l'attribution d'éléments pour le moment, et je pense que c'est un grand inconvénient avec TF.
Je ne pense pas qu'il existe encore une couche de désengagement officielle, ce qui est frustrant car vous devez utiliser le redimensionnement de l'image (interpolation bilinéaire ou voisin le plus proche), ce qui est comme une opération de désengagement moyenne et c'est vraiment lent. Regardez l'api tf dans la section 'image' et vous le trouverez.
Tensorflow a un truc maxpool_with_argmax où vous obtenez votre sortie maxpooled ainsi que la carte d'activation qui est sympa car vous pouvez l'utiliser dans une couche de désengagement pour préserver les informations spatiales `` perdues '' mais il semble qu'il n'y ait pas une telle opération de désengagement qui le fait. Je suppose qu'ils prévoient de l'ajouter ... bientôt.
Edit: J'ai trouvé un gars sur google discuter il y a une semaine qui semble avoir implémenté quelque chose comme ça, mais personnellement je ne l'ai pas encore essayé. https://github.com/ppwwyyxx/tensorpack/blob/master/tensorpack/models/pool.py#L66
Il y a quelques implémentations tensorflow ici pooling.py
À savoir:
1) opération de dissociation ( source ) qui utilise la sortie de tf.nn.max_pool_with_argmax
. Bien que veuillez noter que depuis tensorflow 1.0 tf.nn.max_pool_with_argmax
est uniquement GPU
2) opération de suréchantillonnage qui imite l'inverse du regroupement maximal en remplissant les positions de la région non regroupée avec des zéros ou des copies de l'élément max. Comparé à tensorpack il permet des copies d'éléments au lieu de zéros et supporte des pas autres que [2, 2]
.
Pas de recompilation, back-prop friendly.
Je cherchais une opération de désengagement max et j'ai essayé de l'implémenter. J'ai trouvé une sorte de implémentation hacky pour le gradient , car je luttais avec CUDA.
Le code est ici , vous devrez le construire à partir des sources avec le support GPU. Vous trouverez ci-dessous une application de démonstration. Aucune garantie, cependant!
Il existe également un problème ouvert pour cette opération.
import tensorflow as tf
import numpy as np
def max_pool(inp, k=2):
return tf.nn.max_pool_with_argmax_and_mask(inp, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding="SAME")
def max_unpool(inp, argmax, argmax_mask, k=2):
return tf.nn.max_unpool(inp, argmax, argmax_mask, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding="SAME")
def conv2d(inp, name):
w = weights[name]
b = biases[name]
var = tf.nn.conv2d(inp, w, [1, 1, 1, 1], padding='SAME')
var = tf.nn.bias_add(var, b)
var = tf.nn.relu(var)
return var
def conv2d_transpose(inp, name, dropout_prob):
w = weights[name]
b = biases[name]
dims = inp.get_shape().dims[:3]
dims.append(w.get_shape()[-2]) # adpot channels from weights (weight definition for deconv has switched input and output channel!)
out_shape = tf.TensorShape(dims)
var = tf.nn.conv2d_transpose(inp, w, out_shape, strides=[1, 1, 1, 1], padding="SAME")
var = tf.nn.bias_add(var, b)
if not dropout_prob is None:
var = tf.nn.relu(var)
var = tf.nn.dropout(var, dropout_prob)
return var
weights = {
"conv1": tf.Variable(tf.random_normal([3, 3, 3, 16])),
"conv2": tf.Variable(tf.random_normal([3, 3, 16, 32])),
"conv3": tf.Variable(tf.random_normal([3, 3, 32, 32])),
"deconv2": tf.Variable(tf.random_normal([3, 3, 16, 32])),
"deconv1": tf.Variable(tf.random_normal([3, 3, 1, 16])) }
biases = {
"conv1": tf.Variable(tf.random_normal([16])),
"conv2": tf.Variable(tf.random_normal([32])),
"conv3": tf.Variable(tf.random_normal([32])),
"deconv2": tf.Variable(tf.random_normal([16])),
"deconv1": tf.Variable(tf.random_normal([ 1])) }
## Build Miniature CEDN
x = tf.placeholder(tf.float32, [12, 20, 20, 3])
y = tf.placeholder(tf.float32, [12, 20, 20, 1])
p = tf.placeholder(tf.float32)
conv1 = conv2d(x, "conv1")
maxp1, maxp1_argmax, maxp1_argmax_mask = max_pool(conv1)
conv2 = conv2d(maxp1, "conv2")
maxp2, maxp2_argmax, maxp2_argmax_mask = max_pool(conv2)
conv3 = conv2d(maxp2, "conv3")
maxup2 = max_unpool(conv3, maxp2_argmax, maxp2_argmax_mask)
deconv2 = conv2d_transpose(maxup2, "deconv2", p)
maxup1 = max_unpool(deconv2, maxp1_argmax, maxp1_argmax_mask)
deconv1 = conv2d_transpose(maxup1, "deconv1", None)
## Optimizing Stuff
loss = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(deconv1, y))
optimizer = tf.train.AdamOptimizer(learning_rate=1).minimize(loss)
## Test Data
np.random.seed(123)
batch_x = np.where(np.random.Rand(12, 20, 20, 3) > 0.5, 1.0, -1.0)
batch_y = np.where(np.random.Rand(12, 20, 20, 1) > 0.5, 1.0, 0.0)
prob = 0.5
with tf.Session() as session:
tf.set_random_seed(123)
session.run(tf.initialize_all_variables())
print "\n\n"
for i in range(10):
session.run(optimizer, feed_dict={x: batch_x, y: batch_y, p: prob})
print "step", i + 1
print "loss", session.run(loss, feed_dict={x: batch_x, y: batch_y, p: 1.0}), "\n\n"
Modifier le 29.11.17
Il y a quelque temps, je l'ai réimplémenté de manière propre contre TensorFlow 1.0, les opérations avancées sont également disponibles en version CPU. Vous pouvez le trouver dans cette branche , je vous recommande de rechercher les derniers commits si vous voulez l'utiliser.