صقل Wav2Vec2 برأس LM

عرض على TensorFlow.org تشغيل في Google Colab عرض على جيثب تحميل دفتر انظر نموذج TF Hub

في هذه المفكرة، ونحن سوف تحميل نموذج wav2vec2 المدربين قبل من TFHub وسوف صقل على LibriSpeech بيانات بإلحاق رئيس لغة النمذجة (LM) فوق الجزء العلوي من نموذجنا المدربين قبل. المهمة الأساسية هي لبناء نموذج للالتعرف على الكلام التلقائي أي إعطاء بعض الكلام، ونموذج يجب أن يكون قادرا على تدوين ذلك في النص.

اعداد

قبل تشغيل هذا الكمبيوتر الدفتري، يرجى التأكد من أنك على GPU وقت التشغيل ( Runtime > Change runtime type > GPU ). سوف الخلية التالية تثبيت gsoc-wav2vec2 حزمة وتبعياته.

pip3 install -q git+https://github.com/vasudevgupta7/gsoc-wav2vec2@main
sudo apt-get install -y libsndfile1-dev
pip3 install -q SoundFile
The following packages were automatically installed and are no longer required:
  linux-gcp-5.4-headers-5.4.0-1040 linux-gcp-5.4-headers-5.4.0-1043
  linux-gcp-5.4-headers-5.4.0-1044 linux-gcp-5.4-headers-5.4.0-1049
  linux-headers-5.4.0-1049-gcp linux-image-5.4.0-1049-gcp
  linux-modules-5.4.0-1049-gcp linux-modules-extra-5.4.0-1049-gcp
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  libflac-dev libogg-dev libvorbis-dev libvorbisfile3
The following NEW packages will be installed:
  libflac-dev libogg-dev libsndfile1-dev libvorbis-dev libvorbisfile3
0 upgraded, 5 newly installed, 0 to remove and 143 not upgraded.
Need to get 1040 kB of archives.
After this operation, 4481 kB of additional disk space will be used.
Get:1 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic/main amd64 libogg-dev amd64 1.3.2-1 [156 kB]
Get:2 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic/main amd64 libflac-dev amd64 1.3.2-1 [260 kB]
Get:3 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic/main amd64 libvorbisfile3 amd64 1.3.5-4.2 [16.0 kB]
Get:4 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic/main amd64 libvorbis-dev amd64 1.3.5-4.2 [321 kB]
Get:5 http://asia-east1.gce.archive.ubuntu.com/ubuntu bionic-updates/main amd64 libsndfile1-dev amd64 1.0.28-4ubuntu0.18.04.2 [287 kB]
Fetched 1040 kB in 1s (1041 kB/s)
Selecting previously unselected package libogg-dev:amd64.
(Reading database ... 282211 files and directories currently installed.)
Preparing to unpack .../libogg-dev_1.3.2-1_amd64.deb ...
Unpacking libogg-dev:amd64 (1.3.2-1) ...
Selecting previously unselected package libflac-dev:amd64.
Preparing to unpack .../libflac-dev_1.3.2-1_amd64.deb ...
Unpacking libflac-dev:amd64 (1.3.2-1) ...
Selecting previously unselected package libvorbisfile3:amd64.
Preparing to unpack .../libvorbisfile3_1.3.5-4.2_amd64.deb ...
Unpacking libvorbisfile3:amd64 (1.3.5-4.2) ...
Selecting previously unselected package libvorbis-dev:amd64.
Preparing to unpack .../libvorbis-dev_1.3.5-4.2_amd64.deb ...
Unpacking libvorbis-dev:amd64 (1.3.5-4.2) ...
Selecting previously unselected package libsndfile1-dev.
Preparing to unpack .../libsndfile1-dev_1.0.28-4ubuntu0.18.04.2_amd64.deb ...
Unpacking libsndfile1-dev (1.0.28-4ubuntu0.18.04.2) ...
Setting up libvorbisfile3:amd64 (1.3.5-4.2) ...
Setting up libogg-dev:amd64 (1.3.2-1) ...
Setting up libvorbis-dev:amd64 (1.3.5-4.2) ...
Setting up libflac-dev:amd64 (1.3.2-1) ...
Setting up libsndfile1-dev (1.0.28-4ubuntu0.18.04.2) ...
Processing triggers for libc-bin (2.27-3ubuntu1.2) ...

