Je suis novice en tensorflow pour l'apprentissage en profondeur et je m'intéresse aux opérations de déconvolution (transposition par convolution) dans tensorflow. Je dois jeter un œil au code source pour opérer la déconvolution. La fonction est je suppose conv2d_transpose () dans nn_ops.py .
Cependant, dans la fonction, il appelle une autre fonction appelée gen_nn_ops.conv2d_backprop_input()
. Je dois jeter un œil à ce qui se trouve à l'intérieur de cette fonction, mais je ne parviens pas à le trouver dans le référentiel. Toute aide serait appréciée.
Vous ne pouvez pas trouver cette source car la source est automatiquement générée par bazel. Si vous construisez à partir des sources, vous verrez ce fichier dans bazel-genfiles
. Il est également présent dans votre distribution locale que vous pouvez trouver en utilisant le module inspect
. Le fichier contient des enveloppes Python générées automatiquement pour les implémentations C++ sous-jacentes, donc il se compose essentiellement d'un tas de fonctions de 1 ligne. Un raccourci pour trouver l'implémentation C++ sous-jacente de ces Python op est de convertir l'étui à serpent en étui à chameau, c'est-à-dire conv2d_backprop_input
-> Conv2dBackpropInput
# figure out where gen_nn_ops is
print(tf.nn.conv2d_transpose.__globals__['gen_nn_ops'])
from tensorflow.python.ops import gen_nn_ops
import inspect
inspect.getsourcefile('gen_nn_ops.conv2d_backprop_input')
'/Users/yaroslav/anaconda/lib/python3.5/site-packages/tensorflow/python/ops/gen_nn_ops.py'
Si vous souhaitiez découvrir comment ce fichier a réellement vu le jour, vous pouvez suivre la trace des dépendances bazel dans les fichiers BUILD
. Pour trouver la cible Bazel qui l'a générée à partir de l'arbre source tensorflow:
fullname=$(bazel query tensorflow/python/ops/gen_nn_ops.py)
bazel query "attr('srcs', $fullname, ${fullname//:*/}:*)"
//tensorflow/python:nn_ops_gen
Alors maintenant, allons dans le fichier BUILD
dans tensorflow/python
vous voyez qu'il s'agit d'une cible de type tf_gen_op_wrapper_private_py
qui est défini ici et appelle gen_op_wrapper_py
de tensorflow/tensorflow.bzl
qui ressemble à ceci
def tf_gen_op_wrapper_py(name, out=None, hidden=None, visibility=None, deps=[],
....
native.cc_binary(
name = tool_name,
Cette native.cc_binary
construct est un moyen d'avoir une cible Bazel qui représente l'exécution d'une commande arbitraire. Dans ce cas, il appelle tool_name
avec quelques arguments. Avec quelques étapes supplémentaires, vous pouvez trouver que "l'outil" ici est compilé à partir de framework/python_op_gen_main.cc
La raison de cette complication est que TensorFlow a été conçu pour être indépendant du langage. Donc, dans le monde idéal, vous auriez chaque opération décrite dans ops.pbtxt , puis chaque opération aurait une implémentation par type de matériel en utilisant REGISTER_KERNEL_BUILDER
, donc toutes les implémentations se feraient en C++/CUDA/Assembly et deviendraient automatiquement disponibles pour tous les frontaux du langage. Il y aurait un traducteur équivalent comme "python_op_gen_main" pour chaque langue et tout le code de la bibliothèque client serait généré automatiquement. Cependant, parce que Python est tellement dominant, il y avait une pression pour ajouter des fonctionnalités du côté Python. Il y a donc maintenant deux types d'opérations - les opérations TensorFlow pures) vu dans des fichiers comme gen_nn_ops.py
, et opérations Python uniquement dans des fichiers comme nn_ops.py
qui encapsule généralement les fichiers générés automatiquement par les opérations gen_nn_ops.py
mais ajoutez des fonctionnalités/sucre de syntaxe supplémentaires. De plus, à l'origine, tous les noms étaient camel-case, mais il a été décidé que la version publique devrait être conforme à PEP avec une syntaxe plus courante Python, c'est donc une raison pour camel-case/snake-case non concordance entre les interfaces C++/Python du même op
Malheureusement, le code TensorFlow n'est pas facile à lire :(
Pour accélérer les choses, le code python doit entrelacer du code C++, qui utilise également des dépendances indirectes.
gen_X
les fonctions sont générées à partir de leur code C++; pour le trouver, vous devez rechercher Conv2dBackpropInput
.
Vous pouvez trouver l'enregistrement de l'op du noyau dans ops/nn_ops.cc et l'implémentation concrète dans kernels/conv_grad_input_ops.cc .
Ce fichier est généré lorsque vous générez Tensorflow. Après avoir créé la source Tensorflow, vous devriez voir un fichier de lien symbolique nommé "bazel-genfiles" dans le répertoire racine tensorflow, et allez à l'emplacement qu'il pointe, puis vous pouvez le trouver sur tensorflow/python/ops/gen_nn_ops.py