时间序列聚类的直观方法

一、介绍

        我们将使用轮廓分数和一些距离度量来执行时间序列聚类实验,同时利用直观的可视化,让我们看看下面的时间序列:

        这些可以被视为具有正弦、余弦、方波和锯齿波的四种不同的周期性时间序列

        如果我们添加随机噪声和距原点的距离来沿 y 轴移动序列并将它们随机化以使它们几乎难以辨别,则如下所示 - 现在很难将时间序列列分组为簇:

        上面的图表是使用以下脚本创建的:

# Import necessary libraries
import os
import pandas as pd
import numpy as np# Import random module with an alias 'rand'
import random as rand
from scipy import signal# Import the matplotlib library for plotting
import matplotlib.pyplot as plt# Generate an array 'x' ranging from 0 to 5*pi with a step of 0.1
x = np.arange(0, 5*np.pi, 0.1)# Generate square, sawtooth, sin, and cos waves based on 'x'
y_square = signal.square(np.pi * x)
y_sawtooth = signal.sawtooth(np.pi * x)
y_sin = np.sin(x)
y_cos = np.cos(x)# Create a DataFrame 'df_waves' to store the waveforms
df_waves = pd.DataFrame([x, y_sawtooth, y_square, y_sin, y_cos]).transpose()# Rename the columns of the DataFrame for clarity
df_waves = df_waves.rename(columns={0: 'time',1: 'sawtooth',2: 'square',3: 'sin',4: 'cos'})# Plot the original waveforms against time
df_waves.plot(x='time', legend=False)
plt.show()# Add noise to the waveforms and plot them again
for col in df_waves.columns:if col != 'time':for i in range(1, 10):# Add noise to each waveform based on 'i' and a random valuedf_waves['{}_{}'.format(col, i)] = df_waves[col].apply(lambda x: x + i + rand.random() * 0.25 * i)# Plot the waveforms with added noise against time
df_waves.plot(x='time', legend=False)
plt.show()

二、问题陈述

现在我们需要决定聚类的基础。可能有两种方法:

  1. 我们希望将更接近一组的波形分组——欧氏距离较低的波形将被组合在一起。
  2. 我们想要对看起来相似的波形进行分组 - 它们具有相似的形状,但欧氏距离可能不低

2.1 距离度量

一般来说,我们希望根据形状 (2) 对时间序列进行分组,对于这样的聚类,我们可能希望使用距离度量,例如相关性,它们或多或少独立于波形的线性移位。

让我们检查一下具有上述定义的噪声的波形对之间的欧氏距离和相关性的热图:

        使用欧几里德距离对波形进行分组很困难,因为我们可以看到任何波形对组中的模式都保持相似,例如平方和余弦之间的相关形状与平方和平方非常相似,除了对角线元素之外

        我们可以看到,使用相关热图可以轻松地将所有形状组合在一起 - 因为相似的波形具有非常高的相关性(sin-sin 对),而 sin 和 cos 等对的相关性几乎为零。

2.2 剪影分数

        分析上面显示的热图并根据高相关性分配组看起来是一个好主意,但是我们如何定义相关性阈值,高于该阈值我们应该对时间序列进行分组。看起来像是一个迭代过程,容易出现错误并且需要大量的手动工作。

        在这种情况下,我们可以利用 Silhouette Score 为执行的聚类分配一个分数。我们的目标是最大化剪影得分。Silhouette 分数是如何工作的——尽管这可能需要单独讨论——让我们回顾一下高级定义

  1. 轮廓得分计算:单个数据点的轮廓得分是通过将其与其自身簇中的点的相似度(称为“a”的度量)与其与该点不属于的最近簇中的点的相似度进行比较来计算的(称为“b”的措施)。该点的轮廓得分由 (b — a) / max(a, b) 给出。
  • a(内聚性):衡量该点与其自身簇中其他点的相似程度。较高的“a”表示该点在其簇内的位置很好。
  • b(分离):测量点与最近邻簇中的点的不同程度。较低的“b”表示该点远离最近簇中的点。
  • 轮廓分数的范围从 -1 到 1,其中高值(接近 1)表示该点聚类良好,低值(接近 -1)表示该点可能位于错误的聚类中。

2.解读剪影分数:

  • 所有点的平均轮廓得分较高(接近 1)表明聚类定义明确且不同。
  • 较低或负的平均轮廓分数(接近 -1)表明重叠或形成不良的簇。
  • 0 左右的分数表示该点位于两个簇之间的边界上。

