python系列&deep_study系列:Whisper OpenAI开源语音识别模型
Whisper OpenAI开源语音识别模型
Whisper OpenAI开源语音识别模型
介绍
Whisper 是一个自动语音识别(ASR,Automatic Speech Recognition)系统,OpenAI 通过从网络上收集了 68 万小时的多语言(98 种语言)和多任务(multitask)监督数据对 Whisper 进行了训练。OpenAI 认为使用这样一个庞大而多样的数据集,可以提高对口音、背景噪音和技术术语的识别能力。除了可以用于语音识别,Whisper 还能实现多种语言的转录,以及将这些语言翻译成英语。
语音转文字在许多不同领域都有着广泛的应用。以下是一些例子:
1.字幕制作:语音转文字可以帮助视频制作者快速制作字幕,这在影视行业和网络视频领域非常重要。通过使用语音转文字工具,字幕制作者可以更快地生成字幕,从而缩短制作时间,节省人工成本,并提高制作效率。
2.法律文书:在法律领域,语音转文字可以帮助律师和律所将听证会、辩论和其他法律活动的录音转化为文字文档。这些文档可以用于研究、起草文件和法律分析等目的,从而提高工作效率。
3.医疗文档:医疗专业人员可以使用语音转文字技术来记录病人的医疗记录、手术记录和其他相关信息。这可以减少错误和遗漏,提高记录的准确性和完整性,为患者提供更好的医疗服务。
4.市场调查和分析:语音转文字可以帮助企业快速收集和分析消费者反馈、电话调查和市场研究结果等数据。这可以帮助企业更好地了解其目标受众和市场趋势,从而制定更有效的营销策略和商业计划。
一、Whisper 模型及配置
目前 Whisper 模型的大小,及其内存要求和相对速度:
大小 | 参数 | 纯英文模型 | 多语言模型 | 所需显存 | 相对速度 |
---|---|---|---|---|---|
tiny | 39 M | tiny.en | tiny | ~1 GB | ~32x |
base | 74 M | base.en | base | ~1 GB | ~16x |
small | 244 M | small.en | small | ~2 GB | ~6x |
medium | 769 M | medium.en | medium | ~5 GB | ~2x |
large | 1550 M | N/A | large | ~10 GB | 1x |
Whisper 参数
参数名 | 描述 | 默认值 |
---|---|---|
[–model {tiny.en,tiny,base.en,base,small.en,small,medium.en,medium,large}] | –model 模型类型 从小到大的不同模型,分别为tiny.en,tiny,base.en,base,small.en,small,medium.en,medium,large | |
[–model_dir MODEL_DIR] | 存储模型文件的路径 | ~/.cache/whisper |
[–device DEVICE] | 使用Pytorch的设备(CPU or GPU) | CUDA |
[–output_dir OUTPUT_DIR] | – output_dir 保存输出的路径 | None |
[–verbose VERBOSE] | 是否打印过程和debug信息 | True |
[–task {transcribe,translate}] | –task 任务:是否执行 X->X 语音识别 (‘transcribe’) 或 X->英文翻译 (‘translate’) | transcribe |
[–language {af,am,ar,as,az,ba,be,bg,bn,bo,br,bs,ca,cs,cy,da,de,el,en,es,et,eu,fa,fi,fo,fr,gl,gu,ha,https://www.zhihu.com/search?q=haw&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2778034018%7D,hi,hr,ht,hu,hy,id,is,it,iw,ja,jw,ka,kk,km,kn,ko,la,lb,ln,lo,lt,lv,mg,mi,mk,ml,mn,mr,ms,mt,my,ne,nl,nn,no,oc,pa,pl,ps,pt,ro,ru,sa,sd,si,sk,sl,sn,so,sq,sr,su,sv,sw,ta,te,tg,th,tk,tl,tr,tt,uk,ur,uz,vi,yi,yo,zh,Afrikaans,Albanian,Amharic,Arabic,Armenian,Assamese,Azerbaijani,Bashkir,Basque,Belarusian,Bengali,Bosnian,Breton,Bulgarian,Burmese,Castilian,Catalan,Chinese,Croatian,Czech,Danish,Dutch,English,Estonian,Faroese,Finnish,Flemish,French,Galician,Georgian,German,Greek,Gujarati,Haitian,Haitian Creole,Hausa,Hawaiian,Hebrew,Hindi,Hungarian,Icelandic,Indonesian,Italian,Japanese,Javanese,Kannada,Kazakh,Khmer,Korean,Lao,Latin,Latvian,Letzeburgesch,Lingala,Lithuanian,Luxembourgish,Macedonian,Malagasy,Malay,Malayalam,Maltese,Maori,Marathi,Moldavian,Moldovan,Mongolian,Myanmar,Nepali,Norwegian,Nynorsk,Occitan,Panjabi,Pashto,Persian,Polish,Portuguese,Punjabi,Pushto,Romanian,Russian,Sanskrit,Serbian,Shona,Sindhi,Sinhala,Sinhalese,Slovak,Slovenian,Somali,Spanish,Sundanese,Swahili,Swedish,Tagalog,Tajik,Tamil,Tatar,Telugu,Thai,Tibetan,Turkish,Turkmen,Ukrainian,Urdu,Uzbek,Valencian,Vietnamese,Welsh,Yiddish,Yoruba}] | –language 语言:原音频中使用的语言 | |
[–temperature TEMPERATURE] | –temperature 温度参数:文章使用的是基于温度系数的采样,这个参数就是采样的温度系数 | |
[–best_of BEST_OF] | 在温度非0时的抽样使用的候选词数 | 5 |
[–beam_size BEAM_SIZE] | beam搜索中的beam数据的数目,仅在温度为0时可用 | 5 |
[–patience PATIENCE] | https://www.zhihu.com/search?q=beam%E8%A7%A3%E7%A0%81&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2778034018%7D是使用的可选耐性系数optional patience value to use in beam decoding, as in https://link.zhihu.com/?target=https%3A//arxiv.org/abs/2204.05424, the default(1.0) is equivalent to conventional beam search (default: None) | None |
[–length_penalty LENGTH_PENALTY] | – length_penalty 惩罚系数:用于正则化的optional token length penalty coefficient (alpha) as in https://link.zhihu.com/?target=https%3A//arxiv.org/abs/1609.08144, usessimple length normalization by default (default: None)可选的惩罚系数 α α α α \alpha α ααα | None |
[–suppress_tokens SUPPRESS_TOKENS] | 采样期间要抑制的token ID的逗号分隔列表;“-1”时将抑制大多数特殊字符(https://www.zhihu.com/search?q=%E5%B8%B8%E7%94%A8%E6%A0%87%E7%82%B9%E7%AC%A6%E5%8F%B7&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2778034018%7D除外) | -1 |
[–initial_prompt INITIAL_PROMPT] | 可选文本,作为第一个窗口的提示。 | None |
[–https://www.zhihu.com/search?q=condition_on_previous_text%20CONDITION_ON_PREVIOUS_TEXT&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2778034018%7D] | –condition_on_previous_text 先前文本使用状况:如果为 True,则提供模型的先前输出作为下一个窗口的提示; 禁用可能会使文本跨窗口不一致,但模型变得不太容易陷入故障 | |
[–fp16 FP16] | 在fp16中进行推理 | True |
[–temperature_increment_on_fallback TEMPERATURE_INCREMENT_ON_FALLBACK] | –temperature_increment_on_fallback 回退温度系数:当解码未能满足以下任一阈值时的回退增加的温度 | 0.2 |
[–compression_ratio_https://www.zhihu.com/search?q=threshold%20COMPRESSION_RATIO_THRESHOLD&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2778034018%7D] | compression_ratio_threshold 压缩率阈值:如果gzip压缩比高于这个值,则认为解码失败 | 2.4 |
[–logprob_threshold LOGPROB_THRESHOLD] | 如果平均对数概率低于此值,则将解码视为失败 | -1.0 |
[–https://www.zhihu.com/search?q=no_speech_threshold%20NO_SPEECH_THRESHOLD&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2778034018%7D] | –no_speech_threshold 静音阈值:如果 < | nospeech |
[–threads THREADS] | 使用Pytorch CPU做推理时,使用的CPU线程数 | 0 |
评测数据
模型测试表
原始模型字错率测试表。
使用模型 | 指定语言 | aishell_test | test_net | test_meeting | 下载地址 | CTranslate2模型下载地址 |
---|---|---|---|---|---|---|
whisper-tiny | Chinese | 0.31898 | 0.40482 | 0.75332 | https://pan.baidu.com/s/1q8xHr71XPe1dnRHv2IzldQ?pwd=wjrf | https://pan.baidu.com/s/1Rg8KM1gDKLw8kObZEJQG1A?pwd=hnhe |
whisper-base | Chinese | 0.22196 | 0.30404 | 0.50378 | https://pan.baidu.com/s/1q8xHr71XPe1dnRHv2IzldQ?pwd=wjrf | https://pan.baidu.com/s/1Rg8KM1gDKLw8kObZEJQG1A?pwd=hnhe |
whisper-small | Chinese | 0.13897 | 0.18417 | 0.31154 | https://pan.baidu.com/s/1q8xHr71XPe1dnRHv2IzldQ?pwd=wjrf | https://pan.baidu.com/s/1Rg8KM1gDKLw8kObZEJQG1A?pwd=hnhe |
whisper-medium | Chinese | 0.09538 | 0.13591 | 0.26669 | https://pan.baidu.com/s/1q8xHr71XPe1dnRHv2IzldQ?pwd=wjrf | https://pan.baidu.com/s/1Rg8KM1gDKLw8kObZEJQG1A?pwd=hnhe |
whisper-large | Chinese | 0.08969 | 0.12933 | 0.23439 | https://pan.baidu.com/s/1q8xHr71XPe1dnRHv2IzldQ?pwd=wjrf | https://pan.baidu.com/s/1Rg8KM1gDKLw8kObZEJQG1A?pwd=hnhe |
whisper-large-v2 | Chinese | 0.08817 | 0.12332 | 0.26547 | https://pan.baidu.com/s/1q8xHr71XPe1dnRHv2IzldQ?pwd=wjrf | https://pan.baidu.com/s/1Rg8KM1gDKLw8kObZEJQG1A?pwd=hnhe |
微调AIShell数据集后字错率测试表。
使用模型 | 指定语言 | 数据集 | aishell_test | test_net | test_meeting | 下载地址 | CTranslate2模型下载地址 |
---|---|---|---|---|---|---|---|
whisper-tiny | Chinese | https://openslr.magicdatatech.com/resources/33/ | 0.13043 | 0.4463 | 0.57728 | https://pan.baidu.com/s/1hIximy9ddN3cMHN4_VdhnQ?pwd=nfc2 | https://pan.baidu.com/s/1H-OBD9L0hYV-M_WoPEbiJA?pwd=8hbb |
whisper-base | Chinese | https://openslr.magicdatatech.com/resources/33/ | 0.08999 | 0.33089 | 0.40713 | https://pan.baidu.com/s/1hIximy9ddN3cMHN4_VdhnQ?pwd=nfc2 | https://pan.baidu.com/s/1H-OBD9L0hYV-M_WoPEbiJA?pwd=8hbb |
whisper-small | Chinese | https://openslr.magicdatatech.com/resources/33/ | 0.05452 | 0.19831 | 0.24229 | https://pan.baidu.com/s/1hIximy9ddN3cMHN4_VdhnQ?pwd=nfc2 | https://pan.baidu.com/s/1H-OBD9L0hYV-M_WoPEbiJA?pwd=8hbb |
whisper-medium | Chinese | https://openslr.magicdatatech.com/resources/33/ | 0.03681 | 0.13073 | 0.16939 | https://pan.baidu.com/s/1hIximy9ddN3cMHN4_VdhnQ?pwd=nfc2 | https://pan.baidu.com/s/1H-OBD9L0hYV-M_WoPEbiJA?pwd=8hbb |
whisper-large-v2 | Chinese | https://openslr.magicdatatech.com/resources/33/ | 0.03078 | 0.11359 | 0.14079 | https://pan.baidu.com/s/1hIximy9ddN3cMHN4_VdhnQ?pwd=nfc2 | https://pan.baidu.com/s/1H-OBD9L0hYV-M_WoPEbiJA?pwd=8hbb |
whisper-tiny | Chinese | WenetSpeech | 0.21009 | 0.29352 | 0.41506 | https://pan.baidu.com/s/18l6K59nP0j3XXmEQZ_Up_g?pwd=x7ay | https://pan.baidu.com/s/1X37l5pvbpGmRhDkRkgYCQw?pwd=vm4k |
whisper-large-v2 | Chinese | WenetSpeech | 0.05545 | 0.10280 | 0.20719 |
未加速和加速后的推理速度测试表,使用GPU为GTX3090(24G)。
使用模型 | 原生模型实时率(float16) | 转换CTranslate2加速后实时率(float16) | 转换CTranslate2加速后实时率(int8_float16) |
---|---|---|---|
whisper-tiny | 0.03 | 0.06 | 0.06 |
whisper-base | 0.04 | 0.06 | 0.06 |
whisper-small | 0.08 | 0.08 | 0.08 |
whisper-medium | 0.13 | 0.10 | 0.10 |
whisper-large-v2 | 0.19 | 0.12 | 0.12 |
经过处理的数据列表,添加标点符号的模型为PunctuationModel。
数据列表处理方式 | AiShell | WenetSpeech |
---|---|---|
添加标点符号 | https://pan.baidu.com/s/1Qzalcy0R2SyrOBSxtezN0A?pwd=v45t | https://pan.baidu.com/s/1XrnD_YLYWYUs65lq4StzTg?pwd=hv3i |
添加标点符号和时间戳 | https://pan.baidu.com/s/1zC3CTqPrNkhDIwAwqlZ6kw?pwd=xun4 | https://pan.baidu.com/s/1JrlQ97fZfCD-JEbW7Td_2g?pwd=97ki |
重要说明:
-
在评估的时候移除模型输出的标点符号,并把繁体中文转成简体中文。
-
aishell_test
为AIShell
的测试集,test_net
和test_meeting
为WenetSpeech
的测试集。 -
RTF
=所有音频总时间(单位秒)
/ASR识别所有音频处理时间(单位秒)
。 -
测试速度的音频为
dataset/test.wav
,时长为8秒。 -
训练数据使用的是带标点符号的数据,字错率高一点。
二、安装 ffmpeg
ffmpeg
Win
Scoop 包
管理工具去下载,具体安装方法借鉴
https://zhuanlan.zhihu.com/p/561204256
scoop install ffmpeg
Mac (打开终端(Terminal), 用 homebrew 安装):
brew install ffmpeg --with-libvorbis --with-sdl2 --with-theora
Linux:
apt-get install ffmpeg libavcodec-extra
# contos7
sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
sudo yum install ffmpeg ffmpeg-devel -y
三、python的实现
准备环境
conda create -n whisper python=3.9
conda activate whisper
# 一
git clone https://gitee.com/mirrors/openai-whisper.git
python setup.py install
# 二
pip install git+https://github.com/openai/whisper.git
pip install --upgrade --no-deps --force-reinstall git+https://github.com/openai/whisper.git
pip install -U openai-whisper
pip install setuptools-rust
# 验证调用
whisper audio.mp3 --model medium --language Chinese
pip install setuptools-rust
git clone https://gitee.com/mirrors/openai-whisper.git
python setup.py install
代码
# 音频的前5分钟输出成单独的mp3文件
from pydub import AudioSegment
song = AudioSegment.from_mp3("test.mp3")
# PyDub handles time in milliseconds
five_minutes = 5 * 60 * 1000
first_5_minutes = song[:five_minutes]
first_5_minutes.export("test.mp3", format="mp3")
import whisper
import arrow
# 定义模型、音频地址、录音开始时间
def excute(model_name, file_path, start_time):
model = whisper.load_model(model_name)
result = model.transcribe(file_path)
for segment in result["segments"]:
now = arrow.get(start_time)
start = now.shift(seconds=segment["start"]).format("YYYY-MM-DD HH:mm:ss")
end = now.shift(seconds=segment["end"]).format("YYYY-MM-DD HH:mm:ss")
print("【"+start+"->" +end+"】:" + segment["text"])
if __name__ == '__main__':
excute("base", "55555.mp3", "2023-06-03 16:23:00")
import whisper
# device是计算引擎,可以选择cpu,或者cuda(也就是gpu),不填默认为cpu,有显卡并且显存满足你所选的模型大小可以正常跑起来,不然会报内存错误。
# download_root是模型保存以及读取路径,不填默认为系统用户下的路径,我的为例C:\Users\heyj01\.cache\whisper,第一次加载模型,模型没有在路径下会下载模型到download_root路径下。
Model = 'large-v2' #@param ['tiny.en', 'tiny', 'base.en', 'base', 'small.en', 'small', 'medium.en', 'medium', 'large', 'large-v2']
whisper_model = whisper.load_model("large", device='gpu')
result = whisper_model.transcribe(r"C:\Users\win10\Downloads\test.wav", fp16="False")
print(", ".join([i["text"] for i in result["segments"] if i is not None]))
huggingface
!pip install zhconv
!pip install whisper
!pip install tqdm
!pip install ffmpeg-python
!pip install transformers
!pip install librosa
from transformers import WhisperProcessor, WhisperForConditionalGeneration
import librosa
import torch
from zhconv import convert
import warnings
warnings.filterwarnings("ignore")
audio_file = f"test.wav"
#load audio file
audio, sampling_rate = librosa.load(audio_file, sr=16_000)
# # audio
# display.Audio(audio_file, autoplay=True)
# load model and processor
processor = WhisperProcessor.from_pretrained("openai/whisper-large-v2")
model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-large-v2")
tokenizer = WhisperProcessor.from_pretrained("openai/whisper-large-v2")
processor.save_pretrained("openai/model/whisper-large-v2")
model.save_pretrained("openai/model/whisper-large-v2")
tokenizer.save_pretrained("openai/model/whisper-large-v2")
processor = WhisperProcessor.from_pretrained("openai/model/whisper-large-v2")
model = WhisperForConditionalGeneration.from_pretrained("openai/model/whisper-large-v2")
tokenizer = WhisperProcessor.from_pretrained("openai/model/whisper-large-v2")
# load dummy dataset and read soundfiles
# ds = load_dataset("common_voice", "fr", split="test", streaming=True)
# ds = ds.cast_column("audio", datasets.Audio(sampling_rate=16_000))
# input_speech = next(iter(ds))["audio"]["array"]
model.config.forced_decoder_ids = processor.get_decoder_prompt_ids(language="zh", task="transcribe")
input_features = processor(audio, return_tensors="pt").input_features
predicted_ids = model.generate(input_features)
# transcription = processor.batch_decode(predicted_ids)
transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)
print(transcription)
print('转化为简体结果:', convert(transcription, 'zh-cn'))
transformers
import torch
from transformers import pipeline
from datasets import load_dataset
device = "cuda:0" if torch.cuda.is_available() else "cpu"
pipe = pipeline(
"automatic-speech-recognition",
model="openai/whisper-large-v2",
chunk_length_s=30,
device=device,
)
ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
sample = ds[0]["audio"]
prediction = pipe(sample.copy(), batch_size=8)["text"]
# we can also return timestamps for the predictions
prediction = pipe(sample.copy(), batch_size=8, return_timestamps=True)["chunks"]
出参
{
'id': 1,
'seek': 0,
'start': 4.8, //起始时间
'end': 6.7, //结束时间
'text': '你不要去博这个东西',
'tokens': [50604, 2166, 11962, 6734, 5322, 248, 15368, 38409, 16220, 50699],
'temperature': 0.0, //在语音转文本模型生成结果时,控制输出随机性和多样性的参数
'avg_logprob': -0.2088493855794271, //语音转文字模型预测的置信度评分的平均值
'compression_ratio': 1.649402390438247,
'no_speech_prob': 0.5881261825561523 //指模型在某段时间内检测到没有语音信号的概率
}
//置信度参数你可以用来提高识别准确率
四、加速
HuggingFace
Whisper JAX - a Hugging Face Space by sanchit-gandhi
HuggingFace 新版本Whisper速度提升70倍
Google’s JAX是一个用于高性能数值计算和机器学习的Python库,它可以让用户使用类似NumPy的API进行计算,并且能够在GPU和TPU等加速设备上进行自动的优化和并行化处理。JAX提供了一些强大的功能,包括自动微分,高阶梯度计算和动态编译等,这使得它成为许多机器学习算法的理想实现平台。
与其他深度学习框架类似,JAX提供了一个自动微分系统,可以轻松地计算复杂函数的梯度,并且可以支持高阶导数的计算。此外,JAX还提供了一种称为jax.jit()的动态编译器,可以将Python函数转换为高效的机器码,以实现更快的执行速度和更低的内存占用。
JAX的一个独特之处在于它可以使用XLA(Accelerated Linear Algebra)库来自动并行化和优化计算,从而在GPU和TPU等加速设备上获得更好的性能。此外,JAX还提供了一些用于构建神经网络的高级API,例如jax.nn模块和jax.experimental.stax模块,以帮助用户更轻松地构建复杂的神经网络。
总的来说,JAX是一个非常强大的数值计算和机器学习库,可以帮助用户更轻松地构建高效的模型,并在加速设备上获得更好的性能。
-
Whisper现已在Jax上运行,能够在短短几秒钟内转录1小时的音频。
-
该模型本身已经是最强大的语音转文本系统之一,现在加上了惊人的速度,使用起来几乎是不费吹灰之力。
-
尽管仍有缺点,但这是社区取得的卓越成果。
faster-whisper模型
!pip install faster-whisper
!pip install "faster-whisper @ https://github.com/guillaumekln/faster-whisper/archive/refs/heads/master.tar.gz"
!pip install zhconv -i https://pypi.tuna.tsinghua.edu.cn/simple
from faster_whisper import WhisperModel
from zhconv import convert
import time
model_size = "large-v2"
# Run on GPU with FP16
# model = WhisperModel(model_size, device="cuda", compute_type="float16")
# or run on GPU with INT8
# model = WhisperModel(model_size, device="cuda", compute_type="int8_float16")
# or run on CPU with INT8
model = WhisperModel(model_size, device="cpu", compute_type="int8")
print(time.time())
segments, info = model.transcribe("11685669437.wav", beam_size=5)
print(time.time())
print("Detected language '%s' with probability %f" % (info.language, info.language_probability))
for segment in segments:
print("[%.2fs -> %.2fs] %s" % (segment.start, segment.end, segment.text))
print("[%.2fs -> %.2fs] %s" % (segment.start, segment.end, convert(segment.text, 'zh-cn')))
# whisper转化成faster-whisper
ct2-transformers-converter\
--model openai/whisper-large-v2\
--output_dir whisper-large-v2-ct2 \
--copy_files tokenizer.json\
--quantization float16
faster-whisper是stream-translator的作者最近支持的,相比whisper,faster-whisper速度要快4倍,而显存只用不到50%(在large v2模型下)whisper和faster-whisper的对比测试:
Large-v2 model on GPU
Implementation | Precision | Beam size | Time | Max. GPU memory | Max. CPU memory |
---|---|---|---|---|---|
openai/whisper | fp16 | 5 | 4m30s | 11325MB | 9439MB |
faster-whisper | fp16 | 5 | 54s | 4755MB | 3244MB |
faster-whisper | int8 | 5 | 59s | 3091MB | 3117MB |
Executed with CUDA 11.7.1 on a NVIDIA Tesla V100S.
Small model on CPU
Implementation | Precision | Beam size | Time | Max. memory |
---|---|---|---|---|
openai/whisper | fp32 | 5 | 10m31s | 3101MB |
whisper.cpp | fp32 | 5 | 17m42s | 1581MB |
whisper.cpp | fp16 | 5 | 12m39s | 873MB |
faster-whisper | fp32 | 5 | 2m44s | 1675MB |
faster-whisper | int8 | 5 | 2m04s | 995MB |
Executed with 8 threads on a Intel® Xeon® Gold 6226R.
CTranslate2
众所周知,直接使用Whisper模型推理是比较慢的,所以这里提供了一个加速的方式,主要是使用了CTranslate2
进行加速,首先要转换模型,把合并后的模型转换为CTranslate2模型
。如下命令,--model参数
指定的是合并后的模型路径,同时也支持直接使用Whisper原模型
,例如直接指定openai/whisper-large-v2
。--output_dir参数
指定的是转换后的CTranslate2模型
路径,--quantization参数
指定的是量化模型大小,不希望量化模型的可以直接去掉这个参数。
ct2-transformers-converter --model models/whisper-tiny-finetune --output_dir models/whisper-tiny-ct2 --copy_files tokenizer.json --quantization float16
执行以下程序进行加速语音识别,–audio_path参数指定的是要预测的音频路径。–model_path指定的是转换后的CTranslate2模型。其他更多的参数请查看这个程序。
python infer_ct2.py --audio_path=dataset/test.wav --model_path=models/whisper-tiny-ct2
输出结果如下:
{
"language": "zh",
"duration": 8.39,
"results": [
{
"start": 0.0,
"end": 8.39,
"text": "近几年不但我用书给女儿压岁也劝说亲朋友不要给女儿压岁钱而改送压岁书"
}
],
"text": "近几年不但我用书给女儿压岁也劝说亲朋友不要给女儿压岁钱而改送压岁书"
}
whisper.cpp
https://github.com/ggerganov/whisper.cpp
五、微调训练
安装环境
# Pytorch的GPU版本
conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.6 -c pytorch -c nvidia
# 依赖库
python -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
准备数据
训练的数据集如下,是一个jsonlines
的数据列表,也就是每一行都是一个JSON数据
,数据格式如下。Whisper
是支持有标点符号的,所以训练的数据集中可以带有标点符号。本项目提供了一个制作AIShell数据集
的程序aishell.py
,执行这个程序可以自动下载并生成如下列格式的训练集和测试集,注意: 这个程序可以通过指定AIShell
的压缩文件来跳过下载过程的,如果直接下载会非常慢,可以使用一些如迅雷等下载器下载该数据集,然后通过参数--filepath
指定下载的压缩文件路径,如/home/test/data_aishell.tgz
。如果不使用时间戳训练,可以不包含sentences部分
的数据。
{
"audio": {
"path": "dataset/0.wav"
},
"sentence": "近几年,不但我用书给女儿压岁,也劝说亲朋不要给女儿压岁钱,而改送压岁书。",
"sentences": [
{
"start": 0,
"end": 1.4,
"text": "近几年,"
},
{
"start": 1.42,
"end": 8.4,
"text": "不但我用书给女儿压岁,也劝说亲朋不要给女儿压岁钱,而改送压岁书。"
}
],
"duration": 7.37
}
微调模型
准备好数据之后,就可以开始微调模型了。训练最重要的两个参数分别是,--base_model
指定微调的Whisper模型
,这个参数值需要在HuggingFace
存在的,这个不需要提前下载,启动训练时可以自动下载,当然也可以提前下载,那么--base_model
指定就是路径,同时--local_files_only
设置为True
。第二个--output_path
是是训练时保存的Lora
检查点路径,因为我们使用Lora
来微调模型。如果想存足够的话,最好将–use_8bit
设置为False
,这样训练速度快很多。其他更多的参数请查看这个程序。
单卡训练
单卡训练命令如下,Windows系统
可以不添加CUDA_VISIBLE_DEVICES参数
。
CUDA_VISIBLE_DEVICES=0 python finetune.py --base_model=openai/whisper-tiny --output_dir=output/
多卡训练
多卡训练有两种方法,分别是torchrun
和accelerate
,开发者可以根据自己的习惯使用对应的方式。
使用torchrun
启动多卡训练,命令如下,通过-nproc_per_node
指定使用的显卡数量。torchrun --nproc_per_node=2 finetune.py --base_model=openai/whisper-tiny --output_dir=output/
使用accelerate
启动多卡训练,如果是第一次使用accelerate
,要配置训练参数,方式如下。
首先配置训练参数,过程是让开发者回答几个问题,基本都是默认就可以,但有几个参数需要看实际情况设置。
accelerate config
大概过程就是这样:
----------------------------------In which compute environment are you running?
This machine
----------------------------------Which type of machine are you using?
multi-GPU
How many different machines will you use (use more than 1 for multi-node training)? [1]:
Do you wish to optimize your script with torch dynamo?[yes/NO]:
Do you want to use DeepSpeed? [yes/NO]:
Do you want to use FullyShardedDataParallel? [yes/NO]:
Do you want to use Megatron-LM ? [yes/NO]:
How many GPU(s) should be used for distributed training? [1]:2
What GPU(s) (by id) should be used for training on this machine as a comma-seperated list? [all]:
----------------------------------Do you wish to use FP16 or BF16 (mixed precision)?
fp16
配置完成之后,可以使用以下命令查看配置。
accelerate env
开始训练命令如下。
accelerate launch finetune.py --base_model=openai/whisper-tiny --output_dir=output/
输出日志如下:
{'loss': 0.9098, 'learning_rate': 0.000999046843662503, 'epoch': 0.01}
{'loss': 0.5898, 'learning_rate': 0.0009970611012927184, 'epoch': 0.01}
{'loss': 0.5583, 'learning_rate': 0.0009950753589229333, 'epoch': 0.02}
{'loss': 0.5469, 'learning_rate': 0.0009930896165531485, 'epoch': 0.02}
{'loss': 0.5959, 'learning_rate': 0.0009911038741833634, 'epoch': 0.03}
合并模型
微调完成之后会有两个模型,第一个是Whisper基础模型
,第二个是Lora模型
,需要把这两个模型合并之后才能之后的操作。这个程序只需要传递两个参数,--lora_model
指定的是训练结束后保存的Lora模型路径,注意如何不是最后的checkpoint-final
后面还有adapter_model文件夹
,第二个--output_dir
是合并后模型的保存目录。
python merge_lora.py --lora_model=output/checkpoint-final --output_dir=models/
评估模型
执行以下程序进行评估模型,最重要的两个参数分别是。第一个--model_path
指定的是合并后的模型路径,同时也支持直接使用Whisper原模型
,例如直接指定openai/whisper-large-v2
,第二个是--metric
指定的是评估方法,例如有字错率cer
和词错率wer
。提示: 没有微调的模型,可能输出带有标点符号,影响准确率。其他更多的参数请查看这个程序。
python evaluation.py --model_path=models/whisper-tiny-finetune --metric=cer
预测
执行以下程序进行语音识别,这个使用transformers
直接调用微调后的模型或者Whisper原模型
预测,只适合推理短音频,长语音还是参考infer_ct2.py的使用方式。第一个--audio_path参数
指定的是要预测的音频路径。第二个--model_path
指定的是合并后的模型路径,同时也支持直接使用Whisper原模型,例如直接指定openai/whisper-large-v2
。其他更多的参数请查看这个程序。
python infer_tfs.py --audio_path=dataset/test.wav --model_path=models/whisper-tiny-finetune
六、部署
CTranslate2 Web部署
Web部署
同样是使用了CTranslate2
进行加速,转换模型方式看上面文档。--host
指定服务启动的地址,这里设置为0.0.0.0
,即任何地址都可以访问。--port
指定使用的端口号。--model_path
指定的是转换后的CTranslate2模型
。--num_workers
指定是使用多少个线程并发推理,这在Web部署
上很重要,当有多个并发访问是可以同时推理。其他更多的参数请查看这个程序。
python infer_server.py --host=0.0.0.0 --port=5000 --model_path=models/whisper-tiny-ct2 --num_workers=2
接口文档
目前提供两个接口,普通的识别接口/recognition
和流式返回结果/recognition_stream
,注意这个流式是指流式返回识别结果,同样是上传完整的音频,然后流式返回识别结果,这种方式针对长语音识别体验非常好。他们的文档接口是完全一致的,接口参数如下。
字段 | 是否必须 | 类型 | 默认值 | 说明 |
---|---|---|---|---|
audio | 是 | File | 要识别的音频文件 | |
to_simple | 否 | int | 1 | 是否繁体转简体 |
remove_pun | 否 | int | 0 | 是否移除标点符号 |
task | 否 | String | transcribe | 识别任务类型,支持transcribe和translate |
为了方便理解,这里提供了调用Web接口
的Python代码
,下面的是/recognition
的调用方式。
import requests
response = requests.post(url="http://127.0.0.1:5000/recognition",
files=[("audio", ("test.wav", open("dataset/test.wav", 'rb'), 'audio/wav'))],
json={"to_simple": 1, "remove_pun": 0, "task": "transcribe"}, timeout=20)
print(response.text)
下面的是/recognition_stream
的调用方式。
import json
import requests
response = requests.post(url="http://127.0.0.1:5000/recognition_stream",
files=[("audio", ("test.wav", open("dataset/test_long.wav", 'rb'), 'audio/wav'))],
json={"to_simple": 1, "remove_pun": 0, "task": "transcribe"}, stream=True, timeout=20)
for chunk in response.iter_lines(decode_unicode=False, delimiter=b"\0"):
if chunk:
result = json.loads(chunk.decode())
text = result["result"]
start = result["start"]
end = result["end"]
print(f"[{start} - {end}]:{text}")
whisper-asr-ebservice
https://github.com/ahmetoner/whisper-asr-webservice
七、文档
https://huggingface.co/openai/whisper-large-v2
模型下载:
large-v1:
large-v2: