#python #tensorflow #keras #computer-vision #loss-function
#python #тензорный поток #keras #компьютерное зрение #функция потери
Вопрос:
Я хочу построить сеть, которая должна иметь возможность проверять изображения (например, человеческие лица). Насколько я понимаю, лучшим решением для этого является сиамская сеть с потерей триплета. Я не нашел готовых реализаций, поэтому решил создать свою собственную.
Но у меня есть вопрос о Keras. Например, вот структура сети:
И код примерно такой:
embedding = Sequential([
Flatten(),
Dense(1024, activation='relu'),
Dense(64),
Lambda(lambda x: K.l2_normalize(x, axis=-1))
])
input_a = Input(shape=shape, name='anchor')
input_p = Input(shape=shape, name='positive')
input_n = Input(shape=shape, name='negative')
emb_a = embedding(input_a)
emb_p = embedding(input_p)
emb_n = embedding(input_n)
out = Concatenate()([emb_a, emb_p, emp_n])
model = Model([input_a, input_p, input_n], out)
model.compile(optimizer='adam', loss=<triplet_loss>)
Я определил только одну модель встраивания. Означает ли это, что после начала обучения модели веса будут одинаковыми для каждого ввода?
Если это так, как я могу извлечь веса вложения из model
?
Комментарии:
1. в вашем случае вы можете использовать прямое встраивание.predict(X) для извлечения встраивания
Ответ №1:
Да, в функции потери триплета веса должны быть общими для всех трех сетей, т. Е. Привязка, положительная и отрицательная. В Tensorflow 1.x для достижения разделения веса вы можете использовать reuse=True
в tf.layers
.
Но в Tensorflow 2.x с тех пор, как tf.layers
был перенесен в tf.keras.layers
и reuse
функциональность была удалена. Для достижения разделения веса вы можете написать пользовательский слой, который берет родительский слой и повторно использует его веса.
Ниже приведен пример, чтобы сделать то же самое.
class SharedConv(tf.keras.layers.Layer):
def __init__(
self,
filters,
kernel_size,
strides=None,
padding=None,
dilation_rates=None,
activation=None,
use_bias=True,
**kwargs
):
self.filters = filters
self.kernel_size = kernel_size
self.strides = strides
self.padding = padding
self.dilation_rates = dilation_rates
self.activation = activation
self.use_bias = use_bias
super().__init__(*args, **kwargs)
def build(self, input_shape):
self.conv = Conv2D(
self.filters,
self.kernel_size,
padding=self.padding,
dilation_rate=self.dilation_rates[0]
)
self.net1 = Activation(self.activation)
self.net2 = Activation(self.activation)
def call(self, inputs, **kwargs):
x1 = self.conv(inputs)
x1 = self.act1(x1)
x2 = tf.nn.conv2d(
inputs,
self.conv.weights[0],
padding=self.padding,
strides=self.strides,
dilations=self.dilation_rates[1]
)
if self.use_bias:
x2 = x2 self.conv.weights[1]
x2 = self.act2(x2)
return x1, x2
Ответ №2:
Я отвечу о том, как извлечь вложения (ссылка из моего поста на Github):
Моя обученная сиамская модель выглядела так: siamese_model.summary()
Обратите внимание, что моя недавно переопределенная модель в основном такая же, как выделенная желтым
Затем я переопределил свою модель, которую хотел использовать для извлечения вложений (это должна быть та же модель, которую вы определили, за исключением того, что теперь у нее не будет таких множественных входов, как siamese), которая выглядела следующим образом:
siamese_embeddings_model = build_siamese_model(input_shape)
siamese_embeddings_model .summary()
Затем я просто извлек веса из моей обученной сиамской модели и установил их в свою новую модель
embeddings_weights = siamese_model.layers[-3].get_weights()
siamese_embeddings_model.set_weights(embeddings_weights )
Затем вы можете предоставить новое изображение для извлечения вложений из новой модели
vector = siamese.predict(image)
len(vector[0])
он напечатает 150 из-за моего тонкого плотного слоя (который является выходным вектором)