2. 数据探索与可视化
拿到无人机遥测数据的第一件事是什么?不是急着建模,也不是跑算法。我个人的习惯是——先跟数据「聊聊天」。说白了,就是通过可视化和统计分析,摸清数据的脾气秉性。这一步做扎实了,后面的异常检测才能有的放矢。
我记得刚入行那会儿,有一次处理某款固定翼的遥测数据,上来就套用了一个复杂的LSTM模型。结果折腾了两天,效果惨不忍睹。后来回头一看,原来是数据里有个传感器通道一直输出恒定值——那玩意儿早就坏了。要是早点画个时序图,一眼就能发现问题。嗯,从那以后,我再也不敢跳过数据探索这一步了。
2.1 用Pandas加载遥测数据
遥测数据最常见的格式就是CSV。Pandas读CSV,一行代码的事。但这里有个坑——无人机遥测数据的时间戳,往往不是标准的datetime格式。
import pandas as pd
import numpy as np
# 加载数据
df = pd.read_csv('uav_telemetry.csv')
# 看一眼数据长什么样
print(df.head())
print(df.info())
print(df.describe())
你想想看,如果时间戳是「2024-03-15 14:23:45.123」这种格式,Pandas默认会当成字符串处理。我建议你第一时间把它转成datetime类型:
df['timestamp'] = pd.to_datetime(df['timestamp'])
df.set_index('timestamp', inplace=True)
为什么要这么做?因为后面画时序图、做时间窗口分析,都依赖这个索引。我曾经遇到过一个项目,数据量有上千万条,时间戳没处理好,导致后续所有分析都慢了十倍。血的教训啊。
dtype={'col1': 'float32'} 可以省一半内存。我一般还会用 parse_dates=['timestamp'] 直接在读取时解析时间。
2.2 时序图:一眼看穿数据趋势
时序图是最直观的工具。把时间放在X轴,遥测参数放在Y轴,一条折线画下来,数据有没有异常,基本一目了然。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(14, 6))
plt.plot(df.index, df['altitude'], linewidth=0.8, color='#2c7bb6')
plt.title('无人机高度时序变化', fontsize=14)
plt.xlabel('时间')
plt.ylabel('高度 (m)')
plt.grid(alpha=0.3)
plt.show()
画出来之后,你可能会看到几种典型模式:
- 平稳波动:正常飞行,高度在合理范围内上下浮动
- 突然跳变:比如从100米瞬间跳到-50米——这明显是传感器故障
- 长时间恒定:某个参数连续几百个点数值不变,传感器可能「死」了
- 周期性震荡:可能是PID参数调得不好,或者气流扰动
我个人习惯把多个关键参数画在同一张图上,用不同颜色区分。这样能发现参数之间的联动关系。比如高度下降时,空速是不是也跟着降?如果高度降了空速反而升,那就有意思了——可能是失速前兆。
2.3 箱线图:揪出离群点
时序图能看出趋势,但离群点(outlier)有时候藏在密密麻麻的数据点里,肉眼很难发现。这时候箱线图就派上用场了。
plt.figure(figsize=(10, 6))
sns.boxplot(data=df[['altitude', 'speed', 'battery_voltage', 'gyro_x']])
plt.title('关键参数箱线图', fontsize=14)
plt.ylabel('数值')
plt.show()
箱线图的核心逻辑很简单:
- 箱子中间那条线是中位数
- 箱子上下边缘是四分位数(Q1和Q3)
- 箱子外面的「须」延伸到1.5倍IQR(四分位距)
- 须之外的点,就是离群点
为什么会这样?因为正常数据大部分都集中在箱子内部。那些远远飘在外面的点,要么是传感器噪声,要么是真实异常。
我曾经处理过一批无人机电池电压数据,箱线图显示有几十个点电压低于3.0V。正常锂电池最低也就3.3V左右。后来一查,是那次飞行中电池过放了,差点炸机。嗯,箱线图帮我提前发现了隐患。
2.4 数据分布分析:理解数据的「性格」
数据分布分析,说白了就是看看每个参数的值是怎么分布的。是集中在某个区间?还是分散得到处都是?
最常用的工具是直方图和核密度估计(KDE)。
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
sns.histplot(df['altitude'], bins=50, kde=True, color='#2c7bb6')
plt.title('高度分布直方图')
plt.subplot(1, 2, 2)
sns.kdeplot(df['altitude'], fill=True, color='#d7191c')
plt.title('高度核密度估计')
plt.tight_layout()
plt.show()
看分布图的时候,我一般关注这几个点:
- 单峰还是多峰:单峰说明数据集中在某个值附近;多峰可能意味着飞行状态发生了变化(比如起飞、巡航、降落三个阶段高度分布不同)
- 偏态:数据偏向一边,可能是传感器有系统偏差
- 拖尾:尾巴拖得很长,说明存在极端值
- 尖峰:数据过于集中在某个值,可能是传感器分辨率不够,或者数据被截断了
你想想看,如果某个传感器的数据分布是完美的正态分布,那反而值得怀疑——真实世界的遥测数据很少这么「完美」。我遇到过有人用模拟数据冒充真实遥测,一看分布图就露馅了。
df[df['flight_mode'] == 'cruise']['altitude'] 这样筛选。
2.5 知识体系总览
下面这张图,是我自己总结的数据探索与可视化流程。你可以把它当作一个检查清单,每次拿到新数据都走一遍。
这张图展示了我做数据探索的标准流程:从加载数据开始,经过清洗,然后兵分三路——时序图看趋势、箱线图找离群点、分布分析理解数据性格。最后所有信息汇聚到一起,为异常检测模型提供高质量的特征输入。
说白了,数据探索不是为了画几张漂亮的图。它是为了回答三个问题:数据可信吗?数据有什么规律?哪些地方可能藏着异常?把这三个问题搞清楚了,后面的建模工作才能事半功倍。
可可精品资料库