时间序列表征之SAX(Symbolic Aggregate approXimation)实战python讲解

一、前言

sax理论篇:时间序列表征之SAX(Symbolic Aggregate approXimation)算法

二、sax实现

2.1 过程

  1. 标准化(将数据转换为高斯分布)

  2. paa

  3. discretization

2.2 标准化

因为原文中采用的breakpoints为

4d784722b7bc2964c166d3afc7fa8d61.jpeg

前提假设为:离散化要求产生具有等概率的符号,通过标准化的时间序列具有高斯分布

所以标准的sax之前应该先通过一次标准化得到数据,很多例子这步骤都是直接略过了,因为例子中的数据都是生成的本就具有高斯分布的数据

2.3 paa

这里没啥好讲的,直接看代码

def paa_step_df(self, df):
        n = len(df)
        start = 0
        approximation = []
        i = 0
        df_array = df.to_numpy()
        while start <= n - self.aggregation_sax_size:
            thisFrame = np.array(df_array[start:int(start + self.aggregation_sax_size)])
            approximation.append(np.mean(thisFrame, axis=0))
            i += 1
            start = int(i * self.aggregation_sax_size)

        df_paa = pd.DataFrame(data=np.array(approximation), columns=df.columns)
        return df_paa

2.4 discretization

def discretization_step_df(self, df_paa):
        data = {col: [] for col in df_paa.columns}
        n = len(df_paa)
        for col in df_paa.columns:
            dis = []
            for t in range(n):
                value_for_feature = df_paa[col].iloc[t]
                dis.append(self.alphabet[np.searchsorted(self.breakpoints_for_feature,
                                                         value_for_feature,
                                                         side='left')])
            data[col] = dis
        df_sax = pd.DataFrame(data=data, index=df_paa.index)
        return df_sax

这里有很多可以根据场景调整的点,简单说两种情况

  1. 比如数据中极值点有很多,那是否需要先去除噪声,再离散化

  2. 如果数据对于标准化有一定的限制,不标准化情况下我们怎么定义breakpoints_for_feature

这些情况可以酌情根据自身场景进行调整,甚至可以在做sax之前对数据做尽可能的观察,比如有几个顶峰,是否存在周期,等采用不一样的sax策略

2.5 sax全部代码

import numpy
from matplotlib import pyplot as plt
from scipy.stats import norm
import pandas as pd
import numpy as np
import math

from sklearn.preprocessing import StandardScaler


class SAX(object):

    def __init__(self, alphabet_size=7, aggregation_sax_size=3):

        self.alphabet_size = alphabet_size
        self.alphabet = np.array([chr(i) for i in range(97, 97 + self.alphabet_size)])
        self.aggregation_sax_size = aggregation_sax_size
        self.breakpoints_for_feature = norm.ppf(np.linspace(0, 1, alphabet_size + 1)[1:-1])
        self.scaler = StandardScaler()

    def fit(self, df):
        self.scaler.fit(df)

    def paa_step_df(self, df):
        n = len(df)
        start = 0
        approximation = []
        i = 0
        df_array = df.to_numpy()
        while start <= n - self.aggregation_sax_size:
            thisFrame = np.array(df_array[start:int(start + self.aggregation_sax_size)])
            approximation.append(np.mean(thisFrame, axis=0))
            i += 1
            start = int(i * self.aggregation_sax_size)

        df_paa = pd.DataFrame(data=np.array(approximation), columns=df.columns)
        return df_paa

    def discretization_step_df(self, df_paa):
        data = {col: [] for col in df_paa.columns}
        n = len(df_paa)
        for col in df_paa.columns:
            dis = []
            for t in range(n):
                value_for_feature = df_paa[col].iloc[t]
                dis.append(self.alphabet[np.searchsorted(self.breakpoints_for_feature,
                                                         value_for_feature,
                                                         side='left')])
            data[col] = dis
        df_sax = pd.DataFrame(data=data, index=df_paa.index)
        return df_sax

    def process(self, df):
        # 1. Normalization
        columns = df.columns
        df_int = self.scaler.transform(df)
        df_int = pd.DataFrame(df_int, columns=columns)

        # 2. PAA
        df_paa = self.paa_step_df(df_int)

        # 3. Discretization
        df_sax = self.discretization_step_df(df_paa)

        return df_sax

