You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras中Transformer模型加权与普通准确率不一致问题排查

时间序列分类模型加权准确率异常问题

问题背景

训练时间序列分类Transformer模型,以“以上一个目标值作为下一个预测结果”的Baseline模型做对比基准。为处理不平衡数据集,采用数据生成器+sample_weights样本加权方案。

将所有sample_weights设为1测试时,Baseline模型的加权准确率与普通准确率结果完全一致(符合预期);但Transformer模型的两者差异显著:普通准确率归一化到[0,1]区间,加权准确率却归一化到[0,100]区间,需排查原因。


相关代码

数据生成器样本权重获取函数

def get_sample_weights(self, inputs, labels):
    ''' Obtains sample weights for any number of classes.
        NOTE: sample_weights pertain a weighting to each label
        '''

    # 初始化样本权重为1
    sample_weights = tf.ones_like(labels, dtype=tf.float64)
    
    # 获取类别及对应样本数
    class_counts = np.bincount(self.train_df.price_change)
    total = class_counts.sum()
    n_classes = len(class_counts)

    # 强制所有类别权重为1
    weights = tf.constant([1, 1, 1], dtype=tf.float64)
    for idx, count in enumerate(class_counts):
        weight = weights[idx]
        # 更新对应类别的样本权重
        sample_weights = tf.where(tf.equal(labels, float(idx)), 
                                  weight, 
                                  sample_weights)
    
    return inputs, labels, sample_weights

Baseline模型配置与评估代码

baseline = Baseline(label_index=single_gen.column_indices['price_change'])

baseline.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(),
                 metrics=['accuracy'],
                 weighted_metrics=['accuracy'])

train_metrics = baseline.evaluate(single_gen.train)
val_metrics = baseline.evaluate(single_gen.valid)

Transformer模型配置与评估代码

transformer_model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(),
                  optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),
                  metrics=['sparse_categorical_accuracy'],
                  weighted_metrics=['sparse_categorical_accuracy'])

history = transformer_model.fit(aapl_gen.train, 
                                epochs=2,
                                validation_data=aapl_gen.valid)

train_metrics = transformer_model.evaluate(data_gen.train)
val_metrics = transformer_model.evaluate(data_gen.valid)

原因分析与解决方法

核心原因:指标计算逻辑差异

问题根源在于**accuracy与sparse_categorical_accuracy作为加权指标时的计算逻辑不一致**:

  • accuracy(对应稀疏任务的SparseCategoricalAccuracy)作为加权指标时,会自动对样本权重做归一化(将权重总和缩放到1),因此结果范围与普通准确率一致([0,1])。
  • 部分TensorFlow版本中,sparse_categorical_accuracy作为加权指标时,未正确执行权重归一化,直接返回加权正确样本数(而非除以总权重),导致结果范围变为[0,样本总数],表现为与普通准确率差100倍的现象。

解决方案

  1. 统一指标类型
    将Transformer模型的指标替换为accuracy,与Baseline保持一致:

    transformer_model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(),
                      optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),
                      metrics=['accuracy'],
                      weighted_metrics=['accuracy'])
    
  2. 验证样本权重正确性
    在get_sample_weights函数末尾添加验证代码,确认所有样本权重确实为1:

    print("样本权重唯一值:", tf.reduce_unique(sample_weights).numpy())
    
  3. 手动计算验证指标
    手动计算普通准确率与加权准确率,对比模型返回结果,定位问题:

    y_true, y_pred, weights = [], [], []
    for x, y, w in data_gen.train:
        y_true.extend(y.numpy())
        y_pred.extend(tf.argmax(transformer_model.predict(x), axis=1).numpy())
        weights.extend(w.numpy())
    
    # 普通准确率
    regular_acc = sum(t == p for t, p in zip(y_true, y_pred)) / len(y_true)
    # 加权准确率
    weighted_acc = sum(w for t, p, w in zip(y_true, y_pred, weights) if t == p) / sum(weights)
    
    print(f"手动计算普通准确率: {regular_acc:.4f}")
    print(f"手动计算加权准确率: {weighted_acc:.4f}")
    
  4. 升级TensorFlow版本
    若使用旧版本TensorFlow,升级至最新稳定版,修复指标计算的潜在bug。


内容的提问来源于stack exchange,提问作者Isaac Berrios

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 10:30:52