إعداد النموذج باستخدام TFHub

سنبدأ باستيراد بعض المكتبات / الوحدات.

import os

import tensorflow as tf
import tensorflow_hub as hub
from wav2vec2 import Wav2Vec2Config

config = Wav2Vec2Config()

print("TF version:", tf.__version__)
TF version: 2.7.0

أولا، فإننا سوف تحميل نموذجنا من TFHub وسيتم التفاف توقيعنا نموذج مع hub.KerasLayer لتكون قادرة على استخدام هذا النموذج مثل أي طبقة Keras أخرى. لحسن الحظ، hub.KerasLayer يمكن القيام به سواء في خط فقط 1.

pretrained_layer = hub.KerasLayer("https://tfhub.dev/vasudevgupta7/wav2vec2/1", trainable=True)

يمكنك الرجوع إلى هذا السيناريو في حال كنت مهتما في البرنامج النصي تصدير النموذج. الكائن pretrained_layer هي النسخة جمدت من Wav2Vec2Model . تم تحويل هذه الأوزان المدربين قبل من HuggingFace PyTorch الأوزان مسبقا المدربين باستخدام هذا البرنامج النصي .

في الأصل ، تم تدريب wav2vec2 مسبقًا باستخدام نهج نمذجة اللغة المقنعة بهدف تحديد تمثيل الكلام الكامن الكمي الحقيقي لخطوة زمنية مقنعة. يمكنك قراءة المزيد عن هدف التدريب في paper- wav2vec 2.0: إطار للتعلم الذاتي تحت إشراف ممثليات الكلام .

الآن ، سنقوم بتعريف عدد قليل من الثوابت والمعلمات الفائقة التي ستكون مفيدة في الخلايا القليلة التالية. AUDIO_MAXLEN تم تعيين عمدا إلى 246000 كما توقيع نموذج لا يقبل إلا ثابت طول تسلسل 246000 .

AUDIO_MAXLEN = 246000
LABEL_MAXLEN = 256
BATCH_SIZE = 2

في الخلية التالية، ونحن سوف التفاف pretrained_layer وطبقة كثيفة (رئيس LM) مع API الوظيفي Keras ل .

inputs = tf.keras.Input(shape=(AUDIO_MAXLEN,))
hidden_states = pretrained_layer(inputs)
outputs = tf.keras.layers.Dense(config.vocab_size)(hidden_states)

model = tf.keras.Model(inputs=inputs, outputs=outputs)

طبقة كثيفة (المحددة أعلاه) هو وجود البعد إخراج vocab_size كما نريد للتنبؤ الاحتمالات من كل رمز في المفردات في كل خطوة الوقت.

إقامة حالة التدريب

في TensorFlow، مبنية الأوزان نموذج فقط عندما model.call أو model.build يسمى للمرة الأولى، وبالتالي فإن الخلية التالية ستبني الأوزان نموذج بالنسبة لنا. وعلاوة على ذلك، فإننا سوف تكون قيد التشغيل model.summary() للتحقق من عدد من المعلمات المدربة.

model(tf.random.uniform(shape=(BATCH_SIZE, AUDIO_MAXLEN)))
model.summary()
Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 246000)]          0         
                                                                 
 keras_layer (KerasLayer)    (None, 768, 768)          94371712  
                                                                 
 dense (Dense)               (None, 768, 32)           24608     
                                                                 
=================================================================
Total params: 94,396,320
Trainable params: 94,396,320
Non-trainable params: 0
_________________________________________________________________

