复数¶
复数是可以用以下形式表示的数字,其中 a 和 b 是实数, j 称为虚部单位,它满足方程.复数经常出现在数学和 工程,尤其是在信号处理等主题中。传统上,许多用户和库(例如 TorchAudio)都有 通过用 shape 的 float 张量表示数据来处理复数其中最后一个 dimension 包含实数值和虚数值。
复杂 dtype 的张量在处理复数时提供更自然的用户体验。操作
复杂张量(例如 , ,
)可能更快、内存效率更高
than 对 float 张量的操作来模拟它们。优化 PyTorch 中涉及复数的操作
使用矢量化汇编指令和专用内核(例如 LAPACK、cuBlas)。
注意
torch.fft 模块支持中的光谱运算 原生复杂张量。
警告
复杂张量是一项测试版功能,可能会发生更改。
创建复杂张量¶
我们支持两种复杂的 dtype:torch.cfloat 和 torch.cdouble
>>> x = torch.randn(2,2, dtype=torch.cfloat)
>>> x
tensor([[-0.4621-0.0303j, -0.2438-0.5874j],
[ 0.7706+0.1421j, 1.2110+0.1918j]])
注意
复杂张量的默认 dtype 由默认浮点 dtype 确定。 如果默认浮点 dtype 为 torch.float64,则复数被推断为 的 DTYPE 为 torch.complex128,否则假定它们的 DTYPE 为 torch.complex64。
除 、
和 之外的所有工厂函数都是
支持复杂张量。
从旧表示过渡¶
当前使用形状为的真实张量解决复杂张量缺失问题的用户可以很容易地使用 和 在其代码中使用复张量进行切换。
请注意,这些函数不执行任何复制,而是返回一个
input Tensor 的视图。
>>> x = torch.randn(3, 2)
>>> x
tensor([[ 0.6125, -0.1681],
[-0.3773, 1.3487],
[-0.0861, -0.7981]])
>>> y = torch.view_as_complex(x)
>>> y
tensor([ 0.6125-0.1681j, -0.3773+1.3487j, -0.0861-0.7981j])
>>> torch.view_as_real(y)
tensor([[ 0.6125, -0.1681],
[-0.3773, 1.3487],
[-0.0861, -0.7981]])
访问 real 和 imag¶
复张量的实数值和虚数值可以使用 和 来访问。real
imag
注意
访问 real 和 imag 属性不会分配任何内存,对 real 和 imag 张量的就地更新将更新原始复张量。此外, 返回的 Real 和 imag 张量不连续。
>>> y.real
tensor([ 0.6125, -0.3773, -0.0861])
>>> y.imag
tensor([-0.1681, 1.3487, -0.7981])
>>> y.real.mul_(2)
tensor([ 1.2250, -0.7546, -0.1722])
>>> y
tensor([ 1.2250-0.1681j, -0.7546+1.3487j, -0.1722-0.7981j])
>>> y.real.stride()
(2,)
角钢和 abs¶
>>> x1=torch.tensor([3j, 4+4j])
>>> x1.abs()
tensor([3.0000, 5.6569])
>>> x1.angle()
tensor([1.5708, 0.7854])
序列化¶
复杂张量可以序列化,从而允许将数据保存为复杂值。
>>> torch.save(y, 'complex_tensor.pt')
>>> torch.load('complex_tensor.pt')
tensor([ 0.6125-0.1681j, -0.3773+1.3487j, -0.0861-0.7981j])
自动grad¶
PyTorch 支持对复杂张量进行 autograd。计算出的梯度是共轭 Wirtinger 导数 其负数恰好是 Gradient Descent 算法中使用的最陡下降方向。因此 所有现有的优化器都可以实现,以使用复杂的参数开箱即用。有关更多详细信息, 查看注释 Autograd for Complex Numbers。
优化器¶
从语义上讲,我们将具有复杂参数的 PyTorch 优化器单步执行定义为等效于单步执行
通过等效于 Complex Params 的同一优化器。更具体地说:
>>> params = [torch.rand(2, 3, dtype=torch.complex64) for _ in range(5)]
>>> real_params = [torch.view_as_real(p) for p in params]
>>> complex_optim = torch.optim.AdamW(params)
>>> real_optim = torch.optim.AdamW(real_params)
real_optim 和 complex_optim 将计算参数的相同更新,但可能会有轻微的数值 两个优化器之间的差异,类似于 foreach 与 forloop 优化器之间的数值差异 以及 Capturable 与 Default Optimizers。有关详细信息,请参阅 https://pytorch.org/docs/stable/notes/numerical_accuracy.html。
具体来说,虽然您可以将我们的优化器对复杂张量的处理视为与分别优化其 p.real 和 p.imag 部分相同,但实现细节并非如此。请注意,等效项会将复张量转换为具有 shape 的实张量,
而将一个复张量拆分为两个张量是 2 个大小的张量.这种区别对
pointwise optimizers(如 AdamW),但会导致执行全局归约的优化器(如 LBFGS)略有差异。
我们目前没有进行每 Tensor 缩减的优化器,因此尚未定义此行为。打开一个问题
如果您有一个需要精确定义此行为的用例。
我们不完全支持以下子系统:
量化
JIT
稀疏张量
分散式