我正在与Keras配合使用多层感知器,以预测句子中正确的单词顺序。
我之所以使用train_on_batch()
,是因为我将树中的每个句子都转换了,然后对每个局部子树进行了排序:当每个子树被排序时,整个树甚至都被排序了。
在训练期间,我注意到一个奇怪的事情:由于从第一个时期开始,损失值为0.0。
我的数据集形状为(453732, 300)
(最初的特征数量为838,但是我使用PCA进行了简化),这是代码:
mlp = keras.models.Sequential()
# add input layer
mlp.add(
keras.layers.Dense(
units=training_dataset.shape[1],
input_shape = (training_dataset.shape[1], ),
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
activation='tanh')
)
# add hidden layer
mlp.add(
keras.layers.Dense(
units=training_dataset.shape[1] + 10,
input_shape = (training_dataset.shape[1] + 10,),
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
activation='relu')
)
mlp.add(
keras.layers.Dropout(
0.2,
input_shape=(training_dataset.shape[1] + 10,))
)
# add output layer
mlp.add(
keras.layers.Dense(
units=1,
input_shape = (1, ),
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
activation='softmax')
)
# define SGD optimizer
sgd_optimizer = keras.optimizers.SGD(
lr=0.01, decay=0.01, momentum=0.9, nesterov=True
)
# compile model
mlp.compile(
optimizer=sgd_optimizer,
loss=listnet_loss
)
mlp.summary() # print model settings
losses = np.array([])
# Training
with tf.device('/GPU:0'):
for epoch in range(0, 10):
print('Epoch {0} started!'.format(epoch))
start_range = 0
for group in groups_id_count:
end_range = (start_range + group[1]) # Batch is a group of words with same group id
batch_dataset = training_dataset[start_range:end_range, :]
batch_labels = training_dataset_labels[start_range:end_range]
batch_train_result = mlp.train_on_batch(batch_dataset, batch_labels)
losses = np.append(losses, batch_train_result)
start_range = end_range
print('Epoch {0} loss: {1}'.format(epoch, np.mean(losses)))
listnet_loss
如下:
def get_top_one_probability(vector):
return (K.exp(vector) / K.sum(K.exp(vector)))
def listnet_loss(real_labels, predicted_labels):
return -K.sum(get_top_one_probability(real_labels)) * tf.math.log(get_top_one_probability(predicted_labels))
groups_id_count
是(#subtree_number,#number_of_words_in_subtree)
形式的元组列表,其中#subtree_number
是子树的标识符,而#number_of_words_in_subtree
是子树中的单词数。然后,我的批处理是动态的:批处理由子树中的单词数组成。这就是为什么我使用train_on_batch()
训练模型的原因。
有什么建议吗? 预先感谢。