TL; DR Моя модель обучена в течение 1 эпох - для целей тестирования.Тем не менее, при многократной оценке это дает разную точность каждый раз, когда я запускаю evaluate_generator
метод с одними и теми же данными обучения .Почему это происходит, и есть ли способ получить один и тот же показатель точности при оценке одних и тех же обученных данных для одной и той же модели несколько раз?
Я работаю над лингвистической проблемой классификации актов диалогаи моя модель основана на этой бумаге.Используя инструменты, предоставляемые репозиториями keras
и keras_contrib
, я копирую точную модель, но у меня есть вопрос о том, почему при оценке выдается другая степень точности.
Для справки я обучил модель дляотдельная эпоха, а затем сохраненная обученная модель в файле с помощью утилиты save_load_utils
, предоставляемой модулем keras_contrib
.Однако всякий раз, когда я запускаю модель с теми весами , которые тренировались в течение одной эпохи, я получаю разную степень точности.Я пробовал это 5-10 раз, и это колеблется от 68% до 74%, что довольно много.Поскольку я загружаю предварительно обученные (то есть для 1 эпохи) веса моделей, я ожидаю получить ту же точность.(т.е. за исключением различий в точности чисел с плавающей запятой). Однако, разница в результатах с такой скоростью предполагает, что я, возможно, сделал что-то неправильно.
Кто-нибудь имеет какое-либо представление о том, почему model.evaluate_generator
метод генерирует результаты, которые настолько различаются каждый раз, когда я запускаю его с одним и тем же весом, даже если я использую одни и те же веса, обученные на одной эпохе, чтобы оценить его?Есть ли способ исправить мой код оценки, чтобы точность, полученная для одной и той же обученной модели, была одинаковой при каждой оценке?(т.е. с учетом любых незначительных различий из-за арифметики с плавающей точкой)
Ниже приведен весь соответствующий код.Пример кода немного длиннее по сравнению со стандартным вопросом StackOverflow, но я хотел включить все соответствующие части кода.Извинения программистам Python за длину кода.Я начинающий программист на Python, и, возможно, я мог бы написать все это более кратким идиоматическим языком Python.
Код подготовки модели:
def prepare_kadjk_model(max_mini_batch_size,
max_conversation_length, timesteps, num_word_dimensions,
word_to_index, word_vec_dict,
num_tags):
#Hyperparameters
m = timesteps
h = timesteps
model = Sequential()
dictionary_size = len(word_to_index) + 1
embedding_weights = numpy.zeros((dictionary_size, num_word_dimensions))
for word, index in word_to_index.items():
embedding_weights[index, :] = word_vec_dict[word]
# define inputs here
embedding_layer = Embedding(dictionary_size, num_word_dimensions,
weights=[embedding_weights],
embeddings_regularizer=regularizers.l2(0.0001))
model.add(TimeDistributed(embedding_layer,
input_shape=(max_conversation_length, timesteps)))
model.add(TimeDistributed(Bidirectional(LSTM(m // 2, return_sequences=True,
kernel_regularizer=regularizers.l2(0.0001)))))
model.add(TimeDistributed(Dropout(0.2)))
model.add(TimeDistributed(GlobalMaxPooling1D()))
model.add(Bidirectional(LSTM(h // 2, return_sequences = True,
kernel_regularizer=regularizers.l2(0.0001)), merge_mode='concat'))
model.add(Dropout(0.2))
crf = CRF(num_tags, sparse_target=False, kernel_regularizer=regularizers.l2(0.0001))
model.add(crf)
model.compile(optimizer, loss = crf_loss,
metrics=[crf_accuracy])
return model
Функции подготовки пакета:
def form_mini_batches(dataset_x, max_mini_batch_size):
num_conversations = len(dataset_x)
# Form mini batches of equal-length conversations
mini_batches = {}
for i in range(num_conversations):
num_utterances = len(dataset_x[i])
if num_utterances in mini_batches:
mini_batches[num_utterances].append( i )
else:
mini_batches[num_utterances] = [ i ]
# Enforce max_batch_size on previously formed mini batches
mini_batch_list = []
for conversations in mini_batches.values():
mini_batch_list += [conversations[x: x + max_mini_batch_size] for x in range(0, len(conversations), max_mini_batch_size)]
return mini_batch_list
def kadjk_batch_generator(dataset_x, dataset_y, tag_indices,
mini_batch_list, max_conversation_length,
timesteps, num_word_dimensions, num_tags,
word_index_to_append, tag_index_to_append):
num_mini_batches = len(mini_batch_list)
# Shuffle the order of batches
index_list = [x for x in range(num_mini_batches)]
random.shuffle(index_list)
k = -1
while True:
k = (k + 1) % len(index_list)
index = index_list[k]
conversation_indices = mini_batch_list[index]
num_conversations = len(conversation_indices)
batch_features = numpy.empty(shape = (num_conversations, max_conversation_length, timesteps),
dtype = int)
label_list = []
for i in range(num_conversations):
utterances = dataset_x[conversation_indices[i]]
labels = copy.deepcopy(dataset_y[conversation_indices[i]])
num_utterances = len(utterances)
num_labels_to_append = max(0, max_conversation_length - len(labels))
labels += [tag_index_to_append] * num_labels_to_append
tags = to_categorical(labels, num_tags)
del labels
for j in range(num_utterances):
utterance = copy.deepcopy(utterances[j])
num_to_append = max(0, timesteps - len(utterance))
if num_to_append > 0:
appendage = [word_index_to_append] * num_to_append
utterance += appendage
batch_features[i][j] = utterance
del utterance
remaining_space = (max_conversation_length - num_utterances, timesteps)
batch_features[i][num_utterances:] = numpy.ones(remaining_space) * word_index_to_append
label_list.append(tags)
batch_labels = numpy.array(label_list)
del label_list
yield batch_features, batch_labels
Функция обучения:
def train_kadjk(model, training, validation, num_epochs_to_train, tag_indices, max_mini_batch_size,
max_conversation_length, timesteps, num_word_dimensions, num_tags,
end_of_line_word_index, uninterpretable_label_index):
training_mini_batch_list = form_mini_batches(training[0], max_mini_batch_size)
validation_mini_batch_list = form_mini_batches(validation[0], max_mini_batch_size)
num_training_steps = len(training_mini_batch_list)
num_validation_steps = len(validation_mini_batch_list)
early_stop = EarlyStopping(patience = 5)
change_learning_rate = LearningRateScheduler(learning_rate_scheduler)
model.fit_generator(kadjk_batch_generator(training[0], training[1], tag_indices,
training_mini_batch_list, max_conversation_length,
timesteps, num_word_dimensions, num_tags,
end_of_line_word_index, uninterpretable_label_index),
steps_per_epoch = num_training_steps,
epochs = num_epochs_to_train,
validation_data = kadjk_batch_generator(validation[0], validation[1],
tag_indices,
validation_mini_batch_list,
max_conversation_length, timesteps,
num_word_dimensions, num_tags,
end_of_line_word_index,
uninterpretable_label_index),
validation_steps = num_validation_steps,
callbacks = [early_stop, change_learning_rate])
Функция оценки:
def evaluate_kadjk(model, testing, tag_indices, max_mini_batch_size, max_conversation_length,
timesteps, num_word_dimensions, num_tags,
end_of_line_word_index, uninterpretable_label_index):
testing_mini_batch_list = form_mini_batches(testing[0], max_mini_batch_size)
num_testing_steps = len(testing_mini_batch_list)
score = model.evaluate_generator(kadjk_batch_generator(testing[0], testing[1],
tag_indices,
testing_mini_batch_list,
max_conversation_length, timesteps,
num_word_dimensions, num_tags,
end_of_line_word_index,
uninterpretable_label_index),
steps = num_testing_steps)
print("len(score):" + str(len(score)))
print("score:" + str(score))
Вы можете перемещаться здесь для более полной перспективы дипломного дипломного проектаЯ работаю над этим, но я постарался предоставить все необходимые функциональные возможности, которые могут быть полезны любому.