基于DNN(Keras、TensorFlow)实现分位数/标准差预测的技术问询
实现基于Keras/TensorFlow的分位数回归DNN
很高兴看到你已经有一个效果不错的Keras/TensorFlow DNN做数值预测了!要扩展成分位数形式的分布预测,**分位数回归(Quantile Regression)**是完美的解决方案——它能让你直接预测目标变量在不同分位点的取值,刚好匹配你说的房价场景需求(比如判断某套房子的售价是否高于90%的同类房源)。
核心思路
和普通的均值回归(预测y的期望)不同,分位数回归的目标是预测指定分位点的y值(比如0.1、0.5、0.9分位),核心是替换传统的MSE损失为分位数损失函数,让模型学会拟合不同分位点的分布特征。
具体实现步骤
1. 调整模型输出层
原来的模型输出1个值(对应y的均值),现在我们需要输出多个值,每个值对应一个目标分位数。比如如果你想预测0.1(低估区间)、0.5(中位数)、0.9(高估区间)这三个分位,输出层就设置3个线性激活的神经元:
import tensorflow as tf from tensorflow.keras import layers, Model # 定义需要预测的分位数列表 quantiles = [0.1, 0.5, 0.9] # 构建模型(沿用你原有的DNN隐藏层结构即可) inputs = layers.Input(shape=(X.shape[1],)) x = layers.Dense(64, activation='relu')(inputs) x = layers.Dense(32, activation='relu')(x) # 输出层:每个分位数对应一个输出,用线性激活(回归任务不需要非线性激活) outputs = layers.Dense(len(quantiles), activation='linear')(x) model = Model(inputs=inputs, outputs=outputs)
2. 自定义分位数损失函数
分位数损失的核心逻辑是:对于分位数q,当真实值y_true大于预测值y_pred时,损失为q*(y_true - y_pred);当y_true小于y_pred时,损失为(1-q)*(y_pred - y_true)。用TensorFlow实现如下:
def quantile_loss(y_true, y_pred): total_loss = 0.0 for i, q in enumerate(quantiles): # 计算每个分位数对应的损失 error = y_true - y_pred[:, i] loss = tf.reduce_mean(tf.maximum(q * error, (q - 1) * error)) total_loss += loss # 取所有分位数损失的均值(也可以根据业务需求给不同分位加权重) return total_loss / len(quantiles)
3. 编译并训练模型
和普通回归模型一样编译,只是把损失换成我们自定义的分位数损失:
model.compile(optimizer='adam', loss=quantile_loss) # 训练(用你原有的训练数据即可,标签还是原来的y值) model.fit(X_train, y_train, epochs=50, batch_size=32, validation_split=0.2)
4. 预测与解读
训练完成后,输入样本X'(比如某套房屋的特征),会得到一个包含多个分位预测值的数组:
predictions = model.predict(X_test) # 对应0.1、0.5、0.9分位的预测值 q10_pred, q50_pred, q90_pred = predictions[0]
对应你说的房价场景:如果实际售价是100万美元,而模型预测的90%分位值是95万美元,就说明90%的同类房屋售价≤95万美元,当前这套100万的售价确实偏高。
额外注意事项
- 分位数选择:可以根据业务需求调整,比如增加0.25、0.75分位来更细致地刻画分布
- 损失加权:如果某个分位数(比如0.9分位)对你的业务更重要,可以在损失函数中给它的损失项乘以更高的权重
- 模型评估:可以用分位数覆盖率来验证效果,比如统计真实y值落在0.1和0.9分位预测值之间的比例,理想情况应该接近80%(0.9-0.1)
内容的提问来源于stack exchange,提问作者Jonas Sourlier
相关产品推荐
相关产品推荐

