时间序列聚类

目录

时间序列聚类概述

时间序列相识度衡量

动态时间规整

​编辑

欧式距离

子序列聚类

​编辑 

时间点聚类

基于时间序列形状Kshpe聚类

基于分段统计特征聚类

时间序列聚类概述

时间序列聚类:一种将时间序列数据分为不同组的无监督学习方法。聚类方法旨在找到数据中相似的子集,并将它们归为同一组。对于时间序列数据而言,聚类技术可以发现有相似特征的序列,并将它们划分为同一组,这有助于数据的分类和分析。

时间序列聚类包括两种类型:子序列聚类和时间点聚类。子序列聚类是通过滑动窗口在一个时间序列中提取的一系列子序列上的聚类;时间点聚类基于时间点的时间接近度和对应值的相似性组合的聚类。时间序列聚类通常使用常见的聚类算法,如K-means、Ksahpe 、层次聚类等。

时间序列相识度衡量

动态时间规整

动态时间规整(Dynamic Time Warping,DTW)是一种解决时间序列相似度匹配问题的非常有效的方法。它可以在不同长度和速度的时间序列之间计算距离。

DTW 算法的核心思想是对两个时间序列进行对齐,并计算两个序列之间每个点之间的距离。在对齐的过程中,DTW 可以进行拉伸或压缩时间轴,使得两个序列之间的对应点能够匹配上。因此,DTW 可以处理不同长度和采样率的时间序列数据。

DTW 算法的步骤如下:

  1. 初始化一个距离矩阵,该矩阵为两个时间序列的长度的二维矩阵。
  2. 进行动态规划,按照规定的路径更新距离矩阵,从而找到最优的对齐方案。
  3. 计算两个序列之间的距离,该距离就是对齐后的时间序列之间点之间的距离。
from scipy.spatial.distance import euclidean
from fastdtw import fastdtw

# 定义两个时间序列
x = [1, 2, 3, 4, 5]
y = [1, 2, 2, 4, 4, 5]

# 使用快速DTW算法进行动态时间规整并计算距离
distance, path = fastdtw(x, y, dist=euclidean)

# 打印计算出的距离和对齐路径
print("Distance: ", distance)
print("Path: ", path)

欧式距离

对时间序列数据多标量统计特征,如日、月、年的均值、方差、中位数、峰值、偏度等,用欧式距离衡量其相似度;

子序列聚类

时间序列子序列聚类(Subsequence Clustering)是一种将时间序列数据按相似性分为不同组的无监督学习方法。与传统时间序列聚类不同,子序列聚类算法不是将整个时间序列进行聚类,而是基于一些已知的子序列特征来进行子序列聚类。

代码中定义了样本数、时间步长和特征维度,并生成了随机时间序列数据。接着,我们定义了子序列长度和步长,使用 extract_subsequences() 函数从原始时间序列数据中提取出子序列数据。然后,我们定义了聚类数目为 3,使用 k-means 算法对子序列数据进行聚类,并获取每个样本所属的类别。最后,我们打印输出了每个类别的样本数量;

import numpy as np
from sklearn.cluster import KMeans

def extract_subsequences(X, subseq_len, stride):
    n_samples, n_timesteps, n_features = X.shape
    subsequences = []
    for i in range(n_samples):
        for j in range(0, n_timesteps - subseq_len + 1, stride):
            subseq = X[i, j:j+subseq_len, :]
            subsequences.append(subseq.ravel())
    return np.array(subsequences)

# 定义样本数、时间步长和特征维度
n_samples, n_timesteps, n_features = 100, 40, 5

# 生成随机时间序列数据
X = np.random.rand(n_samples, n_timesteps, n_features)

# 获取子序列数据
subseq_len, stride = 10, 5
X_subseq = extract_subsequences(X, subseq_len=subseq_len, stride=stride)

# 定义聚类数目
n_clusters = 3

# 使用 k-means 算法对数据进行聚类
kmeans = KMeans(n_clusters=n_clusters, random_state=0).fit(X_subseq)

# 获取每个样本所属的类别
labels = kmeans.labels_

# 打印每个类别的样本数量
unique, counts = np.unique(labels, return_counts=True)
print(dict(zip(unique, counts)))

时间点聚类

基于时间序列形状Kshpe聚类

KShape是一种时间序列聚类算法,它可以将时间序列数据分成不同的簇(cluster),使得同一簇内的数据对象的相似度尽可能大。KShape使用了形状距离(Shape distance)来衡量两个时间序列之间的相似度,同时还使用了动态规划(Dynamic Programming)来对每个时间序列进行对齐操作(alignment),以便更准确地计算形状距离。KShape的主要参数包括簇数目(n_clusters)、最大迭代次数(max_iter)和阈值(tol),用户可以根据实际情况进行设置。KShape聚类算法需要先加载tslearn库并调用tslearn.clustering.KShape类。

下面提供了两种基于形状聚类的代码

import numpy as np
import matplotlib.pyplot as plt
from tslearn.datasets import CachedDatasets
from tslearn.preprocessing import TimeSeriesScalerMeanVariance
from tslearn.piecewise import SymbolicAggregateApproximation
from tslearn.clustering import TimeSeriesKMeans

