1 概述
1.1 案例介绍
随着人工智能的发展,语音识别技术已成为连接人与数字世界的重要工具。本实验旨在构建一个基于云主机和 Whisper 语音识别系统的平台,利用云计算资源和先进的人工智能技术,为开发者提供便捷高效的开发环境。Whisper 语音识别系统是一种基于深度学习的语音识别技术。它使用了端到端的模型,能够将语音输入转换为文本输出。Whisper 采用了自注意力机制和卷积神经网络,能够更好地处理不同语音信号的变化和噪音。
通过本实验,开发者可以学习如何使用云计算资源优化模型训练流程、使用 Whisper_AI 进行语音识别处理、应用 LoRA 等微调技术提升模型性能。本实验还将帮助开发者掌握数据预处理、模型训练和结果评估等关键步骤。
1.2 适用对象
1.3 案例时间
本案例总时长预计 120 分钟。
1.4 案例流程
说明:
用户登录华为云开发者空间-Notebook 进行环境配置;
下载预训练数据集和测试数据集;
训练和微调 Whisper_base 语音识别模型;
推理模型实现语音识别。
1.5 资源总览
本案例预计花费 0 元。
2 环境配置
2.1 开发者空间昇腾 Notebook 资源配置
详细步骤请参考案例步骤 2.1。
2.2 环境配置
进入 Notebook 后,点击终端。
在终端输入以下命令完成数据集和库的下载。
pip install kagglehub
pip install datasets transformers librosa
pip install peft torch
pip install ffmpeg-python
复制代码
kagglehub:下载数据集;
datasets:支持多种格式的数据集,并提供方便的数据处理工具;
transformers:包含了大量预训练的语音处理模型;
librosa:一个用于音频分析的 Python 库,提供了音频信号处理的各个功能,如音频读取、特征提取等;
peft:提供了参数高效微调的方法,可以帮助在保持模型性能的同时减少微调所需的参数量;
torch:提供了灵活的张量计算和动态计算图功能;
ffmpeg:可以用于视频和音频的转换、剪辑、编码等操作。
3 下载数据集和预训练模型
3.1 下载预训练数据
新建文件夹,在左侧工程目录空白处鼠标右击新建文件夹,设置名称为 data。
新建文件,在 data 文件夹点击鼠标右键,选择创建文件,设置名称为 data.py。
将以下代码复制到 data.py 文件中,用来下载预训练数据。
import kagglehub
# Download latest version
path = kagglehub.dataset_download("tenffe/common-voice-zh-cn")
print("Path to dataset files:", path)
复制代码
返回终端,进入 data 目录下,运行 data.py 文件,执行预训练代码完成数据集下载。
下载完毕后在终端输入:pwd 获取当前路径。
将预训练语音数据移动到 data 文件的目录下。
mv /home/service/.cache/kagglehub/datasets/tenffe/common-voice-zh-cn/versions/1 /opt/huawei/edu-apaas/src/init/data
复制代码
3.2 下载测试数据
新建文件,在 data 文件夹点击鼠标右键,选择创建文件,设置名称为 data_ce.py
将以下代码复制到 data_ce.py 文件中,用来下载测试数据集。
import kagglehub
# Download latest version
path = kagglehub.dataset_download("shawnchile/voice-female-yuri")
print("Path to dataset files:", path)
复制代码
返回终端,运行 data_ce.py 文件,下载测试所需的数据集。
下载完毕后在 data 文件夹目录下新建 wavs 文件夹,并将测试所需的数据集移动到 wavs 文件夹内。
首先,获取 wavs 文件夹当前路径,终端进入到 wavs 文件夹下输入 pwd 获取当前路径。
获取到 wavs 文件夹路径后,将下载的测试数据集移动到 wavs 文件夹下。
mv /home/service/.cache/kagglehub/datasets/shawnchile/voice-female-yuri/versions/1 /opt/huawei/edu-apaas/src/init/data/wavs
复制代码
3.3 下载预训练模型
在 Notebook 主目录下创建文件夹,将文件夹名称设置为 pretrained_model,用来存放下载的预训练模型。
在终端进入到 pretrained_model 文件夹目录下,并将以下命令复制到终端进行预训练模型下载。
wget -P /opt/huawei/edu-apaas/src/init/pretrained_model wget https://dtse-mirrors.obs.cn-north-4.myhuaweicloud.com/case/0002/whisper_base.tar.gz
复制代码
下载完毕后进行压缩。
tar -zxvf whisper_base.tar.gz
复制代码
解压后内容如下。
4 语音识别
4.1 处理数据
选取 100 个样本,移除不需要的列,将数据统一调整为 16khz,提高模型训练效率,统一数据格式的一致性,将数据转化为模型可接受的输入格式。
在 pretrained_model 目录下新建 prepared_common_voice 文件夹,用来保存处理后的数据。
在 Notebook 主目录下创建文件夹,名称为 whisper_api。
在 whisper_api 文件夹内创建文件名为 preprocess_data.py。
将以下代码复制到 preprocess_data.py 文件中。
注:将以下路径进行更改
model_name_or_path:"/opt/huawei/edu-apaas/src/init/pretrained_model/whisper_base"(预训练模型路径);
dataset_name:"/opt/huawei/edu-apaas/src/init/data/1/common_voice_zh_CN"(训练数据集保存的文件路径);
prepared_dataset_path:"/opt/huawei/eduapaas/src/init/pretrained_model/prepared_common_voice"(创建的 preparde_common_voice 文件夹路径)。
import os
from datasets import load_from_disk, Audio
from transformers import WhisperFeatureExtractor, WhisperTokenizer, WhisperProcessor
# 配置参数
model_name_or_path = "/opt/huawei/edu-apaas/src/init/pretrained_model/whisper_base"
language = "chinese"
language_abbr = "zh"
task = "transcribe"
dataset_name = "/opt/huawei/edu-apaas/src/init/data/1/common_voice_zh_CN"
prepared_dataset_path = "/opt/huawei/edu-apaas/src/init/pretrained_model/prepared_common_voice"
# 加载数据集
common_voice = load_from_disk(dataset_name)
# 选择前1000个样本
common_voice['train'] = common_voice['train'].select(range(100))
if 'test' in common_voice:
common_voice['test'] = common_voice['test'].select(range(100))
if 'validation' in common_voice:
common_voice['validation'] = common_voice['validation'].select(range(100))
# 移除不需要的列
common_voice = common_voice.remove_columns(
["accent", "age", "client_id", "down_votes", "gender", "locale", "path", "segment", "up_votes"]
)
# 将采样率改为16kHz
common_voice = common_voice.cast_column("audio", Audio(sampling_rate=16000))
# 预处理音频数据和对应的文本
def prepare_dataset(batch):
audio = batch["audio"]
batch["input_features"] = feature_extractor(audio["array"], sampling_rate=audio["sampling_rate"]).input_features[0]
batch["labels"] = tokenizer(batch["sentence"]).input_ids
return batch
# 加载特征提取器和分词器
feature_extractor = WhisperFeatureExtractor.from_pretrained(model_name_or_path)
tokenizer = WhisperTokenizer.from_pretrained(model_name_or_path, language=language, task=task)
processor = WhisperProcessor.from_pretrained(model_name_or_path, language=language, task=task)
# 预处理数据集
common_voice = common_voice.map(prepare_dataset, remove_columns=common_voice.column_names["train"], num_proc=1)
# 保存预处理后的数据集
common_voice.save_to_disk(prepared_dataset_path)
复制代码
返回终端页面,进行 MP3 格式解码包的升级,将以下命令复制到终端中运行。
pip install --upgrade soundfile
复制代码
进入到 whisper_api 文件夹目录下,运行 preprocess_data.py。
cd whisper_api/
python preprocess_data.py
复制代码
4.2 设置 LoRA 参数
LoRA(Low-Rank Adaptation)是一种轻量级微调方法。它适用于在预训练模型上进行微调的一种技术。在传统的微调方法中,所有参数都会被更新,但这会导致计算和存储开销较大。相比之下,LoRA 通过将参数分解为两个低秩矩阵,只更新其中一个矩阵,从而减少了计算和存储开销。这种方法在保存模型性能的同时,大大降低了模型的复杂性。它在轻量级应用场景下具有很好的效果,可以提高模型的效率和可用性。
设置 LoRA 参数中,主要通过设置原始模型中低秩矩阵的大小以及缩放因子,用于控制 LoRA 更新速度,以及将 dropout 参数设置到 0.05 左右来增加模型的泛化能力。
将以下代码复制到终端中,进行 torch-NPU 下载。
pip install torch_npu -f https://ascend-repository.obs.cn-east-2.myhuaweicloud.com/ascend-toolkit/23.0.RC3/whl/npu-cpu/
复制代码
将以下命令复制到终端进行 transformers 升级。注:报错和警告可以忽略。
pip install --upgrade transformers
复制代码
在 whisper_api 文件夹中新建文件,名称为 load_model.py。
将以下代码复制到 load_model.py 文件中,用于设置 LoRA 参数的功能。
注:将以下路径进行修改:
model_name_or_path:"/opt/huawei/edu-apaas/src/init/pretrained_model/whisper_base"(预训练模型路径)。
from transformers import WhisperForConditionalGeneration, WhisperProcessor, WhisperTokenizer, AutoConfig
from peft import LoraConfig, get_peft_model
import os
import torch
# 禁用 safetensors
os.environ["TRANSFORMERS_SAFE_TENSORS"] = "false"
model_name_or_path = "/opt/huawei/edu-apaas/src/init/pretrained_model/whisper_base" # 加载模型配置
config = AutoConfig.from_pretrained(model_name_or_path)
# 手动加载模型文件
state_dict = torch.load(f"{model_name_or_path}/pytorch_model.bin", weights_only=True)
# 初始化模型
model = WhisperForConditionalGeneration(config)
# 尝试加载 state_dict,允许忽略缺失的键
model.load_state_dict(state_dict, strict=False)
# 打印模型信息
print(model)
# 定义 LoRA 配置
config = LoraConfig(r=32, lora_alpha=64, target_modules=["q_proj", "v_proj"], lora_dropout=0.05)
# 获取 LoRA 模型
model = get_peft_model(model, config)
# 打印可训练参数
model.print_trainable_parameters()
复制代码
运行 load_model.py 文件,完成 LoRA 参数设置。
4.3 微调模型
微调模型可以帮助模型学习到更多的任务相关特征,从而提高性能。通过特定的数据,可以使模型更好的在特定领域的语音数据,提高识别的准确性、改进性能。
在终端输入以下命令,解决依赖包冲突问题。注:报错和警告可以忽略。
pip install transformers==4.38.0 peft==0.10.0 accelerate==0.26.0 torch_npu==2.1.0
复制代码
在 pretrained_model 文件夹下创建 checkpoint_1000_samples 文件夹保存 LoRA 模型。
在 whisper_api 文件夹下创建文件名为 train_model.py。
将以下代码复制到 train_model.py 文件中,进行模型微调训练。
注:将以下路径进行修改:
model_name_or_path:"/opt/huawei/edu-apaas/src/init/pretrained_model/whisper_base"(修改为预训练模型路径);
prepared_dataset_path:"/opt/huawei/edu-apaas/src/init/pretrained_model/prepared_common_voice"(修改为保存预处理后的数据文件路径);
from transformers import Seq2SeqTrainingArguments, Seq2SeqTrainer
from dataclasses import dataclass
from typing import Any, Dict, List, Union
from transformers import WhisperFeatureExtractor, WhisperTokenizer, WhisperProcessor
from datasets import load_from_disk # 导入 load_from_disk 函数
import torch
from peft import LoraConfig, get_peft_model, PeftModel
@dataclass
class DataCollatorSpeechSeq2SeqWithPadding:
def __init__(self, processor: Any):
self.processor = processor
def __call__(self, features: List[Dict[str, Union[List[int], torch.Tensor]]]) -> Dict[str, torch.Tensor]:
input_features = [{"input_features": feature["input_features"]} for feature in features]
batch = self.processor.feature_extractor.pad(input_features, return_tensors="pt")
label_features = [{"input_ids": feature["labels"]} for feature in features]
labels_batch = self.processor.tokenizer.pad(label_features, return_tensors="pt")
labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)
if (labels[:, 0] == self.processor.tokenizer.bos_token_id).all().cpu().item():
labels = labels[:, 1:]
batch["labels"] = labels
return batch
# 配置参数
model_name_or_path = "/opt/huawei/edu-apaas/src/init/pretrained_model/whisper_base"
language = "chinese"
task = "transcribe"
prepared_dataset_path = "/opt/huawei/edu-apaas/src/init/pretrained_model/prepared_common_voice" # 预处理后的数据集路径
# 加载特征提取器和分词器
feature_extractor = WhisperFeatureExtractor.from_pretrained(model_name_or_path)
tokenizer = WhisperTokenizer.from_pretrained(model_name_or_path, language=language, task=task)
processor = WhisperProcessor.from_pretrained(model_name_or_path, language=language, task=task)
# 加载预处理后的数据集
common_voice = load_from_disk(prepared_dataset_path)
# 定义 LoRA 配置
lora_config = LoraConfig(
r=8, # LoRA attention dimension
lora_alpha=32, # Alpha scaling
target_modules=["q_proj", "v_proj"], # Target modules to apply LoRA
lora_dropout=0.1, # Dropout probability for LoRA layers
)
# 加载模型
from transformers import WhisperForConditionalGeneration
model = WhisperForConditionalGeneration.from_pretrained(model_name_or_path)
# 将 LoRA 配置应用到模型
model = get_peft_model(model, lora_config)
# 设置 Trainer 参数
training_args = Seq2SeqTrainingArguments(
output_dir="your-name/int8-whisper-base-v2-asr",
per_device_train_batch_size=2,
gradient_accumulation_steps=1,
learning_rate=2e-3,
warmup_steps=50,
num_train_epochs=3,
evaluation_strategy="epoch", # 需要 transformers ≥ 4.0.0
fp16=True,
per_device_eval_batch_size=4,
generation_max_length=128,
logging_steps=25,
remove_unused_columns=False,
label_names=["labels"],
no_cuda=False, # 允许使用 NPU/GPU
)
# 创建数据收集器
data_collator = DataCollatorSpeechSeq2SeqWithPadding(processor=processor)
# 创建 Trainer
trainer = Seq2SeqTrainer(
args=training_args,
model=model,
train_dataset=common_voice["train"].select(range(100)), # 仅使用前100个样本进行训练
eval_dataset=common_voice["test"].select(range(100)), # 仅使用前100个样本进行验证
data_collator=data_collator,
tokenizer=processor.feature_extractor,
)
# 开始训练
model.config.use_cache = False
trainer.train()
# 保存 LoRA 模型
model.save_pretrained("/opt/huawei/edu-apaas/src/init/pretrained_model/checkpoint_1000_samples")
复制代码
运行 train_model.py 文件,实现模型微调。
4.4 推理模型实现语音识别
模型推理是指已经训练好的模型对新的数据进行预测或生成的过程。确保在特定领域识别的准确性,具体的流程包括:加载 LoRA 模型配置、加载基础模型、构建 LoRA 模型、合并模型、加载分词器和处理器、构建 pipeline、加载音频文件、进行推理、保存结果。
在 Notebook 主目录下创建文件夹,名称为 output,用来后续保存输出内容。
在 whisper_api 文件夹中创建文件,名称设置为 save_and_infer.py。
注意:将以下路径进行修改:
peft_model_id:"/opt/huawei/edu-apaas/src/init/pretrained_model/checkpoint_1000_samples"(LoRA 模型保存的路径),
output_directory:"/opt/huawei/edu-apaas/src/init/output"(创建的 output 文件夹路径)。
from transformers import WhisperForConditionalGeneration, WhisperTokenizer, WhisperProcessor
from peft import PeftModel, PeftConfig
from transformers import AutomaticSpeechRecognitionPipeline
import torch
import os
import json
# 配置参数
peft_model_id = "/opt/huawei/edu-apaas/src/init/pretrained_model/checkpoint_1000_samples"
language = "chinese"
task = "transcribe"
output_directory = "/opt/huawei/edu-apaas/src/init/output" # 输出文件夹路径
# 确保输出目录存在
os.makedirs(output_directory, exist_ok=True)
# 加载 LoRA 模型配置
peft_config = PeftConfig.from_pretrained(peft_model_id)
# 加载基础模型
model = WhisperForConditionalGeneration.from_pretrained(
peft_config.base_model_name_or_path
)
# 基于基础模型和 LoRA 模型路径构建 LoRA 模型
model = PeftModel.from_pretrained(model, peft_model_id)
# 将 PeftModel 转换为普通的 WhisperForConditionalGeneration 模型
model = model.merge_and_unload()
# 加载分词器(处理文本)和处理器(封装特征抽取器和分词器)、以及特征抽取器(处理音频)
tokenizer = WhisperTokenizer.from_pretrained(peft_config.base_model_name_or_path, language=language, task=task)
processor = WhisperProcessor.from_pretrained(peft_config.base_model_name_or_path, language=language, task=task)
feature_extractor = processor.feature_extractor
forced_decoder_ids = processor.get_decoder_prompt_ids(language=language, task=task)
# 构建一个 pipeline 进行测试
pipeline = AutomaticSpeechRecognitionPipeline(model=model, tokenizer=tokenizer, feature_extractor=feature_extractor)
# 测试音频文件路径
audio_directory = "/opt/huawei/edu-apaas/src/init/data/wavs/1/wavs"
# 获取目录下的所有 .wav 文件
audio_files = [os.path.join(audio_directory, f) for f in os.listdir(audio_directory) if f.endswith('.wav')]
# 只处理前100个文件
audio_files = audio_files[:100]
# 存储结果的列表
results = []
# 遍历所有音频文件并进行语音识别
for audio_file in audio_files:
with torch.no_grad():
text = pipeline(audio_file, generate_kwargs={"forced_decoder_ids": forced_decoder_ids}, max_new_tokens=255)["text"]
results.append({"file": audio_file, "text": text})
print(f"Transcribed text for {audio_file}: {text}")
# 将结果保存到 JSON 文件中
output_file = os.path.join(output_directory, "transcription_results.json")
with open(output_file, "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=4)
print(f"Results saved to {output_file}")
复制代码
在终端输入以下命令进行模型测试。
注:运行结果较慢,请耐心等待,终端会实时输出转换结果。
至此,LoRA 微调 whisper_base 实现语音识别到此结束。
评论