Реализация графа тензорного потока в модели Кераса

Я пытаюсь реализовать примерно следующую архитектуру в Keras (желательно) или Tensorflow.

          ___________      _________      _________     ________    ______
          | Conv    |     | Max    |     | Dense  |    |       |   |     |
Input0--> | Layer 1 | --> | Pool 1 | --> | Layer  | -->|       |   |     |
          |_________|     |________|     |________|    | Sum   |   | Out |
                                                       | Layer |-->|_____|
Input1    ----------- Converted to trainable weights-->|       |              
                                                       |_______|                                                                               |_______|

Короче говоря, это в значительной степени модель с двумя входами, объединенными в один выход с помощью слоя Add ([input0, input1]). Хитрость в том, что один из входных параметров должен рассматриваться как переменная = обучаемый вес.

Слой Keras Add () не позволяет этого, и он принимает input0 и input1 как необучаемые переменные:

input0    = Input((28,28,1))
x         = Conv2D(32, kernel_size=(3, 3), activation='relu',input_shape=input_shape)(mod1)
x         = Conv2D(64, (3, 3), activation='relu')(input0)
x         = MaxPooling2D(pool_size=(2, 2))(x)
x         = Flatten()(x)
x         = Dense(128, activation='relu')(x)

input1    = Input((128,))

x         = Add()([x, input1])
x         = Dense(num_classes, activation='softmax')(x)
model     = Model(inputs = [mod1,TPM], outputs = x)
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Я могу реализовать граф в тензорном потоке, который добавляет заполнитель X с весом b и изучает значение b по отношению к цели Y.

train_X = numpy.asarray([1.0, 2.0])
train_Y = numpy.asarray([0.0, 2.5])
n_samples = train_X.shape[0]

# tf Graph Input
X = tf.placeholder("float")
Y = tf.placeholder("float")

# Set model weights
b = tf.Variable([0.0, 0.0], name = "bias")

# Construct a linear model
pred = tf.add(X, b)

loss = tf.reduce_mean(tf.square(pred - train_Y))
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
grads_and_vars = optimizer.compute_gradients(loss)

train = optimizer.apply_gradients(grads_and_vars)
#init = tf.initialize_all_variables()
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

for step in range(epochs):
    sess.run(train, feed_dict = {X: train_X, Y: train_Y})

Работает именно так, как я хочу. Простое оптимизируемое сложение входа и весов. Но я не могу включить это в модель Кераса, мне не хватает шага, как объединить обе идеи.

Как я могу включить слой, который суммирует только один обучаемый тензор с необучаемым тензором?

Похоже, вы хотите инициализировать переменную, которая будет добавлена ​​к выходным данным вашего первого плотного слоя. Звучит похоже (хотя и не совсем то же самое), чтобы просто инициализировать смещение вашего первого плотного слоя константой вроде [0.0, 0.0]. Подходит ли это тому, что вы хотите?

Y. Luo 01.05.2018 22:02

@ Y.Luo Это, по сути, то, что я хочу, но слой Dense не будет добавлять смещение поэлементно, так как с увеличением единиц, слой Dense добавляет смещение ко всем комбинациям входных данных. Кроме того, мне не нужны веса умножения "W" из обычного плотного слоя. Я безуспешно пытался реализовать это таким образом, но перестановки входов и мультипликативной матрицы W слоя Dense сделали это невозможным ...

hirschme 01.05.2018 23:34

@ Y.Luo Я изменил чертеж архитектуры, чтобы прояснить, что суммарный слой не обязательно должен заменять плотный слой. Input1 действительно ведет себя как смещение, а именно как аддитивный фактор, но слой не ведет себя как плотный слой.

hirschme 01.05.2018 23:46

Является ли создание собственного слоя приемлемым вариантом для вашего случая?

Y. Luo 02.05.2018 00:15

@ Y.Luo, да! Мне бы понравилось решение, включающее настраиваемый слой. Я пробовал это, но безуспешно. В Keras настраиваемые слои наследуют методы, которые мешают (от плотных слоев, та же проблема, что и выше), и то, как включить настраиваемые слои из тензорного потока в модель Keras, отлично ответит на этот вопрос.

hirschme 02.05.2018 00:20

Я видел ваши предыдущие комментарии к моему ответу и не успел на него ответить. Я только что обнаружил, что вы его удалили. Просто чтобы проверить, решена ли ваша проблема?

Y. Luo 02.05.2018 01:30

@ Y.Luo Да, я спрашивал о динамическом доступе к весам настраиваемого слоя (причина, по которой я включил его в чертеж как внешний ввод), но это, конечно, легко сделать с помощью унаследованных методов get и set_weights. На этом все кажется решенным. Я написал тот же код для настраиваемого слоя Keras, но у меня ничего не вышло. Ваш ответ, кажется, работает для меня прямо сейчас. Большое спасибо!

hirschme 02.05.2018 02:51

Хорошо знать. Пожалуйста!

Y. Luo 02.05.2018 08:11
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
8
1 263
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен, что полностью понимаю ваши потребности. Основываясь на вашем коде тензорного потока, я не думаю, что вам придется вводить начальное значение. В этом случае я надеюсь, что следующее, по крайней мере, близко к тому, что вы хотите:

import numpy as np
import keras
from keras import backend as K
from keras.engine.topology import Layer
from keras.models import Model
from keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, Add

class MyLayer(Layer):

    def __init__(self, bias_init, **kwargs):
        self.bias_init = bias_init
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.bias = self.add_weight(name='bias',
                                    shape=input_shape[1:],
                                    initializer=keras.initializers.Constant(self.bias_init),
                                    trainable=True)
        super(MyLayer, self).build(input_shape)  # Be sure to call this somewhere!

    def call(self, x):
        return x + self.bias

input0    = Input((28,28,1))
x         = Conv2D(32, kernel_size=(3, 3), activation='relu',input_shape=(28,28,1))(input0)
x         = Conv2D(64, (3, 3), activation='relu')(input0)
x         = MaxPooling2D(pool_size=(2, 2))(x)
x         = Flatten()(x)
x         = Dense(128, activation='relu')(x)

input1    = np.random.rand(128)

x         = MyLayer(input1)(x)
x         = Dense(10, activation='softmax')(x)
model     = Model(inputs=input0, outputs=x)
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Другие вопросы по теме