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

基于季节性时序数据的Python聚类模型选型求助

解决方案:基于季节性趋势的时序聚类方案

一、核心问题定位

之前使用TimeSeriesKMeans仅得到数值高低的聚类结果,本质是没有把ID自身的季节性相对波动作为聚类依据,而是用了原始时序或全局标准化后的绝对数值,忽略了"相对自身升降"的核心需求。

二、数据预处理:提取季节性特征(关键步骤)

先将数据转换为能体现每个ID月度相对波动的特征向量,这是实现趋势聚类的基础:

  1. 补全缺失月份并填充0
    为每个ID生成完整的1-12月序列,缺失月份的X1设为0:

    import pandas as pd
    
    # 读取原始数据
    df = pd.read_csv("your_data.csv", sep=" ")
    # 解析月份和年份
    df['month'] = pd.to_datetime(df['YR-MONTH']).dt.month
    df['year'] = pd.to_datetime(df['YR-MONTH']).dt.year
    
    # 生成每个ID的完整年月网格
    ids = df['ID'].unique()
    years = df['year'].unique()
    full_index = pd.MultiIndex.from_product([ids, years, range(1,13)], names=['ID', 'year', 'month'])
    full_df = df.set_index(['ID', 'year', 'month']).reindex(full_index, fill_value=0).reset_index()
    
  2. 计算月度相对波动特征
    对每个ID,计算每个月份X1相对于自身全年平均值的比值,突出"相对自身的升降趋势":

    # 计算每个ID每年的X1平均值
    full_df['annual_avg'] = full_df.groupby(['ID', 'year'])['X1'].transform('mean')
    # 避免除以0,添加极小值epsilon
    epsilon = 1e-8
    full_df['seasonal_ratio'] = full_df['X1'] / (full_df['annual_avg'] + epsilon)
    
    # 提取每个ID的12维季节性特征向量(1-12月的平均相对比值)
    seasonal_features = full_df.groupby(['ID', 'month'])['seasonal_ratio'].mean().unstack()
    

三、聚类模型选择与实现

基于提取的季节性特征,可选择以下方案:

1. 改进版K-Means(推荐)

直接用12维季节性特征做聚类,聚焦趋势模式而非绝对数值:

from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# 标准化特征(让每个月份的波动权重一致)
scaler = StandardScaler()
scaled_features = scaler.fit_transform(seasonal_features)

# 训练K-Means,k为自定义聚类数
k = 3
kmeans = KMeans(n_clusters=k, random_state=42)
seasonal_features['cluster'] = kmeans.fit_predict(scaled_features)

2. 层次聚类

适合需要观察聚类层级关系的场景:

from sklearn.cluster import AgglomerativeClustering
import scipy.cluster.hierarchy as sch
import matplotlib.pyplot as plt

hc = AgglomerativeClustering(n_clusters=k, linkage='ward')
seasonal_features['cluster_hc'] = hc.fit_predict(scaled_features)

# 绘制树状图查看聚类层级
plt.figure(figsize=(10,6))
sch.dendrogram(sch.linkage(scaled_features, method='ward'))
plt.title('Dendrogram of Seasonal Trends')
plt.show()

3. 基于形状的时序聚类(tslearn改进)

若坚持用时序聚类,需对每个ID的时序单独做归一化,突出形状而非数值:

from tslearn.clustering import TimeSeriesKMeans
from tslearn.preprocessing import TimeSeriesScalerMinMax

# 整理每个ID的12月时序序列
time_series = []
for idx in seasonal_features.index:
    ts = full_df[full_df['ID'] == idx].sort_values('month')['X1'].values
    time_series.append(ts)

# 对每个时序单独做MinMax归一化
scaler = TimeSeriesScalerMinMax()
scaled_ts = scaler.fit_transform(time_series)

# 用DTW距离训练TimeSeriesKMeans(更适配时序形状匹配)
ts_kmeans = TimeSeriesKMeans(n_clusters=k, metric="dtw", random_state=42)
clusters = ts_kmeans.fit_predict(scaled_ts)

四、聚类效果验证

通过可视化每个聚类的平均季节性趋势,验证是否符合预期:

import seaborn as sns

# 计算每个聚类的月度平均相对比值
cluster_avg = seasonal_features.groupby('cluster').mean().T.reset_index()
cluster_avg = cluster_avg.melt(id_vars='month', var_name='cluster', value_name='avg_ratio')

# 绘制趋势对比图
sns.lineplot(data=cluster_avg, x='month', y='avg_ratio', hue='cluster')
plt.title('Average Seasonal Trend by Cluster')
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 22:30:32