Audio-WestlakeU / FS-EEND

The official Pytorch implementation of "Frame-wise streaming end-to-end speaker diarization with non-autoregressive self-attention-based attractors". [ICASSP 2024]
MIT License
71 stars 4 forks source link

评估 #5

Open DAYTOY-1112 opened 9 months ago

DAYTOY-1112 commented 9 months ago

老师您好,评估的时候是需要先运行gen_h5_output.py再计算DER吗?gen_h5_output.py的输入是什么呢?我训练后的结果中没有看到代码运行所需要的文件

DiLiangWU commented 9 months ago

您好,需要在train/oln_tfm_enc_dec.py文件中test_step函数注释掉的save_dir_parnt....之后的几行取消注释并换成自己的存储路径,保存推理出的preds,然后替换gen_h5_output.py中的out_root。运行gen_h5_output.py得到.h5文件后替换metrics.py中的路径,运行metrics.py。

DAYTOY-1112 commented 9 months ago

老师您好,我有个问题,我看到代码好像attractor的数量是根据设置的max speaker来得到的(max_speaker+2),那就代表都是预测出(max_speaker+2)个发言人,然后计算DER的时候根据标签是几个发言人来取几维数据进行计算。不知道是我理解有误还是别的原因,感觉这样的方式不太合理,麻烦老师帮忙解惑,感谢。

DiLiangWU commented 9 months ago

您好,您看的这一段代码主要是为了方便在训练过程中观察validation set上的DER收敛曲线而写的。实际上我们在evaluation的时候是不用这个结果的。过程是首先设置一个max_speaker,保存下来max_speakers+2个attractors的predictions [shape: (T, max_speakers +2)]。最终计算DER的时候用(T, max_speakers +2)的predictions和label之间进行计算的(metrics.py负责计算DER)。也就是真正最终评估的时候并没有根据label中的speakers数目去取相应数目的attractors。

DAYTOY-1112 commented 9 months ago

假设max_speaker=5,label的speaker数量为3,计算DER的时候用7维的预测结果和3维的label进行计算这样得到的结果不会有问题吗?或者说这样的做法是否就设定了预测的说话人数量都是max_speakers个呢,不管label实际是几个?

DAYTOY-1112 commented 9 months ago

我理解的是,attractor的个数应该是预测出来的,而不是通过设置max_speaker来得到,所以这里我一直想不明白

DiLiangWU commented 9 months ago

实际上我们期望模型可以适应到inference阶段的speaker数目大于训练中见过的最大speaker数时也可以表现很好。但是研究表明这一点仅仅通过网络自身是无法做到的,只能依赖额外的聚类技术,这也是之后我们要继续研究的一个方向。目前只能通过预先设置一个最大说话人数max_speakers,在推理阶段已经可以很好地处理≤max_speakers的情况。在本项工作中训练集中的最大说话人为4,因此在推理阶段相应设置max_speakers=4。

至于您说的max_speakers=5, label的speakers为3这种情况,不用担心,是完全可以处理的。我们在label最上层加上了spk_termination 的marker,目的就是让网络自动学到活动的atrtactors/speakers的数目。对于这个例子,我们人工取7个attractors去计算,但网络实际学习到被激活的只有前3个attractors,所以第4-7维都会被网络预测为0。只是目前网络能hold住inference阶段说话人数目的最大值受限于训练数据中见过的最大说话人数目。

DAYTOY-1112 commented 9 months ago

preds_realspk = [p[:, 1:nspk + 1] for p, nspk in zip(preds, n_spks)] labels_realspk = [l[:, 1:-1] for l in labels] stats = report_diarization_error(preds_realspk, labels_realspk, label_delay=self.label_delay) 在推理脚本的这段代码中,评估的时候取的是1:nspk + 1来计算,但实际推理的时候,我们是不知道nspk是多少的呀,那直接运行推理脚本得到的结果是否不能作为参考,而是需要将preds完整保存下来再运行metrics.py脚本进行计算得到的结果才合理呢

DiLiangWU commented 9 months ago

是的。这一步相当于给出oracle number of speakers的中间结果,可以供自己参考。最终报告的DER根据保存下的preds经由metrics.py计算而来。

DAYTOY-1112 commented 9 months ago

好的,非常感谢您,提供的代码的推理过程是非流式的吗?我好像没看见流式推理的体现

DiLiangWU commented 9 months ago

流式体现在推理过程中每一帧都只能看到之前帧,无法看到后来出现的帧。我们是通过mask attention实现的。当然也可以逐帧推理,和使用mask推理结果一样,因此简化为了attention+mask的推理方式。

DAYTOY-1112 commented 9 months ago

