x_fft = torch.fft.rfft(x, dim=1, norm=ortho)

news/2025/4/1 6:26:43/文章来源:https://www.cnblogs.com/saulstavo/p/18799807

下面给出一个例子,假设我们有如下数据,其形状为
[
(\text{batch} \times \text{ts_d},, \text{seg_num},, d_{\text{model}}) = (4,,4,,3)
]

这里我们设定:

  • batch = 2
  • ts_d = 2
  • seg_num = 4(也就是每个信号长度为 4)
  • d_model = 3(每个时刻有 3 个特征)

因此,共有 4 个信号(可以认为是 4 个独立样本),每个信号是一个 4×3 的矩阵。比如我们定义数据如下(为了方便说明,这里各个样本的数据取不同值):

x = tensor([[ [ 1,  2,  3],    // 第1个样本,第1个通道的信号: [1, 4, 7, 10] 后面会说明[ 4,  5,  6],[ 7,  8,  9],[10, 11, 12] ],[ [ 2,  3,  4],[ 5,  6,  7],[ 8,  9, 10],[11, 12, 13] ],[ [ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11],[12, 13, 14] ],[ [ 4,  5,  6],[ 7,  8,  9],[10, 11, 12],[13, 14, 15] ]
])

这里每个最外层的元素对应一个样本(总数为4,即 batch×ts_d),每个样本内部是一个 4×3 的矩阵,其中:

  • 第一维(索引0到3)为 seg_num,代表一个信号的时间步数;
  • 第二维(索引0到2)为 d_model,对应每个时刻的 3 个特征。

计算过程说明

我们调用

x_fft = torch.fft.rfft(x, dim=1, norm='ortho')

这里说明:

  • dim=1 表示对每个样本中的 seg_num 维度进行快速傅里叶变换(FFT),即对每个通道(d_model)独立地对长度为4的序列进行变换。
  • norm='ortho' 表示采用正交归一化,即每个变换乘以 ( \frac{1}{\sqrt{N}} )(这里 ( N=4 ))。

1. FFT 后的形状

由于输入沿 dim=1 的长度为 4,为了利用实数输入的共轭对称性质,rfft 只计算非负频率部分,其返回的频率个数为
[
\text{freq_num} = \frac{\text{seg_num}}{2} + 1 = 3.
]
因此,计算后的输出形状为
[
(4,, 3,, 3)
]
即 4 个样本,每个样本有 3 个频率成分,每个频率成分对应 3 个特征(d_model)。

2. 对单个样本、单个通道的计算示例

为了详细说明计算过程,我们以第 0 个样本的第 0 个通道为例。
在该样本中,第 0 个通道的信号为:
[
x[0, :, 0] = [1,, 4,, 7,, 10]
]
我们对这个长度为 4 的实数序列进行 rfft,正交归一化版本的离散傅里叶变换公式为
[
X[k] = \frac{1}{\sqrt{4}} \sum_{n=0}^{3} x[n], e^{-i,2\pi,k,n/4},\quad k=0,1,2.
]

  • 频率 ( k=0 ):
    指数部分 ( e^{-i,2\pi,0,n/4} = 1 ) 对所有 ( n ) 都为 1。
    计算:
    [
    X[0] = \frac{1}{2} (1 + 4 + 7 + 10) = \frac{22}{2} = 11.
    ]
    结果为实数 11。

  • 频率 ( k=1 ):
    指数部分为:

    • ( n=0 ):( e^{-i,0} = 1 )
    • ( n=1 ):( e^{-i,2\pi/4} = e^{-i,\pi/2} = -i )
    • ( n=2 ):( e^{-i,\pi} = -1 )
    • ( n=3 ):( e^{-i,3\pi/2} = i )

    对应计算:
    [
    \begin{aligned}
    X[1] &= \frac{1}{2} \Bigl[ 1\cdot1 + 4\cdot(-i) + 7\cdot(-1) + 10\cdot i \Bigr] \
    &= \frac{1}{2} \Bigl[ 1 - 4i - 7 + 10i \Bigr] \
    &= \frac{1}{2} \Bigl[ (1-7) + (-4i+10i) \Bigr] \
    &= \frac{1}{2} \Bigl[ -6 + 6i \Bigr] = -3 + 3i.
    \end{aligned}
    ]

  • 频率 ( k=2 ):
    此时 ( e^{-i,2\pi,2,n/4} = e^{-i,\pi,n} = (-1)^n )。
    计算:
    [
    \begin{aligned}
    X[2] &= \frac{1}{2} \Bigl[ 1\cdot1 + 4\cdot(-1) + 7\cdot1 + 10\cdot(-1) \Bigr] \
    &= \frac{1}{2} \Bigl[ 1 - 4 + 7 - 10 \Bigr] \
    &= \frac{1}{2} \Bigl[ -6 \Bigr] = -3.
    \end{aligned}
    ]
    注意 ( k=2 )(等于 seg_num/2,当 seg_num 为偶数时)对应的频谱值为实数。

3. 对其他样本和通道

对于形状中每个样本(共 4 个)以及每个通道(3 个),rfft 都是沿着 seg_num 维度分别计算。也就是说,对于第 i 个样本和第 j 个通道,其信号为
[
x[i, :, j] = [x[i,0,j],, x[i,1,j],, x[i,2,j],, x[i,3,j]]
]
计算过程与上面完全类似。如果某个信号的取值不同,则各个频率分量 ( X[k] ) 也会不同;但计算步骤始终按照下式进行:
[
X[k] = \frac{1}{\sqrt{4}} \sum_{n=0}^{3} x[i, n, j], e^{-i,2\pi,k,n/4},\quad k=0,1,2.
]

4. 结果的解释

最终,调用

x_fft = torch.fft.rfft(x, dim=1, norm='ortho')

后得到的 x_fft 张量形状为 (4, 3, 3)。其中:

  • 第一维(4)对应 batch*ts_d,每个样本独立处理;
  • 第二维(3)对应非负频率的个数,即 ( k=0,1,2 );
  • 第三维(3)对应每个样本的 d_model 特征。

对每个样本、每个特征通道,你都得到了其频谱表示。正交归一化保证了变换前后能量保持一致(即 Parseval 定理成立)。

总结

  • 我们构造了一个符合形状 ((4,4,3)) 的数据,其中 4 表示 batch×ts_d,4 表示 seg_num,3 表示 d_model。
  • 对每个样本中的每个通道,我们沿 seg_num(长度为 4)的维度进行 rfft,得到 3 个频率成分。
  • 以样本 0,第 0 通道为例,我们详细计算了频率 ( k=0,1,2 ) 的傅里叶变换,分别得到 11、(-3+3i) 和 (-3)(乘以归一化因子 1/2 后的结果)。

这种方法能够推广到更高维度的输入,只要指定正确的 dim 参数,即可沿着特定维度计算 FFT。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Vue] Vue 模板编译原理解析 part 2

转换器 主要的目的是将模板的 AST 转换为 JS 的 AST,整个模板的编译过程如下: // Vue 的模板编译器 function compile(template) {// 1. 得到模板的 ASTconst ast = parse(template);// 2. 将模板 AST 转为 JS ASTtransform(ast); }整个转换实际上可以分为两个大的部分:模板…

Flasher V5 JLink Pro V6

原帖链接:https://nicemcu.github.io/2025/03/29/PSoC4/FlasherV5/ 2025年3月29日,神变月最后一天,我们参加了放生~ 在这个特殊的日子里,我完成了Flasher V5和JLink Pro V6的crack,难掩内心的喜悦与激动,记录下这一时刻。 前不久小黄鱼上收了一枚Flasher ARM,硬件版本V5…

[Vue] Vue模板编译原理解析 part 1

模板编译整体流程 首先我们看一下什么是编译? 所谓编译(Compile),指的是将语言 A 翻译成语言 B,语言 A 就被称之为源码(source code),语言 B 就被称之为目标代码(target code),这个事情谁来做?编译器来做。编译器你也不用想得那么神秘,就是一段程序而已。 完整的编…

[P] 结对项目:影蛇舞

项目 内容这个作业属于哪个课程 2025年春季软件工程(罗杰、任健) 这个作业的要求在哪里 [P] 结对项目:影蛇舞 我在这个课程的目标是 学习软件工程知识,通过团队协作开发一个具备实际应用价值的软件,从需求分析、设计、开发到测试和部署,完整经历软件开发生命周期,提高工…

0329-Never Give Up

前言 用LCD1602 去打印一段话吧。 就当作激励和安慰,毕竟,我今天被坏情绪传染了一下,有点点失落和悲伤。 参考 5-2 LCD1602调试器 效果 Never Give UpAttitude Is Everything代码 LCD1602.h #ifndef __LCD1602_H__ #define __LCD1602_H__//用户调用函数: void LCD_Init(); …

JavaScript 数据结构与算法 — 单向链表

链表(Linked List)是一种基本的数据结构,用于表示一组按顺序排列的元素。链表中的每个元素都与下一个元素连接,元素在内存中并不是连续的,而是通过指针来链接在一起。每个元素都包含两部分:自己的数据和指向下一个元素的指针。我们常说的链表指的是单向链表,第一个元素的…

Ethernaut通关(智能合约漏洞)(有缘更新)

SnowSword笑传之出错币Ethernaut通关 参考文章:文章 - Ethernaut闯关录(上) - 先知社区、 智能合约是什么?把智能合约想象成网络上的赛博自动售货机,每个人都可以写自己的智能合约,使用虚拟货币交易物品,并且网络区块链中的所有节点都在为你的交易记账不怕商家提桶跑路……

QML基本组件 滑动条 Slider

描述 Slider通过手柄沿轨迹滑动来设置数值。 Qt帮助文档搜索 “slider” 获取详细信息。属性 from : real to : real value : real orientation : enumeration stepsize : real touchDragThreshold : qreal信号 onValueChange {}import QtQuick import QtQuick.ControlsWindow …

UE5--006--小结(一)

1. Input2. AI Enmy3.Save Game

阶段升级,zhitan-ems开源能源管理系统--集成建筑能耗支路和分项功能

升级介绍 自从春节上班后开源以来,zhitan-ems收到了大家很多的赞誉和认可,很多朋友也提出了中肯的意见。感谢大家。 很多朋友的建议里提到建筑能耗功能,依据大家意见,我们加班加点实现了简单的建筑能耗功能。如下图: 另外打一波广告,欢迎大家star 项目介绍 通过物联网技…

Static Timing Analysis Basics

Preface This note only introduce the essential concepts about Static Timing Analysis, which not contains:Async, i.e. remove, recover Timing conceptions, i.e. false path, multi cycle path etc. Advance timing domain knowledgePOCV, MCMM etc.什么是 STA 由于时钟…

深圳大学的一些简单题

A打表,发现是这样的东西:然后规律很显然,相邻的两个数,一组在左边,另一组在右边,依次循环,偶数的时候是 \(23\) 开头,奇数的时候是 \(12\) 开头,再处理一下 \(1\) 和 \(n\) 就可以,比较简单的分讨 显然规律不止一个点击查看代码 #include <bits/stdc++.h> usin…