Tinh chỉnh Wav2Vec2 với đầu LM

Xem trên TensorFlow.org Chạy trong Google Colab Xem trên GitHub Tải xuống sổ ghi chép Xem mô hình TF Hub

Trong máy tính xách tay này, chúng tôi sẽ được tải mô hình wav2vec2 pre-đào tạo từ TFHub và sẽ tinh chỉnh nó trên LibriSpeech bộ dữ liệu bằng cách thêm ngôn ngữ mô hình hóa đầu (LM) trên đầu của mô hình pre-đào tạo của chúng tôi. Nhiệm vụ cơ bản là xây dựng một mô hình cho Automatic Speech Recognition tức là đưa ra một số bài phát biểu, mô hình sẽ có thể ghi lại nó vào văn bản.

Đang cài đặt

Trước khi chạy máy tính xách tay này, hãy đảm bảo rằng bạn đang trên thời gian chạy GPU ( Runtime > Change runtime type > GPU ). Các tế bào sau sẽ cài đặt gsoc-wav2vec2 gói & phụ thuộc của nó.

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) ...

Thiết lập mô hình sử dụng TFHub

Chúng tôi sẽ bắt đầu bằng cách nhập một số thư viện / mô-đun.

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

Đầu tiên, chúng ta sẽ tải về mô hình của chúng tôi từ TFHub & sẽ quấn chữ ký mẫu của chúng tôi với hub.KerasLayer để có thể sử dụng mô hình này giống như bất kỳ lớp Keras khác. May mắn thay, hub.KerasLayer thể làm cả hai chỉ trong 1 dòng.

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

Bạn có thể tham khảo này kịch bản trong trường hợp bạn đang quan tâm trong mô hình xuất khẩu kịch bản. Object pretrained_layer là phiên bản đóng băng của Wav2Vec2Model . Những trọng lượng trước-đào tạo đã được chuyển đổi từ HuggingFace PyTorch trọng Pre-đào tạo sử dụng kịch bản này .

Ban đầu, wav2vec2 được đào tạo trước với phương pháp tiếp cận mô hình ngôn ngữ bị che với mục tiêu xác định biểu diễn giọng nói tiềm ẩn được lượng tử hóa thực sự cho một bước thời gian bị che. Bạn có thể đọc thêm về mục tiêu đào tạo trong paper- wav2vec 2.0: Một khuôn khổ cho Học Tự giám sát của Cơ quan đại diện Speech .

Bây giờ, chúng ta sẽ xác định một vài hằng số và siêu tham số sẽ hữu ích trong một vài ô tiếp theo. AUDIO_MAXLEN được cố ý thiết lập để 246000 như chữ ký mẫu chỉ chấp nhận chiều dài chuỗi tĩnh của 246000 .

AUDIO_MAXLEN = 246000
LABEL_MAXLEN = 256
BATCH_SIZE = 2

Trong các tế bào sau đây, chúng tôi sẽ quấn pretrained_layer & một lớp dày đặc (LM đầu) với API chức năng của 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)

Các lớp dày đặc (được định nghĩa ở trên) là có một chiều đầu ra của vocab_size như chúng ta muốn dự đoán xác suất của mỗi thẻ trong vốn từ vựng ở mỗi bước thời gian.

Thiết lập trạng thái đào tạo

Trong TensorFlow, trọng số mô hình được xây dựng chỉ khi model.call hoặc model.build được gọi là lần đầu tiên, vì vậy các tế bào sau đây sẽ xây dựng các mô hình trọng đối với chúng tôi. Hơn nữa, chúng tôi sẽ được chạy model.summary() để kiểm tra tổng số các thông số khả năng huấn luyện.

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
_________________________________________________________________

Bây giờ, chúng ta cần phải xác định loss_fn và tối ưu hóa để có thể đào tạo mô hình. Ô sau sẽ làm điều đó cho chúng ta. Chúng tôi sẽ sử dụng Adam ưu cho đơn giản. CTCLoss là một loại tổn thất chung được sử dụng cho các nhiệm vụ (như ASR ), nơi đầu vào tiểu phần không thể dễ dàng phù hợp với sản lượng tiểu phần. Bạn có thể đọc thêm về CTC-lỗ từ kinh ngạc này bài đăng blog .

CTCLoss (từ gsoc-wav2vec2 gói) chấp nhận 3 đối số: config , model_input_shape & division_factor . Nếu division_factor=1 , sau đó mất sẽ chỉ đơn giản là được tóm tắt, vì vậy thông qua division_factor phù hợp để có được trung bình hàng loạt trên.

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)

Đang tải và xử lý trước dữ liệu

Hãy tải tại các tập dữ liệu LibriSpeech từ trang web chính thức và thiết lập nó.

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

Bộ dữ liệu của chúng tôi nằm trong thư mục LibriSpeech. Hãy cùng khám phá những tập tin này.

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']

Được rồi, vì vậy mỗi thư mục con có nhiều .flac tập tin và một .txt file. Các .txt tập tin chứa phiên âm văn bản cho tất cả các mẫu giọng nói (tức là .flac files) hiện diện trong đó thư mục con.

Chúng tôi có thể tải dữ liệu văn bản này như sau:

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

Tương tự như vậy, chúng ta sẽ định nghĩa một hàm cho tải một mẫu bài phát biểu từ một .flac tập tin.

REQUIRED_SAMPLE_RATE được thiết lập để 16000 như wav2vec2 được pre-đào tạo với 16K tần số và nó được đề nghị để tinh chỉnh nó mà không có bất kỳ sự thay đổi lớn trong phân phối dữ liệu do tần số.

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}

Bây giờ, chúng tôi sẽ chọn một số mẫu ngẫu nhiên và sẽ cố gắng hình dung chúng.

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:

Bây giờ, chúng tôi sẽ kết hợp tất cả các mẫu lời nói & văn bản và sẽ xác định hàm (trong ô tiếp theo) cho mục đích đó.

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

Đã đến lúc xem một vài mẫu ...

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')]

Hãy xử lý trước dữ liệu ngay bây giờ !!!

Đầu tiên chúng ta sẽ xác định tokenizer & xử lý sử dụng gsoc-wav2vec2 gói. Sau đó, chúng tôi sẽ thực hiện sơ chế rất đơn giản. processor sẽ bình thường hóa ngôn luận thô wrto khung trục và tokenizer sẽ chuyển đổi kết quả đầu ra mô hình của chúng tôi vào chuỗi (bằng cách sử dụng từ vựng được định nghĩa) & sẽ chăm sóc của việc loại bỏ các thẻ đặc biệt (tùy thuộc vào cấu hình tokenizer của bạn).

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

Bây giờ, chúng ta sẽ xác định trình tạo python để gọi các hàm tiền xử lý mà chúng ta đã xác định trong các ô ở trên.

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

Thiết lập tf.data.Dataset

Sau di động sẽ thiết lập tf.data.Dataset đối tượng sử dụng của nó .from_generator(...) phương pháp. Chúng tôi sẽ sử dụng generator đối tượng, chúng tôi xác định trong các tế bào trên.

Bạn có thể tham khảo kịch bản này để biết thêm chi tiết về làm thế nào để chuyển đổi dữ liệu LibriSpeech vào 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)

Chúng tôi sẽ chuyển tập dữ liệu thành nhiều lô, vì vậy hãy chuẩn bị các lô trong ô sau. Bây giờ, tất cả các trình tự trong một lô sẽ được đệm vào một độ dài không đổi. Chúng tôi sẽ sử dụng .padded_batch(...) phương pháp cho mục đích đó.

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

Các bộ tăng tốc (như GPU / TPU) rất nhanh và thường quá trình tải dữ liệu (& tiền xử lý) trở thành nút thắt cổ chai trong quá trình đào tạo vì phần tải dữ liệu xảy ra trên CPU. Điều này có thể làm tăng đáng kể thời gian đào tạo, đặc biệt khi có nhiều quá trình xử lý trước trực tuyến liên quan hoặc dữ liệu được truyền trực tuyến từ nhóm GCS. Để xử lý những vấn đề này, tf.data.Dataset cung cấp .prefetch(...) phương pháp. Phương pháp này giúp chuẩn bị song song một số lô tiếp theo (trên CPU) trong khi mô hình đang đưa ra dự đoán (trên GPU / TPU) trên lô hiện tại.

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

Kể từ khi máy tính xách tay này được thực hiện với mục đích trình diễn, chúng tôi sẽ được tham gia đầu tiên num_train_batches và sẽ thực hiện đào tạo theo chỉ đó. Tuy nhiên, bạn được khuyến khích đào tạo trên toàn bộ tập dữ liệu. Tương tự như vậy, chúng tôi sẽ đánh giá chỉ 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)

Đào tạo người mẫu

Đối với đào tạo mô hình của chúng tôi, chúng tôi sẽ trực tiếp gọi .fit(...) Phương pháp sau khi biên dịch mô hình của chúng tôi với .compile(...) .

model.compile(optimizer, loss=loss_fn)

Ô trên sẽ thiết lập trạng thái đào tạo của chúng ta. Bây giờ chúng ta có thể bắt đầu tập luyện với các .fit(...) phương pháp.

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]}

Hãy tiết kiệm mô hình của chúng tôi với .save(...) phương pháp để có thể thực hiện kết luận sau. Bạn cũng có thể xuất SavedModel này để TFHub bằng cách làm theo tài liệu hướng dẫn 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

Đánh giá

Bây giờ chúng ta sẽ tính toán Tỷ lệ lỗi Word qua tập dữ liệu xác thực

Lời tỷ lệ lỗi (WER) là một thước đo chung để đo lường hiệu suất của một hệ thống nhận dạng giọng nói tự động. WER có nguồn gốc từ khoảng cách Levenshtein, hoạt động ở cấp độ từ. Tỷ lệ lỗi Word sau đó có thể được tính như sau: WER = (S + D + I) / N = (S + D + I) / (S + D + C) trong đó S là số lần thay thế, D là số lần xóa , I là số lần chèn, C là số từ đúng, N là số từ trong tham chiếu (N = S + D + C). Giá trị này cho biết phần trăm các từ được dự đoán không chính xác.

Bạn có thể tham khảo bài viết này để tìm hiểu thêm về WER.

Chúng tôi sẽ sử dụng load_metric(...) chức năng từ HuggingFace bộ dữ liệu thư viện. Trước tiên hãy cài đặt các datasets thư viện sử dụng pip và sau đó xác định metric đối tượng.

!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)

Đã đến lúc chạy đánh giá trên dữ liệu xác thực ngay bây giờ.

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

Chúng tôi đang sử dụng tokenizer.decode(...) phương pháp để giải mã những dự đoán và nhãn của chúng tôi trở lại thành văn bản và sẽ thêm chúng vào các số liệu cho WER tính toán sau này.

Bây giờ, hãy tính toán giá trị số liệu trong ô sau:

metric.compute()
1.0

Sự suy luận

Bây giờ chúng ta đang hài lòng với quá trình đào tạo & đã lưu mô hình trong save_dir , chúng tôi sẽ xem làm thế nào mô hình này có thể được sử dụng để suy luận.

Đầu tiên, chúng ta sẽ được tải mô hình của chúng tôi sử dụng 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.

Hãy tải xuống một số mẫu bài phát biểu để thực hiện suy luận. Bạn cũng có thể thay thế mẫu sau bằng mẫu bài phát biểu của mình.

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]

Bây giờ, chúng ta sẽ đọc bài phát biểu mẫu sử dụng soundfile.read(...) và pad nó để AUDIO_MAXLEN để đáp ứng các chữ ký mẫu. Sau đó chúng tôi sẽ bình thường hóa mà mẫu bài phát biểu bằng cách sử dụng Wav2Vec2Processor dụ & sẽ ăn nó vào mô hình.

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)>

Hãy số decode sao vào chuỗi văn bản bằng cách sử dụng Wav2Vec2tokenizer dụ, chúng ta định nghĩa ở trên.

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

Dự đoán này khá ngẫu nhiên vì mô hình chưa bao giờ được đào tạo về dữ liệu lớn trong sổ ghi chép này (vì sổ ghi chép này không dành cho việc đào tạo hoàn chỉnh). Bạn sẽ nhận được những dự đoán tốt nếu đào tạo mô hình này trên tập dữ liệu LibriSpeech hoàn chỉnh.

Cuối cùng, chúng ta đã hoàn thành xong cuốn sổ này. Nhưng nó không phải là dấu chấm hết của việc học TensorFlow cho các nhiệm vụ bài phát biểu liên quan đến, điều này kho chứa một số hướng dẫn tuyệt vời hơn. Trong trường hợp bạn gặp phải bất kỳ lỗi trong máy tính xách tay này, hãy tạo ra một vấn đề ở đây .