الآن، نحن بحاجة إلى تحديد loss_fn ومحسن لتكون قادرة على تدريب النموذج. الخلية التالية ستفعل ذلك لنا. سنكون باستخدام Adam محسن البساطة. CTCLoss هو نوع الخسارة المشترك الذي يتم استخدامه لمهام (مثل ASR ) حيث المدخلات أجزاء فرعية لا يمكن أن تنسجم بسهولة مع الانتاج دون أجزاء. يمكنك قراءة المزيد حول CTC الخسارة من هذا مذهلة بلوق وظيفة .

CTCLoss (من gsoc-wav2vec2 حزمة) تقبل 3 الحجج: config ، model_input_shape و division_factor . إذا division_factor=1 ، ثم فقدان ببساطة الحصول على تلخيص، لذلك تمرير division_factor وفقا لذلك للحصول على دفعة تنته يعني.

from wav2vec2 import CTCLoss

LEARNING_RATE = 5e-5

loss_fn = CTCLoss(config, (BATCH_SIZE, AUDIO_MAXLEN), division_factor=BATCH_SIZE)
optimizer = tf.keras.optimizers.Adam(LEARNING_RATE)

تحميل البيانات والمعالجة المسبقة

دعونا الآن تحميل مجموعة البيانات LibriSpeech من الموقع الرسمي وإعداده.

wget https://www.openslr.org/resources/12/dev-clean.tar.gz -P ./data/train/
tar -xf ./data/train/dev-clean.tar.gz -C ./data/train/
--2021-11-05 11:43:09--  https://www.openslr.org/resources/12/dev-clean.tar.gz
Resolving www.openslr.org (www.openslr.org)... 46.101.158.64
Connecting to www.openslr.org (www.openslr.org)|46.101.158.64|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 337926286 (322M) [application/x-gzip]
Saving to: ‘./data/train/dev-clean.tar.gz’

dev-clean.tar.gz    100%[===================>] 322.27M  11.6MB/s    in 31s     

2021-11-05 11:43:42 (10.3 MB/s) - ‘./data/train/dev-clean.tar.gz’ saved [337926286/337926286]
ls ./data/train/
LibriSpeech/  dev-clean.tar.gz

تقع مجموعة البيانات الخاصة بنا في دليل LibriSpeech. دعنا نستكشف هذه الملفات.

data_dir = "./data/train/LibriSpeech/dev-clean/2428/83705/"
all_files = os.listdir(data_dir)

flac_files = [f for f in all_files if f.endswith(".flac")]
txt_files = [f for f in all_files if f.endswith(".txt")]

print("Transcription files:", txt_files, "\nSound files:", flac_files)
Transcription files: ['2428-83705.trans.txt'] 
Sound files: ['2428-83705-0015.flac', '2428-83705-0004.flac', '2428-83705-0006.flac', '2428-83705-0026.flac', '2428-83705-0023.flac', '2428-83705-0001.flac', '2428-83705-0005.flac', '2428-83705-0040.flac', '2428-83705-0038.flac', '2428-83705-0042.flac', '2428-83705-0008.flac', '2428-83705-0019.flac', '2428-83705-0021.flac', '2428-83705-0002.flac', '2428-83705-0039.flac', '2428-83705-0034.flac', '2428-83705-0028.flac', '2428-83705-0000.flac', '2428-83705-0029.flac', '2428-83705-0041.flac', '2428-83705-0035.flac', '2428-83705-0032.flac', '2428-83705-0020.flac', '2428-83705-0025.flac', '2428-83705-0010.flac', '2428-83705-0014.flac', '2428-83705-0003.flac', '2428-83705-0031.flac', '2428-83705-0017.flac', '2428-83705-0027.flac', '2428-83705-0012.flac', '2428-83705-0043.flac', '2428-83705-0030.flac', '2428-83705-0022.flac', '2428-83705-0016.flac', '2428-83705-0037.flac', '2428-83705-0011.flac', '2428-83705-0036.flac', '2428-83705-0009.flac', '2428-83705-0013.flac', '2428-83705-0007.flac', '2428-83705-0018.flac', '2428-83705-0024.flac', '2428-83705-0033.flac']