其中alphabet_size为离散的部分个数,aggregation_sax_size为聚合时间点数。

三、 例子

3.1 数据

用两种数据

  1. 周期性数据

  2. 非周期性趋势数据

# 设置时间序列长度
    n_points = 200

    # 生成时间索引
    time_index = pd.date_range('2023-01-01', periods=n_points, freq='D')

    # 生成周期性时间序列数据
    # 包含多个正弦波和一些随机噪声
    freq1, freq2 = 5, 25  # 频率
    amp1, amp2 = 1, 0.5  # 振幅
    noise_amp = 0.1  # 噪声振幅
    periodic_series = amp1 * np.sin(2 * np.pi * (time_index.dayofyear / 365) * freq1) + \
                      amp2 * np.sin(2 * np.pi * (time_index.dayofyear / 365) * freq2) + \
                      noise_amp * np.random.randn(n_points)

    # 生成非周期性时间序列数据
    # 包括一个向上的趋势和随机噪声
    trend_slope = 0.05
    non_periodic_series = trend_slope * np.arange(n_points) + \
                          np.cumsum(noise_amp * np.random.randn(n_points))

    # 创建DataFrame
    df = pd.DataFrame({
        'period': periodic_series,
        'no_period': non_periodic_series
    }, index=time_index)

    # 绘制时间序列
    plt.figure(figsize=(14, 6))

    plt.subplot(1, 2, 1)
    plt.plot(df.index, df['period'])
    plt.title('Complex Periodic Time Series')

    plt.subplot(1, 2, 2)
    plt.plot(df.index, df['no_period'])
    plt.title('Complex Non-Periodic Time Series')

    plt.tight_layout()
    plt.show()
6831672ea151a047c1ac7976d96b82da.jpeg

3.2 sax过程

alphabet_size = 12
        aggregation_sax_size = 3
        sax = SAX(alphabet_size=alphabet_size, aggregation_sax_size=aggregation_sax_size)
        sax.fit(df=df)
        df_sax = sax.process(df=df)

3.3 可视化

if __name__ == "__main__":
    # 设置时间序列长度
    n_points = 200

    # 生成时间索引
    time_index = pd.date_range('2023-01-01', periods=n_points, freq='D')

    # 生成周期性时间序列数据
    # 包含多个正弦波和一些随机噪声
    freq1, freq2 = 5, 25  # 频率
    amp1, amp2 = 1, 0.5  # 振幅
    noise_amp = 0.1  # 噪声振幅
    periodic_series = amp1 * np.sin(2 * np.pi * (time_index.dayofyear / 365) * freq1) + \
                      amp2 * np.sin(2 * np.pi * (time_index.dayofyear / 365) * freq2) + \
                      noise_amp * np.random.randn(n_points)

    # 生成非周期性时间序列数据
    # 包括一个向上的趋势和随机噪声
    trend_slope = 0.05
    non_periodic_series = trend_slope * np.arange(n_points) + \
                          np.cumsum(noise_amp * np.random.randn(n_points))

    # 创建DataFrame
    df = pd.DataFrame({
        'period': periodic_series,
        'no_period': non_periodic_series
    }, index=time_index)

    # 绘制时间序列
    plt.figure(figsize=(14, 6))

    plt.subplot(2, 2, 1)
    plt.plot(df.index, df['period'])
    plt.title('Complex Periodic Time Series')

    plt.subplot(2, 2, 2)
    plt.plot(df.index, df['no_period'])
    plt.title('Complex Non-Periodic Time Series')

    for index, fea in enumerate(['period', 'no_period']):
        alphabet_size = 12
        aggregation_sax_size = 3
        sax = SAX(alphabet_size=alphabet_size, aggregation_sax_size=aggregation_sax_size)
        sax.fit(df=df)
        df_sax = sax.process(df=df)

        plt.subplot(2, 2, 2 + index + 1)
        alphabet = np.array([chr(i) for i in range(97, 97 + alphabet_size)])
        # Assign an integer to each letter (for plotting purposes)
        d = dict(zip([np.where(alphabet == e)[0][0]
                      for e in alphabet], alphabet))
        reverse_d = {v: k for k, v in d.items()}
        sax_reverse = [reverse_d[e] for e in df_sax[fea].to_list()]
        plt.step(np.arange(len(df_sax)), sax_reverse, where='post',
                 c='k', linewidth=2, alpha=0.8)

        plt.xticks(rotation='vertical')
        plt.yticks(range(len(alphabet)), alphabet)
        plt.grid()

    plt.tight_layout()
    plt.show()
