【深度学习】TCN,An Empirical Evaluation of Generic Convolutional【二】

文章目录

  • 膨胀卷积
      • 什么是膨胀卷积
      • 膨胀卷积公式
      • PyTorch代码
  • 从零开始手动实现一个1D膨胀卷积,不使用PyTorch的`nn.Conv1d`
      • 1. 基本概念
      • 2. 手动实现1D膨胀卷积
  • TCN结构
  • 如何使用TCN
      • 源码说明
        • 1. Chomp1d 类
        • 2. TemporalBlock 类
        • 3. TemporalConvNet 类
      • 使用方法

膨胀卷积

什么是膨胀卷积

膨胀卷积(Dilated Convolution),也称为空洞卷积(Atrous Convolution),是在标准卷积的基础上通过引入膨胀因子(dilation factor)来扩展感受野,而不增加参数数量或计算复杂度。膨胀卷积通过在滤波器的每两个元素之间插入空洞(即,零值)来实现这一点。

膨胀卷积公式

膨胀卷积的数学公式如下:

F ( s ) = ( x ∗ d f ) ( s ) = ∑ i = 0 k − 1 f ( i ) ⋅ x s − d ⋅ i F(s) = (x *_d f)(s) = \sum_{i=0}^{k-1} f(i) \cdot x_{s - d \cdot i} F(s)=(xdf)(s)=i=0k1f(i)xsdi

其中:

  • (x) 是输入信号。
  • (f) 是卷积滤波器。
  • (s) 是输出信号的位置。
  • (d) 是膨胀因子,表示滤波器元素之间的间隔。
  • (k) 是滤波器的大小。

当 (d=1) 时,膨胀卷积退化为标准卷积。

PyTorch代码

下面是一个使用PyTorch实现膨胀卷积的示例:

import torch
import torch.nn as nn

class DilatedConv1D(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, dilation):
        super(DilatedConv1D, self).__init__()
        self.dilated_conv = nn.Conv1d(
            in_channels=in_channels,
            out_channels=out_channels,
            kernel_size=kernel_size,
            dilation=dilation,
            padding=(kernel_size - 1) * dilation // 2
        )

    def forward(self, x):
        return self.dilated_conv(x)

# 示例输入
batch_size = 1
in_channels = 1
seq_length = 10

x = torch.randn(batch_size, in_channels, seq_length)

# 创建膨胀卷积层
dilated_conv_layer = DilatedConv1D(in_channels=1, out_channels=1, kernel_size=3, dilation=2)

# 前向传播
output = dilated_conv_layer(x)
print(output)

从零开始手动实现一个1D膨胀卷积,不使用PyTorch的nn.Conv1d

1. 基本概念

膨胀卷积的公式为:

y [ t ] = ∑ k x [ t − k ⋅ d ] ⋅ w [ k ] y[t] = \sum_{k} x[t - k \cdot d] \cdot w[k] y[t]=kx[tkd]w[k]

其中:

  • y [ t ] y[t] y[t] 是输出信号。
  • x [ t ] x[t] x[t] 是输入信号。
  • w [ k ] w[k] w[k] 是卷积核的权重。
  • d d d 是膨胀率。

2. 手动实现1D膨胀卷积

下面是手动实现1D膨胀卷积的Python代码:

import torch
import torch.nn as nn
import torch.nn.functional as F

class ManualDilatedConv1D(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, dilation=1):
        super(ManualDilatedConv1D, self).__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.dilation = dilation

        # 初始化卷积核权重
        self.weight = nn.Parameter(torch.randn(out_channels, in_channels, kernel_size))
        self.bias = nn.Parameter(torch.randn(out_channels))

    def forward(self, x):
        batch_size, in_channels, length = x.shape
        assert in_channels == self.in_channels

        # 计算输出的长度
        out_length = length - (self.kernel_size - 1) * self.dilation

        # 初始化输出张量
        out = torch.zeros(batch_size, self.out_channels, out_length)

        # 对每个输出通道进行卷积
        for b in range(batch_size):
            for o in range(self.out_channels):
                for i in range(out_length):
                    sum = 0
                    for k in range(self.kernel_size):
                        sum += x[b, :, i + k * self.dilation] * self.weight[o, :, k]
                    out[b, o, i] = sum + self.bias[o]
        return out

# 示例参数
in_channels = 1
out_channels = 1
kernel_size = 3
dilation = 2

# 创建一个输入张量 (batch_size, channels, length)
input_tensor = torch.randn(1, in_channels, 10)

# 创建手动膨胀卷积层
manual_dilated_conv = ManualDilatedConv1D(in_channels, out_channels, kernel_size, dilation)

# 前向传播
output_tensor = manual_dilated_conv(input_tensor)

print(output_tensor)

TCN结构

在这里插入图片描述

import torch
import torch.nn as nn
from torch.nn.utils import weight_norm


class Chomp1d(nn.Module):
    def __init__(self, chomp_size):
        super(Chomp1d, self).__init__()
        self.chomp_size = chomp_size

    def forward(self, x):
        return x[:, :, :-self.chomp_size].contiguous()


class TemporalBlock(nn.Module):
    def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2):
        super(TemporalBlock, self).__init__()
        self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))
        self.chomp1 = Chomp1d(padding)
        self.relu1 = nn.ReLU()
        self.dropout1 = nn.Dropout(dropout)

        self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))
        self.chomp2 = Chomp1d(padding)
        self.relu2 = nn.ReLU()
        self.dropout2 = nn.Dropout(dropout)

        self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1,
                                 self.conv2, self.chomp2, self.relu2, self.dropout2)
        self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
        self.relu = nn.ReLU()
        self.init_weights()

    def init_weights(self):
        self.conv1.weight.data.normal_(0, 0.01)
        self.conv2.weight.data.normal_(0, 0.01)
        if self.downsample is not None:
            self.downsample.weight.data.normal_(0, 0.01)

    def forward(self, x):
        out = self.net(x)
        res = x if self.downsample is None else self.downsample(x)
        return self.relu(out + res)


class TemporalConvNet(nn.Module):
    def __init__(self, num_inputs, num_channels, kernel_size=2, dropout=0.2):
        super(TemporalConvNet, self).__init__()
        layers = []
        num_levels = len(num_channels)
        for i in range(num_levels):
            dilation_size = 2 ** i
            in_channels = num_inputs if i == 0 else num_channels[i-1]
            out_channels = num_channels[i]
            layers += [TemporalBlock(in_channels, out_channels, kernel_size, stride=1, dilation=dilation_size,
                                     padding=(kernel_size-1) * dilation_size, dropout=dropout)]

        self.network = nn.Sequential(*layers)

    def forward(self, x):
        return self.network(x)

如何使用TCN

以下是如何使用上述Temporal Convolutional Network (TCN) 代码的详细讲解和步骤:

源码说明

1. Chomp1d 类

Chomp1d类用于从输入的末端裁剪指定大小的时间步长。

class Chomp1d(nn.Module):
    def __init__(self, chomp_size):
        super(Chomp1d, self).__init__()
        self.chomp_size = chomp_size

    def forward(self, x):
        return x[:, :, :-self.chomp_size].contiguous()
2. TemporalBlock 类

TemporalBlock类构建了一个基础的时间卷积模块,包括两个卷积层,每个卷积层后都有一个Chomp1d、ReLU激活函数和Dropout。

class TemporalBlock(nn.Module):
    def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2):
        super(TemporalBlock, self).__init__()
        self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))
        self.chomp1 = Chomp1d(padding)
        self.relu1 = nn.ReLU()
        self.dropout1 = nn.Dropout(dropout)

        self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size,
                                           stride=stride, padding=padding, dilation=dilation))
        self.chomp2 = Chomp1d(padding)
        self.relu2 = nn.ReLU()
        self.dropout2 = nn.Dropout(dropout)

        self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1,
                                 self.conv2, self.chomp2, self.relu2, self.dropout2)
        self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else None
        self.relu = nn.ReLU()
        self.init_weights()

    def init_weights(self):
        self.conv1.weight.data.normal_(0, 0.01)
        self.conv2.weight.data.normal_(0, 0.01)
        if self.downsample is not None:
            self.downsample.weight.data.normal_(0, 0.01)

    def forward(self, x):
        out = self.net(x)
        res = x if self.downsample is None else self.downsample(x)
        return self.relu(out + res)
3. TemporalConvNet 类

TemporalConvNet类将多个TemporalBlock组合在一起,形成完整的TCN模型。

class TemporalConvNet(nn.Module):
    def __init__(self, num_inputs, num_channels, kernel_size=2, dropout=0.2):
        super(TemporalConvNet, self).__init__()
        layers = []
        num_levels = len(num_channels)
        for i in range(num_levels):
            dilation_size = 2 ** i
            in_channels = num_inputs if i == 0 else num_channels[i-1]
            out_channels = num_channels[i]
            layers += [TemporalBlock(in_channels, out_channels, kernel_size, stride=1, dilation=dilation_size,
                                     padding=(kernel_size-1) * dilation_size, dropout=dropout)]

        self.network = nn.Sequential(*layers)

    def forward(self, x):
        return self.network(x)