2.3 聚类

        现在让我们利用上面计算的两个版本的距离度量,并尝试在利用 Silhouette 分数的同时对时间序列进行分组。测试结果更容易,因为我们已经知道存在四种不同的波形,因此理想情况下应该有四个簇。

欧氏距离

############ reduing components on eucl distance metrics for visualisation #######
pca = decomposition.PCA(n_components=2)
pca.fit(df_man_dist_euc)
df_fc_cleaned_reduced_euc = pd.DataFrame(pca.transform(df_man_dist_euc).transpose(), index = ['PC_1','PC_2'],columns = df_man_dist_euc.transpose().columns)index = 0
range_n_clusters = [2, 3, 4, 5, 6, 7, 8]# Iterate over different cluster numbers
for n_clusters in range_n_clusters:# Create a subplot with silhouette plot and cluster visualizationfig, (ax1, ax2) = plt.subplots(1, 2)fig.set_size_inches(15, 7)# Set the x and y axis limits for the silhouette plotax1.set_xlim([-0.1, 1])ax1.set_ylim([0, len(df_man_dist_euc) + (n_clusters + 1) * 10])# Initialize the KMeans clusterer with n_clusters and random seedclusterer = KMeans(n_clusters=n_clusters, n_init="auto", random_state=10)cluster_labels = clusterer.fit_predict(df_man_dist_euc)# Calculate silhouette score for the current cluster configurationsilhouette_avg = silhouette_score(df_man_dist_euc, cluster_labels)print("For n_clusters =", n_clusters, "The average silhouette_score is :", silhouette_avg)sil_score_results.loc[index, ['number_of_clusters', 'Euclidean']] = [n_clusters, silhouette_avg]index += 1# Calculate silhouette values for each samplesample_silhouette_values = silhouette_samples(df_man_dist_euc, cluster_labels)y_lower = 10# Plot the silhouette plotfor i in range(n_clusters):# Aggregate silhouette scores for samples in the cluster and sort themith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]ith_cluster_silhouette_values.sort()# Set the y_upper value for the silhouette plotsize_cluster_i = ith_cluster_silhouette_values.shape[0]y_upper = y_lower + size_cluster_icolor = cm.nipy_spectral(float(i) / n_clusters)# Fill silhouette plot for the current clusterax1.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_silhouette_values, facecolor=color, edgecolor=color, alpha=0.7)# Label the silhouette plot with cluster numbersax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))y_lower = y_upper + 10  # Update y_lower for the next plot# Set labels and title for the silhouette plotax1.set_title("The silhouette plot for the various clusters.")ax1.set_xlabel("The silhouette coefficient values")ax1.set_ylabel("Cluster label")# Add vertical line for the average silhouette scoreax1.axvline(x=silhouette_avg, color="red", linestyle="--")ax1.set_yticks([])  # Clear the yaxis labels / ticksax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])# Plot the actual clusterscolors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)ax2.scatter(df_fc_cleaned_reduced_euc.transpose().iloc[:, 0], df_fc_cleaned_reduced_euc.transpose().iloc[:, 1],marker=".", s=30, lw=0, alpha=0.7, c=colors, edgecolor="k")# Label the clusters and cluster centerscenters = clusterer.cluster_centers_ax2.scatter(centers[:, 0], centers[:, 1], marker="o", c="white", alpha=1, s=200, edgecolor="k")for i, c in enumerate(centers):ax2.scatter(c[0], c[1], marker="$%d$" % i, alpha=1, s=50, edgecolor="k")# Set labels and title for the cluster visualizationax2.set_title("The visualization of the clustered data.")ax2.set_xlabel("Feature space for the 1st feature")ax2.set_ylabel("Feature space for the 2nd feature")# Set the super title for the whole plotplt.suptitle("Silhouette analysis for KMeans clustering on sample data with n_clusters = %d" % n_clusters,fontsize=14, fontweight="bold")plt.savefig('sil_score_eucl.png')
plt.show()

        很明显,簇都是混合在一起的,并且不能为任何数量的簇提供良好的轮廓分数。这符合我们基于欧几里得距离热图的初步评估的预期

三、相关性

