基于Paraformer的alpha-token强制对齐

2024-05-30 09:04

本文主要是介绍基于Paraformer的alpha-token强制对齐,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 基本原理

img1

CIF 作为Parafoemr的核心模块,用于预测字数和生成声学向量,从而实现了单轮非自回归解码。其中字数的预测主要通过encoder输出系数alpha的累计得分,满足通关阈值β=1.0即可产生一个token,其中alpha曲线在一定程度上呈现着vad效果,或者依次进行断句。

2. alpha-token 强制对齐

cif的时间戳对齐采用peak(通关方式)得到,这里我们直接尝试alpha-token对齐方式,将识别的token在编码器输出上进行对齐,其中对齐算法采用动态规划。具体参考main.py中的maxSumSubarrayWithGaps()。

以10s窗长进行音频切块,下面展示alpha-token 的对齐效果:
img2

用户可以修改main.py 参数进行试验

3. code

github:https://github.com/coolEphemeroptera/funasr_alpha_token_alignment

import subprocess
from typing import List
import matplotlib.font_manager
import numpy as np 
from funasr_onnx import SeacoParaformer
import os 
import shutil
import matplotlib.pyplot as plt 
import matplotlib
zhfont1 = matplotlib.font_manager.FontProperties(fname="./SourceHanSansSC-Bold.otf")class SeacoParaformerPlus(SeacoParaformer):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.SR = 16000self.SECONDS_PER_FRAME = 0.02self.UPSAMPLE_TIMES = 3def decode(self,am_scores, valid_token_lens):res = []for am_score, valid_token_len in zip(am_scores, valid_token_lens):token_ids = am_score.argmax(axis=-1)token_chs = self.converter.ids2tokens(token_ids)token_chs_valid = token_chs[:valid_token_len]res.append(token_chs_valid)return resdef __call__(self, waveform_list: list, hotwords: str, imgDir = './display',**kwargs) -> List:# 加载热词编码hotwords, hotwords_length = self.proc_hotword(hotwords)[bias_embed] = self.eb_infer(hotwords, hotwords_length)bias_embed = bias_embed.transpose(1, 0, 2)_ind = np.arange(0, len(hotwords)).tolist()bias_embed = bias_embed[_ind, hotwords_length.tolist()]bias_embed = np.expand_dims(bias_embed, axis=0)# onnx推理waveform_nums = len(waveform_list)content = []id = 0duration = 0for beg_idx in range(0, waveform_nums, self.batch_size):end_idx = min(waveform_nums, beg_idx + self.batch_size)# 1.计算mel特征feats, feats_len = self.extract_feat(waveform_list[beg_idx:end_idx])# 2.热词编码同步复制bias_embed_ = np.repeat(bias_embed, feats.shape[0], axis=0)# 3. 解码am_scores, valid_token_lens,us_alphas, us_peaks = self.bb_infer(feats, feats_len, bias_embed_)# 4. 后处理res = self.decode(am_scores, valid_token_lens)for r,alpha,peak in zip(res,us_alphas,us_peaks):content.append({'id':id,'range':[duration,duration+len(waveform_list[id])],'tokens':r,'alpha':alpha,'peak':peak})duration += len(waveform_list[id])id += 1return contentdef align_with_alpha(self,asr_res,img_path="tmp.png"):id = asr_res['id']tokens = asr_res['tokens'][:-1]tokens_n = len(tokens)stime,etime = round(asr_res['range'][0]/self.SR,2),round(asr_res['range'][1]/self.SR,2)alpha = asr_res['alpha']peak = asr_res['peak']# alpha 对齐max_val,max_path = maxSumSubarrayWithGaps(alpha,tokens_n,3)AX,AY = [],[]for ft,i,score in max_path:AX.append(ft*self.SECONDS_PER_FRAME+stime)AY.append(alpha[ft])# 绘图plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = Falseplt.figure(figsize=(20, 8))plt.xlabel('time/seconds')plt.ylabel('alpha')plt.ylim([0,0.4])plt.title("ALPHA-ALIGNMENT (id:%s, range:%s-%s seconds)"%(id,stime,etime))x = np.linspace(stime,etime,len(alpha))plt.plot(x,alpha)plt.plot(AX, AY, 'o',color='red')for i,ax in enumerate(AX):ay = AY[i] + 0.01token = tokens[i]plt.text(ax, ay, token, fontsize=10, color='black',ha='center',fontproperties=zhfont1)plt.savefig(img_path)plt.close()def rebuild_dir(dir):def delete_directory(directory):if os.path.exists(directory):shutil.rmtree(directory)delete_directory(dir)os.makedirs(dir)print(f"Success to create {dir}")def audio_f2i(data,width=16):data = np.array(data)return np.int16(data*(2**(width-1)))def audio_i2f(data,width=16):data = np.array(data)return np.float32(data/(2**(width-1)))def read_audio_file(url):ffmpeg_cmd = ['ffmpeg','-y','-i', url,  '-vn','-f', 's16le','-acodec', 'pcm_s16le','-ar', '16k','-ac', '1','-' ]with subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=False) as proc:stdout_data, stderr_data = proc.communicate()if stderr_data:audio_data = np.frombuffer(stdout_data,dtype=np.int16)audio_data = audio_i2f(audio_data)return audio_data# 动态规划实现alpha-token强制对齐
def maxSumSubarrayWithGaps(NUMS,K,GAP):N = len(NUMS)# 初始化表单dp = [[-float('inf') for j in range(K+1)] for _ in range(N)]path = [[[] for j in range(K+1)] for _ in range(N)]# 初始化边界for i in range(N): # dp[:,0]dp[i][0] = 0path[i][0] = []for j in range(K+1): # dp[0,:]if j==0:dp[0][j] = 0elif j==1:dp[0][j] = NUMS[0]else: dp[0][j] = -float('inf')# dp填表for i in range(1,N):for j in range(1,K+1):# 不满足G间隔if (j-1)*GAP+1>i+1:dp[i][j] = -float('inf')path[i][j] = []# 满足间隔else:for k in range(j-1,i-GAP+1):# 更新最大值且区间内满足极差(停顿)要求if dp[k][j-1]+NUMS[i]>dp[i][j] and max(NUMS[k:i+1])-min(NUMS[k+1:i])>0.02:dp[i][j] = dp[k][j-1]+NUMS[i]path[i][j] = [k,j-1,dp[k][j-1]]# 回溯max_i = np.argmax([dp[i][K] for i in range(N)])max_val = dp[max_i][K]max_path = []i,j,v = max_i,K,max_valmax_path.append([i,j,v])while 1:if not path[i][j]:breaki,j,v = path[i][j]if j>0:max_path.append([i,j,v])if j==1:breakmax_path.reverse()return max_val,max_pathif __name__ == '__main__':SR = 16000# 参数url = "/home/nvidia/funasr_alpha_token_alignment/funasr_models/iic/speech_seaco_paraformer_large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/example/asr_example.wav"img_dir = 'alpha_align_plot'chunk_seconds = 10cache_dir='./funasr_models'model_name = 'iic/speech_seaco_paraformer_large_asr_nat-zh-cn-16k-common-vocab8404-pytorch'model_quant = Truebatch_size = 60# 1. 加载模型paraformer = SeacoParaformerPlus(model_dir=model_name,quantize=model_quant,batch_size=batch_size,cache_dir=cache_dir)# 2. 音频分块audio_data = read_audio_file(url)audio_length = len(audio_data)chunk_size = chunk_seconds*SRbatch = []for i in range(0,audio_length,chunk_size):s,e = i,min(i+chunk_size,audio_length)chunk = audio_data[s:e]batch.append(chunk)# 3. ASRcontent = paraformer(batch,hotwords='')# 4. alpha对齐rebuild_dir(img_dir)for asr_res in content:id = asr_res['id']text = asr_res['tokens']print(id,text)paraformer.align_with_alpha(asr_res,img_path=f"{img_dir}/{id}.png")print("saved into:",f"{img_dir}/{id}.png")

