优化广告投放算法
“优化广告投放算法”指的是改进广告系统中用于决定如何投放广告的算法,以提升广告的点击率(CTR)和转化率(CVR),同时提高投放效率和广告收益。具体来说,优化的目标包括:
- 提高竞价策略的精准性
- 采用更先进的出价算法,比如基于强化学习、梯度提升决策树(GBDT)、深度学习等,动态调整出价,使广告主用最优的价格赢得竞价。
- 结合历史数据,预测不同用户的点击概率(pCTR)和转化概率(pCVR),从而计算eCPM(有效千次展示收入),选择合适的广告进行投放。
- 提升广告投放的精准度
- 用户画像优化:利用用户的行为数据(浏览记录、兴趣标签等),提高用户匹配的精准度,让广告更符合目标受众需求。
- 上下文匹配:分析广告投放的环境(如网站类型、文章内容),确保广告与页面内容高度相关,提高点击率。
- 降低无效曝光和预算浪费
- 过滤低质量广告请求,避免给低转化价值的用户投放广告。
- 控制频次(频次上限策略),防止用户对广告产生视觉疲劳。
- 优化广告创意选择
- 通过A/B测试评估不同广告素材的表现,自动选择最优广告。
- 结合**多模态模型(文本+图像+视频)**分析广告素材的吸引力,提高CTR。
- 实时竞价(RTB)优化
- 通过强化学习或自动调节竞价参数,平衡竞价成功率与成本,优化ROI(投资回报率)。
- 结合外部数据源(如天气、节假日、热点事件)动态调整投放策略。
总结来说,优化广告投放算法就是不断改进广告匹配、出价策略、用户定位和投放规则,以实现更高效、更精准的广告投放,提高收益和用户体验。
在广告营销出价算法中,梯度提升决策树(GBDT) 是目前最常用的,因为它在计算效率、模型效果和可解释性之间取得了较好的平衡。具体来说:
算法 | 应用场景 | 优点 | 缺点 | 主流使用情况 |
---|---|---|---|---|
GBDT(如 XGBoost、LightGBM、CatBoost) | CTR/CVR 预估,竞价优化 | 精度高,计算高效,易于部署,解释性强 | 只能处理静态数据,不能自适应市场变化 | 主流方法(最常见),如 Facebook、Google、阿里等 |
深度学习(如 DNN、Wide & Deep、DeepFM) | 复杂特征学习,CVR/CTR 预测,出价优化 | 能够学习复杂非线性特征关系 | 训练成本高,计算复杂,推理速度慢 | 大厂常用(Google Ads, Facebook Ads),需要大规模计算资源 |
强化学习(如 DQN, PPO, DDPG) | 动态竞价策略优化 | 适应市场变化,长期收益最大化 | 训练难度高,样本需求大,收敛慢 | 研究较多,但实际应用较少,少数大厂实验性使用 |
分析对比
- GBDT(最常见)
- 适用于 点击率(CTR)和转化率(CVR) 预测,出价优化的主要方式之一。
- 计算效率高,可解释性强,可用于出价优化和广告投放。
- 常见于 Facebook、Google、阿里、字节 等广告系统。
- 深度学习(DNN, DeepFM)
- 在特征复杂度高的情况下效果优于 GBDT,适用于非线性数据关系。
- 训练成本高,计算复杂,需要大规模数据和计算资源。
- 适用于大厂(Google Ads, Facebook Ads),小规模广告主较少使用。
- 强化学习(RL)
- 适用于竞价市场变化剧烈的场景,如实时竞价(RTB)。
- 能动态调整出价,但训练成本高,数据需求大。
- 实际应用较少,目前主要在学术研究和少数大厂实验性部署。
结论
- GBDT 是当前最常用的出价优化算法,特别适合 CTR/CVR 预估和竞价优化,计算效率高,效果稳定。
- 深度学习在大规模广告投放中用于复杂特征建模,但计算成本较高,适合头部广告主。
- 强化学习虽然有潜力,但训练难度大,目前实际应用较少,主要用于研究或头部厂商实验性优化。
如果你是 中小型广告投放 或 希望快速上线一个高效的出价系统,GBDT 是最佳选择;如果是 大厂,可以结合 深度学习 进行优化;如果是 想研究长期优化策略,可以尝试 强化学习 🚀。
代码实现
这里我们以 GBDT(使用 XGBoost) 进行出价优化的示例来展示如何实现动态出价。
代码逻辑
- 加载历史数据:训练数据集,包含用户特征(年龄、性别、历史点击记录等)、广告特征(广告类型、展示位置等)、竞价结果(是否点击)。
- 训练 GBDT(使用 XGBoost):训练模型预测 pCTR(点击率)。
- 计算 eCPM:
eCPM = pCTR * 出价 * 1000
,根据 eCPM 确定最优出价。 - 实时竞价:基于请求数据,使用训练好的模型预测 pCTR,并计算最优出价。
1. 依赖
首先,在 pom.xml
添加 XGBoost 依赖:
<dependency>
<groupId>ml.dmlc</groupId>
<artifactId>xgboost4j</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>ml.dmlc</groupId>
<artifactId>xgboost4j-spark</artifactId>
<version>1.4.2</version>
</dependency>
2. 训练 GBDT 模型
import ml.dmlc.xgboost4j.java.Booster;
import ml.dmlc.xgboost4j.java.DMatrix;
import ml.dmlc.xgboost4j.java.XGBoost;
import java.util.HashMap;
import java.util.Map;
public class AdBiddingModel {
private Booster model;
public void trainModel() throws Exception {
// 训练数据(假设已有预处理后的特征数据)
float[][] featureData = {
{25, 1, 3, 0.8f}, // 示例数据 (年龄, 性别, 设备类型, 历史点击率)
{35, 0, 2, 0.5f},
{30, 1, 1, 0.3f}
};
float[] labels = {1, 0, 1}; // 是否点击 (1=点击, 0=未点击)
// 转换数据为 DMatrix 格式
DMatrix trainData = new DMatrix(featureData, labels);
// 设置训练参数
Map<String, Object> params = new HashMap<>();
params.put("eta", 0.1); // 学习率
params.put("max_depth", 3);
params.put("objective", "binary:logistic"); // 目标函数:逻辑回归
params.put("eval_metric", "logloss"); // 评估标准
// 训练 GBDT 模型
model = XGBoost.train(trainData, params, 10, new HashMap<>(), null, null);
}
// 预测 pCTR
public float predictCTR(float[] userFeatures) throws Exception {
DMatrix input = new DMatrix(new float[][]{userFeatures}, -1);
float[][] predictions = model.predict(input);
return predictions[0][0]; // 返回预测的 pCTR
}
}
3. 竞价计算(eCPM & 最优出价)
public class AdBidOptimizer {
private AdBiddingModel biddingModel;
public AdBidOptimizer() throws Exception {
this.biddingModel = new AdBiddingModel();
biddingModel.trainModel();
}
// 计算最优出价
public float calculateOptimalBid(float[] userFeatures, float baseBid) throws Exception {
float pCTR = biddingModel.predictCTR(userFeatures);
float eCPM = pCTR * baseBid * 1000; // eCPM 计算
System.out.println("预测 pCTR: " + pCTR + " 计算 eCPM: " + eCPM);
// 设置出价策略:可以是动态调整(例如,根据 pCTR 适当提高/降低出价)
float optimizedBid = baseBid * pCTR * 1.2f; // 适当提高 20% 以提升竞争力
return Math.min(optimizedBid, baseBid * 2); // 设定最大上限
}
public static void main(String[] args) throws Exception {
AdBidOptimizer optimizer = new AdBidOptimizer();
float[] userFeatures = {28, 1, 2, 0.6f}; // 假设用户年龄 28,男性,设备类型 2,历史点击率 0.6
float baseBid = 0.5f; // 初始出价(美元)
float finalBid = optimizer.calculateOptimalBid(userFeatures, baseBid);
System.out.println("最终出价: " + finalBid);
}
}
代码说明
- AdBiddingModel
- 训练 GBDT 模型,用于预测 pCTR(用户点击概率)。
- 使用 XGBoost 进行模型训练,并进行 pCTR 预测。
- AdBidOptimizer
- 获取预测的 pCTR,并计算 eCPM(有效千次展示成本)。
- 计算最优出价
optimizedBid = baseBid * pCTR * 1.2
。 - 设定上限,防止出价过高。
输出示例
预测 pCTR: 0.55 计算 eCPM: 275.0
最终出价: 0.66
说明:
- pCTR 预测为 0.55
- eCPM 计算为 275.0
- 优化后出价 = 0.66 美元
总结
- GBDT(XGBoost)模型用于预测 pCTR,然后根据 pCTR 计算 eCPM。
- 出价计算基于 eCPM,并结合动态策略优化出价。
- 支持自动竞价(Auto Bidding),可以进一步集成 强化学习(如 DQN) 来优化竞价策略。
这样,广告系统就可以在 DSP 端 实现 智能竞价优化,提高广告投放的点击率(CTR)和转化率(CVR)。
数据源
GBDT(梯度提升决策树)训练时需要数据源,通常是历史广告投放数据,包括用户行为数据、广告特征数据等。数据源的质量直接影响模型效果,所以在训练 GBDT 之前,需要清洗、特征工程和数据标注。
GBDT 训练的数据源
GBDT 主要用于 CTR 预估、CVR 预估和广告竞价优化,训练数据通常包含:
1. 用户行为数据
user_id
:用户唯一标识age
:年龄gender
:性别device_type
:设备类型(iOS、Android、PC等)location
:地理位置historical_clicks
:历史点击行为historical_conversions
:历史转化行为
2. 广告特征数据
ad_id
:广告唯一 IDcampaign_id
:广告投放计划 IDad_category
:广告分类(电商、教育、金融等)ad_creative_features
:广告创意特征(图片、视频、文本等)bid_price
:出价
3. 环境上下文
time_of_day
:时间(早上、中午、晚上)day_of_week
:星期几publisher_id
:投放平台 ID(Facebook, Google, TikTok 等)
4. 目标变量(Label)
clicked
(是否点击,CTR 预估)converted
(是否转化,CVR 预估)
GBDT 训练流程
1. 数据准备
- 采集历史广告数据,清洗和去重
- 进行特征工程,如:
- 数值归一化(标准化)
- 类别变量转换(One-Hot Encoding, Embedding)
- 构造派生特征(如用户历史点击率)
2. 训练 GBDT 模型
- 采用 XGBoost / LightGBM / CatBoost 训练
- 目标:
- CTR 预估:预测用户点击概率
- CVR 预估:预测用户转化概率
- 出价优化:基于CTR/CVR 计算最优出价
3. 预测 & 在线部署
- 训练完成后,将模型部署到 DSP 端
- 实时预测广告的CTR/CVR,并结合广告主预算计算出价
- 调整竞价策略,实现 RTB(实时竞价)优化
Java 代码示例(基于 LightGBM 训练)
使用 LightGBM + Java 训练 GBDT 模型:
import ml.dmlc.xgboost4j.java.DMatrix;
import ml.dmlc.xgboost4j.java.XGBoost;
import ml.dmlc.xgboost4j.java.Booster;
import java.util.HashMap;
import java.util.Map;
public class GBDTTraining {
public static void main(String[] args) throws Exception {
// 1. 加载训练数据
DMatrix trainData = new DMatrix("train.txt"); // 训练数据集
DMatrix testData = new DMatrix("test.txt"); // 测试数据集
// 2. 设置 GBDT 参数
Map<String, Object> params = new HashMap<>();
params.put("eta", 0.1); // 学习率
params.put("max_depth", 6); // 树的最大深度
params.put("objective", "binary:logistic"); // 目标函数(CTR 预估)
params.put("eval_metric", "logloss"); // 评估指标(对数损失)
// 3. 训练模型
Booster booster = XGBoost.train(trainData, params, 100, new HashMap<>(), null, null);
// 4. 进行预测
float[][] predictions = booster.predict(testData);
System.out.println("CTR 预测结果:" + predictions[0][0]);
// 5. 保存模型
booster.saveModel("gbdt_model.model");
}
}
总结
- GBDT 必须有数据源,通常包括 用户行为、广告特征、环境变量 作为输入。
- 需要特征工程,如数值归一化、类别编码等。
- 训练好的模型可以部署在 DSP 端,用于实时竞价(RTB)。
- Java 代码 可以使用 XGBoost / LightGBM 进行训练,并用于CTR/CVR 预估,提高广告投放效率。
数仓
GBDT 训练所需的数据源通常存储在数仓(数据仓库,Data Warehouse,DWH),但也可以来自其他数据存储,如 OLAP 数据库、NoSQL 存储、日志系统等。具体取决于业务需求和数据架构。
广告竞价系统中的数据源
在广告竞价系统(RTB)中,常见的数据存储方式如下:
1. 数仓(Data Warehouse,DWH)
用途:
- 存储长期历史数据(广告投放数据、用户行为数据、竞价日志等)
- 提供数据分析和训练集(用于 GBDT 训练 CTR/CVR 预测模型)
- 数据清洗和特征工程(定期 ETL 处理后存入数仓)
常用数仓技术:
技术 | 说明 |
---|---|
Hive | 基于 Hadoop 的离线数仓,适用于大规模数据分析 |
ClickHouse | 高性能 OLAP 数据库,适合广告分析 |
BigQuery | Google Cloud 的大数据分析服务 |
Snowflake | 云数仓,支持海量数据存储与计算 |
示例:Hive 作为数仓存储广告数据
CREATE TABLE ads_click_data (
user_id STRING,
ad_id STRING,
bid_price FLOAT,
click INT,
conversion INT,
timestamp TIMESTAMP
) STORED AS PARQUET;
2. OLAP 数据库(实时分析)
用途:
- 实时查询和数据分析
- 支持 GBDT 训练时快速取数
- 用于在线计算特征,例如用户过去 7 天的点击率
常用 OLAP 方案:
技术 | 说明 |
---|---|
Druid | 高吞吐的实时数据分析数据库,适用于广告数据分析 |
ClickHouse | 适合超高并发广告查询 |
Apache Kylin | 适用于大规模数据聚合 |
3. NoSQL 存储(在线特征存储)
用途:
- 存储实时用户画像和广告特征
- 支持在线计算 CTR/CVR
- 提供低延迟特征查询
常见 NoSQL 方案:
技术 | 说明 |
---|---|
HBase | 大规模数据存储,可存放广告投放历史 |
Redis | 用于存储用户点击率等高频访问数据 |
MongoDB | 适合存储广告素材和投放日志 |
示例:Redis 存储用户点击率
// 存储用户点击率(CTR)
String redisKey = "user_ctr:" + userId;
redisClient.set(redisKey, "0.05"); // 5% 点击率
4. 日志系统(流式数据源)
用途:
- 存储实时广告竞价日志
- 供流式计算 & 训练数据抽取
- 与 Kafka 集成,实现在线特征计算
常见日志存储方案:
技术 | 说明 |
---|---|
Kafka | 作为广告竞价和点击事件的实时日志系统 |
Flink + Kafka | 流式计算 CTR、CVR 特征 |
Elasticsearch | 适用于存储广告曝光日志,便于搜索 |
示例:Kafka 作为广告竞价日志存储
// 生产广告竞价日志
ProducerRecord<String, String> record = new ProducerRecord<>("ad_bidding_logs", logJson);
kafkaProducer.send(record);
数据仓库(DWH)如何支撑 GBDT 训练?
- ETL 处理
- 通过 Spark、Flink、Hive 提取历史广告投放数据,存入数仓。
- 清洗和预处理数据,去重、补全缺失值。
- 特征工程
- 计算用户点击率(CTR)、转化率(CVR)
- 进行特征筛选、归一化等处理
- 数据导出 & 训练 GBDT
- 从数仓导出数据(Hive -> CSV / Parquet -> 训练 GBDT)
- 在本地/云端训练 GBDT 模型
- 训练好的模型用于CTR 预估、CVR 预估,优化广告出价
示例:从 Hive 导出训练数据
INSERT OVERWRITE LOCAL DIRECTORY '/data/gbdt_training'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
SELECT user_id, ad_id, bid_price, click, conversion
FROM ads_click_data
WHERE timestamp >= DATE_SUB(NOW(), 30);
结论
- GBDT 训练的数据源 可以是 数仓(DWH)、OLAP 数据库、NoSQL、日志系统等。
- 数仓(Hive、ClickHouse、BigQuery)是最常见的存储方案,适合存放长期历史数据。
- OLAP 数据库(Druid、ClickHouse)用于实时分析广告数据。
- NoSQL(Redis、HBase) 适合存储用户画像、广告特征,加速在线查询。
- 日志系统(Kafka + Flink) 用于实时特征计算,支持在线 GBDT 训练。
在广告竞价系统(RTB)中,数仓(Data Warehouse,DWH)是最常用的数据源之一,但它通常与OLAP 数据库、NoSQL 存储、日志系统等搭配使用,以满足不同场景的需求。
广告竞价系统中的数据源使用场景
数据源类型 | 主要用途 | 是否最常用 |
---|---|---|
数仓(DWH) | 训练 GBDT、存储长期历史数据、离线分析 | ✅ 最常用 |
OLAP 数据库 | 实时查询、在线计算特征 | ✅ 常用 |
NoSQL 存储 | 存储用户画像、广告特征,低延迟查询 | ✅ 常用 |
日志系统 | 存储竞价 & 点击日志、流式计算特征 | ✅ 常用 |
为什么数仓最常用?
数仓用于 存储长期历史数据,并为 CTR/CVR 预估、出价优化 训练提供稳定的数据来源。
常见数仓技术
技术 | 适用场景 |
---|---|
Hive(Hadoop) | 大规模历史数据存储 & 批量训练 |
ClickHouse | 高速 OLAP 查询,支持分析 & 训练 |
BigQuery / Snowflake | 云端数据仓库,适用于大规模计算 |
示例:Hive 提取 GBDT 训练数据
SELECT user_id, ad_id, bid_price, click, conversion
FROM ads_click_data
WHERE timestamp >= DATE_SUB(NOW(), 30);
数据仓库 vs 其他数据源
- 离线训练(GBDT、深度学习) → 数仓(最常用)
- 批量存储广告投放数据
- 清洗 & 特征工程
- 离线训练 CTR/CVR 预估模型
- 实时竞价(RTB) → OLAP 数据库 / NoSQL
- 需要快速查询特征
- 用户点击率(CTR)、转化率(CVR)查询
- Redis、Druid、ClickHouse
- 日志系统 → Kafka + Flink
- 存储实时竞价 & 点击日志
- 流式计算 CTR 特征
结论
✅ 数仓(DWH)是最常用的数据源,主要用于历史数据存储 & 训练 GBDT / 深度学习模型。
✅ OLAP 数据库 & NoSQL 主要用于实时计算,为 DSP 提供快速查询能力。
✅ 日志系统 适用于实时数据流 & 在线特征计算。
训练 GBDT 最常用的是离线数仓(离线 DWH),因为 GBDT 训练通常是基于大规模历史数据的离线批量训练,不需要实时计算。
离线数仓 vs 实时数仓 训练 GBDT 的对比
数据仓库类型 | 是否适用于 GBDT 训练 | 适用场景 | 常见技术 |
---|---|---|---|
离线数仓(最常用) | ✅ 适用 | 批量训练、历史数据存储、特征工程 | Hive、ClickHouse、BigQuery、Snowflake |
实时数仓 | ❌ 不常用 | 在线特征计算、实时决策 | Druid、Apache Pinot、Flink + Kafka |
为什么 GBDT 训练最常用离线数仓?
- GBDT 需要海量历史数据训练
- 需要 用户行为、广告点击、转化率 等长期数据。
- 训练数据量通常较大,无法实时计算。
- 离线数仓支持高吞吐、批量计算
- Hadoop/Hive、ClickHouse 适合 批量计算
- 离线训练任务(如每日更新 CTR/CVR 预测模型)
- GBDT 训练是离线任务,不需要实时响应
- GBDT 主要用于 预估模型训练,然后 模型部署到实时系统
- 在线竞价阶段 只使用 已训练好的模型 进行预测
示例:Hive 离线数仓训练 GBDT
1. 在 Hive 中提取训练数据
SELECT user_id, ad_id, bid_price, click, conversion
FROM ads_click_data
WHERE timestamp >= DATE_SUB(NOW(), 30); -- 取最近 30 天数据
2. 在 Spark MLlib 上训练 GBDT
import org.apache.spark.ml.classification.GBTClassifier;
import org.apache.spark.ml.feature.VectorAssembler;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
// 加载数据
Dataset<Row> data = spark.read().format("csv").load("hdfs://path/to/data.csv");
// 特征工程
VectorAssembler assembler = new VectorAssembler()
.setInputCols(new String[]{"bid_price", "click", "conversion"})
.setOutputCol("features");
Dataset<Row> transformedData = assembler.transform(data);
// 训练 GBDT 模型
GBTClassifier gbt = new GBTClassifier()
.setLabelCol("click")
.setFeaturesCol("features")
.setMaxIter(100);
GBTClassificationModel model = gbt.fit(transformedData);
// 保存模型
model.write().overwrite().save("hdfs://path/to/model");
实时数仓适用于什么?
实时数仓(如 Druid、Pinot)主要用于:
- 实时特征计算(如 近 5 分钟用户点击率)
- 实时广告竞价(如 CTR 预估)
- 数据快速查询
示例:Flink 实时计算用户点击率
SELECT user_id, COUNT(*) AS recent_clicks
FROM click_logs
WHERE event_time >= NOW() - INTERVAL '5' MINUTE
GROUP BY user_id;
但 实时数仓不适合直接训练 GBDT,因为:
- 实时数据更新频繁,但 GBDT 训练需要稳定的历史数据
- 实时计算资源消耗大,不适合大规模训练
- GBDT 训练通常是批量计算,而不是流式计算
结论
✅ 训练 GBDT 最常用的是离线数仓,如 Hive、ClickHouse,适合大规模历史数据的批量训练。
✅ 实时数仓(Druid、Pinot) 主要用于 实时特征计算,不适合直接训练 GBDT。
✅ 离线训练 + 在线预测 是广告系统的最佳实践。
训练结果
GBDT 的训练结果通常是间歇性的,而非实时的。这意味着 GBDT 模型的训练过程是在离线数仓中批量进行的,每次训练更新模型时,通常会选择定期训练(如每天、每周或每月),而不是实时地进行训练。
原因:
- GBDT 模型训练需要大量历史数据:
- GBDT 是一种基于梯度提升树的集成学习算法,训练过程中需要通过遍历大量历史数据(如广告点击、用户行为数据等)来学习数据中的模式。
- 离线数仓(如 Hive、ClickHouse)通常存储这些大规模历史数据,能够进行高效的批量训练。
- 训练过程相对计算密集:
- GBDT 的训练过程计算量较大,尤其是对大规模数据进行训练时,训练过程需要 消耗较长时间,可能需要几小时甚至几天才能完成。
- 实时训练会造成系统负担,因此通常不会在每次广告竞价时实时进行训练。
- 模型更新是周期性的:
- 在广告竞价系统中,模型的更新并不需要实时进行,而是通过定期的批量训练和更新来适应广告市场的变化。
- 定期训练(间歇性更新) 确保了模型的稳定性,同时可以通过新的数据来调整模型。
GBDT 模型训练的周期
- 日常训练:每隔一段时间(例如每天、每周),会使用最新的数据重新训练 GBDT 模型。
- 离线计算 & 更新:离线数仓会将数据预处理、特征工程等操作做完,模型训练完成后,通过 批量更新 的方式将新模型部署到生产环境。
- 模型上线:更新后的模型会在线下进行测试,确认效果后再部署上线。
间歇性训练的流程示例:
- 数据收集:通过数仓从历史数据中收集最近的广告点击数据(如过去一天的广告点击、展示数据等)。
- 数据预处理:对数据进行清洗和特征工程(如计算广告展示次数、点击次数等)。
- 训练模型:
- 在 离线数仓(如 Hive)中,使用 Spark 或其他分布式框架训练 GBDT 模型。
- 训练过程中使用批量计算来优化模型参数。
- 模型评估与更新:定期评估模型的效果,并进行更新。如果模型效果不理想,会调整特征或使用新的训练算法。
- 上线使用:新的 GBDT 模型会部署到广告投放系统,用于下一轮的竞价和预测。
实时 vs 间歇性训练
- 实时训练:
- 实时训练适用于 深度学习 等能够处理流数据并实时更新模型的算法(如在线学习、增量学习)。
- GBDT 训练通常不适合实时更新,因为它需要大量的数据集来提高准确性,实时更新会影响系统性能。
- 间歇性训练:
- GBDT 最常用的训练方式就是 周期性更新 模型,通常通过 批量训练 来完成,这样能确保模型的稳定性和准确性。
结论:
✅ GBDT 的训练结果是间歇性的,通常是定期(例如每天、每周)通过离线数仓进行批量训练和模型更新,而非实时更新。
✅ 这种间歇性训练能够平衡计算负载与广告系统的实时需求,同时保证模型的效果。