From 75a92ceb6476a5a2ea03480f69e612001438bce3 Mon Sep 17 00:00:00 2001 From: ModelHub XC Date: Tue, 26 May 2026 11:35:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=8C=E7=94=B1ModelHub=20XC=E7=A4=BE=E5=8C=BA=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Model: jonatasgrosman/wav2vec2-large-xlsr-53-persian Source: Original Platform --- .gitattributes | 17 ++++ README.md | 195 +++++++++++++++++++++++++++++++++++++++ config.json | 76 +++++++++++++++ flax_model.msgpack | 3 + preprocessor_config.json | 8 ++ pytorch_model.bin | 3 + special_tokens_map.json | 1 + vocab.json | 1 + 8 files changed, 304 insertions(+) create mode 100644 .gitattributes create mode 100644 README.md create mode 100644 config.json create mode 100644 flax_model.msgpack create mode 100644 preprocessor_config.json create mode 100644 pytorch_model.bin create mode 100644 special_tokens_map.json create mode 100644 vocab.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d699711 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +*.bin.* filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tar.gz filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000..715f7e2 --- /dev/null +++ b/README.md @@ -0,0 +1,195 @@ +--- +language: fa +datasets: +- common_voice +metrics: +- wer +- cer +tags: +- audio +- automatic-speech-recognition +- speech +- xlsr-fine-tuning-week +license: apache-2.0 +model-index: +- name: XLSR Wav2Vec2 Persian by Jonatas Grosman + results: + - task: + name: Speech Recognition + type: automatic-speech-recognition + dataset: + name: Common Voice fa + type: common_voice + args: fa + metrics: + - name: Test WER + type: wer + value: 30.12 + - name: Test CER + type: cer + value: 7.37 +--- + +# Fine-tuned XLSR-53 large model for speech recognition in Persian + +Fine-tuned [facebook/wav2vec2-large-xlsr-53](https://huggingface.co/facebook/wav2vec2-large-xlsr-53) on Persian using the train and validation splits of [Common Voice 6.1](https://huggingface.co/datasets/common_voice). +When using this model, make sure that your speech input is sampled at 16kHz. + +This model has been fine-tuned thanks to the GPU credits generously given by the [OVHcloud](https://www.ovhcloud.com/en/public-cloud/ai-training/) :) + +The script used for training can be found here: https://github.com/jonatasgrosman/wav2vec2-sprint + +## Usage + +The model can be used directly (without a language model) as follows... + +Using the [HuggingSound](https://github.com/jonatasgrosman/huggingsound) library: + +```python +from huggingsound import SpeechRecognitionModel + +model = SpeechRecognitionModel("jonatasgrosman/wav2vec2-large-xlsr-53-persian") +audio_paths = ["/path/to/file.mp3", "/path/to/another_file.wav"] + +transcriptions = model.transcribe(audio_paths) +``` + +Writing your own inference script: + +```python +import torch +import librosa +from datasets import load_dataset +from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor + +LANG_ID = "fa" +MODEL_ID = "jonatasgrosman/wav2vec2-large-xlsr-53-persian" +SAMPLES = 5 + +test_dataset = load_dataset("common_voice", LANG_ID, split=f"test[:{SAMPLES}]") + +processor = Wav2Vec2Processor.from_pretrained(MODEL_ID) +model = Wav2Vec2ForCTC.from_pretrained(MODEL_ID) + +# Preprocessing the datasets. +# We need to read the audio files as arrays +def speech_file_to_array_fn(batch): + speech_array, sampling_rate = librosa.load(batch["path"], sr=16_000) + batch["speech"] = speech_array + batch["sentence"] = batch["sentence"].upper() + return batch + +test_dataset = test_dataset.map(speech_file_to_array_fn) +inputs = processor(test_dataset["speech"], sampling_rate=16_000, return_tensors="pt", padding=True) + +with torch.no_grad(): + logits = model(inputs.input_values, attention_mask=inputs.attention_mask).logits + +predicted_ids = torch.argmax(logits, dim=-1) +predicted_sentences = processor.batch_decode(predicted_ids) + +for i, predicted_sentence in enumerate(predicted_sentences): + print("-" * 100) + print("Reference:", test_dataset[i]["sentence"]) + print("Prediction:", predicted_sentence) +``` + +| Reference | Prediction | +| ------------- | ------------- | +| از مهمونداری کنار بکشم | از مهمانداری کنار بکشم | +| برو از مهرداد بپرس. | برو از ماقدعاد به پرس | +| خب ، تو چیكار می كنی؟ | خوب تو چیکار می کنی | +| مسقط پایتخت عمان در عربی به معنای محل سقوط است | مسقط پایتخت عمان در عربی به بعنای محل سقوط است | +| آه، نه اصلاُ! | اهنه اصلا | +| توانست | توانست | +| قصیده فن شعر میگوید ای دوستان | قصیده فن شعر میگوید ایدوستون | +| دو استایل متفاوت دارین | دوبوست داریل و متفاوت بری | +| دو روز قبل از کریسمس ؟ | اون مفتود پش پشش | +| ساعت های کاری چیست؟ | این توری که موشیکل خب | + +## Evaluation + +The model can be evaluated as follows on the Persian test data of Common Voice. + +```python +import torch +import re +import librosa +from datasets import load_dataset, load_metric +from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor + +LANG_ID = "fa" +MODEL_ID = "jonatasgrosman/wav2vec2-large-xlsr-53-persian" +DEVICE = "cuda" + +CHARS_TO_IGNORE = [",", "?", "¿", ".", "!", "¡", ";", ";", ":", '""', "%", '"', "�", "ʿ", "·", "჻", "~", "՞", + "؟", "،", "।", "॥", "«", "»", "„", "“", "”", "「", "」", "‘", "’", "《", "》", "(", ")", "[", "]", + "{", "}", "=", "`", "_", "+", "<", ">", "…", "–", "°", "´", "ʾ", "‹", "›", "©", "®", "—", "→", "。", + "、", "﹂", "﹁", "‧", "~", "﹏", ",", "{", "}", "(", ")", "[", "]", "【", "】", "‥", "〽", + "『", "』", "〝", "〟", "⟨", "⟩", "〜", ":", "!", "?", "♪", "؛", "/", "\\", "º", "−", "^", "ʻ", "ˆ"] + +test_dataset = load_dataset("common_voice", LANG_ID, split="test") + +wer = load_metric("wer.py") # https://github.com/jonatasgrosman/wav2vec2-sprint/blob/main/wer.py +cer = load_metric("cer.py") # https://github.com/jonatasgrosman/wav2vec2-sprint/blob/main/cer.py + +chars_to_ignore_regex = f"[{re.escape(''.join(CHARS_TO_IGNORE))}]" + +processor = Wav2Vec2Processor.from_pretrained(MODEL_ID) +model = Wav2Vec2ForCTC.from_pretrained(MODEL_ID) +model.to(DEVICE) + +# Preprocessing the datasets. +# We need to read the audio files as arrays +def speech_file_to_array_fn(batch): + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + speech_array, sampling_rate = librosa.load(batch["path"], sr=16_000) + batch["speech"] = speech_array + batch["sentence"] = re.sub(chars_to_ignore_regex, "", batch["sentence"]).upper() + return batch + +test_dataset = test_dataset.map(speech_file_to_array_fn) + +# Preprocessing the datasets. +# We need to read the audio files as arrays +def evaluate(batch): + inputs = processor(batch["speech"], sampling_rate=16_000, return_tensors="pt", padding=True) + + with torch.no_grad(): + logits = model(inputs.input_values.to(DEVICE), attention_mask=inputs.attention_mask.to(DEVICE)).logits + + pred_ids = torch.argmax(logits, dim=-1) + batch["pred_strings"] = processor.batch_decode(pred_ids) + return batch + +result = test_dataset.map(evaluate, batched=True, batch_size=8) + +predictions = [x.upper() for x in result["pred_strings"]] +references = [x.upper() for x in result["sentence"]] + +print(f"WER: {wer.compute(predictions=predictions, references=references, chunk_size=1000) * 100}") +print(f"CER: {cer.compute(predictions=predictions, references=references, chunk_size=1000) * 100}") +``` + +**Test Result**: + +In the table below I report the Word Error Rate (WER) and the Character Error Rate (CER) of the model. I ran the evaluation script described above on other models as well (on 2021-04-22). Note that the table below may show different results from those already reported, this may have been caused due to some specificity of the other evaluation scripts used. + +| Model | WER | CER | +| ------------- | ------------- | ------------- | +| jonatasgrosman/wav2vec2-large-xlsr-53-persian | **30.12%** | **7.37%** | +| m3hrdadfi/wav2vec2-large-xlsr-persian-v2 | 33.85% | 8.79% | +| m3hrdadfi/wav2vec2-large-xlsr-persian | 34.37% | 8.98% | + +## Citation +If you want to cite this model you can use this: + +```bibtex +@misc{grosman2021xlsr53-large-persian, + title={Fine-tuned {XLSR}-53 large model for speech recognition in {P}ersian}, + author={Grosman, Jonatas}, + howpublished={\url{https://huggingface.co/jonatasgrosman/wav2vec2-large-xlsr-53-persian}}, + year={2021} +} +``` \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..428a17c --- /dev/null +++ b/config.json @@ -0,0 +1,76 @@ +{ + "_name_or_path": "facebook/wav2vec2-large-xlsr-53", + "activation_dropout": 0.05, + "apply_spec_augment": true, + "architectures": [ + "Wav2Vec2ForCTC" + ], + "attention_dropout": 0.1, + "bos_token_id": 1, + "conv_bias": true, + "conv_dim": [ + 512, + 512, + 512, + 512, + 512, + 512, + 512 + ], + "conv_kernel": [ + 10, + 3, + 3, + 3, + 3, + 2, + 2 + ], + "conv_stride": [ + 5, + 2, + 2, + 2, + 2, + 2, + 2 + ], + "ctc_loss_reduction": "mean", + "ctc_zero_infinity": true, + "do_stable_layer_norm": true, + "eos_token_id": 2, + "feat_extract_activation": "gelu", + "feat_extract_dropout": 0.0, + "feat_extract_norm": "layer", + "feat_proj_dropout": 0.05, + "final_dropout": 0.0, + "gradient_checkpointing": true, + "hidden_act": "gelu", + "hidden_dropout": 0.05, + "hidden_size": 1024, + "initializer_range": 0.02, + "intermediate_size": 4096, + "layer_norm_eps": 1e-05, + "layerdrop": 0.05, + "mask_channel_length": 10, + "mask_channel_min_space": 1, + "mask_channel_other": 0.0, + "mask_channel_prob": 0.0, + "mask_channel_selection": "static", + "mask_feature_length": 10, + "mask_feature_prob": 0.0, + "mask_time_length": 10, + "mask_time_min_space": 1, + "mask_time_other": 0.0, + "mask_time_prob": 0.05, + "mask_time_selection": "static", + "model_type": "wav2vec2", + "num_attention_heads": 16, + "num_conv_pos_embedding_groups": 16, + "num_conv_pos_embeddings": 128, + "num_feat_extract_layers": 7, + "num_hidden_layers": 24, + "pad_token_id": 0, + "transformers_version": "4.5.0.dev0", + "vocab_size": 67 +} diff --git a/flax_model.msgpack b/flax_model.msgpack new file mode 100644 index 0000000..0b86665 --- /dev/null +++ b/flax_model.msgpack @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1c25fc4a3db03fb9610f8d954703e5b1497168dac2d4a5e67eaf1e400badb1f +size 1262044974 diff --git a/preprocessor_config.json b/preprocessor_config.json new file mode 100644 index 0000000..0886a48 --- /dev/null +++ b/preprocessor_config.json @@ -0,0 +1,8 @@ +{ + "do_normalize": true, + "feature_size": 1, + "padding_side": "right", + "padding_value": 0.0, + "return_attention_mask": true, + "sampling_rate": 16000 +} diff --git a/pytorch_model.bin b/pytorch_model.bin new file mode 100644 index 0000000..caa437a --- /dev/null +++ b/pytorch_model.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b859c7f562a2cc3c6002c2eb5178b66777406c4fccf53f196ead46a4f6c4796 +size 1262208535 diff --git a/special_tokens_map.json b/special_tokens_map.json new file mode 100644 index 0000000..25bc396 --- /dev/null +++ b/special_tokens_map.json @@ -0,0 +1 @@ +{"bos_token": "", "eos_token": "", "unk_token": "", "pad_token": ""} \ No newline at end of file diff --git a/vocab.json b/vocab.json new file mode 100644 index 0000000..85f8f13 --- /dev/null +++ b/vocab.json @@ -0,0 +1 @@ +{"": 0, "": 1, "": 2, "": 3, "|": 4, "٬": 5, "و": 6, "ـ": 7, "ئ": 8, "ل": 9, "ج": 10, "ک": 11, "R": 12, "ِ": 13, "ع": 14, "َ": 15, "م": 16, "ض": 17, "-": 18, "I": 19, "F": 20, "ذ": 21, "ن": 22, "ژ": 23, "A": 24, "ش": 25, "ث": 26, "Y": 27, "د": 28, "ر": 29, "ّ": 30, "أ": 31, "ق": 32, "ب": 33, "ح": 34, "ظ": 35, "پ": 36, "ت": 37, "خ": 38, "غ": 39, "ط": 40, "ك": 41, "ي": 42, "E": 43, "Ā": 44, "؛": 45, "ی": 46, "چ": 47, "ه": 48, "M": 49, "ف": 50, "آ": 51, "ز": 52, "ص": 53, "س": 54, "گ": 55, "N": 56, "ُ": 57, "T": 58, "S": 59, "Š": 60, "ٔ": 61, "B": 62, "ء": 63, "ً": 64, "ا": 65, "ى": 66} \ No newline at end of file