我一直在尝试在我创建的虚拟数据集上的Keras中实现三重损失函数。我关注了多个消息源,包括关于Stackoverflow的类似问题,但是无论我做什么,我似乎都无法正常工作。更具体地说,我尝试复制this。
这是我的完整代码:
ALPHA = 0.2 # Triplet Loss Parameter
input_shape = Input(shape=(80, 26, 1))
def fake_loss(X):
item, _,_ = X
# item = X
loss = K.sum(ALPHA * item, axis=-1, keepdims=True)
print(loss.shape)
return loss
def triplet_loss_function(x):
anchor, positive, negative = x
pos_dist = K.sum(K.square(anchor-positive), 1)
neg_dist = K.sum(K.square(anchor-negative), 1)
basic_loss = pos_dist-neg_dist + ALPHA
basic_loss = K.sum(pos_dist, neg_dist, ALPHA)
print(basic_loss.shape)
loss = K.mean(K.maximum(basic_loss, 0.0), 0)
return loss
def triplet_loss_f2(x):
anchor, positive, negative = x
pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), 1)
neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), 1)
basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), ALPHA)
loss = tf.reduce_mean(tf.maximum(basic_loss, 0.0), 0)
print(loss.shape)
return loss
def build_model(input_shape):
anchor, positive, negative = Pipeline()
input_shape = Input(shape=(80, 26,1))
conv1 = Conv2D(64, kernel_size=4, activation='relu')(input_shape)
conv2 = MaxPooling2D(pool_size=(3, 3))(conv11)
conv3 = Conv2D(32, kernel_size=4, activation='relu')(conv2)
conv4 = MaxPooling2D(pool_size=(2, 2))(conv3)
flat1 = Flatten()(conv4)
hidden1 = Dense(64, activation='relu')(flat1)
d1 = Dropout(rate=0.4, name="dropout1")(hidden1)
hidden2 = Dense(32, activation='relu')(d1)
# Create Common network to share the weights along different examples (+/-/Anchor)
embedding_network = Model(input_shape, hidden2)
print('done')
positive_example = Input(shape=(80, 26, 1))
negative_example = Input(shape=(80, 26, 1))
anchor_example = Input(shape=(80, 26, 1))
positive_embedding = embedding_network(positive_example)
negative_embedding = embedding_network(negative_example)
anchor_embedding = embedding_network(anchor_example)
#loss = Lambda(triplet_loss_function)([anchor_embedding,positive_embedding,negative_embedding])
loss = merge([anchor_embedding, positive_embedding, negative_embedding],mode=triplet_loss_f2, output_shape=(1,))
print('done')
output = Dense(1, activation='sigmoid')(loss)
model = Model(inputs=[anchor_example, positive_example, negative_example],outputs=output)
model.compile(loss='mean_square_error', optimizer=Adam())
model.fit([anchor, positive, negative], np.ones(100)*0, epochs=10,batch_size=2048)
def toydataset():
X, y = make_blobs(n_samples=80, centers=1, n_features=26)
return X,y
def Pipeline():
X1 = list()
X2 = list()
X3 = list()
Y = list()
for j in range(100):
x1,y1 = toydataset()
X1.append(x1)
x2,y2 = toydataset()
X2.append(x2)
x3,y3 = toydataset()
X3.append(x3)
X1 = np.asarray(X1).reshape(100, 80, 26, 1)
X2 = np.asarray(X2).reshape(100, 80, 26, 1)
X3 = np.asarray(X3).reshape(100, 80, 26, 1)
Y = np.ones(300)*0
return X1,X2, X3
build_model(input_shape)
修改此代码时会遇到一些错误。您可能会注意到,我有不同的实现方法。一种是通过调用Keras合并层,另一种是通过调用Keras Lambda层。另外,我有两种不同的三重损失函数,一种使用Tensorflow操作(triplet_loss_f2
),另一种使用Keras后端。当我使用合并层和Keras后端操作运行以上代码时,我得到:
TypeError: Expected bool for argument 'keep_dims' not 0.2.
当我使用合并图层+ Tensorflow操作或lambda + Tensorflow尝试时,出现此错误:
ValueError: Input 0 is incompatible with layer dense_3: expected min_ndim=2, found ndim=0
当我使用Lambda层+ Keras后端运行它时,出现此错误:
TypeError: Expected bool for argument 'keep_dims' not 0.2.
我创建了3个形状为(100,80,26,1)
的数据数组,并尝试了我能想到的每种变化。我还创建了一个fake_loss
函数,我不得不说它是唯一使它真正进行训练的函数。当然,我希望真正的东西起作用。我不完全了解Tensorflow或Keras后端,但是我遵循了说明,但仍然无法正常工作。有关如何执行此操作的任何想法?