tensorflow - 训练集上对比损失函数的准确性有所提高,但验证准确性变差或没有提高

标签 tensorflow keras conv-neural-network python-3.5 loss-function

我正在尝试创建一个说话人识别暹罗神经网络,该网络将两个样本作为输入并确定它们是否来自同一说话人。为此,我使用了对比损失函数,如我检查过的一些来源中所述( herehere )。

我有一个玩具数据集,我在其中训练了一个小模型(9500 个训练样本和 500 个测试样本)。训练集的准确率提高到 0.97,而验证集的准确率提高到 0.93。到目前为止,一切都很好。 然而,当我尝试在更大的数据集上应用相同的配置时,我得到的结果很差;训练准确度会提高,但验证损失永远不会超过 0.5,这与此类问题的随机猜测一样好。这是我的代码:

import numpy as np
import keras
import tensorflow as tf
from keras.models import Sequential, Model
from keras.layers import Dense, Activation, Flatten, Input, Concatenate, Lambda, merge
from keras.layers import Dropout
from keras.layers import LSTM, BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras import backend as K

K.set_image_dim_ordering('tf')

def Siamese_Contrastive_Loss():
    filepath = 'C:/Users/User/Documents/snet.h5'
    X_1, X_2, x1_val, x2_val, Y, val_y = data_preprocessing_load()
    input_shape = (sample_length, features, 1)
    left_input = Input(input_shape)
    right_input = Input(input_shape)

    baseNetwork = createBaseNetworkSmaller(sample_length, features, 1)
    encoded_l = baseNetwork(left_input)
    encoded_r = baseNetwork(right_input)
    distance = Lambda(euclidean_distance,output_shape=eucl_dist_output_shape)([encoded_l, encoded_r])
    model = Model([left_input, right_input], distance)

    checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
    callbacks_list = [checkpoint]
    model.compile(loss=contrastive_loss, optimizer='rmsprop', metrics=[acc])
    model.fit([X_1,X_2], Y, validation_data=([x1_val, x2_val],val_y), epochs=20, batch_size=32, verbose=2, callbacks=callbacks_list)


def data_preprocessing_load():
    ...
    return X_1, X_2, x1_val, x2_val, Y, val_y



def createBaseNetworkSmaller(sample_length, features, ii):
    input_shape = (sample_length, features, ii)
    baseNetwork = Sequential()
    baseNetwork.add(Conv2D(64,(10,10),activation='relu',input_shape=input_shape))
    baseNetwork.add(MaxPooling2D(pool_size=3))
    baseNetwork.add(Conv2D(64,(5,5),activation='relu'))
    baseNetwork.add(MaxPooling2D(pool_size=1))
    #baseNetwork.add(BatchNormalization())
    baseNetwork.add(Flatten())
    baseNetwork.add(Dense(32, activation='relu'))
    #baseNetwork.add(Dropout(0.2))
    baseNetwork.add(Dense(32, activation='relu'))
    return baseNetwork

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


def eucl_dist_output_shape(shapes):
    shape1, shape2 = shapes
    return (shape1[0], 1)


def contrastive_loss(y_true, y_pred):
    '''Contrastive loss from Hadsell-et-al.'06
    http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
    '''
    margin = 1
    square_pred = K.square(y_pred)
    margin_square = K.square(K.maximum(margin - y_pred, 0))
    #return K.mean(y_true * square_pred + (1 - y_true) * margin_square)
    return K.mean((1 - y_true) * K.square(y_pred) + y_true * K.square(K.maximum(margin - y_pred, 0)))


def acc(y_true, y_pred):
    ones = K.ones_like(y_pred)
    return K.mean(K.equal(y_true, ones - K.clip(K.round(y_pred), 0, 1)), axis=-1)


我认为问题在于我不确切知道对比损失应该做什么。我有一个正对子集(来自同一说话人的样本)标记为 0,另一个负对子集(来自不同说话人的样本)标记为 1。据我了解,这个想法是尝试最大化负对之间的距离配对并最小化正值之间的值。我不确定这里是否是这种情况。名为“acc”的函数确定训练每个步骤的准确性。名为“contrastive_loss”的函数是主要的损失函数,我在其中放置了两个返回语句,其中一个已被注释掉。我在一个论坛上读到,根据人们如何标记正负对(分别为 0/1 或 1/0),他们应该使用相应的公式。此时我很困惑。我应该使用什么配置?正数对应该是 0,负数对应该是 1,还是反之亦然?最后,对比损失应该是什么样的?

最佳答案

如何获得音频对的音频样本和标签(0 代表不同的人,1 代表同一个人)。我建议你在最后一层使用 sigmoid 函数,有 2 个神经元。这样你就可以使用“binary_crossentropy”损失函数。网络的输出将是 0 到 1 之间的值,其中 0 是 2 个音频样本之间的最大差异,1 是最大相似度。

`def createBaseNetworkSmaller(sample_length, features, ii):
    input_shape = (sample_length, features, ii)
    baseNetwork = Sequential()
    baseNetwork.add(Conv2D(64,(10,10),activation='relu',input_shape=input_shape))
    baseNetwork.add(MaxPooling2D(pool_size=3))
    baseNetwork.add(Conv2D(64,(5,5),activation='relu'))
    baseNetwork.add(MaxPooling2D(pool_size=1))
    #baseNetwork.add(BatchNormalization())
    baseNetwork.add(Flatten())
    baseNetwork.add(Dense(32, activation='relu'))
    #baseNetwork.add(Dropout(0.2))
    baseNetwork.add(Dense(2, activation='sigmoid'))
    return baseNetwork`

`model.compile(loss=contrastive_loss, optimizer='rmsprop', metrics=[acc])`

关于tensorflow - 训练集上对比损失函数的准确性有所提高,但验证准确性变差或没有提高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56950239/

相关文章:

python - Tensorflow Keras LSTM 未训练 - 受 number_of_epochs、优化器 a​​dam 影响

python - 在 Keras 中合并 2 个顺序模型

python - 在 tensorflow 中预测上传的图像时如何解释 expand_dims

TensorFlow:如何使用具有可变输入长度的 CudnnLSTM(如 dynamic_rnn)?

image-processing - 如何将 EMNIST 数据加载到 Tensorflow

tensorflow - 将 AutoML Tables 生成的模型导入 BigQuery ML 会引发错误 "Op type not registered ' DecodeProtoSparseV 2'"

tensorflow - 如何在本地查看远程服务器的张量板

python - Keras - on_batch_end 方法很慢,但我只有回调是检查点

python - 我在 google colab 上训练了一个 keras 模型。现在无法将其加载到我的系统本地。

python - 使用 CNN 和 Keras-Tf python 的 dogs_cats 分类数据集的准确性不够高