Улучшение точности для сиамской сети - PullRequest
2 голосов
/ 06 февраля 2020

Я написал эту маленькую модель, используя Keras Functional API, чтобы найти сходство диалога между двумя людьми. Я использую вложения Gensim Doc2Ve c для преобразования текстовых данных в векторы (размер вокаба: 4117). Мои данные поровну поделены на 56 положительных и 64 отрицательных случая. (да, я знаю, что набор данных небольшой, но это все, что у меня есть на данный момент).

def euclidean_distance(vects):
    x, y = vects
    sum_square = K.sum(K.square(x - y), axis=1, keepdims=True)
    return K.sqrt(K.maximum(sum_square, K.epsilon()))

ch_inp = Input(shape=(38, 200))
csr_inp = Input(shape=(38, 200))

inp = Input(shape=(38, 200))
net = Embedding(int(vocab_size), 16)(inp)
net = Conv2D(16, 1, activation='relu')(net)
net = TimeDistributed(LSTM(8, return_sequences=True))(net)
out = Activation('relu')(net)

sia = Model(inp, out)

x = sia(csr_inp)
y = sia(ch_inp)

sub = Subtract()([x, y])
mul = Multiply()([sub, sub])

mul_x = Multiply()([x, x])
mul_y = Multiply()([y, y])
sub_xy = Subtract()([x, y])

euc = Lambda(euclidean_distance)([x, y])
z = Concatenate(axis=-1)([euc, sub_xy, mul])
z = TimeDistributed(Bidirectional(LSTM(4)))(z)
z = Activation('relu')(z)
z = GlobalMaxPooling1D()(z)
z = Dense(2, activation='relu')(z)
out = Dense(1, activation = 'sigmoid')(z)

model = Model([ch_inp, csr_inp], out)
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])

Проблема в том, что моя точность не улучшится с 60,87% - я пробежал 10 эпох и точность остается постоянным. Есть ли что-то, что я сделал здесь, в моем коде, что вызывает это? Или, может быть, проблема с моими данными?

View Training Accuracy And Loss here

Я также провел проверку K-Fold для некоторых моделей Sklearn и получил следующие результаты из набора данных:

Statistical Models Results

Кроме того, ниже приведен обзор моего набора данных:

Dataframe Snapshot

Я определенно борюсь с этим - так что буквально любая помощь здесь будет оценили. Спасибо!

ОБНОВЛЕНИЕ: Я увеличил размер данных до 1875 выборок поездов. Его точность улучшена до 70,28%. Но он все еще постоянен на всех итерациях.

1 Ответ

0 голосов
/ 11 февраля 2020

Я вижу две вещи, которые могут быть важны там.

  • Вы используете 'relu' после LSTM. LSTM в Keras уже имеет 'tanh' в качестве активации по умолчанию. Таким образом, хотя вы не блокируете свою модель, вы усложняете ее изучение с помощью активации, которая ограничивает результаты как малый диапазон плюс единица, которая сокращает отрицательные значения

  • Вы используете 'relu' с очень немногими юнитами! Relu с небольшим количеством юнитов, плохой инициализацией, большими скоростями обучения и неудачей застрянет в нулевой области без каких-либо градиентов.

Если ваша потеря полностью замерзает, это, скорее всего, связано со вторым пунктом выше. И даже если он не замерзает, он может использовать только одну единицу из 2 плотных единиц, например, делая слой очень плохим.

Вы должны сделать что-то снизу:

  • Ваша модель небольшая, поэтому прекратите использовать 'relu' и используйте 'tanh'. Это даст вашей модели ожидаемую мощность, которую она должна иметь.
  • В противном случае вам определенно следует увеличить количество юнитов, как для LSTM, так и для Dense, чтобы 'relu' не застряло легко.
  • Вы можете добавить слой BatchNormalization после Dense и до 'relu', таким образом вы гарантируете, что хорошее количество единиц будет всегда выше нуля.

В любом случае, не используйте 'relu' после LSTM.


Другой подход - сделать модель более мощной.

Например:

z = TimeDistributed(Bidirectional(LSTM(4)))(z)
z = Conv1D(10, 3, activation = 'tanh')(z) #or 'relu' maybe
z = MaxPooling1D(z)
z = Conv1D(15, 3, activation = 'tanh')(z) #or 'relu' maybe
z = Flatten()(z) #unless the length is variable, then GlobalAveragePooling1D()(z)
z = Dense(10, activation='relu')(z)
out = Dense(1, activation = 'sigmoid')(z)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...