############ reduing components on eucl distance metrics for visualisation #######
pca = decomposition.PCA(n_components=2)
pca.fit(df_man_dist_corr)
df_fc_cleaned_reduced_corr = pd.DataFrame(pca.transform(df_man_dist_corr).transpose(), index = ['PC_1','PC_2'],columns = df_man_dist_corr.transpose().columns)index=0
range_n_clusters = [2,3,4,5,6,7,8]
for n_clusters in range_n_clusters:# Create a subplot with 1 row and 2 columnsfig, (ax1, ax2) = plt.subplots(1, 2)fig.set_size_inches(15, 7)# The 1st subplot is the silhouette plot# The silhouette coefficient can range from -1, 1 but in this example all# lie within [-0.1, 1]ax1.set_xlim([-0.1, 1])# The (n_clusters+1)*10 is for inserting blank space between silhouette# plots of individual clusters, to demarcate them clearly.ax1.set_ylim([0, len(df_man_dist_corr) + (n_clusters + 1) * 10])# Initialize the clusterer with n_clusters value and a random generator# seed of 10 for reproducibility.clusterer = KMeans(n_clusters=n_clusters, n_init="auto", random_state=10)cluster_labels = clusterer.fit_predict(df_man_dist_corr)# The silhouette_score gives the average value for all the samples.# This gives a perspective into the density and separation of the formed# clusterssilhouette_avg = silhouette_score(df_man_dist_corr, cluster_labels)print("For n_clusters =",n_clusters,"The average silhouette_score is :",silhouette_avg,)sil_score_results.loc[index,['number_of_clusters','corrlidean']] = [n_clusters,silhouette_avg]index=index+1sample_silhouette_values = silhouette_samples(df_man_dist_corr, cluster_labels)y_lower = 10for i in range(n_clusters):# Aggregate the silhouette scores for samples belonging to# cluster i, and sort themith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]ith_cluster_silhouette_values.sort()size_cluster_i = ith_cluster_silhouette_values.shape[0]y_upper = y_lower + size_cluster_icolor = cm.nipy_spectral(float(i) / n_clusters)ax1.fill_betweenx(np.arange(y_lower, y_upper),0,ith_cluster_silhouette_values,facecolor=color,edgecolor=color,alpha=0.7,)# Label the silhouette plots with their cluster numbers at the middleax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))# Compute the new y_lower for next ploty_lower = y_upper + 10  # 10 for the 0 samplesax1.set_title("The silhouette plot for the various clusters.")ax1.set_xlabel("The silhouette coefficient values")ax1.set_ylabel("Cluster label")# The vertical line for average silhouette score of all the valuesax1.axvline(x=silhouette_avg, color="red", linestyle="--")ax1.set_yticks([])  # Clear the yaxis labels / ticksax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])# 2nd Plot showing the actual clusters formedcolors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)ax2.scatter(df_fc_cleaned_reduced_corr.transpose().iloc[:, 0], df_fc_cleaned_reduced_corr.transpose().iloc[:, 1], marker=".", s=30, lw=0, alpha=0.7, c=colors, edgecolor="k")#     for i in range(len(df_fc_cleaned_cleaned_reduced.transpose().iloc[:, 0])):
#                         ax2.annotate(list(df_fc_cleaned_cleaned_reduced.transpose().index)[i], 
#                                      (df_fc_cleaned_cleaned_reduced.transpose().iloc[:, 0][i], 
#                                       df_fc_cleaned_cleaned_reduced.transpose().iloc[:, 1][i] + 0.2))# Labeling the clusterscenters = clusterer.cluster_centers_# Draw white circles at cluster centersax2.scatter(centers[:, 0],centers[:, 1],marker="o",c="white",alpha=1,s=200,edgecolor="k",)for i, c in enumerate(centers):ax2.scatter(c[0], c[1], marker="$%d$" % i, alpha=1, s=50, edgecolor="k")ax2.set_title("The visualization of the clustered data.")ax2.set_xlabel("Feature space for the 1st feature")ax2.set_ylabel("Feature space for the 2nd feature")plt.suptitle("Silhouette analysis for KMeans clustering on sample data with n_clusters = %d"% n_clusters,fontsize=14,fontweight="bold",)plt.show()

        当选择的簇数为 4 时,我们可以看到清晰分离的簇,并且结果通常比欧几里德距离好得多。

欧氏距离和相关轮廓分数之间的比较

        Silhouette 分数表示,当簇数为 4 时,基于相关性的距离矩阵提供最佳结果,而在欧几里德距离的情况下,其效果并不那么清晰

