1. 项目背景与核心价值
去年双十一大促期间,我们电商团队遇到了一个典型问题:面对突然爆发的流量,库存调配完全跟不上节奏。热销商品三天就断货,而滞销品却堆积如山。这次经历让我下定决心搭建一个智能化的销售预测系统。
经过两个月的技术选型,最终选择Spark ML作为核心框架。这不仅因为Spark能轻松处理我们日均TB级的交易数据,更因其MLlib库提供了从特征工程到模型部署的全流程解决方案。下面我就详细记录从零开始构建这个预测系统的完整过程。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与数据准备
2.1 集群配置方案
我们使用5台Dell R740xd服务器组建集群,每台配置:
- 2颗Intel Xeon Gold 6248R (24核/48线程)
- 384GB DDR4内存
- 8块1.92TB SSD (RAID 10)
- Mellanox ConnectX-6 100Gbps网卡
Spark版本选择3.3.2,与CDH6.3.2集成部署。关键配置参数:
bash复制spark.executor.memory=64g
spark.executor.cores=16
spark.dynamicAllocation.enabled=true
spark.sql.shuffle.partitions=2000
2.2 数据管道设计
原始数据源包括:
- MySQL订单表(日增200万条)
- MongoDB用户行为日志
- Kafka实时点击流数据
使用Spark Structured Streaming构建ETL管道:
python复制from pyspark.sql import functions as F
orders_df = spark.read.format("jdbc") \
.option("url", "jdbc:mysql://...") \
.option("dbtable", "orders") \
.load()
user_logs = spark.read.format("mongo") \
.option("uri", "mongodb://...") \
.option("collection", "user_logs") \
.load()
joined_df = orders_df.join(user_logs, "user_id") \
.withColumn("discount_impact", F.when(F.col("coupon_amount")>0, 0.2).otherwise(0.1)) \
.withColumn("weekday", F.dayofweek("order_date"))
3. 特征工程实战
3.1 时序特征提取
对于每个SKU,我们构建了以下特征:
- 移动平均值(3/7/15天窗口)
- 同比变化率(与去年同期的对比)
- 星期周期特征(周一至周日的销售系数)
- 节假日标记(春节、618等特殊日期)
使用Spark窗口函数实现:
python复制from pyspark.sql.window import Window
window_spec = Window.partitionBy("sku_id").orderBy("date").rowsBetween(-7, 0)
df = df.withColumn("7d_avg", F.avg("sales").over(window_spec))
3.2 交叉特征构建
我们发现这些特征组合效果显著:
- 价格段 × 用户年龄段
- 商品类别 × 地域
- 促销力度 × 历史复购率
使用VectorAssembler进行特征合并:
python复制from pyspark.ml.feature import VectorAssembler
assembler = VectorAssembler(
inputCols=["price_level", "user_age", "discount_rate"],
outputCol="features")
4. 模型训练与调优
4.1 算法选型对比
我们测试了三种算法表现:
| 算法 | RMSE | 训练时间 | 可解释性 |
|---|---|---|---|
| 随机森林 | 12.4 | 45min | ★★★☆ |
| GBT | 11.2 | 68min | ★★☆☆ |
| 线性回归 | 15.7 | 12min | ★★★★ |
最终选择梯度提升树(GBT)作为基础模型,因其在准确率和时效性上的平衡。
4.2 超参数优化
使用CrossValidator进行网格搜索:
python复制from pyspark.ml.tuning import ParamGridBuilder
paramGrid = ParamGridBuilder() \
.addGrid(gbt.maxDepth, [5, 10]) \
.addGrid(gbt.maxIter, [20, 50]) \
.build()
crossval = CrossValidator(estimator=pipeline,
estimatorParamMaps=paramGrid,
evaluator=RegressionEvaluator(),
numFolds=3)
5. 生产部署与监控
5.1 模型服务化
将训练好的模型导出为PMML格式,通过JPMML-Spark加载:
java复制SparkContext sc = ...;
JavaRDD<Row> testData = ...;
PMMLModel pmmlModel = PMMLModelUtil.loadPMML("hdfs:///models/gbt_v3.pmml");
Transformer transformer = new PMMLTransformer(pmmlModel);
Dataset<Row> predictions = transformer.transform(testData);
5.2 监控指标设计
在Grafana中配置的监控看板包括:
- 预测准确率(±10%误差带)
- 特征重要性变化趋势
- 各品类预测偏差TOP10
- 模型推理延迟P99
6. 踩坑经验实录
-
数据倾斜问题:
- 现象:某些热门SKU导致任务卡在99%
- 解决:添加随机前缀进行二次聚合
python复制df = df.withColumn("salt", F.round(F.rand()*10)) -
类别特征处理:
- 错误做法:直接对category_id做OneHot
- 正确方案:先统计出现频次,合并长尾类别
-
模型退化应对:
- 建立自动回滚机制
- 保留最近3个版本的模型
- 当预测误差连续3天>15%时触发报警
7. 效果验证与业务收益
上线三个月后的关键指标提升:
- 库存周转率提高37%
- 缺货率下降至5.2%
- 促销资源利用率提升28%
特别是在今年618期间,系统准确预测了iPhone新品预售量,帮助我们提前备货避免了2000万的潜在损失。这个项目让我深刻体会到:好的数据产品必须既懂技术逻辑,更要理解业务本质。