حسنا، لذلك كل دليل فرعي لديه العديد من .flac الملفات و .txt الملف. و .txt يحتوي ملف تدوين النص لجميع العينات الكلام (أي .flac الملفات) موجودة في ذلك دون دليل.

يمكننا تحميل هذه البيانات النصية على النحو التالي:

def read_txt_file(f):
  with open(f, "r") as f:
    samples = f.read().split("\n")
    samples = {s.split()[0]: " ".join(s.split()[1:]) for s in samples if len(s.split()) > 2}
  return samples

وبالمثل، فإننا سوف تحدد وظيفة لتحميل عينة من خطاب .flac الملف.

REQUIRED_SAMPLE_RATE ومن المقرر أن 16000 كما كان قبل المدربين wav2vec2 مع 16K تردد وينصح لصقل دون أي تغيير كبير في توزيع البيانات بسبب تردد.

import soundfile as sf

REQUIRED_SAMPLE_RATE = 16000

def read_flac_file(file_path):
  with open(file_path, "rb") as f:
      audio, sample_rate = sf.read(f)
  if sample_rate != REQUIRED_SAMPLE_RATE:
      raise ValueError(
          f"sample rate (={sample_rate}) of your files must be {REQUIRED_SAMPLE_RATE}"
      )
  file_id = os.path.split(file_path)[-1][:-len(".flac")]
  return {file_id: audio}

الآن ، سنختار بعض العينات العشوائية وسنحاول تصورها.

from IPython.display import Audio
import random

file_id = random.choice([f[:-len(".flac")] for f in flac_files])
flac_file_path, txt_file_path = os.path.join(data_dir, f"{file_id}.flac"), os.path.join(data_dir, "2428-83705.trans.txt")

print("Text Transcription:", read_txt_file(txt_file_path)[file_id], "\nAudio:")
Audio(filename=flac_file_path)
Text Transcription: HE HAS GIVEN US FREE PASSES ALL THE WAY TO THE END OF OUR JOURNEY AND ALL THE WAY BACK AGAIN AND COUPONS FOR FREE BOARD AND LODGING AT THE HOTEL IT'S A WEDDING PRESENT 
Audio:

الآن ، سنقوم بدمج جميع عينات الكلام والنص وسوف نحدد الوظيفة (في الخلية التالية) لهذا الغرض.

def fetch_sound_text_mapping(data_dir):
  all_files = os.listdir(data_dir)

  flac_files = [os.path.join(data_dir, f) for f in all_files if f.endswith(".flac")]
  txt_files = [os.path.join(data_dir, f) for f in all_files if f.endswith(".txt")]

  txt_samples = {}
  for f in txt_files:
    txt_samples.update(read_txt_file(f))

  speech_samples = {}
  for f in flac_files:
    speech_samples.update(read_flac_file(f))

  assert len(txt_samples) == len(speech_samples)

  samples = [(speech_samples[file_id], txt_samples[file_id]) for file_id in speech_samples.keys() if len(speech_samples[file_id]) < AUDIO_MAXLEN]
  return samples

حان الوقت لإلقاء نظرة على بعض العينات ...

