whisper.cpp 学习笔记

whisper.cpp 学习笔记

whisper 介绍


whisper 是基于 OpenAI 的自动语音识别(ASR)模型。他可以识别包括英语、普通话等在内多国语言。

whisper 分为 whisper (python 版本)和 whisper.cpp(C/C++ 版本)。

python 版本的 whisper 可以直接通过 pip install whisper 安装;whisper.cpp 可以通过源码进行安装。

以下主要介绍 whisper.cpp,因为其识别速度要快于 python 版本的 whisper。

源码下载


  • 源码下载

网址:https://github.com/ggerganov/whisper.cpp

git clone https://github.com/ggerganov/whisper.cpp.git
  • 下载模型
bash ./models/download-ggml-model.sh base.en

源码编译


方法一

直接在 whisper.cpp 目录下执行 make 命令就可以编译

# build the main example
make

# transcribe an audio file
./main -f samples/jfk.wav

默认会生成 main benchquantize 这三个命令:

  • main :whisper 的命令
  • quantize : 对 whisper 的模型进行量化处理
  • bench :性能测试

注:

使用此方法生成的可执行文件会包含 whisper 的代码,即没有生成 whisper 的库文件

whisper 只能识别音频采样频率为 16000 Hz 的声音数据,数据格式为 float类型——如果是 wav 文件则内部会自动转成 float 格式

方法二

make build
cd build
cmake xxx	#xxx 为 cmake 传入的参数,例如 prefix 等等,单独的 cmake 不能生成 Makefile
make

使用这种方式会在 build 目录下生成 liwhisper.so liwhisper.so.1liwhisper.so。1.5.5 库文件 —— 对应的头文件在 whisper.cpp 目录下 whisper.h 可以直接将这几个文件防盗 /usr/lib/usr/include 下即可使用。

支持的模型


whisper 目前支持:tiny、base、small、medium 以及 large 模型,其中带 .en 的表示之支持英文。

通过 make xxx 可以直接下载模型,例如:

make small

各种模型的内存使用情况:

ModelDiskMem
tiny75 MiB~273 MB
base142 MiB~388 MB
small466 MiB~852 MB
medium1.5 GiB~2.1 GB
large2.9 GiB~3.9 GB

优化/加速


使用硬件加速

whipser 支持多种加速(详见 whisper.cpp 的 Readme)

  • OpenVINO
  • NVIDIA GPU
  • CLBlast
  • OpenBLAS
  • MKL

这里只介绍 MKL。

首先通过 Intel® oneAPI Math Kernel Library 下载 intel 的 oneapi 数学库;

该数学库是二进制安装的,在安装完后需要执行一个脚本用于产生命令和连接库位置的环境

source /opt/intel/oneapi/setvars.sh 
mkdir build
cd build
cmake -DWHISPER_MKL=ON ..
WHISPER_MKL=1 make -j

通过上步可以生成依赖 intel oneapi 的 whisper 动态库。这里为了能够开机使用 intel oneapi,可以将 source /opt/intel/oneapi/setvars.sh 命令放到 ~/.bashrc 配置文件中——要想所有用户都可以使用,可以在 /ect/profile.d 目录下建一个 intel oneapi 的脚本,这样在用户登陆时可以自动配置环境变量。

注:

如果使用 root 权限安装 intel oneapi 则该软件安装在 /opt 目录下,否则安装在用户的 home 目录下。

量化模型

编译生成的可执行文件中有 quantize 这个命令,该命令用来量化模型可以减少模型的体积和加快运行的速度。

usage: ./quantize model-f32.bin model-quant.bin type
  type = "q2_k" or 10
  type = "q3_k" or 11
  type = "q4_0" or 2
  type = "q4_1" or 3
  type = "q4_k" or 12
  type = "q5_0" or 8
  type = "q5_1" or 9
  type = "q5_k" or 13
  type = "q6_k" or 14
  type = "q8_0" or 7

例如量化前 ggml-medium.bin 的大小为 1.5 G,采用 q4_k 量化后大小为 424 M。

执行速度:

量化前

time whisper --language chinese --model models/ggml-medium.bin output.wav
system_info: n_threads = 4 / 8 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | METAL = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | CUDA = 0 | COREML = 0 | OPENVINO = 0