使用方法

  1. 准备输入数据
    TCN适用于一维序列数据,如时间序列。输入数据的形状应该是(batch_size, num_inputs, sequence_length)

  2. 初始化模型
    定义模型的输入通道数num_inputs,每一层的输出通道数列表num_channels,卷积核大小kernel_sizedropout比例。

num_inputs = 10  # 输入通道数,例如10个特征
num_channels = [16, 32, 64]  # 每个TemporalBlock的输出通道数
kernel_size = 2
dropout = 0.2

model = TemporalConvNet(num_inputs, num_channels, kernel_size, dropout)
  1. 训练模型
    使用PyTorch常规的训练步骤,定义损失函数和优化器,然后进行前向传播、计算损失、反向传播和参数更新。
# 示例:随机生成输入数据
batch_size = 8
sequence_length = 30
input_data = torch.randn(batch_size, num_inputs, sequence_length)

# 模型输出
output = model(input_data)
print(output.shape)  # 输出形状为(batch_size, num_channels[-1], sequence_length)

batch_size, num_inputs, 和 sequence_length 是与输入数据和模型有关的参数。以下是对它们的详细解释:

  • batch_size:

    • 表示每次输入模型的样本数量。
    • 例如,如果你有1000个样本数据,并且你希望每次输入模型进行训练时处理32个样本,那么batch_size将是32。
    • 这个参数通常用于加速训练过程,并使得计算更高效,因为可以利用并行计算。
  • num_inputs:

    • 表示输入数据的特征数量或通道数。
    • 在时间序列数据中,通常每个时间步可能包含多个特征。例如,如果你的时间序列数据在每个时间步包含温度和湿度两个特征,那么num_inputs将是2。
    • 对于一维时间序列数据,如果每个时间步只有一个值(如单变量时间序列),则num_inputs为1。
  • sequence_length:

    • 表示时间序列的长度,即每个样本中包含的时间步数。
    • 例如,如果你有一个每天记录温度的时间序列数据,记录了30天的数据,那么sequence_length将是30。
    • 这个参数决定了输入数据的时间维度长度。
  1. 定义损失函数和优化器
    可以使用MSELoss或其他适合具体任务的损失函数。
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# 示例:随机生成目标数据
target_data = torch.randn(batch_size, num_channels[-1], sequence_length)

# 前向传播
output = model(input_data)

# 计算损失
loss = criterion(output, target_data)

# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()

print('Loss:', loss.item())

以上是如何使用Temporal Convolutional Network (TCN)代码的详细步骤和示例。通过这些步骤,你可以定义并训练一个TCN模型来处理一维序列数据。

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

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

相关文章

计算机毕业设计hadoop+spark+hive知识图谱股票推荐系统 股票数据分析可视化大屏 股票基金爬虫 股票基金大数据 机器学习 大数据毕业设计

哈 尔 滨 理 工 大 学 毕业设计开题报告 题 目: 基于Spark的股票大数据分析及可视化系统 院 系: 计算机科学与技术学院 数据科学与大数据技术系 2023年10月 一、选题的依据…

String常用方法详解

auth:别晃我的可乐 date:2024年06月16日 比较大小 equals(Object obj): 用于比较字符串内容是否相等。compareTo(String anotherString): 按字典顺序比较两个字符串。 String str1 "hello"; String str2 "world";boolean isEqual …

Android面试题 之 网络通信基础 面试题

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点 序列化 判断标准 序列化后的码流大小性能跨语言 Serializable方式 码流偏大性能较低 XML方式 人机可读性好文件格式复杂、占带宽 JSON …

version-manager最好用的SDK版本管理器,v0.6.2发布

项目地址:https://github.com/gvcgo/version-manager 中文文档:https://gvcgo.github.io/vdocs/#/zh-cn/introduction 功能特点: 跨平台,支持Windows,Linux,MacOS支持多种语言和工具,省心受到…

Spark运行spark-shell与hive运行时均报错的一种解决方案

环境按照尚硅谷的配置的。 在运行hive的时候,报错代码为30041,无法执行insert语句。 在运行spark-shell的时候,报错,无法进入到shell脚本中。 可能的问题: 对集群设置的域名与集群的主机名称不一致。 例如:…

MySQL数据库管理(一)

目录 1.MySQL数据库管理 1.1 常用的数据类型​编辑 1.2 char和varchar区别 2. 增删改查命令操作 2.1 查看数据库结构 2.2 SQL语言 2.3 创建及删除数据库和表 2.4 管理表中的数据记录 2.5 修改表名和表结构 3.MySQL的6大约束属性 1.MySQL数据库管理 1.1 常用的数据类…

python包管理器--- pip、conda、mamba的比较

