专栏名称: 机器学习初学者
号主黄博Github全球排名前90,3.6万Star!致力于为初学者提供学习路线和基础资料,公众号可以当作随身小抄,文章很全,建议收藏!点击菜单可以进入学习!
目录
相关文章推荐
Insight数据库  ·  Nectin-4 ADC ... ·  18 小时前  
药渡  ·  “First-in-class”小分子达3期 ... ·  2 天前  
药渡  ·  当投资人下场做BD ·  昨天  
51好读  ›  专栏  ›  机器学习初学者

【深度学习】突破CNN!时间序列分类 !!

机器学习初学者  · 公众号  ·  · 2025-02-05 14:38

正文

咱们今天来聊一个话题:基于CNN的时间序列分类方法。

其中给大家展示了其中详细的原理,以及完整的一个案例,完整的代码~

假设我们有一组一维时间序列数据,每个样本的输入为长度为 的信号 ,目标是将其分为 个类别中的一个。为此,我们构建一个基于 CNN 的分类器,利用局部特征提取和层级特征融合实现分类。

数据预处理

通常,输入数据需要经过归一化或标准化处理,例如将每个时间序列归一化到均值为0、方差为1:

其中 分别为该序列的均值和标准差。

CNN 模型架构

对于一维时间序列,常采用 1D 卷积操作。典型的 CNN 模型结构可以包含以下几个模块:

  1. 卷积层(Convolutional Layer)
  2. 激活层(Activation Layer,如 ReLU)
  3. 池化层(Pooling Layer,如最大池化)
  4. 全连接层(Fully Connected Layer)
  5. 输出层(Softmax 分类器)

下面咱们就来详细介绍各部分的计算过程~

卷积层

卷积操作:

给定输入信号 和一个长度为 的卷积核(滤波器) ,以及偏置 ,卷积操作在位置 上的输出 定义为:

其中

对于多通道(例如前几层特征图)的情况,假设输入为 通道,每个通道的信号为 ,则卷积核也扩展为 ,卷积结果为:

步幅与填充:

  • 步幅(stride) 决定了卷积核滑动的步长;
  • 填充(padding) 用于控制输出长度。

若使用填充,输出长度 为:

激活函数

常用的激活函数为 ReLU,其公式为:

即,对卷积层输出的每个元素 应用:

池化层

池化层用于降维和提取最显著的局部特征。以 1D 最大池化(Max Pooling)为例,假设池化窗口大小为 ,步幅为 ,在窗口 内,输出为:

这样可以减少特征图的长度,同时增强特征的不变性。

多层 CNN 结构

一个典型的 CNN 模型可以堆叠多个卷积层和池化层。

例如,假设模型包含两层卷积层,每层后接 ReLU 激活和池化层:

  1. 第一层卷积层
  • 卷积核大小:
  • 卷积核数量:
  • 输出特征图: 其中,每个特征图的长度为:
  1. 第一层池化层
  • 池化窗口:
  • 输出长度变为:
  1. 第二层卷积层
  • 卷积核大小:
  • 卷积核数量:
  • 输出特征图:
  1. 第二层池化层
  • 池化窗口:
  • 输出长度:

经过以上层级提取后,将得到形状为 的特征图,再将其展平为一个向量,输入到全连接层。

全连接层与 Softmax 分类器

设展平后的特征向量为 ,其中 。全连接层对 的线性变换为:

其中

接下来通过 Softmax 层计算各类别的预测概率:

损失函数与模型训练

通常采用交叉熵损失函数(Cross-Entropy Loss)来衡量模型输出与真实标签之间的差距。对于单个样本,若真实标签的 one-hot 编码为 (其中只有正确类别为1,其余为0),则交叉熵损失定义为:

其中 为真实类别。

在训练过程中,模型参数(卷积核权重、全连接层权重等)通过反向传播算法(Backpropagation)和梯度下降(如 Adam、SGD 等优化器)进行更新。

