Xiaobin-Rong / gtcrn

The official implementation of GTCRN, an ultra-lite speech enhancement model.
MIT License
202 stars 34 forks source link

提问,关于SFE模块使用nn.unfold的目的。 #4

Open TungyuYoung opened 8 months ago

TungyuYoung commented 8 months ago

您好,恭喜您完成了一个非常棒的工作并且被ICASSP 2024 收录。关于Subband Feature Extraction这一块中,您使用了nn.Unfold的操作,我想请教一下这一块的设计思想和作用是什么?感谢您的回答!

Xiaobin-Rong commented 8 months ago

谢谢你的支持!

Unfold操作被用来实现子带单元的划分。它的基本思想是,认为相邻频带的信息对当前频带的增强具有重要作用。把一个频带及其相邻的若干频带共同视为一个子带单元,通过unfold来实现子带单元的划分。然后将子带单元在通道维度堆叠起来,从而将频域的信息融合到通道维度,有利于后续的卷积等操作更高效地利用频域信息。

这一设计在 FullSubNet (Hao X, Su X, Horaud R, et al. Fullsubnet: A full-band and sub-band fusion model for real-time single-channel speech enhancement[C]//ICASSP 2021-2021 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2021: 6633-6637.) 和 TFGridNet (Wang Z Q, Cornell S, Choi S, et al. TF-GridNet: Integrating full-and sub-band modeling for speech separation[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2023.) 中都有被使用。

TungyuYoung commented 8 months ago

感谢您的解答。那请问为何不直接用一个Conv2d来实现同样的功能呢?另外,请问TRA模块是不是可以理解成近似于提取基频的操作以提高性能?

Xiaobin-Rong commented 8 months ago

@TungyuYoung Conv2d模块固然可以处理相邻频带的关系,但其在时间维度上是局部的(只能处理卷积核内的帧之间的依赖关系),unfold操作则是对时间维度上的所有帧并行地操作。 第二个问题,TRA 模块没有一个显式的基频提取的设计。 文章预计三月中旬将会见刊,欢迎你持续的关注!

HuixiangH commented 2 months ago

谢谢你的支持!

Unfold操作被用来实现子带单元的划分。它的基本思想是,认为相邻频带的信息对当前频带的增强具有重要作用。把一个频带及其相邻的若干频带共同视为一个子带单元,通过unfold来实现子带单元的划分。然后将子带单元在通道维度堆叠起来,从而将频域的信息融合到通道维度,有利于后续的卷积等操作更高效地利用频域信息。

这一设计在 FullSubNet (Hao X, Su X, Horaud R, et al. Fullsubnet: A full-band and sub-band fusion model for real-time single-channel speech enhancement[C]//ICASSP 2021-2021 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2021: 6633-6637.) 和 TFGridNet (Wang Z Q, Cornell S, Choi S, et al. TF-GridNet: Integrating full-and sub-band modeling for speech separation[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2023.) 中都有被使用。

正如您在前文所说,SFE模块将频域的信息融合到channel维度,因此后续的p-conv即使是使用1 * 1的conv,也可以在卷积过程中考虑到频带信息。 但是如果将p-conv的kernel_size修改为k * 1(此时p-conv不能被称作point-conv,就是普通卷积),即频率维度上的kernel长度等于SFE模块的k,那么卷积操作仍然可以考虑到频带信息。 因此,使用kernel_size = k * 1的p-conv,和使用SFE模块 + 1*1的p-conv,两者的目标是一致的,而且计算量、参数量都相等。同时由于融合了SFE模块和1*1 p-conv模块,还省去了SFE模块后数据的内存占用。 以上是我对SFE模块的理解,以及可能的修改方案,不确定是否正确,希望您给我做个解答,谢谢。 另外,上述讨论仅针对于GTCRN模块中的SFE模块操作。注意到在Encoder module之前也使用了一个SFE模块,如果按照上述理解的话,我认为此时Encoder的第一个卷积应该带了一部分的冗余权重,即卷积操作中对单个频点的weight被拆分到了多个weight上,如果省略SFE模块,效果应该还是一致的。

TungyuYoung commented 2 months ago

谢谢你的支持! Unfold操作被用来实现子带单元的划分。它的基本思想是,认为相邻频带的信息对当前频带的增强具有重要作用。把一个频带及其相邻的若干频带共同视为一个子带单元,通过unfold来实现子带单元的划分。然后将子带单元在通道维度堆叠起来,从而将频域的信息融合到通道维度,有利于后续的卷积等操作更高效地利用频域信息。 这一设计在 FullSubNet (Hao X, Su X, Horaud R, et al. Fullsubnet: A full-band and sub-band fusion model for real-time single-channel speech enhancement[C]//ICASSP 2021-2021 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2021: 6633-6637.) 和 TFGridNet (Wang Z Q, Cornell S, Choi S, et al. TF-GridNet: Integrating full-and sub-band modeling for speech separation[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2023.) 中都有被使用。

正如您在前文所说,SFE模块将频域的信息融合到channel维度,因此后续的p-conv即使是使用1 1的conv,也可以在卷积过程中考虑到频带信息。 但是如果将p-conv的kernel_size修改为k 1(此时p-conv不能被称作point-conv,就是普通卷积),即频率维度上的kernel长度等于SFE模块的k,那么卷积操作仍然可以考虑到频带信息。 因此,使用kernel_size = k 1的p-conv,和使用SFE模块 + 11的p-conv,两者的目标是一致的,而且计算量、参数量都相等。同时由于融合了SFE模块和1*1 p-conv模块,还省去了SFE模块后数据的内存占用。 以上是我对SFE模块的理解,以及可能的修改方案,不确定是否正确,希望您给我做个解答,谢谢。 另外,上述讨论仅针对于GTCRN模块中的SFE模块操作。注意到在Encoder module之前也使用了一个SFE模块,如果按照上述理解的话,我认为此时Encoder的第一个卷积应该带了一部分的冗余权重,即卷积操作中对单个频点的weight被拆分到了多个weight上,如果省略SFE模块,效果应该还是一致的。

谢谢你的支持! Unfold操作被用来实现子带单元的划分。它的基本思想是,认为相邻频带的信息对当前频带的增强具有重要作用。把一个频带及其相邻的若干频带共同视为一个子带单元,通过unfold来实现子带单元的划分。然后将子带单元在通道维度堆叠起来,从而将频域的信息融合到通道维度,有利于后续的卷积等操作更高效地利用频域信息。 这一设计在 FullSubNet (Hao X, Su X, Horaud R, et al. Fullsubnet: A full-band and sub-band fusion model for real-time single-channel speech enhancement[C]//ICASSP 2021-2021 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2021: 6633-6637.) 和 TFGridNet (Wang Z Q, Cornell S, Choi S, et al. TF-GridNet: Integrating full-and sub-band modeling for speech separation[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2023.) 中都有被使用。

正如您在前文所说,SFE模块将频域的信息融合到channel维度,因此后续的p-conv即使是使用1 1的conv,也可以在卷积过程中考虑到频带信息。 但是如果将p-conv的kernel_size修改为k 1(此时p-conv不能被称作point-conv,就是普通卷积),即频率维度上的kernel长度等于SFE模块的k,那么卷积操作仍然可以考虑到频带信息。 因此,使用kernel_size = k 1的p-conv,和使用SFE模块 + 11的p-conv,两者的目标是一致的,而且计算量、参数量都相等。同时由于融合了SFE模块和1*1 p-conv模块,还省去了SFE模块后数据的内存占用。 以上是我对SFE模块的理解,以及可能的修改方案,不确定是否正确,希望您给我做个解答,谢谢。 另外,上述讨论仅针对于GTCRN模块中的SFE模块操作。注意到在Encoder module之前也使用了一个SFE模块,如果按照上述理解的话,我认为此时Encoder的第一个卷积应该带了一部分的冗余权重,即卷积操作中对单个频点的weight被拆分到了多个weight上,如果省略SFE模块,效果应该还是一致的。

我尝试了您的想法,直接使用(k, 1)的卷积和经过SFE后再1*1卷积得到的输出结果是不一样的,请问你的代码具体是如何实现的?

HuixiangH commented 2 months ago

我尝试了您的想法,直接使用(k, 1)的卷积和经过SFE后再1*1卷积得到的输出结果是不一样的,请问你的代码具体是如何实现的?

做法上应该是一致的,输出结果不一样可能是因为权重初始化的时候有区别。仅作为验证的话,可以将conv权重都初始化为0.5.具体做法为:

import torch
import torch.nn as nn
from gtcrn import SFE

batch_size = 1
in_channel = 3
seq_len = 10
feat_dim = 32
inputs = torch.rand(batch_size, in_channel, seq_len, feat_dim)
kernel_size = 3
out_channel = 3

sfe = SFE(kernel_size=kernel_size)    
p_conv = nn.Conv2d(in_channel * kernel_size, out_channel, kernel_size=(1, 1), bias=False)
for m in p_conv.modules():
    nn.init.constant_(m.weight, 0.5)
num_params_1 = sum(p.numel() for p in p_conv.parameters() if p.requires_grad)

modify_conv = nn.Conv2d(in_channel, out_channel, kernel_size=(1, kernel_size), padding=(0, (kernel_size-1)//2), bias=False)
for m in modify_conv.modules():
    nn.init.constant_(m.weight, 0.5)
num_params_2 = sum(p.numel() for p in p_conv.parameters() if p.requires_grad)

raw_output = p_conv(sfe(inputs))
modify_output = modify_conv(inputs)

print(torch.allclose(raw_output, modify_output))
print(num_params_1 == num_params_2)

两个结果相等

Xiaobin-Rong commented 2 months ago

@HuixiangH 您好,我认同你说的SFE+1x1 conv等价于kx1 conv的观点;但是SFE+conv是否等价于conv我还需要再思考。感谢您的意见

HuixiangH commented 2 months ago

@HuixiangH 您好,我认同你说的SFE+1x1 conv等价于kx1 conv的观点;但是SFE+conv是否等价于conv我还需要再思考。感谢您的意见

好。感谢您的回复。