4579cb3d1ebd2cba87c101f2137efe37.jpeg

3.4 全部代码

import numpy
from matplotlib import pyplot as plt
from scipy.stats import norm
import pandas as pd
import numpy as np
import math

from sklearn.preprocessing import StandardScaler


class SAX(object):

    def __init__(self, alphabet_size=7, aggregation_sax_size=3):

        self.alphabet_size = alphabet_size
        self.alphabet = np.array([chr(i) for i in range(97, 97 + self.alphabet_size)])
        self.aggregation_sax_size = aggregation_sax_size
        self.breakpoints_for_feature = norm.ppf(np.linspace(0, 1, alphabet_size + 1)[1:-1])
        self.scaler = StandardScaler()

    def fit(self, df):
        self.scaler.fit(df)

    def paa_step_df(self, df):
        n = len(df)
        start = 0
        approximation = []
        i = 0
        df_array = df.to_numpy()
        while start <= n - self.aggregation_sax_size:
            thisFrame = np.array(df_array[start:int(start + self.aggregation_sax_size)])
            approximation.append(np.mean(thisFrame, axis=0))
            i += 1
            start = int(i * self.aggregation_sax_size)

        df_paa = pd.DataFrame(data=np.array(approximation), columns=df.columns)
        return df_paa

    def discretization_step_df(self, df_paa):
        data = {col: [] for col in df_paa.columns}
        n = len(df_paa)
        for col in df_paa.columns:
            dis = []
            for t in range(n):
                value_for_feature = df_paa[col].iloc[t]
                dis.append(self.alphabet[np.searchsorted(self.breakpoints_for_feature,
                                                         value_for_feature,
                                                         side='left')])
            data[col] = dis
        df_sax = pd.DataFrame(data=data, index=df_paa.index)
        return df_sax

    def process(self, df):
        # 1. Normalization
        columns = df.columns
        df_int = self.scaler.transform(df)
        df_int = pd.DataFrame(df_int, columns=columns)

        # 2. PAA
        df_paa = self.paa_step_df(df_int)

        # 3. Discretization
        df_sax = self.discretization_step_df(df_paa)

        return df_sax


if __name__ == "__main__":
    # 设置时间序列长度
    n_points = 200

    # 生成时间索引
    time_index = pd.date_range('2023-01-01', periods=n_points, freq='D')

    # 生成周期性时间序列数据
    # 包含多个正弦波和一些随机噪声
    freq1, freq2 = 5, 25  # 频率
    amp1, amp2 = 1, 0.5  # 振幅
    noise_amp = 0.1  # 噪声振幅
    periodic_series = amp1 * np.sin(2 * np.pi * (time_index.dayofyear / 365) * freq1) + \
                      amp2 * np.sin(2 * np.pi * (time_index.dayofyear / 365) * freq2) + \
                      noise_amp * np.random.randn(n_points)

    # 生成非周期性时间序列数据
    # 包括一个向上的趋势和随机噪声
    trend_slope = 0.05
    non_periodic_series = trend_slope * np.arange(n_points) + \
                          np.cumsum(noise_amp * np.random.randn(n_points))

    # 创建DataFrame
    df = pd.DataFrame({
        'period': periodic_series,
        'no_period': non_periodic_series
    }, index=time_index)

    # 绘制时间序列
    plt.figure(figsize=(14, 6))

    plt.subplot(2, 2, 1)
    plt.plot(df.index, df['period'])
    plt.title('Complex Periodic Time Series')

    plt.subplot(2, 2, 2)
    plt.plot(df.index, df['no_period'])
    plt.title('Complex Non-Periodic Time Series')

    for index, fea in enumerate(['period', 'no_period']):
        alphabet_size = 12
        aggregation_sax_size = 3
        sax = SAX(alphabet_size=alphabet_size, aggregation_sax_size=aggregation_sax_size)
        sax.fit(df=df)
        df_sax = sax.process(df=df)

        plt.subplot(2, 2, 2 + index + 1)
        alphabet = np.array([chr(i) for i in range(97, 97 + alphabet_size)])
        # Assign an integer to each letter (for plotting purposes)
        d = dict(zip([np.where(alphabet == e)[0][0]
                      for e in alphabet], alphabet))
        reverse_d = {v: k for k, v in d.items()}
        sax_reverse = [reverse_d[e] for e in df_sax[fea].to_list()]
        plt.step(np.arange(len(df_sax)), sax_reverse, where='post',
                 c='k', linewidth=2, alpha=0.8)

        plt.xticks(rotation='vertical')
        plt.yticks(range(len(alphabet)), alphabet)
        plt.grid()

    plt.tight_layout()
    plt.show()

