From cd8b3597ee33415e6125b96e02f011cd3ea78eaf Mon Sep 17 00:00:00 2001 From: ModelHub XC Date: Tue, 26 May 2026 11:35:27 +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-arabic Source: Original Platform --- .gitattributes | 17 ++++ README.md | 200 +++++++++++++++++++++++++++++++++++++++ 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, 309 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..4b4eeda --- /dev/null +++ b/README.md @@ -0,0 +1,200 @@ +--- +language: ar +datasets: +- common_voice +- arabic_speech_corpus +metrics: +- wer +- cer +tags: +- audio +- automatic-speech-recognition +- speech +- xlsr-fine-tuning-week +license: apache-2.0 +model-index: +- name: XLSR Wav2Vec2 Arabic by Jonatas Grosman + results: + - task: + name: Speech Recognition + type: automatic-speech-recognition + dataset: + name: Common Voice ar + type: common_voice + args: ar + metrics: + - name: Test WER + type: wer + value: 39.59 + - name: Test CER + type: cer + value: 18.18 +--- + +# Fine-tuned XLSR-53 large model for speech recognition in Arabic + +Fine-tuned [facebook/wav2vec2-large-xlsr-53](https://huggingface.co/facebook/wav2vec2-large-xlsr-53) on Arabic using the train and validation splits of [Common Voice 6.1](https://huggingface.co/datasets/common_voice) and [Arabic Speech Corpus](https://huggingface.co/datasets/arabic_speech_corpus). +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-arabic") +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 = "ar" +MODEL_ID = "jonatasgrosman/wav2vec2-large-xlsr-53-arabic" +SAMPLES = 10 + +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 Arabic 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 = "ar" +MODEL_ID = "jonatasgrosman/wav2vec2-large-xlsr-53-arabic" +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-05-14). 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-arabic | **39.59%** | **18.18%** | +| bakrianoo/sinai-voice-ar-stt | 45.30% | 21.84% | +| othrif/wav2vec2-large-xlsr-arabic | 45.93% | 20.51% | +| kmfoda/wav2vec2-large-xlsr-arabic | 54.14% | 26.07% | +| mohammed/wav2vec2-large-xlsr-arabic | 56.11% | 26.79% | +| anas/wav2vec2-large-xlsr-arabic | 62.02% | 27.09% | +| elgeish/wav2vec2-large-xlsr-53-arabic | 100.00% | 100.56% | + +## Citation +If you want to cite this model you can use this: + +```bibtex +@misc{grosman2021xlsr53-large-arabic, + title={Fine-tuned {XLSR}-53 large model for speech recognition in {A}rabic}, + author={Grosman, Jonatas}, + howpublished={\url{https://huggingface.co/jonatasgrosman/wav2vec2-large-xlsr-53-arabic}}, + year={2021} +} +``` \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..06c9472 --- /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": 51 +} diff --git a/flax_model.msgpack b/flax_model.msgpack new file mode 100644 index 0000000..29b4a47 --- /dev/null +++ b/flax_model.msgpack @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b44a67c277854fbcd96179ee8bfedb9f03f3826efc2af35f8eb9b964fd0df2b1 +size 1261979372 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..62e06a8 --- /dev/null +++ b/pytorch_model.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0b26f6d9d3edfde1784aef863c192a8cc1e438a23b45910ab648531ebe1857b +size 1262142936 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..a0572dd --- /dev/null +++ b/vocab.json @@ -0,0 +1 @@ +{"": 0, "": 1, "": 2, "": 3, "|": 4, "-": 5, "ء": 6, "آ": 7, "أ": 8, "ؤ": 9, "إ": 10, "ئ": 11, "ا": 12, "ب": 13, "ة": 14, "ت": 15, "ث": 16, "ج": 17, "ح": 18, "خ": 19, "د": 20, "ذ": 21, "ر": 22, "ز": 23, "س": 24, "ش": 25, "ص": 26, "ض": 27, "ط": 28, "ظ": 29, "ع": 30, "غ": 31, "ـ": 32, "ف": 33, "ق": 34, "ك": 35, "ل": 36, "م": 37, "ن": 38, "ه": 39, "و": 40, "ى": 41, "ي": 42, "ً": 43, "ٌ": 44, "ٍ": 45, "َ": 46, "ُ": 47, "ِ": 48, "ّ": 49, "ْ": 50} \ No newline at end of file