# 加载数据集并对时间序列进行预处理
X_train, y_train, _, _ = CachedDatasets().load_dataset("Trace")
X_train = TimeSeriesScalerMeanVariance().fit_transform(X_train[:6])
X_train = SymbolicAggregateApproximation(n_segments=10, alphabet_size_avg=2).fit_transform(X_train)

# 定义并训练KMeans聚类器
km = TimeSeriesKMeans(n_clusters=3, verbose=True, random_state=42)
y_pred = km.fit_predict(X_train)

# 可视化聚类结果
plt.figure(figsize=(10, 10))
for yi in range(3):
    plt.subplot(3, 1, 1 + yi)
    for xx in X_train[y_pred == yi]:
        plt.plot(xx.ravel(), "k-", alpha=.2)
    plt.plot(km.cluster_centers_[yi].ravel(), "r-")
    plt.xlim(0, X_train.shape[1])
    plt.ylim(-4, 4)
    plt.title("Cluster %d" % (yi + 1))

plt.tight_layout()
plt.show()
from tslearn.clustering import KShape
from tslearn.generators import random_walks
from sklearn_extra.cluster import KMedoids
import tslearn.metrics as metrics
from tslearn.clustering import silhouette_score
from tslearn.generators import random_walks
# X:需要训练的时间序列矩阵

#定义分成6类
num_cluster = 6

# precomputed自定义相似度计算方法
km = KMedoids(n_clusters= num_cluster, random_state=0,metric="precomputed")

 # 采用tslearn中的DTW系列及变种算法计算相似度,生成距离矩阵dists
# dists = metrics.cdist_dtw(X) # dba + dtw
dists = metrics.cdist_soft_dtw_normalized(X,gamma=0.5) # softdtw

#预测结果
y_pred = km.fit_predict(dists)

# 计算轮廓系数
np.fill_diagonal(dists,0)
score = silhouette_score(dists,y_pred,metric="precomputed")

print(X.shape)
print(y_pred.shape)
print("silhouette_score: " + str(score)

基于分段统计特征聚类

时间序列统计特征:

  1. 基于整个时间序列统计特征有最大值、最小值、均值、方差、偏度、峰度、熵;
  2. 可以时间序列进行分段,如周、月、年或者自定义分段参数,统计最大值、最小值、均值、方差、偏度、峰度、熵等特征;
  3. 基于tsfresh时间特征提取特征;
  4. 基于1,2,3方法选取合适特征,再采用Kmeans、层次聚类、密度聚类等方法聚类;

时间序列计算峰度代码

import pandas as pd

# 读取时间序列数据,要求数据第一列为时间,第二列为数值
data = pd.read_csv('time_series.csv', parse_dates=['time'], index_col='time')

# 计算时间序列峰度
kurtosis = data.kurtosis()[0]

print("该时间序列的峰度为:", kurtosis)

时间序列计算偏度代码

import pandas as pd

# 读取时间序列数据,要求数据第一列为时间,第二列为数值
data = pd.read_csv('time_series.csv', parse_dates=['time'], index_col='time')

# 计算时间序列偏度
skewness = data.skew()[0]

print("该时间序列的偏度为:", skewness)

时间序列计算

t1 =[1,3,1,3,1,3,1,3]

t2 =[1,3,3,1,1,1,3,3]

t1,t2两个序列是不一样的,t1是有规律的,t2相对无序,想描述这种确定与不确定性。可用熵来表示;以下是计算时间序列熵的代码;

from pyentrp import entropy as ent

# 读取时间序列数据,要求数据第一列为时间,第二列为数值
data = pd.read_csv('time_series.csv', parse_dates=['time'], index_col='time')

# 将时间序列转化为一维数组,并计算其熵
ts = data['value'].values
entropy = ent.shannon_entropy(ts)
print("该时间序列的熵为:", entropy)

tsfresh 可以自动计算大量的时间序列特性,包含许多特征提取方法和强大的特征选择算法。

# 时间序列特征提取
from tsfresh import extract_features, extract_relevant_features, select_features
from tsfresh.feature_extraction import extract_features, EfficientFCParameters
from tsfresh.utilities.dataframe_functions import impute
from tsfresh.feature_extraction import ComprehensiveFCParameters


# extraction_settings = EfficientFCParameters()#计算算所有默认特征和带参数的特征的多种参数组合
extraction_settings = ComprehensiveFCParameters()

X = extract_features(data, column_id="id", column_sort='time',
                     default_fc_parameters=extraction_settings,
                     # impute就是自动移除所有NaN的特征
                     impute_function=impute)
X.head()

Kmeans聚类

 提供一个Kmeans选取k值函数

from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
from sklearn import preprocessing

# Kmeans选取k值函数

def get_silhouette_K(data, range_K):
    K = range(2, range_K)
    Scores = [] 
    for k in K:
        kmeans = KMeans(n_clusters=k)
        kmeans.fit(data)
        Scores.append(silhouette_score(data, kmeans.labels_, metric='euclidean'))

    max_idx = Scores.index(max(Scores))
    best_k = K[max_idx]
    plt.plot(K, Scores, 'bx-')
    plt.xlabel('k')
    plt.ylabel('silhouette')
    plt.title('Selecting k with the silhouette Method')
    plt.show()
    return best_k

  • 11
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值