Convertir el modelo Tensorflow al modelo Caffe
(2)
Me gustaría poder convertir un modelo de Tensorflow al modelo de Caffe.
Busqué en Google pero solo pude encontrar convertidores de caffe a tensorflow pero no al contrario.
¿Alguien tiene una idea de cómo hacerlo?
Gracias evi
Como lo sugiere el comentario de @Patwie, debe hacerlo manualmente copiando los pesos capa por capa. Por ejemplo, para copiar los pesos de la primera capa conv desde un punto de control de tensorflow a un modelo de caffl, debe hacer algo como lo siguiente:
sess = tf.Session()
new_saver = tf.train.import_meta_graph("/path/to/checkpoint.meta")
what = new_saver.restore(sess, "/path/to/checkpoint")
all_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)
conv1 = all_vars[0]
bias1 = all_vars[1]
conv_w1, bias_1 = sess.run([conv1,bias1])
net = caffe.Net(''path/to/conv.prototxt'', caffe.TEST)
net.params[''conv_1''][0].data[...] = conv_w1
net.params[''conv_1''][1].data[...] = bias_1
...
net.save(''modelfromtf.caffemodel'')
Nota 1: Este código NO ha sido probado. No estoy seguro de si esto funcionará, pero creo que debería. Además, esto es solo para una capa conv. En la práctica, primero debe analizar el punto de control de tensorflow para verificar qué pesos de capa están en qué índice (imprimir todos los valores ) y luego copiar los pesos de cada capa individualmente.
Nota2: Se puede hacer algo de automatización iterando sobre las capas conv iniciales, ya que generalmente siguen un patrón establecido (conv1-> bn1-> relu1-> conv2-> bn2-> relu2 ...)
Nota 3: Tensorflow puede dividir aún más los pesos de cada capa en índices separados. Por ejemplo: los pesos y los sesgos se separan para una capa conv como se muestra arriba. Además, gamma , media y varianza se separan para la capa de normalización de lotes.
He tenido el mismo problema y he encontrado una solución. El código se puede encontrar aquí ( https://github.com/lFatality/tensorflow2caffe ) y también he documentado el código en algunos videos de Youtube.
La Parte 1 cubre la creación de la arquitectura de VGG-19 en Caffe y tflearn (la API de nivel superior para TensorFlow, con algunos cambios en el código nativo TensorFlow también debería funcionar).
En la Parte 2, se describe la exportación de los pesos y sesgos del modelo TensorFlow a un archivo numpy. En tflearn puedes obtener los pesos de una capa como esta:
#get parameters of a certain layer
conv2d_vars = tflearn.variables.get_layer_variables_by_name(layer_name)
#get weights out of the parameters
weights = model.get_weights(conv2d_vars[0])
#get biases out of the parameters
biases = model.get_weights(conv2d_vars[1])
Para una capa convolucional, layer_name es Conv_2D
. Las capas totalmente conectadas se llaman FullyConnected
. Si usa más de una capa de un determinado tipo, se usa un entero Conv_2D_1
con un subrayado anterior (por ejemplo, la segunda capa conv se llama Conv_2D_1
). He encontrado estos nombres en la gráfica del TensorBoard. Si nombra las capas en la definición de su arquitectura, estos nombres de capa podrían cambiar a los nombres que definió.
En TensorFlow nativo, la exportación necesitará un código diferente, pero el formato de los parámetros debe ser el mismo, por lo que los pasos posteriores deben seguir siendo aplicables.
La parte 3 cubre la conversión real. Lo que es crítico es la conversión de los pesos cuando se crea el modelo de caffem (los sesgos se pueden llevar a cabo sin cambios). TensorFlow y Caffe utilizan diferentes formatos al guardar un filtro. Mientras TensorFlow usa [height, width, depth, number of filters]
( documentos de TensorFlow, en la parte inferior ), Caffe usa [number of filters, depth, height, width]
( documentos de Caffe, capítulo ''Almacenamiento y comunicación de blobs'' ). Para convertir entre los formatos, puede utilizar la función de transpose
(por ejemplo: weights_of_first_conv_layer.transpose((3,2,0,1))
. La secuencia 3,2,0,1 se puede obtener al enumerar el formato TensorFlow (origen) y luego cambiarlo al formato Caffe (formato de destino) mientras se mantienen los números en su variable específica.
Si desea conectar una salida de tensor a una capa completamente conectada, las cosas se ponen un poco difíciles. Si usa VGG-19 con un tamaño de entrada de 112x112, se verá así.
fc1_weights = data_file[16][0].reshape((4,4,512,4096))
fc1_weights = fc1_w.transpose((3,2,0,1))
fc1_weights = fc1_w.reshape((4096,8192))
Lo que obtiene de TensorFlow si exporta los parámetros en la conexión entre el tensor y la capa totalmente conectada es una matriz con la forma [entries in the tensor, units in the fc-layer]
(aquí: [8192, 4096]
). Debe averiguar cuál es la forma de su tensor de salida y luego cambiar la forma de la matriz para que se ajuste al formato TensorFlow (ver arriba, la number of filters
es la number of units in the fc-layer
). Después de eso, utiliza la conversión de transposición que ha usado anteriormente y luego vuelve a dar forma a la matriz, pero al revés. Mientras TensorFlow guarda los pesos de la capa fc como [number of inputs, number of outputs]
, Caffe lo hace al revés.
Si conecta dos capas fc entre sí, no tiene que realizar el complejo proceso descrito anteriormente, pero tendrá que tener en cuenta los diferentes formatos de capa fc mediante la transposición de nuevo ( fc_layer_weights.transpose((1,0))
)
A continuación, puede configurar los parámetros de la red utilizando
net.params[''layer_name_in_prototxt''][0].data[...] = weights
net.params[''layer_name_in_prototxt''][1].data[...] = biases
Esta fue una visión general rápida Si quieres todo el código, está en mi repositorio github. Espero que ayude. :)
Aclamaciones,
Fatalidad