如何在Keras中使用convnet实现三重丢失

时间:2018-08-31 21:37:37

标签: python machine-learning keras conv-neural-network loss-function

我一直在尝试在我创建的虚拟数据集上的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后端,但是我遵循了说明,但仍然无法正常工作。有关如何执行此操作的任何想法?

0 个答案:

没有答案