PyTorch torch.signal.windows 窗函数完全指南:从 Bartlett 到 Kaiser 的频谱分析工具详解
【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch
导读
本文围绕 PyTorch 官方文档 docs/source/signal.md 中定义的torch.signal模块展开,重点讲解其子模块torch.signal.windows提供的 11 个窗函数(Bartlett、Blackman、Cosine、Exponential、Gaussian、General Cosine、General Hamming、Hamming、Hann、Kaiser、Nuttall)的数学定义、参数语义与实战用法。读完本文,你将掌握如何在 PyTorch 中生成用于频谱分析(periodic 窗)与滤波器设计(symmetric 窗)的各类窗函数张量,理解M、sym、dtype、device等通用参数的作用,并了解这些函数与 SciPysignal.get_window的对应关系及仓库内的实现细节与测试验证。
torch.signal 模块概述
torch.signal是 PyTorch 中面向信号处理领域的模块,官方文档明确说明其设计参照 SciPy 的signal模块。当前仓库中该模块的实体位于 torch/signal/init.py,顶层__init__.py仅导出一个子模块:
from . import windows __all__ = ["windows"]在 torch/init.py 中通过from torch.signal import windows as windows将其挂载到torch.signal.windows命名空间,因此可以通过torch.signal.windows.<name>直接调用。
从源码结构看,torch.signal目前的核心内容是窗函数子模块 torch/signal/windows/windows.py,共导出 11 个函数,完整清单与__all__一致(见 torch/signal/windows/init.py):
bartlett, blackman, cosine, exponential, gaussian, general_cosine, general_hamming, hamming, hann, kaiser, nuttall窗函数的通用参数模型
所有窗函数共享一套由window_common_args定义的参数规范(见 windows.py),它由窗函数专属参数、PyTorch 通用工厂参数(来自factory_common_args,定义于 torch/_torch_docs.py)以及归一化说明三部分合并而成。
核心参数表
| 参数 | 类型 | 说明 |
|---|---|---|
M | int | 窗的长度,即返回张量的采样点数 |
sym | bool | 默认True,返回对称窗(适用于滤波器设计);设为False返回周期窗(适用于频谱分析) |
dtype | torch.dtype | 返回张量的数据类型,默认None时取torch.get_default_dtype();仅支持float32与float64 |
layout | torch.layout | 返回张量的布局,默认torch.strided,目前仅支持 strided 张量 |
device | torch.device | 返回张量所在设备,默认取当前默认设备 |
requires_grad | bool | 返回张量是否参与自动微分,默认False |
其中M与sym的定义原文如下(节选自window_common_args):
M (int): the length of the window. In other words, the number of points of the returned window.sym (bool): IfFalse, returns a periodic window suitable for use in spectral analysis. IfTrue, returns a symmetric window suitable for use in filter design. Default:True.
归一化说明
window_common_args中特别注明:窗函数归一化到 1(即最大值恒为 1),但当M为偶数且sym=True时,峰值 1 不会出现在返回张量中——因为对称窗的样本点分布在两端,偶数长度下没有任何采样点恰好落在峰值位置。这一点从各函数示例输出中可以验证,例如hann(10)的最大值为0.9698而非 1。
底层参数校验
每个窗函数在计算前都会调用_window_function_checks(见 windows.py),统一完成三类校验:
M < 0时抛出ValueError(提示 "requires non-negative window length");layout不是torch.strided时抛出ValueError(提示 "implemented for strided tensors only"),例如稀疏布局不可用;dtype不在[torch.float32, torch.float64]中时抛出ValueError(提示 "expects float32 or float64 dtypes")。
余弦类窗函数族
PyTorch 的窗函数实现具有清晰的层级复用关系:hann、hamming是general_hamming的特例,而general_hamming、blackman、nuttall又统一由general_cosine实现。理解这条调用链(见 windows.py 中hann→general_hamming→general_cosine、blackman→general_cosine、nuttall→general_cosine),就能掌握大部分窗函数的本质。
general_cosine:通用余弦窗
通用余弦窗的数学定义为:
w_n = Σ (-1)^i · a_i · cos(2π·i·n / (M-1)) (i 从 0 到 len(a)-1)参数a为可迭代的系数集合,源码要求其必须为非空 list/tuple(否则抛出TypeError或ValueError)。实现上,源码先将系数按(-1)^i交替取符号(a_i = [(-1) ** i * w for i, w in enumerate(a)]),再通过torch.cos(i.unsqueeze(-1) * k)构造张量并沿第 0 维求和。当M == 0时返回空张量,M == 1时返回全 1 张量。
示例:
>>> torch.signal.windows.general_cosine(10, a=[0.46, 0.23, 0.31], sym=True) tensor([0.5400, 0.3376, 0.1288, 0.4200, 0.9136, 0.9136, 0.4200, 0.1288, 0.3376, 0.5400]) >>> torch.signal.windows.general_cosine(10, a=[0.5, 1 - 0.5], sym=False) tensor([0.0000, 0.0955, 0.3455, 0.6545, 0.9045, 1.0000, 0.9045, 0.6545, 0.3455, 0.0955])第二个例子中a=[0.5, 0.5]恰好退化为 Hann 窗(见下文),可以作为验证函数等价性的快速手段。
general_hamming:通用 Hamming 窗
通用 Hamming 窗是general_cosine的两系数特例,数学定义为:
w_n = α - (1 - α) · cos(2π·n / (M-1))唯一专属参数alpha默认0.54。源码实现直接将a=[alpha, 1.0 - alpha]转发给general_cosine(见 windows.py)。
hann:Hann 窗
Hann 窗即alpha=0.5的通用 Hamming 窗,其等价形式为:
w_n = 0.5 · [1 - cos(2π·n / (M-1))] = sin²(π·n / (M-1))源码中hann直接调用general_hamming(M, alpha=0.5, ...)(见 windows.py)。典型输出:
>>> torch.signal.windows.hann(10) tensor([0.0000, 0.1170, 0.4132, 0.7500, 0.9698, 0.9698, 0.7500, 0.4132, 0.1170, 0.0000]) >>> torch.signal.windows.hann(10, sym=False) tensor([0.0000, 0.0955, 0.3455, 0.6545, 0.9045, 1.0000, 0.9045, 0.6545, 0.3455, 0.0955])对比可见:周期窗(sym=False)的端点与对称窗不同,且周期窗的最大值恰好为 1,这正是频谱分析中优先选择周期窗的原因——它保证了 FFT 后主瓣对齐且避免端点不连续带来的频谱泄漏。
hamming:Hamming 窗
Hamming 窗即默认alpha=0.54的通用 Hamming 窗:
w_n = 0.54 - 0.46 · cos(2π·n / (M-1))源码中hamming直接转发给general_hamming(见 windows.py),因此二者结果完全一致:
>>> torch.signal.windows.hamming(10) tensor([0.0800, 0.1876, 0.4601, 0.7700, 0.9723, 0.9723, 0.7700, 0.4601, 0.1876, 0.0800])blackman:Blackman 窗
Blackman 窗是三系数通用余弦窗,系数固定为[0.42, 0.5, 0.08]:
w_n = 0.42 - 0.5·cos(2π·n/(M-1)) + 0.08·cos(4π·n/(M-1))源码同样转发给general_cosine(见 windows.py)。注意其示例输出中存在-1.4901e-08量级的浮点噪声,这是数值计算中的正常现象,不影响实际使用:
>>> torch.signal.windows.blackman(5) tensor([-1.4901e-08, 3.4000e-01, 1.0000e+00, 3.4000e-01, -1.4901e-08])nuttall:Nuttall 窗(最小 4 项 Blackman-Harris)
Nuttall 窗是四系数通用余弦窗,专用于旁瓣抑制性能要求较高的场景。其数学定义为:
w_n = 1 - 0.36358·cos(z_n) + 0.48917·cos(2·z_n) - 0.13659·cos(3·z_n) + 0.01064·cos(4·z_n) 其中 z_n = 2π·n / M注意这里分母是M而非M-1,与一般余弦窗的相位定义不同。源码中系数取更高精度的[0.3635819, 0.4891775, 0.1365995, 0.0106411](见 windows.py)。文档同时给出两篇参考文献(A. Nuttall 1981 年发表于 IEEE 的论文及 Heinzel 等人的 DFT 窗函数综述),说明该窗的旁瓣特性有严格的学术依据。
指数族窗函数
exponential:指数窗(Poisson 窗)
指数窗又称 Poisson 窗,数学定义为:
w_n = exp(-|n - c| / τ)其中c为窗中心。专属参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
center | M/2(周期窗)或(M-1)/2(对称窗) | 窗中心位置;对称窗下必须为None,否则抛出ValueError |
tau | 1.0 | 衰减值,必须为正数(tau <= 0时抛出ValueError);通常与百分比关联,取值范围在 (0, 100],当tau=100时退化为均匀窗 |
源码实现先将center与tau组合为线性坐标k = linspace(-center/τ, (-center+(M-1))/τ, M),再返回exp(-|k|)(见 windows.py)。示例:
>>> torch.signal.windows.exponential(10) tensor([0.0111, 0.0302, 0.0821, 0.2231, 0.6065, 0.6065, 0.2231, 0.0821, 0.0302, 0.0111]) >>> torch.signal.windows.exponential(10, sym=False, tau=.5) tensor([4.5400e-05, 3.3546e-04, 2.4788e-03, 1.8316e-02, 1.3534e-01, 1.0000e+00, 1.3534e-01, 1.8316e-02, 2.4788e-03, 3.3546e-04])gaussian:高斯窗
高斯窗的数学定义为:
w_n = exp(-(n / (2σ))²)专属参数std(标准差)默认1.0,必须为正数(std <= 0时抛出ValueError)。源码中constant = 1/(std·√2),通过exp(-(k²))计算(见 windows.py)。std直接控制窗的宽窄:std越小,窗越窄、主瓣越宽,频域分辨率越差但旁瓣越低。
>>> torch.signal.windows.gaussian(10) tensor([4.0065e-05, 2.1875e-03, 4.3937e-02, 3.2465e-01, 8.8250e-01, 8.8250e-01, 3.2465e-01, 4.3937e-02, 2.1875e-03, 4.0065e-05])基础三角函数窗
cosine:余弦窗(sine 窗)
cosine窗虽然名字叫 cosine,但实现上使用的是正弦波形,与 SciPy 保持一致,因此也被称为 sine 窗:
w_n = sin(π·(n + 0.5) / M)源码注释明确指出:该公式与典型的余弦窗公式不同,分子中引入了0.5偏移项,使得窗的首尾采样点取非零值(见 windows.py)。在周期模式下,分母变为M+1:
>>> torch.signal.windows.cosine(10) tensor([0.1564, 0.4540, 0.7071, 0.8910, 0.9877, 0.9877, 0.8910, 0.7071, 0.4540, 0.1564]) >>> torch.signal.windows.cosine(10, sym=False) tensor([0.1423, 0.4154, 0.6549, 0.8413, 0.9595, 1.0000, 0.9595, 0.8413, 0.6549, 0.4154])bartlett:Bartlett 窗(三角窗)
Bartlett 窗即三角窗,数学定义为:
w_n = 1 - |2n/(M-1) - 1|等价于分段函数:左半段2n/(M-1),右半段2 - 2n/(M-1)。源码实现为1 - |k|,其中k = linspace(-1, 1, M)(见 windows.py);M == 0返回空张量,M == 1返回全 1 张量。
>>> torch.signal.windows.bartlett(10) tensor([0.0000, 0.2222, 0.4444, 0.6667, 0.8889, 0.8889, 0.6667, 0.4444, 0.2222, 0.0000]) >>> torch.signal.windows.bartlett(10, sym=False) tensor([0.0000, 0.2000, 0.4000, 0.6000, 0.8000, 1.0000, 0.8000, 0.6000, 0.4000, 0.2000])kaiser:Kaiser 窗
Kaiser 窗以零阶第一类修正贝塞尔函数定义:
w_n = I₀(β·√(1 - ((n - N/2)/(N/2))²)) / I₀(β) 其中 N = M - 1(对称)或 M(周期),I₀ 为 torch.special.i0专属参数beta为形状参数,默认12.0,必须非负(beta < 0时抛出ValueError)。beta是 Kaiser 窗最核心的自由度:它控制主瓣宽度与旁瓣衰减之间的权衡,beta越大旁瓣衰减越强、主瓣越宽。源码直接使用torch.i0计算修正贝塞尔函数,并特别处理了M == 1时返回全 1 张量以避免 NaN(见 windows.py)。
>>> torch.signal.windows.kaiser(5, sym=False, beta=0.9) tensor([1.9858e-07, 5.1365e-05, 3.8659e-03, 8.4658e-02, 5.3941e-01, 1.0000e+00, 5.3941e-01, 8.4658e-02, 3.8659e-03, 5.1365e-05])实战:窗函数在信号处理中的应用方式
频谱分析中的标准流程
torch.signal.windows的典型用法是配合torch.fft进行加窗频谱分析。周期窗(sym=False)专为此场景设计:将窗与信号逐点相乘后再做 FFT,可显著抑制因信号截断造成的频谱泄漏。基本范式如下:
import torch M = 512 window = torch.signal.windows.hann(M, sym=False) signal = torch.sin(2 * torch.pi * 50 * torch.arange(M) / 1000.0) spectrum = torch.fft.rfft(signal * window)滤波器设计中的对称窗
对称窗(sym=True,默认值)适用于 FIR 滤波器设计——窗函数与理想脉冲响应相乘后截断,得到有限长的滤波器系数,对称性保证了滤波器具有线性相位特性。
设备与自动微分
所有窗函数均为标准张量工厂函数,支持device与requires_grad参数。在 GPU 上生成窗只需:
window = torch.signal.windows.kaiser(256, beta=8.0, device="cuda", dtype=torch.float32)由于窗由torch.linspace与初等运算组合而成,整个计算图可微分,requires_grad=True时可将窗参数(如std、tau、beta)纳入端到端训练流程。
测试与 SciPy 一致性验证
仓库在 test/test_tensor_creation_ops.py 中对该模块提供了系统性的数值验证,是理解函数行为的可靠参考:
test_signal_windows_functions对bartlett、blackman、cosine、hamming、hann、nuttall六个函数,在多种长度(1、2、5、10、50、100、1024、2048)与周期/对称两种模式下,与 SciPy 的scipy.signal.get_window逐一比对结果(assertEqual(res, ref, exact_dtype=False));test_kaiser随机生成 50 组beta值(0~30 均匀分布)与 SciPy 结果比对;- 测试还验证了非浮点 dtype 会抛出 "floating point" 相关
RuntimeError、稀疏布局会报 "not implemented for sparse types",与_window_function_checks的校验逻辑互相印证。
测试中的关键映射关系为:PyTorch 的sym=False等价于 SciPy 的fftbins=True(周期窗),sym=True等价于fftbins=False。此外,仓库中 test/test_decomp.py 与 test/distributed/tensor/test_dtensor_ops.py 也涉及torch.signal的分解与分布式张量路径,说明该模块已接入 PyTorch 的分解(decomposition)与 DTensor 体系,可用于torch.compile等编译路径。
函数关系速查表
| 函数 | 数学本质 | 专属参数 | 底层实现 |
|---|---|---|---|
bartlett | 三角窗 | 无 | 独立实现(1 - \|k\|) |
blackman | 3 系数余弦窗 | 无 | general_cosine(a=[0.42, 0.5, 0.08]) |
cosine | sine 波形余弦窗 | 无 | 独立实现(sin) |
exponential | Poisson 窗 | center、tau | 独立实现(exp) |
gaussian | 高斯窗 | std | 独立实现(exp) |
general_cosine | 通用余弦窗 | a(系数列表) | 核心实现 |
general_hamming | 2 系数余弦窗 | alpha(默认 0.54) | general_cosine(a=[alpha, 1-alpha]) |
hamming | Hamming 窗 | 无 | general_hamming(alpha=0.54) |
hann | Hann 窗 | 无 | general_hamming(alpha=0.5) |
kaiser | 修正贝塞尔窗 | beta(默认 12.0) | 独立实现(torch.i0) |
nuttall | 4 系数 Blackman-Harris | 无 | general_cosine(a=[0.3635819, 0.4891775, 0.1365995, 0.0106411]) |
使用注意事项小结
sym的选择:频谱分析用sym=False(周期窗),滤波器设计用sym=True(对称窗,默认);周期窗的峰值恰为 1,对称窗在偶数M下峰值不出现。- dtype 限制:窗函数仅接受
float32与float64,整数或半精度 dtype 会被_window_function_checks拒绝;如默认 dtype 不满足需求,应显式传入dtype=torch.float64等。 - 边界情况:所有函数均处理了
M == 0(返回空张量);bartlett、general_cosine、kaiser额外处理了M == 1(返回全 1 张量),其中 Kaiser 的特殊处理用于避免修正贝塞尔函数在零点附近的 NaN。 - 与 SciPy 的一致性:结果与
scipy.signal.get_window一致(SciPy 始终返回 float64,PyTorch 按所给 dtype 返回),可放心在迁移 SciPy 信号处理代码时使用。
【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考