samples = fetch_sound_text_mapping(data_dir)
samples[:5]
[(array([ 6.10351562e-05,  9.15527344e-05,  9.15527344e-05, ...,
         -3.05175781e-04, -5.79833984e-04, -8.23974609e-04]),
  'WHEN SHE HEARD OF MY ENGAGEMENT WITH MARY ANN SHE WROTE AND SUGGESTED THAT WE SHOULD SPEND OUR HONEYMOON IN HER COTTAGE OR PIGSTYE AND THAT I SHOULD PAY HER RENT FOR IT'),
 (array([-0.00112915, -0.00131226, -0.00158691, ...,  0.00067139,
          0.00091553,  0.00100708]),
  "IT MIGHT JUST AS WELL BE SOME ONE ELSE'S WEDDING SO UNIMPORTANT IS THE PART WHICH I AM SET TO PLAY IN IT"),
 (array([ 3.05175781e-05, -6.10351562e-05,  2.13623047e-04, ...,
         -5.18798828e-04, -2.13623047e-04, -2.74658203e-04]),
  'THE ACCIDENT IN QUESTION OCCURRED UPON THE SUNDAY EVENING'),
 (array([ 3.05175781e-04,  3.05175781e-05, -1.83105469e-04, ...,
          7.62939453e-04,  6.10351562e-04,  5.79833984e-04]),
  "OF COURSE THERE ARE SOME PEOPLE WITH WHOM YOU CAN'T BE PERFECTLY PLAIN BUT I SHALL BE AS PLAIN AS I CAN THERE'S A WAY AND A MANNER OF DOING THAT KIND OF THING"),
 (array([ 6.10351562e-05, -3.05175781e-05,  0.00000000e+00, ...,
         -3.66210938e-04, -7.93457031e-04, -1.19018555e-03]),
  'I KNOW WHAT MAMMA CAN AFFORD TO GIVE AND I WILL SEE SHE GIVES IT')]

دعونا نعالج البيانات مسبقًا الآن !!!

وعلينا أولا تحديد tokenizer والمعالج باستخدام gsoc-wav2vec2 الحزمة. بعد ذلك ، سنقوم بمعالجة مسبقة بسيطة للغاية. processor سوف تطبع خطاب الخام wrto إطارات المحور و tokenizer سيتم تحويل مخرجات نموذجنا في سلسلة (باستخدام مفردات محددة) وسوف تأخذ الرعاية من إزالة الرموز الخاصة (اعتمادا على تكوين tokenizer الخاص بك).

from wav2vec2 import Wav2Vec2Processor
tokenizer = Wav2Vec2Processor(is_tokenizer=True)
processor = Wav2Vec2Processor(is_tokenizer=False)

def preprocess_text(text):
  label = tokenizer(text)
  return tf.constant(label, dtype=tf.int32)

def preprocess_speech(audio):
  audio = tf.constant(audio, dtype=tf.float32)
  return processor(tf.transpose(audio))
Downloading `vocab.json` from https://github.com/vasudevgupta7/gsoc-wav2vec2/raw/main/data/vocab.json ... DONE

الآن ، سنقوم بتعريف مولد python لاستدعاء وظائف المعالجة المسبقة التي حددناها في الخلايا أعلاه.

def inputs_generator():
  for speech, text in samples:
    yield preprocess_speech(speech), preprocess_text(text)

إنشاء tf.data.Dataset

بعد الإعداد إرادة خلية tf.data.Dataset الكائن باستخدام لها .from_generator(...) الأسلوب. وسوف يتم استخدام generator الكائن، حددنا في الخلية المذكورة أعلاه.

يمكنك الرجوع إلى هذا البرنامج النصي لمزيد من التفاصيل حول كيفية تحويل البيانات LibriSpeech إلى tfrecords.

output_signature = (
    tf.TensorSpec(shape=(None),  dtype=tf.float32),
    tf.TensorSpec(shape=(None), dtype=tf.int32),
)

dataset = tf.data.Dataset.from_generator(inputs_generator, output_signature=output_signature)
BUFFER_SIZE = len(flac_files)
SEED = 42

dataset = dataset.shuffle(BUFFER_SIZE, seed=SEED)

سنقوم بتمرير مجموعة البيانات إلى دفعات متعددة ، لذلك دعونا نجهز الدُفعات في الخلية التالية. الآن ، يجب أن تكون جميع التسلسلات في الدفعة مبطنة بطول ثابت. سوف نستخدم .padded_batch(...) طريقة لهذا الغرض.

