在自动驾驶数据闭环中的特征工程应用(上)
本文将设计一套可以直接在工程中落地、高度模块化的自动驾驶特征工程方案。
这套方案将严格遵循《特征工程入门与实践》的方法论,并为多模态数据(摄像头、激光雷达、毫米波雷达、GNSS-IMU、CAN总线、高精地图)量身定制。我们将按照 理解 → 增强 → 构建 → 选择 → 转换 → 学习 → 评估与闭环 的完整流程,并提供可直接用于代码实现的 scikit-learn 风格设计。
核心原则:流水线(Pipeline)优先,杜绝数据泄露
在动工之前,必须确立最重要的工程实践:所有预处理步骤(填充、缩放、转换等)都必须封装在 scikit-learn 的 Pipeline 中。
-
原因:如果在划分训练/验证/测试集之前,就对全量数据计算均值、方差等统计量来进行填充或标准化,那么测试集的信息就提前“泄露”给了训练过程。这会导致模型在线下评估时过于乐观,而在线上实际应用时性能大幅下降。
-
实践:始终将数据预处理、特征选择、模型训练打包成一个 Pipeline,然后将整个 Pipeline 对象喂给交叉验证(Cross-Validation)工具。这本书中反复强调了这一原则的重要性。

1. 特征理解(Feature Understanding)
目标:摸清多模态数据的家底,进行探索性数据分析(EDA)
1.1 数据对齐与同步
-
时间戳对齐:所有传感器数据(CAN、IMU、摄像头帧、LiDAR扫描)必须对齐到统一的事件时间轴。这是所有后续工作的基础。
-
坐标系对齐:将所有传感器数据统一到同一个坐标系下,通常是车辆的自车坐标系(ego-vehicle frame)。
1.2 建立特征清单与EDA
-
定量特征 (Quantitative):
-
定比 (Ratio): 车速 (km/h)、加速度 (m/s²)、激光雷达点坐标 (x, y, z)、物体距离 (m)。这类数据有绝对零点,可做任何数学运算。
-
定距 (Interval): GPS时间戳(相对时间)、温度。
-
1.3 定性特征 (Qualitative)
-
定类 (Nominal): 道路类型(高速、城市)、天气(晴、雨、雪)、交通信号灯状态(红、绿、黄)。
-
定序 (Ordinal): 拥堵程度(通畅、缓行、拥堵)、光照条件(白天、黄昏、夜晚)。
-
可视化分析:
-
用直方图和箱线图检查车速、加速度的分布和异常值。
-
用相关性热力图初步识别CAN总线信号之间的多重共线性。
-
检查各特征的缺失值比例 (df.isnull().sum())。
-
2.特征增强(Feature Enhancement / Cleaning)
目标:处理数据中的“垃圾”,如缺失值和异常值,并统一量纲。
这些操作应作为 Pipeline 的第一批步骤。
2.1 缺失值处理
-
数值型:对于CAN、IMU等时序数据,使用前向/后向填充 (method='ffill'/'bfill') 比均值填充更合理。对于非时序数值特征,可使用均值或中位数填充。
-
类别型:使用众数填充。
-
实现:使用 sklearn.impute.SimpleImputer 或自定义填充器。
2.2 异常值处理
-
基于物理规则:设定物理上限。例如,车辆加速度不可能超过20m/s²,转向角速度有极限。超过阈值的可视为异常。
-
基于统计:使用IQR(四分位距)或孤立森林(Isolation Forest)来识别和处理异常点。
2.3 标准化/归一化
-
Z分数标准化 (StandardScaler):适用于特征分布近似高斯分布的情况。
-
Min-Max归一化 (MinMaxScaler):将特征缩放到 [0, 1] 区间,适用于深度学习模型和距离计算类模型。例如,图像像素值、点云坐标。
3. 特征构建(Feature Construction)
目标:结合领域知识,从原始数据中“榨取”出信息量更大的新特征。这是最能体现算法工程师价值的一步。
建议按数据源分层构建,并使用 sklearn.compose.ColumnTransformer 将不同来源的特征处理流程并行组合。
3.1 基于车辆动力学 (CAN/GNSS/IMU)
-
瞬时特征:jerk (加速度的变化率,反映平顺性)、航向角速度、曲率(航向角速度 / 速度)。
-
时序窗口特征:使用滑动窗口计算过去N秒的平均速度、速度方差、最大加速度等。
-
安全指标:计算 TTC (碰撞时间)、THW (车头时距),并提取窗口内的最小值、低于安全阈值的次数等。
3.2 基于地图与几何 (HD Map)
-
车道内特征:自车到车道中心线的横向距离 (lane_offset)、自车航向与车道方向的夹角 (heading_delta)、当前车道曲率、坡度、限速。
-
拓扑与语义特征:距离下一个路口/匝道/停车线的距离、当前是否处于可换道区域、前方车道汇入/汇出关系。
3.3 基于感知与场景 (Camera/LiDAR/Radar)
-
目标级特征:与前方最近车辆的纵向/横向距离、相对速度、周围车道车辆计数、ROI内行人/非机动车计数。
-
环境统计特征:BEV(鸟瞰图)视角下,可通行区域面积、障碍物点云密度、图像语义分割后不同类别(道路、建筑、植被)的像素占比。
3.4 编码与分箱
-
类别编码:天气、道路类型使用 OneHotEncoder。
-
定序编码:光照条件、拥堵程度,需自定义映射顺序,确保其大小关系有意义。
-
连续值分箱 (KBinsDiscretizer):将车速、距离等划分为"近/中/远"或"低速/中速/高速"等区间,可以增加模型的非线性能力和鲁棒性。
4. 特征选择(Feature Selection)
目标:剔除噪声和冗余特征,降低模型复杂度,防止过拟合。
4.1 过滤法 (Filter)
-
计算特征与目标变量(如下一步的决策:直行/左转/右转)的相关性、卡方值或互信息。
-
实现:sklearn.feature_selection.SelectKBest。速度快,但忽略了特征间的组合效应。
4.2 嵌入法 (Embedded)
-
L1正则化 (Lasso):能够将不重要特征的系数压缩至0,实现自动特征选择。非常适合处理高维且有共线性的CAN信号。
-
基于树模型的特征重要性:使用随机森林或GDBT模型训练后,提取 feature_importances_ 属性,按重要性筛选。
-
实现:sklearn.feature_selection.SelectFromModel。
4.3 包装法 (Wrapper)
-
通过递归特征消除(RFE)等方法,反复训练模型来寻找最优特征子集。效果好但计算成本高。
5. 特征转换(Feature Transformation)
目标:对特征进行数学变换,以发现更深层次的结构或降低维度。
5.1 主成分分析 (PCA)
-
应用场景:当有大量高度相关的连续特征时(如BEV栅格化后的特征、多个IMU读数),使用PCA可以将其转换为少数几个线性无关的主成分,同时保留大部分信息。
-
作用:降维、去噪、加速模型训练。
5.2 其他数学变换
-
对数变换 (np.log1p):处理长尾分布的特征(如某些传感器读数)。
-
Box-Cox变换:更通用的正态化变换方法。
6. 特征学习(Feature Learning)
目标:利用深度学习模型自动提取特征,适用于图像、点云等非结构化数据
6.1 以AI促进AI
-
上游(特征提取器):使用一个在大规模数据集上预训练好的深度模型(如用于图像的 ResNet、用于点云的 PointPillars)作为特征提取器。冻结其大部分层,只取其倒数第二层的输出作为特征向量。
-
下游(任务模型):将上一步提取的特征向量,输入到一个轻量级的传统机器学习模型中(如 XGBoost, LogisticRegression)。
-
优势:兼具深度学习强大的表征能力和传统模型训练快、可解释性强的优点,是工程落地的绝佳实践。
7.评估与闭环——一个可落地的示例
任务:实现一个简单的换道决策分类器(决策:保持车道/向左换道/向右换道)
7.1. 特征工程 Pipeline 设计 (代码骨架)
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
import lightgbm as lgb# 1. 定义不同类型的特征列名
numeric_features = ['ego_speed', 'ego_accel', 'lane_offset', 'heading_delta', 'ttc_to_front_vehicle']
categorical_features = ['weather_condition', 'lane_change_permission']# 2. 为不同类型的特征创建独立的预处理流水线
numeric_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')), # 缺失值填充('scaler', StandardScaler()) # 标准化
])categorical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='most_frequent')),('onehot', OneHotEncoder(handle_unknown='ignore')) # One-Hot编码
])# 3. 使用 ColumnTransformer 将多个流水线合并
preprocessor = ColumnTransformer(transformers=[('num', numeric_transformer, numeric_features),('cat', categorical_transformer, categorical_features)])# 4. 构建完整的端到端流水线
# 预处理 -> 特征选择 -> 模型训练
model_pipeline = Pipeline(steps=[('preprocessor', preprocessor),('selector', SelectFromModel(RandomForestClassifier(n_estimators=50, random_state=42), threshold='median')), # 基于树模型的特征选择('classifier', lgb.LGBMClassifier(random_state=42)) # 最终的分类器
])# 5. 训练和评估
# from sklearn.model_selection import cross_val_score
# X_train, y_train = ...
# model_pipeline.fit(X_train, y_train)
# scores = cross_val_score(model_pipeline, X, y, cv=5) # 在交叉验证中评估整个流水线
# print(f"交叉验证平均分: {scores.mean():.3f}")
7.2. 评估与迭代
-
基线对比:始终与一个不包含复杂特征工程(只做最基本清洗)的基线模型进行性能对比。
-
分场景评估:绝不能只看总体准确率。必须分组评估模型在不同天气(雨天/夜晚)、不同道路类型(高速/城市)、不同交通密度下的性能表现,确保模型的鲁棒性和安全性。
-
特征监控:将特征构建逻辑部署上线后,必须持续监控线上数据的分布,防止发生“特征漂移”(线上数据分布与训练时差异过大),并建立自动告警和模型更新机制。
这套结合了《特征工程入门与实践》理论和自动驾驶领域实践的方案,为你提供了一个结构清晰、可扩展、易于维护的工程化框架。更加细节的讨论大家可以阅读在自动驾驶数据闭环中的特征工程应用(下)