1 pip 1.1 简介 pip是一个 Python 的包(Package)管理工具,用于从 PyPI 安装和管理 Python 标准库之外的其他包(第三方包)。从 Python 3.4 起,pip 已经成为 Python 安装程序的一部分,也是官方标准…

如何在不懂足球的情况下对欧洲杯进行预测

指北君不懂足球,只是懂点数据。简单聊下欧洲杯预测。 体育活动中的数据分析和预测 数据早就融入到了专业的体育活动中,无论是提高运动员的表现,还是战术和策略制定,伤病预防和恢复,甚至球迷和商业分析,都离…

【面经总结】Java集合 - Map

Map 概述 Map 架构 HashMap 要点 以 散列(哈希表) 方式存储键值对,访问速度快没有顺序性允许使用空值和空键有两个影响其性能的参数:初始容量和负载因子。 初始容量:哈希表创建时的容量负载因子:其容量自动扩容之前被允许的最大…

国际统计年鉴(1995-2023年)

数据年份:1995-2023 数据格式:pdf、excel 数据内容:《国际统计年鉴》是一部综合性的国际经济社会统计资料年刊,收录了世界200多个国家和地区的统计数据,并对其中40多个主要国家和地区的经济社会发展指标及国际组织发布…

【数据结构】初识集合深入剖析顺序表(Arraylist)

【数据结构】初识集合&深入剖析顺序表(Arraylist) 集合体系结构集合的遍历迭代器增强for遍历lambda表达式 List接口中的增删查改List的5种遍历ArrayList详解ArrayList的创建ArrayList的增删查改ArrayList的遍历ArrayList的底层原理 🚀所属…

卡尔曼滤波源码注释和调用示例

卡尔曼滤波源码注释和调用示例 flyfish Python版本代码地址 C版代码地址 主要用于分析代码,增加了中文注释 import numpy as np import scipy.linalg""" 0.95分位数的卡方分布表,N自由度(包含N1到9的值)。 取自…

多源最短路径算法 -- 弗洛伊德(Floyd)算法

1. 简介 Floyd算法,全名为Floyd-Warshall算法,亦称弗洛伊德算法或佛洛依德算法,是一种用于寻找给定加权图中所有顶点对之间的最短路径的算法。这种算法以1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特弗洛伊德的名字命名。 2. 核心思…

打造私密的通信工具,极空间搭建免费开源的电子邮件管理程序『Cypht』

打造私密的通信工具,极空间搭建免费开源的电子邮件管理程序『Cypht』 哈喽小伙伴门好,我是Stark-C~ 说起电子邮件大家都不陌生,哪怕是在当前微信或者QQ已经非常普遍的今天,电子邮件在我们很多人的工作中都充当了重要的通信工具。…

【星座运势】本周财运分析,巨蟹座财富潜力大开!

大家好!今天我们来谈谈巨蟹座本周的财富运势。经过调查和数据分析,我发现巨蟹座这周的财运潜力很大!接下来,我将用通俗易懂的语言,通过代码说明,向大家展示巨蟹座的财富运势。 首先,我们需要通…

多设备互通、开箱即用的私有化笔记软件,极空间部署最强备忘录项目『Memos』

多设备互通、开箱即用的私有化笔记软件,极空间部署最强备忘录项目『Memos』 哈喽小伙伴们好,我是Stark-C~ 手机上的备忘录我想绝大多数的小伙伴都会用到,日常用来记录一下生活中的消费开支清单,或者工作中记录一些重要的任务或项…

【动态规划】0-1背包问题

【动态规划】0-1背包问题 题目:现在有四个物品,背包总容量为8,背包最多能装入价值为多少的物品? 我的图解 表格a【i】【j】表示的是容量为j的背包装入前i个物品的最大价值。 拿a【1】【1】来说,它的值就是背包容量为1,只考虑…

4.1 初探Spring Boot

初探Spring Boot实战概述 Spring Boot简介 Spring Boot是一个开源的Java框架,由Pivotal团队(现为VMware的一部分)开发,旨在简化Spring应用程序的创建和部署过程。它通过提供一系列自动化配置、独立运行的特性和微服务支持&#…

低代码开发MES系统,一周实现数字化

随着工业4.0和智能制造的兴起,企业对于生产过程的数字化、智能化需求日益迫切。制造执行系统(MES)作为连接计划层与控制层的关键信息系统,在提升生产效率、优化资源配置、保障产品质量等方面发挥着重要作用。然而,传统…

数据质量管理解决方案(55页PPT)

方案介绍: 数据质量管理解决方案是一个系统性的方法,旨在确保数据的准确性、完整性、一致性、可靠性和可用性。该解决方案覆盖了数据从产生到消亡的整个生命周期,包括数据的计划、获取、存储、共享、维护、应用和消亡等各个阶段。数据质量管…