模型训练流程概述

  1. 前向传播:

  • 对输入时间序列 依次经过各个卷积、激活、池化层提取局部特征。
  • 将多层提取的特征展平后输入全连接层,得到类别得分
  • 利用 Softmax 得到预测概率分布
  • 计算损失:

    • 使用交叉熵损失函数计算单个样本或批次样本的损失。
  • 反向传播:

    • 计算各层参数的梯度,并通过优化算法更新模型参数。
  • 迭代训练:

    • 重复以上步骤直至损失收敛或达到预设的训练轮次。

    完整案例

    传统方法通常依赖特征工程和经典机器学习算法,而深度学习中的卷积神经网络(CNN)在自动提取局部特征、捕捉时序数据局部模式等方面具有明显优势。

    这里,主要想给大家展现的是:利用一维卷积网络对时间序列数据进行特征提取,并结合全连接层进行分类。相较于传统的基于 RNN 或 LSTM 的模型,CNN具有并行计算和局部感受野的优势,能够更快收敛且具有较好的鲁棒性。

    数据集

    为了说明问题,我们构造一个虚拟时间序列数据集。数据集包括三类信号,分别代表不同的模式(例如:正弦波、方波、锯齿波),并加入噪声模拟真实数据中的随机扰动。数据集共包含3000个样本,每个样本的时间步长为128,标签取值为0、1、2。这样可以模拟多类别分类场景。

    数据可视化说明

    在数据构造阶段,我们会绘制以下图形:

    1. 样本波形图 :原始时间序列数据的波形形态,便于观察各类别信号的不同模式。

    2. 数据分布直方图 :各类别样本数量分布情况。

    3. 训练过程损失曲线 :模型在训练集和验证集上的损失变化。

    4. 分类准确率曲线 :每个训练周期(epoch)在训练集和验证集上的分类准确率。

    5. 预测曲线(混淆矩阵、ROC 曲线等) :模型在测试集上的预测结果,如混淆矩阵可以直观反映各类别的识别效果;另外我们也可以绘制各类别的 ROC 曲线。

    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torch.utils.data import Dataset, DataLoader, random_split
    from sklearn.metrics import confusion_matrix, roc_curve, auc
    import itertools
    import random

    # 固定随机种子,保证结果可重复
    np.random.seed(42)
    torch.manual_seed(42)
    random.seed(42)

    # 虚拟数据集生成
    def generate_time_series(n_samples=3000, seq_length=128):
        """
        生成包含三类的虚拟时间序列数据:正弦波、方波、锯齿波,并加入高斯噪声。
        参数:
            n_samples: 总样本数
            seq_length: 每个样本的时间步数
        返回:
            X: 数据矩阵,形状 (n_samples, seq_length)
            y: 标签向量,取值 0,1,2
        """

        X = []
        y = []
        t = np.linspace(02*np.pi, seq_length)
        for i in range(n_samples):
            label = np.random.choice([0,1,2])
            if label == 0:
                # 正弦波
                signal = np.sin(t) + np.random.normal(00.1, seq_length)
            elif label == 1:
                # 方波:利用正弦波阈值化
                signal = np.where(np.sin(t) > 01.0-1.0) + np.random.normal(00.1, seq_length)
            else:
                # 锯齿波:使用线性函数再取周期性
                signal = ((t / np.pi) - 1) + np.random.normal(00.1, seq_length)
            X.append(signal)
            y.append(label)
        X = np.array(X)
        y = np.array(y)
        return X, y

    # 生成数据
    X, y = generate_time_series()

    # 数据可视化:样本波形图
    def plot_sample_waveforms(X, y, n_samples=3):
        """
        随机选择n_samples个样本,并绘制波形图,每种类别选择一个样本。
        """

        plt.figure(figsize=(126))
        colors = ['dodgerblue''crimson''limegreen']  # 鲜艳的蓝色、红色、绿色
        labels = ['Sine Wave''Square Wave''Sawtooth Wave']
        for class_label in range(3):
            idx = np.where(y==class_label)[0]
            sample_idx = np.random.choice(idx, 1)[0]
            plt.plot(X[sample_idx], color=colors[class_label], linewidth=2, label=labels[class_label])
        plt.title("Sample Waveforms of Time Series", fontsize=16)
        plt.xlabel("Time Step", fontsize=14)
        plt.ylabel("Signal Value", fontsize=14)
        plt.legend(fontsize=12)
        plt.grid(alpha=0.3)
        plt.tight_layout()
        plt.show()

    plot_sample_waveforms(X, y)

    # 数据可视化:数据分布直方图
    def plot_data_distribution(y):
        """
        绘制不同类别的样本数直方图
        """

        plt.figure(figsize=(8,6))
        colors = ['darkorange''mediumorchid''teal']  # 橙色、紫色、青色
        sns.countplot(x=y, palette=colors, edgecolor='black')
        plt.title("Class Distribution", fontsize=16)
        plt.xlabel("Class Label", fontsize=14)
        plt.ylabel("Count", fontsize=14)
        plt.tight_layout()
        plt.show()

    plot_data_distribution(y)

    • 样本波形图 :展示了三个典型时间序列样本(正弦波、方波、锯齿波),便于观察各信号形态及噪声干扰情况。






    请到「今天看啥」查看全文