dataset = dataset.padded_batch(BATCH_SIZE, padded_shapes=(AUDIO_MAXLEN, LABEL_MAXLEN), padding_values=(0.0, 0))

المسرعات (مثل GPUs / TPU) سريعة جدًا وغالبًا ما يصبح تحميل البيانات (والمعالجة المسبقة) عنق الزجاجة أثناء التدريب حيث يحدث جزء تحميل البيانات على وحدات المعالجة المركزية. يمكن أن يؤدي ذلك إلى زيادة وقت التدريب بشكل كبير خاصةً عندما يكون هناك الكثير من المعالجة المسبقة عبر الإنترنت المتضمنة أو يتم دفق البيانات عبر الإنترنت من دلاء GCS. للتعامل مع هذه القضايا، tf.data.Dataset يقدم .prefetch(...) الأسلوب. تساعد هذه الطريقة في إعداد الدُفعات القليلة التالية بالتوازي (على وحدات المعالجة المركزية) أثناء قيام النموذج بعمل تنبؤات (على وحدات معالجة الرسومات / وحدات المعالجة المركزية) على الدُفعة الحالية.

dataset = dataset.prefetch(tf.data.AUTOTUNE)

منذ يتكون هذا الكمبيوتر الدفتري لأغراض العرض التوضيحي، سوف نتخذ أول num_train_batches وسوف بعمل تدريب على هذا فقط. نشجعك على التدرب على مجموعة البيانات بأكملها. وبالمثل، سوف نقوم بتقييم فقط num_val_batches .

num_train_batches = 10
num_val_batches = 4

train_dataset = dataset.take(num_train_batches)
val_dataset = dataset.skip(num_train_batches).take(num_val_batches)

تدريب نموذجي

لتدريب نموذج، فإننا سوف تكون مباشرة داعيا .fit(...) طريقة بعد تجميع نموذجنا مع .compile(...) .

model.compile(optimizer, loss=loss_fn)

ستُنشئ الخلية أعلاه حالة التدريب الخاصة بنا. الآن يمكننا بدء التدريب مع .fit(...) الأسلوب.

