CTC Loss报错求助:input_lengths超出上限问题排查
基于Conformer的ASR系统CTC Loss训练报错解决
我用Conformer模型开发自动语音识别(ASR)系统,训练编码器时采用CTC Loss,训练过程中出现报错:
"Expected input_lengths to have value at most 144, but got value 174 (while checking arguments for ctc_loss_cpu)"
调整张量维度排列后问题仍未解决,不清楚数值174的来源,相关代码及张量形状信息如下:
相关代码
encoder = ConformerEncoder( d_input=80, d_model=144, num_layers=3, conv_kernel_size=31, dropout=0.1, feed_forward_residual_factor=0.5, feed_forward_expansion_factor=4, num_heads=4) char_decoder = GreedyCharacterDecoder().eval() criterion = nn.CTCLoss() optimizer = torch.optim.AdamW(encoder.parameters(), lr=0.01) num_steps = len(train_dataloader) * 50 lr_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=num_steps, eta_min=0.00001) cerwer = CerWer() for epoch in range(50): train_cer, train_wer, val_wer, val_cer = 0.0, 0.0, 0.0, 0.0 train_losses = [] encoder.train() #model = model.float() for inputs, inputs_length, targets, targets_length in tqdm(train_dataloader): #inputs = inputs.to(device) #targets = targets.to(device) print(inputs.shape) print(inputs_length.shape) print(targets.shape) print(targets_length.shape) outputs = torch.tensor(encoder(inputs.float())) print(outputs.size()) outputs = outputs.permute(2, 0, 1) print(outputs.log_softmax(dim=2).shape) optimizer.zero_grad() loss = criterion(outputs.log_softmax(dim=2), targets, inputs_length, targets_length) loss.backward() torch.nn.utils.clip_grad_norm_(encoder.parameters(), 15) optimizer.step() lr_scheduler.step() train_losses.append(loss.item()) _, max_probs = torch.max(outputs, 2) train_epoch_cer, train_epoch_wer, train_decoded_words, train_target_words = cerwer(max_probs.T.cpu().numpy(), targets.cpu().numpy(), inputs_length, targets_length) train_wer += train_epoch_wer train_cer += train_epoch_cer
张量形状信息
- 输入模型前的张量形状:
torch.Size([32, 80, 659]) # batch_size=32,特征维度=80,原始音频时间步=659 - 输入损失函数前的张量形状(已permute):
torch.Size([144, 32, 164]) # 编码器输出时间步T=144,batch_size=32,类别数=164
报错原因及解决方法
原因
CTC Loss要求传入的input_lengths(编码器输出序列的有效长度)必须小于等于编码器输出的时间步T(此处T=144)。你当前传入的inputs_length是原始音频的长度(如659),未经过编码器下采样后的长度转换,导致计算后得到的数值174超过了T=144,触发报错。
解决步骤
计算编码器输出后的有效长度
Conformer中的卷积模块会对时间步做下采样(如stride=2),原始音频长度经过编码器后会缩短,需要根据编码器的下采样逻辑将inputs_length转换为编码器输出后的长度。修改代码中的
input_lengths参数
根据样本情况选择对应方式:- 如果所有样本经过编码器后的输出长度相同(输入已做固定长度裁剪/填充):
# 生成与编码器输出时间步一致的长度张量 output_lengths = torch.full((inputs_length.size(0),), outputs.size(0), dtype=torch.long) # 替换原有loss计算中的inputs_length loss = criterion(outputs.log_softmax(dim=2), targets, output_lengths, targets_length) - 如果样本原始长度不同,根据卷积公式计算每个样本的输出长度:
# 定义单步卷积输出长度计算函数 def compute_conv_output_len(input_len, kernel_size=31, stride=2, padding=15): return (input_len - kernel_size + 2 * padding) // stride + 1 # 根据编码器卷积层数计算最终输出长度 output_lengths = inputs_length.clone() for _ in range(3): # 对应ConformerEncoder的num_layers=3 output_lengths = compute_conv_output_len(output_lengths) # 确保长度不超过编码器输出的最大时间步 output_lengths = torch.clamp(output_lengths, max=outputs.size(0)) # 传入CTC Loss loss = criterion(outputs.log_softmax(dim=2), targets, output_lengths, targets_length)
- 如果所有样本经过编码器后的输出长度相同(输入已做固定长度裁剪/填充):
验证张量排列
你已将输出张量做permute(2, 0, 1)转换,符合CTC Loss要求的(T, N, C)格式(T=时间步,N=batch_size,C=类别数),这部分无需修改。
内容的提问来源于stack exchange,提问作者nameisnoname
相关产品推荐
相关产品推荐