main: processing 'output.wav' (42624 samples, 2.7 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = chinese, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:02.000]  你好 你好 你好

whisper_print_timings:     load time =   606.10 ms
whisper_print_timings:     fallbacks =   0 p /   0 h
whisper_print_timings:      mel time =     6.12 ms
whisper_print_timings:   sample time =    12.43 ms /    24 runs (    0.52 ms per run)
whisper_print_timings:   encode time =  9836.69 ms /     1 runs ( 9836.69 ms per run)
whisper_print_timings:   decode time =    69.17 ms /     2 runs (   34.59 ms per run)
whisper_print_timings:   batchd time =   364.41 ms /    20 runs (   18.22 ms per run)
whisper_print_timings:   prompt time =     0.00 ms /     1 runs (    0.00 ms per run)
whisper_print_timings:    total time = 10899.75 ms

real    0m11.000s
user    0m44.862s
sys     0m2.151s

量化后

time whisper --language chinese --model models/ggml-medium_q4_k.bin output.wav
system_info: n_threads = 4 / 8 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | METAL = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | CUDA = 0 | COREML = 0 | OPENVINO = 0

main: processing 'output.wav' (42624 samples, 2.7 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = chinese, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:02.000]  你好 你好 你好

whisper_print_timings:     load time =   303.66 ms
whisper_print_timings:     fallbacks =   0 p /   0 h
whisper_print_timings:      mel time =     6.37 ms
whisper_print_timings:   sample time =    13.74 ms /    27 runs (    0.51 ms per run)
whisper_print_timings:   encode time =  8979.33 ms /     1 runs ( 8979.33 ms per run)
whisper_print_timings:   decode time =    34.54 ms /     2 runs (   17.27 ms per run)
whisper_print_timings:   batchd time =   289.84 ms /    23 runs (   12.60 ms per run)
whisper_print_timings:   prompt time =     0.00 ms /     1 runs (    0.00 ms per run)
whisper_print_timings:    total time =  9632.14 ms

real    0m9.702s
user    0m42.165s
sys     0m1.342s

从量化前后的执行速度来看,执行时间提升了1秒左右。

生成库文件


在前面我们介绍了使用 cmake & make 命令可以生成动态库。

使用 whispe.cpp 的 demo


example 目录下有各种使用的 demo ,通过在 whisper.cpp 目录下执行 make xxx (xxx 为 example 中演示 demo 的名字),即可生成该 demo 的可执行文件。

通过分析各种 demo 文件可以发现,主要使用了 whisper 中的如下几个函数:

  • whisper_lang_id() 语言支持检测——这里要使用小写,如 chinese 而不能用 Chinese
  • whisper_context_default_params() 设置默认的上下文参数
  • whisper_init_from_file_with_params() 初始化上下文
  • whisper_is_multilingual() 检查上下文是否支持多国语言
  • whisper_full() 语音识别过程的函数
  • whisper_full_n_segments() 获取一共产生了多少段文字
  • whisper_full_get_segments_text() 获取识别到的一段文字
  • whisper_full_n_token() 一段识别中有多少个 tokern
  • whisper_full_get_token_id() 获取对应 id 的 token

以下是参考 example/main/main.cpp 改写的简单 cpp 文件。

#include "common.h"

#include "whisper.h"
#include "grammar-parser.h"

#include <cmath>
#include <fstream>
#include <cstdio>
#include <regex>
#include <string>
#include <thread>
#include <vector>
#include <cstring>

bool wav_read(std::string fname, std::vector<float>& pcmf32)
{
    std::vector<std::vector<float>> pcmf32s;

    if (!::read_wav(fname, pcmf32, pcmf32s, false)) {
        fprintf(stderr, "error: failed to read WAV file '%s'\n", fname.c_str());
        return false;
    }

    return true;
}

int whisper_init(struct whisper_context * *ctx, whisper_full_params& wparams)
{
    if (whisper_lang_id("chinese") == -1) {
        fprintf(stderr, "error: unknown language '%s'\n", "Chinese");
        exit(0);
    }

    struct whisper_context_params cparams = whisper_context_default_params();
    cparams.use_gpu = false;

   *ctx = whisper_init_from_file_with_params("models/ggml-small.bin", cparams);
    if (*ctx == nullptr) {
        fprintf(stderr, "error: failed to initialize whisper context\n");
        return 3;
    }


    wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY);
    wparams.language         = "chinese";

    return 0;
}

