whisper.cpp参数调优
前期文章
Ubuntu 下搭建 whisper.cpp 本地环境-CSDN博客
前置知识
什么是温度采样?
温度参数的作用
温度(Temperature)控制模型预测的随机性:
温度 = 0:完全确定性,总是选择概率最高的词
温度 > 0:引入随机性,概率低的词也有机会被选中
温度越高:输出越随机、越有创意,但可能不太准确
在温度采样模式下的工作机制
当
temperature > 0
时:# 假设 best-of=5,temperature=0.4 1. 模型生成 5 个不同的候选文本序列(引入随机性) 2. 计算每个候选的评分(基于概率、长度等) 3. 选择评分最高的一个作为最终输出
为什么需要"样本池"?
问题:温度采样引入随机性,单次采样可能得到低质量结果 解决:生成多个样本,从中选择最佳的,类似于"抽奖多次选最好的"
实际例子
假设音频中有模糊的词汇,模型不确定:
温度=0.0(确定性): "今天天气很好" 温度=0.4,best-of=1: "今天天气很棒"(单次随机采样) 温度=0.4,best-of=5: 候选1: "今天天气很棒" (评分: -2.1)候选2: "今天天气不错" (评分: -1.8) ← 最佳候选3: "今天天气真好" (评分: -2.3)候选4: "今天阳光明媚" (评分: -2.9)候选5: "今天心情很好" (评分: -3.1)最终选择: "今天天气不错"
在同一次解码过程中,beam-size
(-bs
)和 best-of
(-bo
)只能选择其中一个生效,具体规则如下:
-
当温度序列中包含 大于 0 的值(即启用采样模式)时,Whisper 会自动禁用
beam-size
,只使用best-of
。 -
当温度序列全部为 0(即纯确定性模式)时,Whisper 会自动禁用
best-of
,只使用beam-size
。
特征 | 贪婪采样 | 束搜索 |
---|---|---|
搜索空间 | 最小(每步1个选择) | 中等(每步k个选择) |
计算复杂度 | 最低 | 中等 |
结果质量 | 局部最优 | 通常更优 |
确定性 | 完全确定 | 相对确定 |
算法策略
模型数据流:
模型加载 -》 音频样本归一化 -》模型参数设置 -》 编码解码 -》 state.tokens文本转化自然语言处理
其中编码解码:
音频分段,滑动窗口输入 -》 特征提取 -》 mel频谱特征 -》 多层次Transformer -》 输出 embeddings(向量化)-》 首次解码后state.tokens=prompt
-》1. greedy策略贪婪采样:
基于 state 和 embeddings 计算下一个 token的 logits(信誉分)
抑制与重置计算 logits 相关策略
最终选择最高概率的tokens,加入state->tokens序列末端
-》
-》2. Beam Search 并行解码策略:
初始化beam次数,只有一个活跃的beam
在每个时间步 t,对每条当前 beam(共有 B 条)分别计算一次 logits,此时总共会产生 B×V 个候选 token。
迭代扩展与剪枝,维护多个候选序列(beam)logits
扩展所有候选
剪枝并保留
-》
源码分析
whisper/whisper.cpp/src/whisper.cpp 默认决策,二选一
switch (strategy) {case WHISPER_SAMPLING_GREEDY:{result.greedy = {/*.best_of =*/ 5,};} break;case WHISPER_SAMPLING_BEAM_SEARCH:{result.beam_search = {/*.beam_size =*/ 5,/*.patience =*/ -1.0f,};} break;}
正确使用代码
whisper_full_params WhisperASR::configureWhisperParams() {std::cout << "配置 Whisper 参数..." << std::endl;// 自动选择搜索策略WhisperConfig::SearchStrategy actual_strategy = determineOptimalSearchStrategy();whisper_full_params wparams;switch (actual_strategy) {case WhisperConfig::GREEDY: {std::cout << "使用贪婪搜索策略(快速模式)" << std::endl;wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY);// 贪婪模式核心设置wparams.greedy.best_of = config_.best_of;wparams.temperature = 0.0f; // 贪婪模式使用零温度wparams.temperature_inc = 0.0f; // 不增加温度// 贪婪模式优化设置wparams.entropy_thold = 2.4f; // 放宽熵阈值以提高速度wparams.logprob_thold = -1.0f; // 放宽对数概率阈值break;}case WhisperConfig::BEAM_SEARCH: {std::cout << "使用束搜索策略(高质量模式)" << std::endl;wparams = whisper_full_default_params(WHISPER_SAMPLING_BEAM_SEARCH);// 束搜索核心设置wparams.beam_search.beam_size = config_.beam_size;wparams.beam_search.patience = config_.beam_search_patience;// 束搜索质量优化wparams.temperature = config_.temperature_start;wparams.temperature_inc = config_.temperature_inc;wparams.entropy_thold = config_.entropy_threshold;wparams.logprob_thold = config_.logprob_threshold;break;}default: // AUTO 已经在 determineOptimalSearchStrategy 中处理break;}// 通用基本设置wparams.language = config_.language.c_str();wparams.n_threads = config_.n_threads;wparams.translate = false; // 转录,不翻译wparams.detect_language = false; // 语言已明确设置wparams.print_progress = false; // 不输出处理进度// 移除initial_prompt相关代码,统一设置为falsewparams.prompt_tokens = nullptr;wparams.prompt_n_tokens = 0;wparams.initial_prompt = nullptr;// 质量和性能平衡wparams.n_max_text_ctx = config_.mc;wparams.max_len = config_.ml;wparams.no_speech_thold = config_.no_speech_thold_min;// 输出和分割设置wparams.split_on_word = config_.split_on_word;wparams.no_context = false; // 允许使用初始提示作为上下文!wparams.print_special = false; // 不输出特殊字符// 语言相关的关键设置,确保简体中文输出wparams.suppress_blank = false; // 抑制空白标记wparams.suppress_nst = true; // 不抑制非语音标记// 时间戳相关设置wparams.no_timestamps = false;wparams.print_timestamps = config_.print_timestamps;wparams.token_timestamps = config_.token_timestamps;wparams.thold_pt = config_.thold_pt;if (wparams.token_timestamps) {wparams.thold_ptsum = config_.thold_ptsum;}// 设置实时回调if (config_.real_time_output) {wparams.new_segment_callback = [](struct whisper_context* ctx, struct whisper_state* state, int n_new, void* user_data) {WhisperASR* asr = static_cast<WhisperASR*>(user_data);asr->onNewSegment(ctx, state, n_new);};wparams.new_segment_callback_user_data = this;}std::cout << "✓ Whisper 参数配置完成" << std::endl;return wparams;
}
质量过滤参数(阈值控制)
-et N (--entropy-thold)
概念:基于词汇重复度的"卡顿检测器"
-
作用:计算最近32个token的香农熵,低于阈值时认为模型"卡住了"(重复生成相同词汇)
-
默认值:2.40
-
调优思路:
-
降低(如1.8-2.0):对重复更敏感,更容易触发重试,适合处理"优优独播剧场"这类循环输出
-
提高(如2.8-3.2):容忍更多重复,减少重试次数,提升速度但可能保留重复文本
-
-lpt N (--logprob-thold)
概念:模型"自信度检测器"
-
作用:检查平均对数概率,低于阈值说明模型对输出不够自信
-
默认值:-1.00
-
调优思路:
-
提高(如-0.5到-0.8):只接受高自信度输出,质量更好但可能丢失弱音频片段
-
降低(如-1.5到-2.0):接受更多不确定输出,召回率高但可能包含幻听
-
-wt N (--word-thold)
概念:词级时间戳"置信度门槛"
-
作用:控制生成词级时间戳的概率阈值
-
默认值:0.01
-
调优思路:
-
提高(如0.05-0.1):只为高置信度词汇生成时间戳,时间戳更准确
-
降低(如0.001):为更多词汇生成时间戳,覆盖率高但可能不准确
-
搜索策略参数(解码控制)
-bs N (--beam-size)
概念:解码时的"候选路径数量"
-
作用:同时维护N条最优解码路径,最终选择最好的一条
-
默认值:5(-1表示禁用束搜索)
-
调优思路:
-
增大(如8-10):探索更多可能性,质量更好但计算量大幅增加
-
减小(如1-3):速度优先,适合实时场景但可能错过最优解
-
设为1:等价于贪心搜索,最快但质量一般
-
-bo N (--best-of)
概念:温度采样时的"样本池大小"
-
作用:在温度>0时,生成N个候选样本并选择最佳的
-
默认值:5
-
调优思路:
-
增大(如8-10):更充分的随机探索,可能找到更好结果
-
减小(如1-3):减少计算开销,适合对速度敏感的场景
-
-sow (--split-on-word)
概念:文本分割的"边界对齐器"
-
作用:确保音频分段在词边界处切分,避免截断单词
-
调优思路:
-
开启:文本更自然,适合长音频和需要高质量输出的场景
-
关闭:处理速度稍快,但可能在分段边界出现断词
-
采样温度参数
-tp N (--temperature)
概念:采样随机性控制器
-
作用:控制模型预测的确定性程度
-
默认值:渐进序列 [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
-
工作机制:
温度 = 0.0:完全确定性,总是选概率最高的词 温度 = 0.2-0.8:引入适量随机性,可能选择概率较低但合理的词 温度 = 1.0:最大随机性,输出更有创造性但可能不准确
-
调优策略:
-
低温度(0.0-0.2):适合技术文档、会议纪要等需要准确性的场景
-
中温度(0.4-0.6):平衡准确性与灵活性,适合一般对话
-
高温度(0.8-1.0):处理困难音频时增加探索性,但可能产生幻听
-
-tpi N (--temperature-inc)
概念:温度递增策略
-
作用:当前温度解码失败时,自动递增的步长
-
默认值:通常 0.2
-
工作流程:
-
调优思路:
-
小步长(0.1-0.15):更细致的温度探索,质量更稳定但计算量大
-
大步长(0.3-0.5):快速跳到高温度,适合处理很困难的音频
-
优化示例
./bin/whisper-cli \-m /home/jbj/openai/whisper/whisper_modle/ggml-tiny.bin \-f /home/jbj/openai/whisper/test/out3.wav \--prompt "以下是普通话的句子,使用简体中文输出。" \-l zh \-t $(nproc) \--processors 1 \-l zh -et 1.8 -lpt -0.8 -bs 1 -bo 0 -tp 0.0,0.2 -tpi 0.1 \-ml 80 -mc -1 -nth 0,10 -sow \--no-timestamps --no-real-time \./bin/whisper_asr \-m /home/jbj/openai/whisper/whisper_modle/ggml-tiny.bin \-f /home/jbj/openai/whisper/test/out3.wav \--prompt "以下是普通话的句子,使用简体中文输出。" \-l zh \-t $(nproc) \--processors 1 \--et 1.8 \--lpt -0.8 \--bs 0 \--bo 5 \--tp 0.0,0.2 \--tpi 0.1 \--nth 0,10 \--sow \--no-timestamps \--no-real-time