推荐阅读:

我的2022届互联网校招分享

我的2021总结

浅谈算法岗和开发岗的区别

互联网校招研发薪资汇总

公众号:AI蜗牛车

保持谦逊、保持自律、保持进步

a8cce591b3c67733da217a9a188a858f.jpeg

发送【蜗牛】获取一份《手把手AI项目》(AI蜗牛车著)

发送【1222】获取一份不错的leetcode刷题笔记

发送【AI四大名著】获取四本经典AI电子书

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis五种数据类型及应用场景

1、数据类型 String(字符串&#xff0c;整数&#xff0c;浮点数)&#xff1a;做简单的键值对缓存 List(列表)&#xff1a;储存一些列表类型的数据结构 Hash(哈希)&#xff1a;包含键值对的无序散列表&#xff0c;结构化的数据 Set(无序集合)&#xff1a;交集&#xff0c;并集…

Java多线程--同步机制解决线程安全问题方式二:同步方法

文章目录 一、同步方法&#xff08;1&#xff09;同步方法--案例11、案例12、案例1之同步监视器 &#xff08;2&#xff09;同步方法--案例21、案例2之同步监视器的问题2、案例2的补充说明 二、代码及重要说明&#xff08;1&#xff09;代码&#xff08;2&#xff09;重要说明 …

云计算HCIE备考经验分享

大家好&#xff0c;我是来自深圳信息职业技术学院22级鲲鹏3-1班的刘同学&#xff0c;在2023年9月19日成功通过了华为云计算HCIE认证&#xff0c;并且取得了A的成绩。下面把我的考证经验分享给大家。 转专业进鲲鹏班考HCIE 大一上学期的时候&#xff0c;在上Linux课程的时候&…

代码随想录 Leetcode222.完全二叉树的节点个数

题目&#xff1a; 代码&#xff08;首刷自解 2024年1月30日&#xff09;&#xff1a; class Solution { public:int countNodes(TreeNode* root) {int res 0;if (root nullptr) return res;queue<TreeNode*> deque;TreeNode* cur root;deque.push(cur);int size 0;w…

注册亚马逊店铺用动态IP可以吗?

注册亚马逊店铺可以用动态IP&#xff0c;只要是独立且干净的网线就没问题&#xff0c;亚马逊规则要求一个IP地址只能出现一个亚马逊店铺&#xff0c;若使用不当会导致关联账户。 固定ip可以给我们的账户带来更多的安全&#xff0c;要知道关联问题是亚马逊上的一个大问题&#…

DBCO-PEG8-Amine,二苯并环辛炔 PEG8 氨基,具有良好反应活性

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;二苯并环辛炔-八聚乙二醇-氨基&#xff0c;二苯并环辛炔 PEG8 氨基&#xff0c;DBCO-PEG8-NH2&#xff0c;DBCO-PEG8-Amine 一、基本信息 产品简介&#xff1a;DBCO-PEG8-NH2 is a compound with good reactivity. …

ubuntu20.04安装sumo

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 有问题&#xff0c;请大家指出&#xff0c;争取使方法更完善。这只是ubuntu安装sumo的一种方法。一、注意事项1、首先明确你的ubuntu的用户名是什么 二、sumo安装1.…

Python爬虫实践指南:利用cpr库爬取技巧

引言 在信息时代&#xff0c;数据是无价之宝。为了获取网络上的丰富数据&#xff0c;网络爬虫成为了不可或缺的工具。在Python这个强大的编程语言中&#xff0c;cpr库崭露头角&#xff0c;为网络爬虫提供了便捷而高效的解决方案。本文将深入探讨如何利用cpr库实现数据爬取的各…

Ruff应用:打破传统,IoT技术赋能工业制造数字化转型之路

近年来&#xff0c;随着物联网、大数据、云计算、5G等数字技术的快速应用&#xff0c;工业制造领域正在经历着前所未有的变革。工业4.0时代&#xff0c;各种数字技术与工业制造的结合&#xff0c;不仅提高了工业生产效率、降低运营成本&#xff0c;更是极大地推动了传统工业数字…

智能小程序事件系统——SJS响应事件实现方案

背景信息 如有频繁用户交互&#xff0c;在小程序上表现是比较卡顿的。例如&#xff0c;页面有 2 个元素 A 和 B&#xff0c;用户在 A 上做 touchmove 手势&#xff0c;要求 B 也跟随移动&#xff0c;movable-view 就是一个典型的例子。一次 touchmove 事件的响应过程为&#x…

GPT-4 Vision调试任何应用,即使缺少文本日志 升级Streamlit七

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

springboot 个人网盘系统 java web网盘文件分享系统 web在线云盘

springboot 个人网盘系统 java web网盘文件分享系统 web在线云盘 开发工具&#xff1a;Eclipse/idea Java开发环境&#xff1a;JDK8.0 Web服务器:Tomcate9.0。 数据库&#xff1a;MySQL数据库。 技术框架&#xff1a;Struts2SpringHibernate和JSP 有详细的源码&#xff0…

人脸识别技术在网络安全中有哪些应用前景?

人脸识别技术在网络安全中有广泛的应用前景。以下是一些主要的应用方向&#xff1a; 1. 身份验证和访问控制&#xff1a;人脸识别可以用作一种更安全和方便的身份验证方法。通过将用户的人脸与事先注册的人脸进行比对&#xff0c;可以实现强大的身份验证&#xff0c;避免了传统…

自动驾驶:Apollo如何塑造人类的未来出行

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言1. 什么是自定义指令&#xff1f;2. Apollo中的自定义指令2.1 查询中的自定…

开源博客项目Blog .NET Core源码学习(8:EasyCaching使用浅析)

开源博客项目Blog使用EasyCaching模块实现缓存功能&#xff0c;主要是在App.Framwork项目中引用了多类包&#xff0c;包括内存缓存&#xff08;EasyCaching.InMemory&#xff09;、Redis缓存&#xff08;EasyCaching.CSRedis&#xff09;&#xff0c;同时支持多种序列化方式&am…

微软Office Plus与WPS Office的较量:办公软件市场将迎来巨变?

微软Office Plus在功能表现上远超WPS Office&#xff1f; 微软出品的Office套件实力强劲&#xff0c;其不仅在办公场景中扮演着不可或缺的角色&#xff0c;为用户带来高效便捷的体验&#xff0c;而且在娱乐生活管理等多元领域中同样展现出了卓越的应用价值 作为中国本土办公软…

GPT-4 Vision根据应用程序截图生成博客和Readme 升级Streamlit八

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测

回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测 目录 回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-B…

python中的josn方法相关介绍

如果需要在不同的编程语言之间传递对象&#xff0c;就必须把对象序列化为标准格式&#xff0c;比如XML&#xff0c;但更好的方法是序列化为JSON&#xff0c;因为JSON表示出来就是一个字符串&#xff0c;可以被所有语言读取&#xff0c;也可以方便地存储到磁盘或者通过网络传输。…

maven helper 解决jar包冲突方法

一 概要说明 1.1 说明 首先&#xff0c;解决idea中jar包冲突&#xff0c;使用maven的插件&#xff1a;maven helper插件&#xff0c;它能够给我们罗列出来同一个jar包的不同版本&#xff0c;以及他们的来源&#xff0c;但是对不同jar包中同名的类没有办法。 1.2 依赖顺序 …