int whisper_exit(struct whisper_context ** ctx)
{
    whisper_free(*ctx);
    return 0;
}

int whisper_identify(struct whisper_context **ctx, whisper_full_params& wparams, std::vector<float> pcmf32, std::string& result)
{
    if(whisper_full(*ctx, wparams, pcmf32.data(), pcmf32.size()) != 0){
        return -1;
    }

    const int n_segments = whisper_full_n_segments(*ctx);
    for (int i = 0; i < n_segments; ++i) {
        const char * text = whisper_full_get_segment_text(*ctx, i);

        result += text;
    }

    return 0;
}

int main(int argc, char ** argv) {
    std::vector<float> pcmf32;
    struct whisper_context *ctx = nullptr;
    whisper_full_params wparams;
    std::string text;

    if(!wav_read("output.wav", pcmf32)){
        fprintf(stderr, "wave read failed !\n");
        return -1;
    }

    if(whisper_init(&ctx, wparams)){
        fprintf(stderr, "whisper init error !\n");
        return -1;
    }

    if(whisper_identify(&ctx, wparams, pcmf32, text)){
        fprintf(stderr, "identify error !\n");
        return 0;
    }

    whisper_exit(&ctx);

   fprintf(stdout, "text is : %s\n", text.c_str());

    return 0;
}

该文件简化为 wav 文件读、whisper 初始化、whisper 识别以及 whisper 退出这几个函数,结构简单更容易理解。将其替换 example/main/main.cpp 重新编译即可以执行。

注:
在 whisper 的 api 函数中涉及到的语言全部用小写,不能使用大写,否则会提示不支持。

参考文献

whisper.cpp