history = model.fit(train_dataset, validation_data=val_dataset, epochs=3)
history.history
Epoch 1/3
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/ctc_ops.py:1447: alias_inplace_add (from tensorflow.python.ops.inplace_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Prefer tf.tensor_scatter_nd_add, which offers the same functionality with well-defined read-write semantics.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/ctc_ops.py:1447: alias_inplace_add (from tensorflow.python.ops.inplace_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Prefer tf.tensor_scatter_nd_add, which offers the same functionality with well-defined read-write semantics.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/ctc_ops.py:1430: alias_inplace_update (from tensorflow.python.ops.inplace_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Prefer tf.tensor_scatter_nd_update, which offers the same functionality with well-defined read-write semantics.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/ctc_ops.py:1430: alias_inplace_update (from tensorflow.python.ops.inplace_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Prefer tf.tensor_scatter_nd_update, which offers the same functionality with well-defined read-write semantics.
WARNING:tensorflow:Gradients do not exist for variables ['wav2vec2/masked_spec_embed:0'] when minimizing the loss. If you're using `model.compile()`, did you forget to provide a `loss`argument?
WARNING:tensorflow:Gradients do not exist for variables ['wav2vec2/masked_spec_embed:0'] when minimizing the loss. If you're using `model.compile()`, did you forget to provide a `loss`argument?
WARNING:tensorflow:Gradients do not exist for variables ['wav2vec2/masked_spec_embed:0'] when minimizing the loss. If you're using `model.compile()`, did you forget to provide a `loss`argument?
WARNING:tensorflow:Gradients do not exist for variables ['wav2vec2/masked_spec_embed:0'] when minimizing the loss. If you're using `model.compile()`, did you forget to provide a `loss`argument?
10/10 [==============================] - 32s 2s/step - loss: 649.3215 - val_loss: 315.0721
Epoch 2/3
10/10 [==============================] - 17s 2s/step - loss: 242.1202 - val_loss: 336.5721
Epoch 3/3
10/10 [==============================] - 17s 2s/step - loss: 222.1239 - val_loss: 253.0467
{'loss': [649.321533203125, 242.1201629638672, 222.1239013671875],
 'val_loss': [315.0721435546875, 336.5721130371094, 253.0466766357422]}

دعونا حفظ نموذجنا مع .save(...) طريقة لتكون قادرة على أداء الاستدلال في وقت لاحق. يمكنك أيضا تصدير هذه SavedModel إلى TFHub باتباع الوثائق TFHub .

save_dir = "finetuned-wav2vec2"
model.save(save_dir, include_optimizer=False)
2021-11-05 11:44:54.280793: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Found untraced functions such as restored_function_body, restored_function_body, restored_function_body, restored_function_body, restored_function_body while saving (showing 5 of 855). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: finetuned-wav2vec2/assets
INFO:tensorflow:Assets written to: finetuned-wav2vec2/assets

تقييم

سنقوم الآن بحساب معدل خطأ الكلمات على مجموعة بيانات التحقق

معدل خطأ كلمة (WER) هو مقياس مشترك لقياس أداء نظام التعرف على الكلام التلقائي. يُشتق WER من مسافة Levenshtein ، ويعمل على مستوى الكلمة. يمكن بعد ذلك حساب معدل أخطاء الكلمات على النحو التالي: WER = (S + D + I) / N = (S + D + I) / (S + D + C) حيث S هو عدد الاستبدالات ، D هو عدد عمليات الحذف ، I هو عدد الإدخالات ، C هو عدد الكلمات الصحيحة ، N هو عدد الكلمات في المرجع (N = S + D + C). تشير هذه القيمة إلى النسبة المئوية للكلمات التي تم توقعها بشكل غير صحيح.

يمكنك الرجوع إلى هذه الورقة لمعرفة المزيد عن WER.

سوف نستخدم load_metric(...) وظيفة من مجموعات البيانات HuggingFace المكتبة. دعونا أولا تثبيت datasets المكتبة باستخدام pip ثم تحدد metric الكائن.

!pip3 install -q datasets

from datasets import load_metric
metric = load_metric("wer")
Downloading:   0%|          | 0.00/1.95k [00:00<?, ?B/s]
@tf.function(jit_compile=True)
def eval_fwd(batch):
  logits = model(batch, training=False)
  return tf.argmax(logits, axis=-1)

حان الوقت الآن لإجراء التقييم على بيانات التحقق من الصحة.

from tqdm.auto import tqdm

for speech, labels in tqdm(val_dataset, total=num_val_batches):
    predictions  = eval_fwd(speech)
    predictions = [tokenizer.decode(pred) for pred in predictions.numpy().tolist()]
    references = [tokenizer.decode(label, group_tokens=False) for label in labels.numpy().tolist()]
    metric.add_batch(references=references, predictions=predictions)
0%|          | 0/4 [00:00<?, ?it/s]
2021-11-05 11:45:11.575128: W tensorflow/compiler/tf2xla/kernels/random_ops.cc:57] Warning: Using tf.random.uniform with XLA compilation will ignore seeds; consider using tf.random.stateless_uniform instead if reproducible behavior is desired. model/keras_layer/StatefulPartitionedCall/StatefulPartitionedCall/wav2vec2/encoder/layers/0/stochastic_depth/random_uniform/RandomUniform

نحن نستخدم tokenizer.decode(...) طريقة فك توقعاتنا وتسميات العودة إلى النص، وسوف إضافتها إلى متري ل WER حساب في وقت لاحق.

الآن ، دعنا نحسب القيمة المترية في الخلية التالية:

metric.compute()
1.0

الإستنباط

والآن ونحن راضون عن عملية التدريب وأنقذت نموذج في save_dir ، وسوف نرى كيف أن هذا النموذج يمكن أن تستخدم في الاستدلال.

أولا، فإننا سوف تحميل نموذجنا باستخدام tf.keras.models.load_model(...) .

finetuned_model = tf.keras.models.load_model(save_dir)
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.

لنقم بتنزيل بعض عينات الكلام لأداء الاستدلال. يمكنك أيضًا استبدال النموذج التالي بعينة حديثك.

wget https://github.com/vasudevgupta7/gsoc-wav2vec2/raw/main/data/SA2.wav
--2021-11-05 11:45:28--  https://github.com/vasudevgupta7/gsoc-wav2vec2/raw/main/data/SA2.wav
Resolving github.com (github.com)... 13.114.40.48
Connecting to github.com (github.com)|13.114.40.48|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://raw.githubusercontent.com/vasudevgupta7/gsoc-wav2vec2/main/data/SA2.wav [following]
--2021-11-05 11:45:28--  https://raw.githubusercontent.com/vasudevgupta7/gsoc-wav2vec2/main/data/SA2.wav
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 94252 (92K) [audio/wav]
Saving to: ‘SA2.wav’

SA2.wav             100%[===================>]  92.04K  --.-KB/s    in 0.02s   

2021-11-05 11:45:29 (5.38 MB/s) - ‘SA2.wav’ saved [94252/94252]

الآن، سنقرأ العينة الكلام باستخدام soundfile.read(...) ولوحة ل AUDIO_MAXLEN لتلبية توقيع نموذج. ثم سنقوم تطبيع تلك العينة خطاب باستخدام Wav2Vec2Processor المثال وسوف يطعمه في النموذج.

import numpy as np

speech, _ = sf.read("SA2.wav")
speech = np.pad(speech, (0, AUDIO_MAXLEN - len(speech)))
speech = tf.expand_dims(processor(tf.constant(speech)), 0)

outputs = finetuned_model(speech)
outputs
<tf.Tensor: shape=(1, 768, 32), dtype=float32, numpy=
array([[[ 5.5087714 , -1.0872856 , -1.0728477 , ..., -1.3125695 ,
         -0.7992846 , -0.94512135],
        [ 5.508977  , -1.0873723 , -1.0727195 , ..., -1.3125291 ,
         -0.79928476, -0.9449429 ],
        [ 5.5091047 , -1.0871643 , -1.0728203 , ..., -1.312533  ,
         -0.7992611 , -0.94483167],
        ...,
        [ 5.5094743 , -1.0874028 , -1.0729864 , ..., -1.3126655 ,
         -0.7994431 , -0.9449925 ],
        [ 5.509465  , -1.0873648 , -1.072943  , ..., -1.3126557 ,
         -0.79943836, -0.94500387],
        [ 5.509408  , -1.0872416 , -1.0728781 , ..., -1.3125473 ,
         -0.7993649 , -0.9449776 ]]], dtype=float32)>

أرقام فك دعونا مرة أخرى في تسلسل النص باستخدام Wav2Vec2tokenizer سبيل المثال، فإننا المحدد أعلاه.

predictions = tf.argmax(outputs, axis=-1)
predictions = [tokenizer.decode(pred) for pred in predictions.numpy().tolist()]
predictions
['']

هذا التوقع عشوائي تمامًا حيث لم يتم تدريب النموذج مطلقًا على البيانات الكبيرة في هذا الكمبيوتر المحمول (حيث أن هذا الكمبيوتر الدفتري غير مخصص لإجراء تدريب كامل). ستحصل على تنبؤات جيدة إذا قمت بتدريب هذا النموذج على مجموعة بيانات LibriSpeech الكاملة.

أخيرًا ، لقد وصلنا إلى نهاية هذا دفتر الملاحظات. ولكنها ليست نهاية التعلم TensorFlow للمهام المتعلقة الكلام، هذا المستودع يحتوي على بعض الدروس أكثر مذهلة. في حال واجهتك أي خلل في هذه المفكرة، يرجى إنشاء قضية هنا .