数据采集与存储:日志系统设计、数据清洗、特征工程、数据仓库选型
数据回放这件事,说白了就是「把历史数据喂给算法看」。但有个问题——你喂进去的是垃圾,吐出来的只能是垃圾。我在项目中见过太多团队,算法模型调得飞起,结果数据一换全崩了。为什么?数据采集和存储这步就没走稳。
今天咱们就聊聊,怎么把数据从源头管好,让后续的算法迭代少踩坑。
日志系统设计:别让数据丢了
日志系统是数据回放的起点。你想想看,如果日志丢了、格式乱了、时间戳对不上,后面所有工作都是白费。
我个人习惯,日志系统设计要抓住三个核心:
- 完整性:每条日志都不能丢,尤其是关键事件
- 时序性:时间戳必须精确到毫秒,最好用NTP同步
- 可回溯:能根据某个ID把整条链路串起来
举个例子,我在做自动驾驶数据采集时,要求每帧数据必须包含:
{
"timestamp": 1680000000123, // 毫秒级时间戳
"vehicle_id": "car_001",
"sensor_type": "lidar",
"data": "...", // 原始数据
"context": { // 上下文信息
"weather": "sunny",
"location": "lat,lon"
}
}
我曾经遇到过一个项目,日志里时间戳格式五花八门,有的用UTC,有的用本地时间,还有的干脆没写时区。结果数据回放时,算法看到的事件顺序全是乱的。嗯,那次我们花了整整一周才把数据对齐。
数据清洗:脏数据是算法的天敌
数据清洗听着简单,做起来全是坑。我总结了一套「三步清洗法」:
- 格式清洗:统一字段类型、单位、编码
- 异常清洗:处理缺失值、重复值、离群点
- 逻辑清洗:检查数据间的逻辑一致性
举个实际例子,传感器数据里经常出现「跳变」——前一帧速度是30km/h,下一帧突然变成300km/h。这种数据不洗掉,算法会学出什么奇怪的东西?
def clean_sensor_data(df):
# 1. 格式清洗:确保时间戳是数值型
df['timestamp'] = pd.to_numeric(df['timestamp'], errors='coerce')
# 2. 异常清洗:速度超过物理极限的,直接剔除
df = df[df['speed'] < 200] # 单位km/h
# 3. 逻辑清洗:加速度变化不能太离谱
df['accel'] = df['speed'].diff() / df['timestamp'].diff()
df = df[df['accel'].abs() < 20] # 单位m/s²
return df
特征工程:把原始数据变成算法能懂的语言
特征工程,说白了就是「翻译」。原始数据是传感器读数、日志文本,算法看不懂。你得把它翻译成数值、向量、特征组合。
我常用的特征工程方法:
- 统计特征:均值、方差、最大值、最小值、分位数
- 时序特征:滑动窗口、差分、傅里叶变换
- 组合特征:两个字段的比值、乘积、差值
- 编码特征:类别变量做one-hot或embedding
举个例子,处理车辆轨迹数据时,我习惯这样构造特征:
def extract_features(trajectory_df):
features = {}
# 统计特征
features['avg_speed'] = trajectory_df['speed'].mean()
features['max_accel'] = trajectory_df['accel'].max()
# 时序特征:过去5秒的滑动窗口
window = trajectory_df.tail(50) # 假设10Hz采样
features['window_avg_speed'] = window['speed'].mean()
# 组合特征:速度与转向角的关系
features['speed_turn_ratio'] = (
trajectory_df['speed'] * trajectory_df['steering_angle']
).mean()
return features
核心原则:特征不是越多越好。我见过有人一口气造了200个特征,结果模型过拟合得一塌糊涂。记住:每个特征都要有物理意义,能解释「为什么这个特征对算法有帮助」。
数据仓库选型:选对了省一半力气
数据仓库选型,我把它分成三个场景:
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 小规模(<1TB) | PostgreSQL + TimescaleDB | 部署简单,时序查询快,适合团队起步 |
| 中规模(1-10TB) | ClickHouse | 列式存储,聚合查询极快,适合分析场景 |
| 大规模(>10TB) | Apache Doris / StarRocks | 分布式架构,支持实时写入和高并发查询 |
我个人习惯,起步阶段先用PostgreSQL。为什么?因为团队小,折腾不起分布式。等数据量上来了,再平滑迁移到ClickHouse。我曾经见过一个团队,一上来就上Hadoop,结果三个月过去了,数据还没导进去。
知识体系总览
下面这张图,是我对数据采集与存储整个流程的理解:
你看,从日志系统到数据仓库,每个环节都在为「高质量数据」服务。数据质量上去了,算法迭代才能快起来。我见过太多团队在算法上花90%的精力,却忽略了数据基础——结果就是事倍功半。
好了,数据采集与存储这部分就聊到这儿。记住:数据是算法的燃料,燃料不纯,引擎再牛也跑不远。