<think>好的,我现在需要帮助用户了解如何微调预训练模型,比如Whisper。首先,用户之前询问了AI语音训练的步骤和软件,现在他们想进一步深入,特别是关于微调预训练的模型。这说明用户可能已经有一定的背景知识,但需要更具体的指导。 我应该先回忆一下Whisper的基本情况。Whisper是OpenAI开源的语音识别模型,支持多语言,基于Transformer架构。微调需要准备特定领域的数据,比如用户的专业术语或口音。接下来需要确定用户的使用场景,比如是中文还是其他语言,是否有特定的需求,比如医疗或法律领域的术语。 用户可能是开发者或者研究人员,想要在自己的数据集上优化模型。因此,我需要提供具体的步骤,包括环境配置、数据准备、模型加载、训练配置、评估和部署。同时,要推荐合适的工具和库,比如Hugging Face的Transformers和Datasets库,这些对微调非常有用。 数据准备是关键部分,要详细说明格式要求和预处理步骤,比如音频文件的格式、文本标注的清理。可能需要提到数据增强的方法,比如添加噪声或改变语速,以提高模型的鲁棒性。 在代码示例方面,给出一个简单的训练循环是必要的,但也要提醒用户根据实际情况调整参数,比如学习率、批次大小。此外,评估部分要介绍WER和CER,这些是衡量ASR性能的重要指标。 最后,用户可能需要部署微调后的模型,所以需要提到转换和优化的工具,比如ONNX或TensorRT,以及部署到服务器或移动端的方法。还要注意硬件要求,尤其是GPU的使用,因为训练需要较高的计算资源。 需要检查是否有遗漏的步骤,比如数据分割(训练集、验证集、测试集),或者如何处理常见错误,比如内存不足。另外,应该提醒用户注意数据版权和隐私问题,确保使用的数据是合法的。 总结来说,回答需要结构清晰,步骤明确,工具推荐具体,并提供实际代码示例,帮助用户快速上手。同时,考虑到用户可能的实际应用场景,给出实用建议,如使用Hugging Face的Trainer类简化训练流程,以及如何利用现有资源加速开发。</think>以下是基于预训练模型(如OpenAI Whisper)进行微调的入门指南,以语音识别(ASR)为例: --- ### **一、微调核心流程** #### 1. **环境准备** - **硬件**:至少需要GPU(如NVIDIA RTX 3090/4090,显存≥24GB) - **软件**: ```bash # 基础依赖 pip install torch transformers datasets librosa soundfile # 专为Whisper优化 pip install accelerate evaluate jiwer ``` #### 2. **数据准备** - **数据格式**: - 音频文件:`.wav`格式,16kHz采样率(Whisper强制要求) - 标注文本:与音频同名的`.txt`文件,UTF-8编码 - **目录结构**: ``` dataset/ train/ audio1.wav audio1.txt ... test/ ... ``` #### 3. **加载预训练模型** ```python from transformers import WhisperForConditionalGeneration, WhisperProcessor model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-small") processor = WhisperProcessor.from_pretrained("openai/whisper-small", task="transcribe") ``` #### 4. **数据预处理** ```python from datasets import load_dataset, Audio dataset = load_dataset("audiofolder", data_dir="dataset") # 重采样至16kHz dataset = dataset.cast_column("audio", Audio(sampling_rate=16000)) def process(batch): audio = batch["audio"]["array"] text = batch["text"] # 提取log-Mel特征 inputs = processor(audio, sampling_rate=16000, text=text, return_tensors="pt") return inputs dataset = dataset.map(process, remove_columns=["audio", "text"]) ``` #### 5. **训练配置** ```python from transformers import Seq2SeqTrainingArguments training_args = Seq2SeqTrainingArguments( output_dir="./whisper-finetuned", per_device_train_batch_size=8, # 根据显存调整 learning_rate=1e-5, warmup_steps=500, max_steps=4000, fp16=True, # 启用混合精度训练 evaluation_strategy="steps", predict_with_generate=True # 生成文本用于评估 ) ``` #### 6. **启动微调** ```python from transformers import Seq2SeqTrainer trainer = Seq2SeqTrainer( args=training_args, model=model, train_dataset=dataset["train"], eval_dataset=dataset["test"], tokenizer=processor.tokenizer, ) trainer.train() ``` --- ### **二、关键技巧** #### 1. **数据增强** - 添加背景噪声(使用`noisereduce`库) - 随机变速(±10%速度变化) - 音量扰动(±6dB范围) #### 2. **评估指标** ```python import evaluate wer_metric = evaluate.load("wer") cer_metric = evaluate.load("cer") def compute_metrics(pred): pred_ids = pred.predictions label_ids = pred.label_ids # 解码预测结果 pred_str = processor.batch_decode(pred_ids, skip_special_tokens=True) label_str = processor.batch_decode(label_ids, skip_special_tokens=True) # 计算WER/CER wer = wer_metric.compute(predictions=pred_str, references=label_str) cer = cer_metric.compute(predictions=pred_str, references=label_str) return {"wer": wer, "cer": cer} ``` --- ### **三、部署优化** #### 1. 模型导出 ```python model.save_pretrained("./whisper-finetuned") processor.save_pretrained("./whisper-finetuned") ``` #### 2. 推理加速 - 转换为ONNX格式: ```bash pip install optimum[exporters] optimum-cli export onnx --model ./whisper-finetuned --task automatic-speech-recognition ./onnx-whisper ``` - 使用C++推理库:`whisper.cpp`(适合嵌入式设备) --- ### **四、常见问题** 1. **显存不足**: - 减小`per_device_train_batch_size` - 启用梯度累积(`gradient_accumulation_steps=2`) - 使用LoRA微调(需安装`peft`库) 2. **中文支持**: - 使用`openai/whisper-large-v3`(支持96种语言) - 标注文本需为简体中文(无需分词) 3. **长音频处理**: ```python # 自动分割30秒片段 inputs = processor(audio, return_tensors="pt", chunk_length_s=30, stride_length_s=(5,5)) ``` --- ### **五、推荐学习资源** 1. **官方文档**: - [Hugging Face Whisper文档](https://huggingface.co/docs/transformers/model_doc/whisper) - [OpenAI Whisper GitHub](https://github.com/openai/whisper) 2. **实战案例**: - 医疗领域术语微调(需专用数据集) - 方言识别(如粤语、吴语) 建议从100小时以上的领域数据开始微调,使用`whisper-small`模型可在单卡上1-2天完成训练。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值