# price_predict **Repository Path**: fubob/price_predict ## Basic Information - **Project Name**: price_predict - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-13 - **Last Updated**: 2026-04-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 1. 数据及划分 1. 数据shuffle,并编入唯一id 2. 14000条数据用作训练,剩余1000条用于模型评测 # 2. 数据概况及分布分析 ## 2.1 字段含义 | 字段 | 含义(简要) | | :----------------- | :----------------------------------------------------------- | | RFQID | 询价单(RFQ)编号,一次询价可含多行零件/方案。 | | ProjectNumber | 项目编号,用于把多条记录归到同一项目。 | | PartNumber | 零件标识,常为 STEP 等文件名,与几何一一对应。 | | CostEngineer | 负责成本/报价的工程师账号(类别特征)。 | | Country | 国家/地区代码(如 US、GB),多与区域或供应链相关。 | | BilletType | 坯料类型:如板料(Plate)、圆棒(Round Bar)等。 | | Difficulty | 加工难度:Easy / Medium / Difficult。 | | MillingTurning | 工艺大类:如铣削(Milling)、车削等(你这份数据里多为 Milling)。 | | X, Y, Z | 零件包络尺寸(外接长方体的长、宽、高类尺寸)。 | | Volume | 体积(由 CAD 计算,与几何实体对应)。 | | FacesNumber | 面数量(CAD 模型拓扑)。 | | EdgeNumber | 边数量(CAD 模型拓扑)。 | | SurfaceArea | 表面积(加工接触面、工艺难度常与之相关)。 | | PriceHKD | 与材料/采购单价相关的数值(名称带 HKD,多与港币计价体系有关;具体口径以业务定义为准)。 | | Density | 密度(材料属性,用于重量/体积关系)。 | | Machinability | 可加工性系数或评分(材料越难加工值往往不同)。 | | Complexity | 复杂度评分(几何或工艺复杂程度)。 | | AIComplexity | 另一套复杂度指标(可能来自规则或模型,与 `Complexity` 并存)。 | | ToleranceLevel | 公差等级/要求(越高通常加工与检测成本越高)。 | | BilletWeight | 坯料重量(下料/投料重量类指标)。 | | BilletPrice | 与坯料/材料成本相关的单价或金额类输入(与 `BilletWeight`、材料方案等一起参与报价)。 | | MaterialMultiplier | 材料倍率(对材料成本的放大系数类业务参数)。 | | PPP | 业务侧计价倍率/系数。 | | Quantity | 订购数量(同零件可有多行不同数量档)。 | | ScrapQty | 废品/余量数量(或含损耗的件数,与批量报价相关)。 | | MinPrice | 最低可报价格或底价类约束 | ## 2.2 数据分析 ## 1)数据整体概况(shape / 目标列) - **样本量**:`train` = **(13999, 29)** - **目标列**:自动识别为 **`ManualPrice`** - **特征数**:**28 列** - **ID/高基数字段(不建议朴素 one-hot)**:`RFQID`、`ProjectNumber`、`PartNumber` --- ## 2)字段概览(dtype / unique) 从 `overview_df` 可见: - **类别列(7 个)**:`PartNumber`、`ProjectNumber`、`Country`、`CostEngineer`、`Difficulty`、`BilletType`、`MillingTurning` - `PartNumber`(5226 unique)与 `ProjectNumber`(1939 unique)属于**典型高基数类别**。 - **建议**:用 **CatBoost 原生类别** 或 **KFold Target Encoding** / hashing / 频次截断;不要全量 one-hot。 - **数值列(21 个)**:尺寸几何(`X,Y,Z,Volume,SurfaceArea,FacesNumber,EdgeNumber`)、材料与复杂度(`Density,Machinability,Complexity,AIComplexity,ToleranceLevel`)、成本相关(`BilletWeight,BilletPrice,MaterialMultiplier,PPP,Quantity,ScrapQty,MinPrice,PriceHKD`)等。 --- ## 3)缺失、重复(数据质量) - **缺失值**:各列缺失率 **均为 0**(对建模非常友好) - **重复行**:`duplicated rows = 349 (2.493%)` - **建议**:先不要直接删。 - 若“完全重复且目标也相同”,可以去重。 - 若“特征完全相同但 `ManualPrice` 不同”,说明存在噪声/隐藏变量,建模更适合 **MAE/Huber** 等鲁棒目标,并加强分组特征。 --- ## 4)数值特征分布(长尾/量纲跨度) 从 `describe` 分位数可见,多数关键数值列都呈现长尾(p99 显著大于 p50): - 典型长尾:`Volume`、`SurfaceArea`、`FacesNumber/EdgeNumber`、`Quantity/ScrapQty`、`MinPrice/BilletPrice/BilletWeight` **建议(高收益特征工程)**: - **log1p 变换**:对 `Volume/SurfaceArea/BilletPrice/BilletWeight/MinPrice/Quantity/ScrapQty` 尝试 `log1p`(必要时先 `clip(x, >=0)`)。 - **比例/密度特征(强烈推荐)** - `SurfaceArea / Volume` - `BilletPrice / BilletWeight` - `ScrapQty / Quantity`、`Quantity - ScrapQty`、`ScrapQty > 0` - **交互项**:`Complexity/AIComplexity` × `FacesNumber/EdgeNumber` × `ToleranceLevel` --- ## 5)目标 `ManualPrice` 分布(回归难点) `ManualPrice.describe()`(你输出的关键值): - **count=13999** - **mean=688.16,median=409.72**(均值明显高于中位数,右偏长尾) - **min=0.18,max=2960.19** **结论与建议**: - 这是典型的**右偏长尾回归**。 - **强建议**:训练时优先用 **`log1p(ManualPrice)`** 做目标(预测后 `expm1` 还原)。 - 评估指标优先 **MAE**(原始价用 MAPE/SMAPE 需谨慎处理接近 0 的样本)。 --- ## 6)Quantity 分组(规模效应非常明显) 按 `Quantity` 聚合的结果显示:**数量越大,mean/median 整体下降**(典型规模效应)。 **建议**: - 增加 `log1p(Quantity)`、`1/(Quantity+1)`、`Quantity` 分箱(1、2-5、6-20、21-100、100+) - 加交互:`log1p(Quantity) * BilletPrice`、`log1p(Quantity) * Complexity` 等 --- ## 7)与目标的数值相关性(快速筛强信号) 输出的相关性(`corr_with_target`)中,信号较强的数值列: - **正相关较强**:`MinPrice(0.333)`、`BilletPrice(0.326)`、`X/Y(~0.30)`、`BilletWeight(0.284)`、`Volume/SurfaceArea(~0.246)`、`PPP(0.211)`、`Complexity/Z(~0.199)` - **弱负相关**:`Quantity(-0.095)`、`ScrapQty(-0.095)`(与规模效应一致) **建议**: - 建模要重点吃到 **材料成本(BilletPrice/Weight/MinPrice) + 尺寸几何(X/Y/Z/Volume/SurfaceArea) + 工艺复杂度(PPP/Complexity)**。 - **风险提示(重要)**:`MinPrice` 可能与 `ManualPrice` 存在“下限约束/派生关系”。建议额外检查: - 是否几乎总满足 `ManualPrice >= MinPrice` - `ManualPrice` 是否由 `MinPrice` 直接规则计算 - 若是强派生,使用 `MinPrice` 会造成“伪高分/信息泄漏” --- ## 8)类别特征分组差异(结构性差异明显) 按类别分组的 mean/median 输出表明: - **Country 差异显著**:例如 `US` 均值高于 `GB`,`RU` 较低,少样本国家(如 `SE/IE`)均值高但需谨慎(样本少)。 - **BilletType**:`Plate` 的 mean/median 明显高于 `Round Bar`。 - **Difficulty**:`Easy` 的均值/中位数反而高于 `Difficult`(反直觉,提示该字段与尺寸/数量等强相关,需要树模型自动学习交互)。 - **MillingTurning**:全为 `Milling`,对模型几乎无信息,可直接丢弃。 - **CostEngineer**:不同工程师均值差异明显(强信号但易过拟合)。 **编码建议**: - `Country/BilletType/Difficulty/CostEngineer/ProjectNumber/PartNumber`: - 优先 **CatBoost**(原生类别)或 **KFold Target Encoding**(必须分折防泄漏) - 增加**频次特征**: - `count(PartNumber)`、`count(ProjectNumber)`、低频标记(<=k)等 - 低频合并: - `Country` 低频合并为 `Other`,提升稳定性 --- ## 9)异常值与分布(为什么树模型更合适) 多列长尾 + 极端值存在,线性模型对尺度/异常值敏感。 **建议**: - 首选 **LightGBM / CatBoost / XGBoost**(表格回归强项) - 线性模型(Ridge/Lasso)仅做 sanity check --- ## 10)最短建模路径 - **Baseline**: - 目标:`y = log1p(ManualPrice)` - 模型:`CatBoostRegressor`(或 LightGBM + 目标编码) - 验证:KFold - 指标:MAE - **第一轮特征工程(高收益低风险)**: - `log1p`:`Volume/SurfaceArea/BilletPrice/BilletWeight/MinPrice/Quantity/ScrapQty` - 比例:`SurfaceArea/Volume`、`BilletPrice/BilletWeight`、`ScrapQty/Quantity` - 频次:`PartNumber/ProjectNumber` 的频次与低频标记 - 低频合并:`Country -> Other` - **防过拟合要点**: - `PartNumber/ProjectNumber/CostEngineer` 必须用 **CV 目标编码** 或 CatBoost;不要直接全量 one-hot # 3. 启动mlflow ``` mlflow ui --backend-store-uri "file:./mlruns" --port 5000 ``` # 4. 构建baseline 设置评估指标 - MAE - MedianAE - RMSE - R2 - MAPE(自动过滤 y≤1e−9*y*≤1*e*−9 避免爆炸) - sMAPE ![img_v3_0210k_74441ef4-17ce-4b35-a163-5a0dce2122hu](https://p.ipic.vip/2owf7l.jpg) # 6. 误差分析 ```json { "mae":44.2693403749, "median_ae":15.934, "rmse":94.7654648107, "r2":0.9817165833, "mape":0.1363821129, "smape":0.0883950595 } ``` ![hist_err](https://p.ipic.vip/6v4pf9.png) ![hist_log1p_abs_err](https://p.ipic.vip/dfnmsw.png) ![scatter_pred_vs_true](https://p.ipic.vip/uxcmc4.png) 误差分析: - 模型:`xgboost`(`objective=reg:absoluteerror`),log_target=true,target_enc=true,n_splits=20 - 总体效果(true.csv 上):`MAE≈47.76`,`MedianAE≈17.68`,`RMSE≈100.21`,`R2≈0.9796`,`MAPE≈0.126`,`sMAPE≈0.094` - 误差结构:`MedianAE` 远小于 `MAE/RMSE`,说明主要问题来自少量大错样本(长尾) - 最差样本特征(`worst_abs_err_top50.csv`):很多是 高价(ManualPrice 2000~3000)被明显低估,单点绝对误差 500~700+ - 最差 APE(`worst_ape_top50.csv`):存在 真实值极小(例如 0.6)但预测到 21+,这是典型的小目标样本被系统性高估(也可能是 target encoding 对稀有类别过拟合导致) - 分组(`group_error__Country.csv`):`GB` 的 MAPE 很高(~0.255),说明 GB 组里“相对误差”更大(通常与低价样本更多/分布更偏小有关) - 分桶(`bin_error__Quantity.csv`):`Quantity` 很低的桶(1~2)MAE=137 且 `mean_y≈1909`,表明单件/小批量高价样本是大错主来源 # 7. 特征改进/参数调优 #### 7.1 “目标编码(TE)过拟合”问题(对 worst APE 最有效) 现在的 TE 是“直接取均值”,没有平滑/最小样本数约束,稀有类别会把预测拉飞(特别容易造成 true 很小但 pred 很大这种 APE 爆炸)。 做两组对比实验(用 MLflow 记录): - A:关掉 TE,只保留__freq + __cat - B:保留 TE 但加平滑 预期:MAPE/sMAPE 和 worst_ape 会明显改善,MAE可能小幅变化。 #### 2)把 `Quantity` 的规模效应“显式建模”(对 worst_abs 最有效) 从分桶看,`Quantity` 很低时误差最大,建议加更强的特征: - `Quantity` 分箱特 - 与成本/几何的交互:`log1p(Quantity)*log1p(BilletPrice)`、`log1p(Quantity)*Complexity`、`log1p(Quantity)*log1p(Volume)` - 甚至做 两阶段模型:先按 `Quantity<=2` / `>2` 切开分别训练(先用最简单的分段就能验证收益) #### 3)XGBoost 的目标/超参(把大错样本压下来) 在 log 目标 上用 `reg:absoluteerror`,是可以的,但为了减少 “高价被低估” 的大错,建议试: - 目标函数对比 (只改 1 个因素做 ablation): - 继续 `reg:absoluteerror` - 改成 `reg:squarederror`(在 log 空间常常更稳,且对大偏差更敏感) - 容量/正则方向 (优先试这几项): - `max_depth`: 6/8/10 - `min_child_weight`: 1/5/10(提高可抑制过拟合与极端预测) - `subsample`/`colsample_bytree`: 0.7~0.9 网格 - `reg_lambda`: 1/3/10(更强 L2 有时能显著减少 worst APE) > 你现在没有早停(XGB 没配 eval_set),建议后面加 early stopping,调参会快很多。 #### 4)评估与 CV 策略:避免“同类泄漏”导致线下偏乐观 如果 `PartNumber/ProjectNumber` 同类样本跨折出现,随机 KFold 会更乐观。建议做一版: - GroupKFold by `PartNumber`(或 `ProjectNumber`) 用来检验你模型对“新零件/新项目”的泛化能力;这会直接影响你下一步特征工程方向。