Как реализовать потерю триплетов с помощью конвеета в керасе - PullRequest
0 голосов
/ 01 сентября 2018

Я пытался реализовать функцию потери триплета в Keras в фиктивном наборе данных, который я создал. Я следил за несколькими источниками, включая похожие проблемы со Stackoverflow, но независимо от того, что я делаю, я не могу заставить его работать. В частности, я попытался повторить этот .

Вот мой полный код:

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, но я следовал инструкциям, и он все еще не работает. Есть идеи как это сделать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...