四、结论

        在本文中,我们研究了如何使用欧几里德距离和相关性度量来执行时间序列聚类,并且我们还观察了这两种情况下结果的变化。如果我们在评估聚类时结合 Silhouette,我们可以使聚类步骤更加客观,因为它提供了一种很好的直观方法来查看聚类的分离程度。

参考

  1. https://scikit-learn.org [KMeans 和 Silhouette 分数]
  2. Plotly: Low-Code Data App Development [可视化库]
  3. https://scipy.org [用于创建信号数据]
  4. 吉里什·戴夫·库马尔·乔拉西亚·

        如果您觉得我的讲解对您有帮助,请关注我以获取更多内容!如果您有任何问题或建议,请随时发表评论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/129571.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

测试Whisper效果

先去官方上面看看,是否有对应的测试结果 简单找了一下,没找到对应的测试数据 去hugging face 上面找对应的数据集,发现没有现成的数据 找到了几个数据集,但是是收费的 101 Hours – Scene Noise Data by Voice Recorder 1,29…

#stm32整理(一)flash读写

以这篇未开始我将进行stm32学习整理为期一个月左右完成stm32知识学习整理内容顺序没有一定之规写到哪想到哪想到哪写到哪,主要是扫除自己知识上的盲区完成一些基本外设操作。 以stm32f07为例子进行flash读写操作 stm32flash简介 参考资料正点原子和野火开发手册 …

通过akshare获取股票分钟数据

参考:https://blog.csdn.net/qnloft/article/details/131218295 import akshare as ak 个股的 df ak.stock_zh_a_hist_min_em(symbol“000001”, start_date“2023-11-03 09:30:00”, end_date“2023-11-03 15:00:00”, period‘1’, adjust‘’) print(df) date_info df[‘…

6-3 堆排序

description 本题要求实现堆排序中的筛选函数&#xff0c;待排序列的长度1<n<1000。 函数接口定义&#xff1a; void HeapAdjust( HeapType H, int s, int m); 其中L是待排序表&#xff0c;使排序后的数据从小到大排列。 ###类型定义&#xff1a; typedef int KeyType…

自动曝光算法(第二讲)

序言 第一章说了&#xff0c;自动曝光算法的目的&#xff1a;已知当前raw图亮度、当前曝光时间、当前增益和目标亮度&#xff0c;当环境光发生变化的时候&#xff0c;是通过控制增益、曝光时间和光圈使raw图的亮度&#xff0c;保持在目标亮度附近。本章想讲一下目标亮度的相关…

【杂记-遇到的坑】mysql-查询条件不达预期

前言&#xff1a; 业务开发时&#xff0c;遇到的坑&#xff0c;栽进去了&#xff0c;写这个博客&#xff0c;涨点记性 1.连表查询 左连接为例子 A left join B 把A的数据全部取出&#xff0c;能够跟B对应的上&#xff0c;B表的扩展数据也跟着展示出俩 A有B没有的&#xff0c;B的…

路由器基础(九):防火墙基础

防火墙 (Fire Wall) 是网络关联的重要设备&#xff0c;用于控制网络之间的通信。外部网络用户的访问必须先经过安全策略过滤&#xff0c;而内部网络用户对外部网络的访问则无须过滤。现在的防火墙还具有隔离网络、提供代理服务、流量控制等功能。 一、三种防火墙技术 常见的…

hadoop进程启停管理(看这一篇就足够了!)

一、一键启停脚本 Hadoop HDFS组件内置了HDFS集群的一键启停脚本 $HADOP_HOME/sbin/start-all.sh,一键启动HDFS集群 执行原理&#xff1a; 在执行此脚本的机器上&#xff0c;启动SecondaryNameNode 读取core-site.xml内容(fs.defaultFS项)&#xff0c;确认NameNode所在机器&…

【MySQL索引与优化篇】数据库的设计规范

数据库的设计规范 文章目录 数据库的设计规范1. 范式2. 键和相关属性的概念3. 第一范式4. 第二范式5. 第三范式6. 小结7. 反范式化7.1 概述7.2 反范式的新问题7.3 反范式适用场景 8. 巴斯范式9. 第四范式、第五范式和域键范式 1. 范式 在关系型数据库中&#xff0c;关于数据表…

Qt实验室

前言 本系列文章是研究和记录Qt开发过程中遇到的各种问题的集合 由于Qt是一个庞大的开发体系&#xff0c;很难用有限的文案对其做全面深入细致的讲解&#xff0c;因此市面上大多数Qt开发相关的教程都显得极其粗浅入门&#xff0c;通常只能作为最基本的入门教程。但是实际项目…

