нашел тут некий код для визуализации слоев но никак не могу раскурить его
def layer_to_visualize(layer):
inputs = [K.learning_phase()] + model.inputs
_convout1_f = K.function(inputs, [layer.output])
def convout1_f(X):
# The [0] is to disable the training phase flag
return _convout1_f([0] + [X])
convolutions = convout1_f(img_to_visualize)
насколько я понял K.learning_phase возвращает тензоры для сети ... что дает сложение со входами модели ? и как это вообще работает?
дальнейший код для меня вообще по нулям — кто что и зачем ... не ну както понятно что K.function какимто образом связывает вход с выходом опроеделенного слоя,
но что такое _convout1_f([0] + [X]) для меня вообще непонятно.
пересмотрел книжонки свои — никакого внятного обьяснения, может кто тыкнет пальцем — с чего начинать такой код раскуривать.
Здравствуйте, The Passenger, Вы писали:
...
TP> # The [0] is to disable the training phase flag
TP> return _convout1_f([0] + [X])
...
TP>насколько я понял K.learning_phase возвращает тензоры для сети ... что дает сложение со входами модели ? и как это вообще работает?
TP>дальнейший код для меня вообще по нулям — кто что и зачем ... не ну както понятно что K.function какимто образом связывает вход с выходом опроеделенного слоя,
TP>но что такое _convout1_f([0] + [X]) для меня вообще непонятно.
Это скорее всего broadcasting. Когда складываются два массива/тензора разной длины, то обычно правый растягивается под левый. Но как конкретно это происходит впитоне — хз, может меньший растягивается под больший. Тогда результатом будет тензор X, к которому добавили столбик нулей слева.
Соответственно все, что выше, уже можно попытаться понять.
https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
Это просто лист, первый элемент которого — 0, а второй — массив X
(1) def layer_to_visualize(layer):
(2) inputs = [K.learning_phase()] + model.inputs
(3) _convout1_f = K.function(inputs, [layer.output])
(4) def convout1_f(X):
# The [0] is to disable the training phase flag
(5) return _convout1_f([0] + [X])
(6) convolutions = convout1_f(img_to_visualize)
(1) передается слой, выходы которого интересуют.
(2) создается массив входных данных, в который затем будут заливать данные в п.5. А может, нас интересует только его shape
(3) получаем указатель на функцию, которая сгенерит выход сети , у которой входным параметром является тензор входных данных, а также
указатель на выход нужного слоя.
(4)(5) — вызываем эту самую функцию, которая а) загрузит данные изображения куда-то (возможно, в inputs), а потом прогонит сеть до тех пор, пока
в layer.output не появятся новые данные. Затем она что-то вернет. Возможно, веса layer.output.
Здравствуйте, The Passenger, Вы писали:
TP>TP>def layer_to_visualize(layer):
TP> inputs = [K.learning_phase()] + model.inputs
TP> _convout1_f = K.function(inputs, [layer.output])
TP> def convout1_f(X):
TP> # The [0] is to disable the training phase flag
TP> return _convout1_f([0] + [X])
TP> convolutions = convout1_f(img_to_visualize)
TP>
Я так понимаю, что K тут это tf.keras.backend
Так ли это? Ты же на tf+Keras пытаешься AI двигать, я верно помню?
Смотри, tf -- это библиотека символьных тензорных вычислений.
То есть ты внутри сессии tf создаёшь некий граф вычислений тензоров.
Там могут быть плейсхолдеры переменных и входов этого графа вычислений, и могут быть выходы.
То есть когда ты пишешь на Keras+tf что-то вроде
def my_loss( x, y ) :
return тут какое-то выражение от (x, y)
То x и y тут не сами параметры, а некие ссылки внутрь графа вычислений. Ну например, входные данные, или выходы какого-то слоя или ещё что-то. Когда keras потом использует эту my_loss при компиялции модели, например, он вызывает её от выхода финального слоя и плейсхолдера для gt
В ответ эта функция возвращает тоже не разультат вычислений, а ещё одну ссылку в граф вычислений, на "сток" вычислений этого loss'а
При этом кЕрас всё делает так хитро, что обычно сам тут же получает и как обратно распространять градиенты.
То есть этот граф в кЕрасе получается такой, что можно вперёд прогоняться, а можно обратно распространять.
У флага этого режима есть свой плейсхолдер -- это K.learning_phase()
Ну и когда у нас наконец весь этот граф собран, мы можем попробовать его заставить что-то посчитать (если это не tf, а ph, то там ещё надо компилировать с Си код, описывающий вычисления, так что там ещё сложнее, но я надеюсь, что у тебя таки tf)
У tf есть способы заставить эту штуку считать прямо, но для этого нужно, например, знать сессию, на которой всё происходит, и всякие другие подробности, так как кЕрас это всё инкапсулирует, у него есть способ запустить кусочек изделия.
это функция function и делает. Она просто берёт на вход список плейсхолдеров входов в граф вычислений, которые нужно задать, и список плейсхолдеров стоков выичислений, которые надо получить, в результате расчётов. Предполагается, что этих входов хватит для вычисления этих выходов.
Она по этим входам выходам находит путь в графе вычислений, и отдаёт функцию, которая, получив на вход numpy-данные нужной формы, в ответ отдаёт другие numpy-данные (если я верно помню и там и там списки массивов фигурируют, хотя если тензор один, то может и без списка обходится, лучше в доках глянуть.
Ну и вот,
inputs = [K.learning_phase()] + model.inputs # строит список плейсхолдеров входов. 0-элемент это флажок вперёд или назад мы будем считать, а остальные -- список входов модели.
_convout1_f = K.function(inputs, [layer.output]) # собственно генерит функцию-считалку по вычислительному графу модели
А
def convout1_f(X):
return _convout1_f([0] + [X])
передаёт в _convout1_f список параметров (0-элемент говорит, что прогон прямой, а остальное -- входы модели в том, виде, в кком модели их скармливаешь)
В принципе в конце layer_to_visualize можно просто вернуть convout1_f, и потом вызывать её на тех данных, на каких хочется.
Правда лучше пакетные вызовы делать, конечно, если быстродействие интересует (там у входов выходов кЕрасовских моделей 0-е измерение — номер образца в пакете, можно там не один образец за раз отдавать, а сразу пачку)
Подробнее можно, как ни странно, почитать где-то рядом с тут:
https://www.tensorflow.org/api_docs/python/tf/keras/backend/function
https://www.programcreek.com/python/example/93732/keras.backend.function
Да, если использовать не последовательную кЕрасовскую модель, а обычную, то там можно иметь кучу выходов, например выходы всех слоёв взять.
То есть берёшь обычную или последовательную модель, учишь там, как хочешь,
потом делаешь обычный input, применяешь к нему всю ту модель, как слой, а выходы тех или иных слоёв модели, берёшь в список выходов и от этих входов-выходов генеришь обычную модель.
Ну и потом можешь просто прямой прогон с ней генерить и получать визуализацию всех нужных слоёв сразу...
Удачи. Пиши, что получится. Визуализилка под винду -- это очень позитивно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском