You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Scikit Learn/Numpy区分线性飞行航迹与非线性异常路径

基于Numpy与Scikit-learn的线性/非线性航迹区分实现

你已经完成航迹中心化,无需再处理全局坐标偏移问题,核心抓两类航迹的本质差异即可:民航线性航迹几乎沿直线行进,仅存在小幅方向微调;异常军机航迹偏离直线程度高,存在大角度急转弯。整个实现分两步走,特征工程用Numpy完成,分类用Scikit-learn实现,不需要复杂模型。

第一步:特征计算(Numpy实现,核心环节)

先统一处理每条航迹:先按时间戳排序避免点序混乱,再计算5个区分度极高的统计特征,代码如下:

import numpy as np

def extract_track_features(track):
    """
    输入单条中心化后的航迹数组,shape=(N,3),列顺序为纬度、经度、时间戳
    输出该航迹的特征向量
    """
    # 按时间戳重排,避免原始数据乱序
    track = track[np.argsort(track[:, 2])]
    lats, lons, ts = track[:, 0], track[:, 1], track[:, 2]
    features = []

    # 1. 线性拟合残差:线性航迹的点会紧贴时间-经纬度的拟合直线,残差极小
    t_norm = (ts - ts.min()) / (ts.max() - ts.min() + 1e-8)  # 时间归一化避免数值问题
    # 分别对纬度、经度做一阶线性拟合
    lat_coef = np.polyfit(t_norm, lats, deg=1)
    lon_coef = np.polyfit(t_norm, lons, deg=1)
    lat_pred = np.polyval(lat_coef, t_norm)
    lon_pred = np.polyval(lon_coef, t_norm)
    total_residual = np.mean(np.abs(lats - lat_pred)) + np.mean(np.abs(lons - lon_pred))
    features.append(total_residual)

    # 2. 转向角统计:异常航迹存在大角度急转,该类特征区分度最高
    displacements = np.diff(track[:, :2], axis=0)  # 相邻点位移向量
    angles = np.arctan2(displacements[:, 1], displacements[:, 0])  # 每个航段的方位角
    turn_angles = np.abs(np.diff(np.unwrap(angles)))  # 相邻航段的转角绝对值,unwrap处理角度环绕问题
    features.extend([
        np.max(turn_angles),   # 最大转角
        np.mean(turn_angles),  # 平均转角
        np.std(turn_angles)    # 转角波动标准差
    ])

    # 3. 航迹弯曲度:总路径长度/首尾点直线距离,直线航迹该值接近1,越弯曲值越大
    segment_lengths = np.linalg.norm(displacements, axis=1)
    total_length = segment_lengths.sum()
    start_end_length = np.linalg.norm(track[-1, :2] - track[0, :2])
    sinuosity = total_length / (start_end_length + 1e-8)
    features.append(sinuosity)

    return np.array(features)

第二步:航迹分类(Scikit-learn实现)

根据你有没有标注数据,选监督或者无监督方案即可:

有标注数据(监督分类,准确率最高)

特征维度只有5个,不需要复杂模型,用随机森林或者逻辑回归就足够,泛化性强还不容易过拟合:

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

# 先批量提取所有航迹的特征,X shape=(航迹总数, 5),y为标签:0=民航线性航迹,1=异常军机航迹
# X = np.array([extract_track_features(t) for t in all_tracks])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 构建分类流水线:先做特征标准化,再训练分类器
clf = make_pipeline(
    StandardScaler(),
    RandomForestClassifier(n_estimators=100, random_state=42)
)
clf.fit(X_train, y_train)

# 效果评估
print(classification_report(y_test, clf.predict(X_test)))

无标注数据(无监督异常检测)

实际场景中民航航迹占绝大多数,异常航迹属于离群点,直接用孤立森林检测即可,甚至手动设阈值都能达到很高的准确率:

手动阈值参考(可根据自有数据集微调):

  • 最大转角超过0.5弧度(约30度)直接判定为异常
  • 航迹弯曲度大于1.15直接判定为异常
  • 线性拟合残差超过正常航迹均值+3倍标准差判定为异常

无监督检测代码:

from sklearn.ensemble import IsolationForest

# contamination为数据集中异常航迹的预估占比,按实际场景调整
detector = IsolationForest(contamination=0.05, random_state=42)
detector.fit(X)
# 预测结果:1=正常线性航迹,-1=异常非线性航迹
predict_result = detector.predict(X)

补充说明

  • 如果航迹采样间隔不均匀,先按固定时间间隔对航迹重采样再算特征,避免采样点疏密带来的计算偏差
  • 如果航迹覆盖的纬度范围超过5度,建议先把经纬度转成局部平面坐标(比如UTM投影)再计算角度、距离,结果会更精准
  • 这几个手工特征的区分度已经足够,不需要上深度学习或者复杂的轨迹模型,可解释性远高于黑盒模型

内容的提问来源于stack exchange,提问作者JHM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:09:59