Ubuntu安装Redis

目录 1. 更新软件包列表2. 安装 Redis3. 启动 Redis4. 验证 Redis 是否启动成功5. 配置 Redis6. 启用 Redis 开机启动7. 验证 Redis 是否可用8. 测试 Redis 在 Ubuntu 20.04 上安装 Redis 非常简单。只需按照以下步骤操作即可&#xff1a; 1. 更新软件包列表 sudo apt update…

解锁AI语言模型的秘密武器 - 提示工程

文章目录 一、LLM概念1.1 什么是LLMs1.2 LLMs类别1.3 如何构建LLM 二、提示工程简介2.1 基础提示2.2 使用提示词的必要性 三、 提示3.1 如何写好提示词3.1.1 使用分隔符3.1.2 结构化输出3.1.3 风格信息3.1.4 给定条件3.1.5 给出示例3.1.6 步骤分解3.1.7 不断迭代 3.2 提示工程3…

【Docker】Linux路由连接两个不同网段namespace,连接namespace与主机

如果两个namespace处于不同的子网中&#xff0c;那么就不能通过bridge进行连接了&#xff0c;而是需要通过路由器进行三层转发。然而Linux并未像提供虚拟网桥一样也提供一个虚拟路由器设备&#xff0c;原因是Linux自身就具备有路由器功能。 路由器的工作原理是这样的&#xff…

Qt控件 UI设计 QPushbutton、QToolButton、QMenu

Qt控件 UI设计 QPushbutton、QToolButton、QMenu 个人设计QToolButton效果设计效果运行效果 Chapter1 Qt控件 UI设计 QPushbutton、QToolButton、QMenu1.QPushbutton和QToolButton的关联和区别&#xff1a;2.QMenu 可以配合QPushbutton做个下拉菜单3.点击按钮的功能&#xff0c…

k8s:endpoint

在 Kubernetes 中&#xff0c;Endpoint 是一种 API 对象&#xff0c;它用于表示集群内某个 Service 的具体网络地址。换句话说&#xff0c;它连接到一组由 Service 选择的 Pod&#xff0c;从而使它们能够提供服务。每个 Endpoint 对象都与相应的 Service 对象具有相同的名称&am…

【C语言初学者周冲刺计划】5.1C语言知识点小总结

目录 1知识点一&#xff1a; 2知识点二&#xff1a; 3知识点三&#xff1a; 4代码&#xff1a; 5总结&#xff1a; 1知识点一&#xff1a; 1 C语言中要求对变量作强制定义的主要理由是( )。 便于确定类型和分配空间 2 【单选题】若有定义&#xff1a;int m7; float x…

ssh 免密连接远程服务器并使用Python执行scp传输文件

找到自己Mac的ssh公钥&#xff0c;如果没有ssh密钥的话&#xff0c;需要生成一下 cat ~/.ssh/id_rsa.pub# 在~/.ssh路径下面执行命令生成ssh密钥 ssh-keygen -t rsa然后找到要免密登陆的远程服务器 ~/.ssh/authorized_keys 把自己Mac上面的公钥拷贝到这里面即可 Python脚本 …

云安全-云原生k8s攻击点(8080,6443,10250未授权攻击点)

0x00 k8s简介 k8s&#xff08;Kubernetes&#xff09; 是容器管理平台&#xff0c;用来管理容器化的应用&#xff0c;提供快速的容器调度、弹性伸缩等诸多功能&#xff0c;可以理解为容器云&#xff0c;不涉及到业务层面的开发。只要你的应用可以实现容器化&#xff0c;就可以部…

Webpack搭建本地服务器

一、搭建webpack本地服务 1.为什么要搭建本地服务器&#xff1f; 目前我们开发的代码&#xff0c;为了运行需要有两个操作&#xff1a; 操作一&#xff1a;npm run build&#xff0c;编译相关的代码&#xff1b;操作二&#xff1a;通过live server或者直接通过浏览器&#x…

Docker 查看Image镜像的Dockerfile方法

1、创建测试镜像 Dockerfile: FROM centos LABEL maintainer"NGINX Docker Maintainers docker-maintnginx.com" RUN yum install -y nginx RUN echo "Nginx Web: CMD defining default arguments for an ENTRYPOINT" > /usr/share/nginx/html/index.…