如何解决微调Whisper模型转录输出长度受限及报错问题
解决微调后Whisper模型转录输出过短及max_new_tokens报错问题
问题分析
你遇到的IndexError是因为模型生成时无法获取有效的logits序列,大概率是tokenizer的pad/eos token配置缺失,或者直接使用max_new_tokens不符合Whisper的生成逻辑;而输出过短则是因为默认生成长度限制未匹配音频实际需求。
解决方案
1. 修正Token配置与生成参数
Whisper默认未显式设置pad token,需要手动指定以避免生成时维度异常。同时建议通过generate_kwargs传递生成参数,而非直接使用max_new_tokens:
from transformers import pipeline, WhisperForConditionalGeneration, WhisperTokenizer # 加载微调后的模型和tokenizer model_path = "/path/to/your/fine-tuned-model" model = WhisperForConditionalGeneration.from_pretrained(model_path) tokenizer = WhisperTokenizer.from_pretrained(model_path) # 配置pad token(Whisper用eos token作为pad token) tokenizer.pad_token = tokenizer.eos_token model.config.pad_token_id = model.config.eos_token_id # 重建语音识别pipeline asr_pipe = pipeline( "automatic-speech-recognition", model=model, tokenizer=tokenizer ) # 调用时设置足够的max_length,通过generate_kwargs传递参数 result = asr_pipe( "/content/path_to_file", generate_kwargs={ "max_length": 2000, # 根据音频长度调整,比如1分钟音频设为1000-1500 "pad_token_id": tokenizer.pad_token_id } ) print(result["text"])
2. 长音频分段处理
如果音频过长(比如超过5分钟),直接生成会触发内存或模型限制,建议先分割音频再转录拼接:
from pydub import AudioSegment import os # 加载音频并分割为30秒小段(可根据需求调整时长) audio = AudioSegment.from_file("/content/path_to_file") chunk_duration = 30 * 1000 # 转换为毫秒 chunks = [audio[i:i+chunk_duration] for i in range(0, len(audio), chunk_duration)] # 创建临时目录保存分段音频 temp_dir = "/content/temp_audio_chunks" os.makedirs(temp_dir, exist_ok=True) chunk_paths = [] for idx, chunk in enumerate(chunks): chunk_path = f"{temp_dir}/chunk_{idx}.wav" chunk.export(chunk_path, format="wav") chunk_paths.append(chunk_path) # 逐段转录并拼接完整结果 full_transcript = "" for path in chunk_paths: segment_result = asr_pipe( path, generate_kwargs={"max_length": 400} # 单段长度足够即可 ) full_transcript += segment_result["text"] + " " print(full_transcript)
3. 检查微调训练配置
如果上述方法无效,可能是微调时的训练参数限制了模型生成能力:
- 训练时需确保
max_target_length设置足够大(匹配你最长音频的转录长度) - 训练脚本中是否正确配置了
pad_token_id,避免模型学习时的序列截断
4. 用Streamer优化长序列生成
Colab内存有限时,使用TextStreamer可以逐步输出转录结果,降低内存压力:
from transformers import TextStreamer streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True) asr_pipe = pipeline( "automatic-speech-recognition", model=model, tokenizer=tokenizer, streamer=streamer, generate_kwargs={"max_length": 2000} ) asr_pipe("/content/path_to_file")
内容的提问来源于stack exchange,提问作者user22347502
相关产品推荐
相关产品推荐