这篇关于基于Paraformer的alpha-token强制对齐的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016035

相关文章

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init

自定义结构体的对齐问题

一、跨平台通用数据类型 之前的一篇博客Linux数据类型(通用移植),已经自定义尝试解决了数据通用类型问题。 这里通过源码进行分析,利用源码进行解决问题。在<stdint.h>中我们发现: typedef signed char int8_t;typedef unsigned char uint8_t;typedef short int16_t;typedef unsigned s

Matplotlib图像读取和输出及jpg、png格式对比,及透明通道alpha设置

图像像素值 图像像素值一般size为3,也就是通道数,分别代表R,G,B,如果只有单一 一个值则表示灰度值,也就是说一张二维图片,当长和宽都为1080时,那么若是灰度图像,图像尺寸为(1080,1080,1)若是RGB图像则为(1080,1080,3), jpg、png图像格式 jpg图像的灰度值范围和RGB范围为[0,255],数值类型为uint8,也就是无符号整数 png图像的灰度值范

【NodeJS】Unexpected token (109:0) 返回错误码500

刚开始报错是这样的: Unexpected token call 是什么我没看懂,但我发现 span.label.lable-success 后面的 #[i+1] 写错了,应该是 #{i+1} 改成完这个错误后又是一个错误提示: What? Unexpected token (109:0) 返回错误码500是什么鬼 我先将自己这段源码的 - if ... - else 检查下

