孪生RNN网络时间序列分类准确率始终50%问题求助
问题根源分析与解决方案
核心问题:Embedding网络的输出设计错误
你的孪生网络中,Embedding网络最后用了Dense(2, activation='softmax'),这是分类任务的输出头,而非度量学习所需的特征嵌入。Softmax会把输出压缩为和为1的概率分布,导致两个样本的嵌入失去特征空间的区分度,无论输入如何,计算出的欧氏距离都无法有效反映样本相似性,最终模型只能随机猜测,准确率卡在50%。
修正步骤
1. 重构Embedding网络
移除最后的softmax分类层,保留高维特征向量作为嵌入输出:
def euclidean_distance(vects): x, y = vects sum_square = tf.math.reduce_sum(tf.math.square(x - y), axis=1, keepdims=True) return tf.math.sqrt(tf.math.maximum(sum_square, tf.keras.backend.epsilon())) input = layers.Input((1000, 4)) x = SimpleRNN(100, input_shape=(1000,4))(input) x = Dropout(0.5)(x) x = Dense(128, activation='relu')(x) # 移除softmax层,直接输出128维特征作为嵌入 embedding_network = keras.Model(input, x) input_1 = layers.Input((1000, 4)) input_2 = layers.Input((1000, 4)) tower_1 = embedding_network(input_1) tower_2 = embedding_network(input_2) merge_layer = layers.Lambda(euclidean_distance)([tower_1, tower_2]) # 移除不必要的BatchNormalization和sigmoid层,contrastive loss直接基于距离计算 siamese = keras.Model(inputs=[input_1, input_2], outputs=merge_layer)
2. 正确实现Contrastive Loss
确保损失函数逻辑匹配孪生网络的输出(欧氏距离):
def contrastive_loss(y_true, y_pred): margin = 1.0 square_pred = tf.math.square(y_pred) margin_square = tf.math.square(tf.math.maximum(margin - y_pred, 0)) return tf.math.reduce_mean(y_true * square_pred + (1 - y_true) * margin_square)
3. 数据对构造验证
- 确保训练数据中同类样本对(y=0)和异类样本对(y=1)比例均衡
- 样本对标签需准确:同类对标签为0(距离应较小),异类对标签为1(距离应大于margin)
4. 其他调优建议
- 替换SimpleRNN为LSTM或GRU,更好捕捉时间序列的长期依赖
- 调整Embedding网络的层数和神经元数量,增强特征提取能力
- 在0.5到2.0区间内尝试不同margin值,结合验证集损失变化选择最优值
补充说明
原网络在距离后添加的BatchNormalization和sigmoid层是多余的,Contrastive Loss直接基于欧氏距离与标签的关系计算损失,无需将距离转换为概率值。
内容的提问来源于stack exchange,提问作者msskx
相关产品推荐
相关产品推荐

