秒懂算法 | 基于K-Means算法的汽车行驶运动学片段的分类

举报
TiAmoZhang 发表于 2023/02/24 11:16:52 2023/02/24
【摘要】 汽车在行进过程中会产生连续的一组数据,包含加速度,速度等参数,汽车形式运动学片段是指是从一个怠速开始到下一个怠速开始之间的运动行程,通常包括一个怠速部分和一个行驶部分。而怠速指的是汽车停止运动,但发动机保持最低转速运转的连续过程。行驶部分通常包含加速、巡航和减速三种运动模式。

图片1.png

如图1所示为汽车行进过程中产生的数据,图2为一个汽车行驶运动学的片段。

图片2.png

1 汽车行进中产生的数据

图片3.png

2 运动学片段

本文的任务是将汽车行进的数据切分为一个个的运动学片段,再对这些运动学片段进行分类,从而获得每一类运动学片段的代表片段,合成汽车工况。

01、基于K-Means的汽车行驶运动学片段分类

下面用K-Means来对运动学片段进行聚类。聚类时关键的一点在聚类数目的选取上,本文将采取两种方案来对聚类数目进行选取,如代码清单1所示。首先是定义并计算SSE的函数,并绘制出随着聚类数目变化,SSE变化的折线图。

代码清单1 绘制SSE变化曲线图函数

def getSSE(input):
    # 存储不同簇数的SSE值
    distortions = []
    for i in range(1, 11):
        km = KMeans(n_clusters=i, init="k-means++", n_init=10, max_iter=300, tol=1e-4, random_state=0)
        km.fit(input)
        distortions.append(km.inertia_)
    # 绘制结果
    plt.plot(range(1, 11), distortions, marker='o')
    plt.xlabel("Cluster_num")
    plt.ylabel("SSE")
    plt.show()

由于原始数据中,不同特征的量纲不尽相同,如果使用原始数据直接进行聚类,会存在量纲不一致的问题,即数字较大的特征会对模型产生较大影响,因此在进行聚类之前,还需要进行数据归一化的处理,如代码清单2修改main函数为

代码清单2  主函数1

if __name__ == "__main__":
    feature = cutPart()
    scaler = preprocessing.StandardScaler().fit(feature)
    feature = scaler.transform(feature)
    getSSE(feature)

运行main函数,可得SSE变化图如图3所示。

图片4.png

3 SSE随聚类数目变化折线图

如图3所示,随着聚类数目增多,并没有出现及其明显的手肘,但通过观察可得,当聚类数目为23时,误差下降的幅度是最为明显的,从4开始往后,基本上就处于线性递减的状态。因此,最优的聚类数目可能为234中的某一个。

下面通过轮廓图从另一个角度进行分析。首先是绘制轮廓图有关的函数,如代码清单2所示。

代码清单2 绘制轮廓图函数

def getSilehotte(input, n_cluster):
    km = KMeans(n_clusters=n_cluster, init="k-means++", n_init=10, max_iter=300, tol=1e-4, random_state=0)
    y_km = km.fit_predict(input, n_cluster)
    # 获取簇的标号
    cluster_labels = np.unique(y_km)
    silehoutte_vals = silhouette_samples(input, y_km, metric="euclidean")
    y_ax_lower, y_ax_upper = 0, 0
    y_ticks = []
    for i, c in enumerate(cluster_labels):
        # 获得不同簇的轮廓系数
        c_silhouette_vals = silehoutte_vals[y_km == c]
        c_silhouette_vals.sort()
        y_ax_upper += len(c_silhouette_vals)
        color = cm.jet(i / n_cluster)
        plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, edgecolor="none", color=color)
        y_ticks.append((y_ax_lower + y_ax_upper) / 2)
        y_ax_lower += len(c_silhouette_vals)

    silehoutte_avg = np.mean(silehoutte_vals)
    plt.axvline(silehoutte_avg, color="red", linestyle="--")
    plt.yticks(y_ticks, cluster_labels + 1)
    plt.ylabel("Cluster")
    plt.xlabel("Silehotte_value")
plt.show()

该函数的输入为特征以及聚类数目,每个聚类数目可得一个轮廓图。如代码清单3修改main函数为

代码清单3 主函数2

if __name__ == "__main__":
    feature = cutPart()
    scaler = preprocessing.StandardScaler().fit(feature)
    feature = scaler.transform(feature)
    getSilehotte(feature, 2)
    getSilehotte(feature, 3)
    getSilehotte(feature, 4)

分别绘制聚类数目为234时的轮廓图帮助后期分析,运行脚本可得如图4、图5、图6所示。

图片5.png

4 聚类数目为2时轮廓图

图片6.png

5 聚类数目为3时轮廓图

图片7.png

6 聚类数目为4时轮廓图

如图4、图5、图6所示,当聚类个数为2时,轮廓系数表现不错,说明可以有效地聚类。当聚类数目上升到3时,第一类开始出现负值,即聚类效果开始下降,进一步上升到4时,出现了严重的数目不均等,第4类的数目远远小于前三类,基于对轮廓图的分析,可以选择聚类数目为2或者3

倘若将运动学片段分为3类,并对每一类进行分析,可以发现这三类中,第1类平均速度最高,怠速时间比例最低,代表在畅通路段行驶的工况;第3类平均车速最低,怠速时间比例最高,代表拥堵路段行驶的工况;第2类代表一般工况。

对每一类按照距离聚类中心的距离从小到大进行排序,就可以得到每一类的典型运动学片段。在将这些运动学片段进行组合,就可以最终获得汽车行驶工况。

如图7所示为基于K-Means方法合成的汽车行驶工况。

图片8.png

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。