Официально предоставляемая Tensorflow Tensorboard умеет визуализировать схему структуры нейронной сети, но, честно говоря, я ей почти не пользуюсь. Главным образом потому, что структура графа, просматриваемая в Tensorboard, слишком хаотична, включая все вычислительные узлы в сети (узлы чтения данных, сетевые узлы, вычислительные узлы потерь и т. д.). Что еще более пугает, так это то, что если вычислительный узел состоит из нескольких базовых вычислений (таких как сложение, вычитание, умножение и деление и т. д.), базовый вычислительный узел будет отображаться в Tensorboard вместо того, чтобы отображаться как единое целое (как правило, Сожмите вычислительный узел). В последнее время на устранение BUG структуры сети ушла неделя, поэтому я решил сам написать инструмент для отображения самой критической структуры сети самым простым способом на графике в Tensorflow.
1 объект тензора и объект операции
В Tensorflow объекты Tensor в основном используются для хранения данных, таких как константы и переменные (параметры обучения), а объекты Operation — это вычислительные узлы, такие как вычисления свертки, вычисления деконволюции, ReLU и т. д. Каждый объект операции имеет входные и выходные тензоры.Точно так же каждый объект тензора имеет объект операции, который генерирует тензор, и объект операции, который использует объект тензора в качестве входных данных. В объектах Tensor и Operation есть связанные свойства и функции для получения связанных с ними объектов Operation и Tensor.
Атрибут op объекта Tensor указывает на объект Operation, сгенерировавший Tensor. Функция Consumers() объекта Tensor получает объект Operation, который использует объект Tensor в качестве входных данных. Свойство inputs объекта Operation указывает на входной объект Tensor вычислительного узла. Свойство outputs объекта Operation выполняет выходной объект Tensor этого вычислительного узла.
В структуре сети, показанной на рисунке ниже, вызовитеTensor_2
объектconsumers()
функция, которая возвращает[op_1,op_2]
.Tensor_3
Атрибут op указывает наop_1
.op_1
Свойство inputs указывает на[Tensor_1,Tensor_2]
,op_1
Выходной атрибут указывает на[Tensor_3]
.
Имея на графике взаимосвязь между тензором и операцией, можно нарисовать структуру сети.
2 Извлеките диаграмму структуры сети из pb-файла.
Файл pb представляет собой файл протокола protobuf, полученный путем закрепления параметров модели в графическом файле, объединения некоторых основных вычислений и удаления вычислений, связанных с обратным распространением. Если читатели не знают, как преобразовать файлы моделей CKPT в файлы pb, обратитесь к другой моей статье.«Tensorflow MobileNet портирован на Android»Часть 1 раздела 1. Следующим шагом после получения файла модели pb является загрузка модели.Пример кода для загрузки модели pb показан ниже.
def read_graph_from_pb(tf_model_path ,input_names,output_name):
with open(tf_model_path, 'rb') as f:
serialized = f.read()
tf.reset_default_graph()
gdef = tf.GraphDef()
gdef.ParseFromString(serialized)
with tf.Graph().as_default() as g:
tf.import_graph_def(gdef, name='')
with tf.Session(graph=g) as sess:
OPS=get_ops_from_pb(g,input_names,output_name)
return OPS
Среди них функция, вызываемая предпоследней строкойget_ops_from_pb()
Используется для получения вычислительных узлов между указанным входным узлом и указанным выходным узлом на диаграмме структуры сети. Причина указания ввода и вывода состоит в том, чтобы удалить вычислительные узлы перед вводом (например, связанные вычислительные узлы, такие как загрузка очередей данных) и вычислительные узлы после вывода (например, вычислительные потери и другие связанные вычислительные узлы), чтобы чтобы не быть бельмом на глазу. функцияget_ops_from_pb()
Код реализации выглядит следующим образом.
def get_ops_from_pb(graph,input_names,output_name,save_ori_network=True):
if save_ori_network:
with open('ori_network.txt','w+') as w:
OPS=graph.get_operations()
for op in OPS:
txt = str([v.name for v in op.inputs])+'---->'+op.type+'--->'+str([v.name for v in op.outputs])
w.write(txt+'\n')
inputs_tf = [graph.get_tensor_by_name(input_name) for input_name in input_names]
output_tf =graph.get_tensor_by_name(output_name)
OPS =get_ops_from_inputs_outputs(graph, inputs_tf,[output_tf] )
with open('network.txt','w+') as w:
for op in OPS:
txt = str([v.name for v in op.inputs])+'---->'+op.type+'--->'+str([v.name for v in op.outputs])
w.write(txt+'\n')
OPS = sort_ops(OPS)
OPS = merge_layers(OPS)
return OPS
Прежде чем обрезать сетевую структуру (то есть оставить только узлы между input_names и output_name), сначала запишите исходную сетевую структуру вori_network.txt
, в файле каждая строка пишет:输入Tensor---->op---->输出Tensor
. Далее вызовите функциюget_ops_from_inputs_outputs
Получить узлы между указанными узлами. и позвониsort_ops
Функция сортирует все узлы, чтобы гарантировать, что зависимые узлы всегда появляются перед зависимыми узлами. последний звонокmerge_layers
функция для объединения некоторых вычислений, которые можно объединить в один узел, например,Squeeze
Узлы, связанные с вычислениями, объединяются в один узел Squeeze, как вconst-->identity
Два вычислительных узла можно игнорировать (т. е. удалять) напрямую.
Примечание: место ограничено, и функция здесь больше не используется.get_ops_from_inputs_outputs
,sort_ops
,merge_layers
Разместите его, пожалуйста, перейдите по адресу исходного кода, указанному в конце статьи, чтобы прочитать соответствующий код.
3 Рисование структуры сети
учитываяSVG
Простота использования преимущества рисования графиков, позволит сортировать сетевые вычислительные узлы и связанные с нимиTensor
Данные объекта начинаются сJavascript
записывается как строка дляHTML
в использовании<line>
ярлык для рисования стрелок, используйте<rect>
label, чтобы нарисовать прямоугольник, используйте<ellipse>
метка, чтобы нарисовать эллипс, используйте<text>
Метки отображают текст. Нарисуйте изображение, подобное показанному ниже
Примечание: место ограничено, и принципы, связанные со структурой модели синтаксического анализа кода Javascript и отображением SVG, здесь не представлены.Пожалуйста, ознакомьтесь с соответствующим кодом по адресу исходного кода, указанному в конце статьи.
4 Отображение тестовой модели
от«Использование официальной модели предварительного обучения MobileNet V1»Возьмите в качестве примера структуру сети MobileNet V1, представленную в статье, загрузитеMobileNet_v1_1.0_192
файл и сжать его, получитьmobilenet_v1_1.0_192_frozen.pb
документ. нам еще нужно знатьmobilenet_v1_1.0_192_frozen.pb
Соответствующий вход и выход моделиTensor
название предмета, к счастьюMobileNet_v1_1.0_192
zip-файл содержит файлыmobilenet_v1_1.0_192_info.txt
. Из этого файла видно, что вводTensor
называется:input:0
, выходное имя тензора:MobilenetV1/Predictions/Reshape_1:0
. С этой информацией вызовите функциюread_graph_from_pb
Получите операции объекта списка узлов статического графа и вызовите функциюgen_graph(ops,"save/path/graph.html")
После этого в каталогеsave/path
Залезайgraph.html
файл, открытьgraph.html
После этого результат отображения выглядит следующим образом.
Структура сети отображения разделена на два режима: режим слияния и режим расширения, как показано на следующих рисунках.