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

基于有限特征预测Uber订单完成概率:Keras模型概率质量不佳求方案

Uber订单完成预测:概率质量差的问题排查与优化方案

问题描述

我遇到一个实践问题:预测Uber订单被下单后是否会完成,以及对应的准确率/概率。该问题的特征包括:Available Drivers(int64)、Placed Time(float64)、Response Distance(float64)、Car Type(int32)、Day Of Week(int64)、Response Delay(float64),目标变量为Order Completion(int32)。

我的解决方法是使用tf.Keras Sequential模型进行预测,模型结构如下:

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(16, activation='relu', input_shape=input_shape),
    tf.keras.layers.Dense(16, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
adam_optimizer = tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE)
binary_crossentropy_loss = tf.keras.losses.BinaryCrossentropy()
model.compile(optimizer=adam_optimizer, loss=binary_crossentropy_loss, metrics=['accuracy'])
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=ES_PATIENCE)
history = model.fit(train_dataset, validation_data=validation_dataset, epochs=EPOCHS, verbose=2, callbacks=[early_stop])

我对数据做了如下归一化处理(train_data为DataFrame):

train_data = tf.keras.utils.normalize(train_data)

预测时使用:

predictions = model.predict_proba(prediction_dataset, batch_size=None)

训练结果为:loss: 0.3506 - accuracy: 0.8817 - val_loss: 0.3493 - val_accuracy: 0.8773

但模型输出的事件对应概率质量仍然较差。请问这种方法是否错误?针对此类问题有什么推荐方案?神经网络是否不适合解决该问题?恳请赐教!


解决方案与优化建议

先别急,你的方法本身没走错方向,但确实有几个关键环节可以优化,咱们一步步拆解:

1. 修正数据预处理方式

你用的tf.keras.utils.normalize默认是按行做L2归一化,这对你的特征分布很不友好:

  • 不同特征的量级差异极大(比如时间戳Placed Time的数值远大于Available Drivers),按行归一化会让小量级特征的信息被稀释,模型很难学到有效模式。
  • 正确的做法是按列做标准化/归一化:用sklearn.preprocessing.StandardScaler(将特征缩放到均值为0、方差为1)或MinMaxScaler(缩放到0-1区间),针对每个特征单独处理。
  • 另外,Car Type是类别特征,直接用int32输入会让模型误以为类别间有大小关系,建议换成独热编码(One-Hot Encoding)或嵌入层(Embedding)。

2. 重新评估模型性能指标

只看accuracy会误导你:

  • 如果订单完成的样本占比极高(比如90%都是完成的),模型随便猜“完成”就能拿到高准确率,但对少数未完成订单的预测概率会非常差。
  • 你需要关注这些更靠谱的指标:混淆矩阵、Precision/Recall、F1-score、ROC-AUC曲线,以及概率校准曲线(Calibration Curve)——这个能直接反映模型输出概率与实际事件发生概率的匹配程度。

3. 优化模型结构与训练策略

你的模型容量偏小,且训练细节可以调整:

  • 尝试增加模型容量:把Dense层的单元数调到32/64,或者增加1-2层Dense层,同时适当提高Dropout比例(比如0.3)防止过拟合。
  • 调整损失函数:给BinaryCrossentropy加上标签平滑(label_smoothing=0.1),这能避免模型输出过于极端的0或1,让概率更接近真实分布。
  • 改用model.predict()替代predict_proba():在Keras中,直接用predict()就能得到sigmoid输出的概率值,predict_proba()是为兼容sklearn保留的,两者效果一致,但前者更直接。

4. 做概率校准

这是提升概率质量的关键一步:

  • 即使模型分类准确率不错,输出概率也可能出现校准偏差(比如模型预测80%概率的事件,实际发生概率只有60%)。
  • 可以用sklearn的CalibratedClassifierCV来校准概率,支持Platt缩放(适合线性模型)和等渗回归(适合非线性模型)。这里给你一个适配Keras的示例:
from sklearn.calibration import CalibratedClassifierCV
from tensorflow.keras.wrappers.scikit_learn import KerasClassifier

def build_model():
    model = tf.keras.models.Sequential([
        tf.keras.layers.Dense(32, activation='relu', input_shape=input_shape),
        tf.keras.layers.Dense(32, activation='relu'),
        tf.keras.layers.Dropout(0.3),
        tf.keras.layers.Dense(1, activation='sigmoid')
    ])
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    return model

# 把Keras模型包装成sklearn兼容的 estimator
keras_estimator = KerasClassifier(build_fn=build_model, epochs=EPOCHS, batch_size=32, verbose=0)
# 用Platt缩放校准概率,3折交叉验证
calibrated_model = CalibratedClassifierCV(keras_estimator, cv=3, method='sigmoid')
calibrated_model.fit(X_train, y_train)

# 得到校准后的概率
calibrated_predictions = calibrated_model.predict_proba(X_test)[:, 1]

5. 强化特征工程

时间和类别特征还有挖掘空间:

  • 对Placed Time:提取小时、是否处于早高峰/晚高峰、是否为深夜时段等衍生特征。
  • 对Day Of Week:转换成“周末/工作日”的二元特征,或者保留独热编码后的类别特征。
  • 尝试交互特征:比如Available Drivers / Response Distance(司机密度与响应距离的比值)、Response Delay * Car Type(不同车型的响应延迟影响),这些能帮模型捕捉更复杂的业务逻辑。

6. 尝试传统模型对比

神经网络完全适合这类问题,但如果你想快速验证效果,可以试试XGBoost/LightGBM:

  • 树模型对特征工程的要求稍低,且天然输出校准度较好的概率,适合业务场景下的概率预测需求。
  • 你可以把树模型的结果作为基准,再对比优化后的神经网络效果,选择更适合业务的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:09:28