解决OAuth Token,点击退出登录报404问题

首先,认证服务器发送请求 http://auth.test.com:8085/logout?redirect_uri=http://admin.test.com:8080’ 退出后报404无法跳转到网站首页,这个时候增加一个参数redirect_uri指定退出成功后跳转的路径,因为是自定义的,所以需在认证服务器做一些处理 找到源码默认实现接口DefaultLogoutPageGeneratingF

OAuth2 Token实现授权码模式

文章目录 OAuth2 授权:Resource owner password(密码模式)OAuth2 授权:Authorization code grant授权码模式,适用于浏览器模式OAuth2:Implicit(简化授权模式)OAuth:Client credentials(客户端证书)授权码模式使用案例 OAuth2 授权:Resource owner password(密

selenium的webdriver三种等待方式(显式等待WebDriverWait+implicitly_wait隐式等待+sleep强制等待)

隐式等待是等页面加载,不是等元素!!! 1、显式等待  一个显式等待是你定义的一段代码,用于等待某个条件发生然后再继续执行后续代码。显式等待是等元素加载!!! from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import

SylixOS ARM平台下内存对齐访问

1.内存对齐 1.1     内存对齐概要 现代计算机中内存空间都是按照byte划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 1.2     内存对齐作用和原因 各个硬件平台对存储空间的处理上有很大的不同。一些平

记一次knife4j文档请求异常 SyntaxError: Unexpected token ‘<‘, ... is not valid JSON

knife4j页面报错问题定位 前几天开发新接口,开发完成后想使用knife4j测试一下接口功能,突然发现访问页面报错提示:knife4j文档请求异常,但之前运行还是正常的,想想会不会与升级依赖有关系,启动其他微服务发现文档接口访问正常,排除因依赖版本升级导致在线API文档无法使用情况,还是和本服务新增接口有关系。 定位问题 首先f12打开调试台,重新刷新页面,看到console有报错提示

Kubernetes的alpha.kubernetes.io/nvidia-gpu无法限制GPU个数

问题描述: Pod.yaml文件中关于GPU资源的设置如下: 然而在docker中运行GPU程序时,发现宿主机上的两块GPU都在跑。甚至在yaml文件中删除关于GPU的请求,在docker中都可以运行GPU。 原因: 上例说明alpha.kubernetes.io/nvidia-gpu无效。查看yaml文件,发现该docker开启了特权模式(privileged:ture): 而