不好意思,我还是有点不明白,假设我现在用你提供的callhome的模型进行推理,max-speaker=4,但是我的音频实际上只有两个说话人,那推理出的pred是四维的,但是label却是两维的,这样子再去运行metrics.py计算DER,得到的结果合理吗?

DiLiangWU commented 9 months ago

合理的,metrics.py会提供脚本将4维的preds转换成rttm文件格式,即speaker id和活动的起止时间段,然后去和label做匹配计算DER。

只是您需要注意,CALLHOME的model是已经adapt到特定数据下fintune后的模型,直接用在你的音频上做推理可能会因为数据分布差异而导致效果变差。

DAYTOY-1112 commented 9 months ago

可是会出现DER大于1的情况

DiLiangWU commented 9 months ago

您确定用了训练后的CALLHOME模型做推理吗,我用FS-EEND_ch_90_100epo_avg_model.ckpt测试了一下,即使直接在simulated dataset上的Simu2spk做推理,preliminary_DER也只有18.4%。 image

确定在推理的时候注释掉了这几行load训练得到的ckpt的代码,以及在config文件里修改init_ckpt了吗:

test_state = defaultdict(float) for c in ckpts: state_dict = torch.load(test_folder + "/" + c, map_location=torch.device("cuda:{}".format(gpus[0])))["state_dict"] for name, param in state_dict.items(): test_state[name] += param / len(ckpts) if configs["log"]["save_avg_path"]: torch.save(test_state, configs["log"]["save_avg_path"]) spk_dia_main.load_state_dict(test_state)

DAYTOY-1112 commented 9 months ago

没有注释和修改,但是加载的是我预先存好的FS-EEND_ch_90_100epo_avg_model.ckpt模型,在模拟的数据集上DER还算正常,但是笔试aishell4数据集上,我用的4个说话人的数据去测试,会出现DER大于1的情况,微调之后也是

DAYTOY-1112 commented 9 months ago

我这边测试的结果,用的metrics.py进行评估,得到的结果是在mini_librispeech数据集上进行模拟,两个说话人的DER是7%,4个说话人是39%,四个说话人的aishell4数据集DER是85%(且出现很多DER大于1的情况,例如1.0345),以上结果加载的模型为FS-EEND_ch_90_100epo_avg_model.ckpt

DiLiangWU commented 9 months ago

有尝试用预训练的simu_avg_41_50epo.ckpt在你的数据集上做fintune吗。因为EEND_ch_90_100epo_avg_model.ckpt是已经在特定的CALLHOME数据集上做完fine-tune后的结果。另外我看aishell4是多通道的数据集,目前模型train/adaption/test都是在单channel数据集上进行的。

DAYTOY-1112 commented 9 months ago

我是在FS-EEND_ch_90_100epo_avg_model.ckpt上面fintune的,可能不太合理?fintune后的结果并没有改善,对于aishell4的数据集我已经做了预处理将通道数合并了,其实我只是想确保我现在评估结果的流程是合理的,比如你上面提到的需要注释和修改config的init_ckpt,这两个操作我并没有进行,而是直接修改load模型的路径,加载预训练模型进行推理。想确保一下我得到的结果是正确的,对比效果我可以重新再simu_avg_41_50epo.ckpt上面fintune

jeremy110 commented 9 months ago

@DAYTOY-1112 CALLHOME是8k電話對話音檔,aishell-4是會議的16k多通道音檔,如果直接拿FS-EEND_ch_90_100epo_avg_model.ckpt去fine-tune應該會有問題,另外我當初在其他方法上有做aishell-4,當時是抽取出第三通道還第四通道有點忘了,因為我發現有些通道的聲音並沒有那麼乾淨,如果將全部合併效果上會有差別,提供給你參考。

DAYTOY-1112 commented 9 months ago

请问推理时设置chunk=10000,当输入的单条数据大于chunk时,如何保证完整数据前后chunk的说话人的一致性呢

DiLiangWU commented 8 months ago
  1. 这里的chunk可以手动设置为更大以cover推理的语音长度,10000只是因为CALLHOME数据集上单条语音都小于1000s。
  2. 非常长的语音推理目前可能会因为模型masked attention复杂度为O(T^2)而在计算和内存上挑战比较大,这也是之后需解决的问题。
  3. 此外,也可以借助算法本身保证chunk前后的说话人一致性,可参考[1]的做法。

[1] Yawen Xue, et. al,“Online Streaming End-to-End Neural Diarization Handling Overlapping Speech and Flexible Numbers of Speakers,” in INTERSPEECH, 2021, pp. 3116–3120.

DAYTOY1112 commented 6 months ago

老师您好,请问在评估时,这里的metric = DiarizationErrorRate(collar=50),50的单位是ms吗