एमएल समुदाय दिवस 9 नवंबर है! TensorFlow, JAX से नई जानकारी के लिए हमसे जुड़ें, और अधिक जानें

सरल ऑडियो पहचान: खोजशब्दों को पहचानना

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

यह ट्यूटोरियल आपको दिखाएगा कि दस अलग-अलग शब्दों को पहचानने वाला एक बुनियादी वाक् पहचान नेटवर्क कैसे बनाया जाए। यह जानना महत्वपूर्ण है कि वास्तविक भाषण और ऑडियो पहचान प्रणाली बहुत अधिक जटिल हैं, लेकिन छवियों के लिए MNIST की तरह, यह आपको शामिल तकनीकों की एक बुनियादी समझ प्रदान करनी चाहिए। एक बार जब आप इस ट्यूटोरियल को पूरा कर लेते हैं, तो आपके पास एक मॉडल होगा जो एक सेकंड की ऑडियो क्लिप को "डाउन", "गो", "लेफ्ट", "नो", "राइट", "स्टॉप", "अप" के रूप में वर्गीकृत करने का प्रयास करता है। " और हां"।

सेट अप

आवश्यक मॉड्यूल और निर्भरता आयात करें।

import os
import pathlib

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import models
from IPython import display


# Set seed for experiment reproducibility
seed = 42
tf.random.set_seed(seed)
np.random.seed(seed)

स्पीच कमांड डेटासेट आयात करें

आप के एक हिस्से को डाउनलोड करने के लिए एक स्क्रिप्ट लिखेंगे भाषण आदेश डाटासेट । मूल डेटासेट में तीस अलग-अलग शब्द कहने वाले लोगों की 105,000 से अधिक WAV ऑडियो फ़ाइलें होती हैं। यह डेटा Google द्वारा एकत्र किया गया था और CC BY लाइसेंस के तहत जारी किया गया था।

डेटा लोड करने में समय बचाने के लिए आप डेटासेट के एक हिस्से का उपयोग करेंगे। निकालें mini_speech_commands.zip और प्रयोग करने में इसे लोड tf.data एपीआई।

data_dir = pathlib.Path('data/mini_speech_commands')
if not data_dir.exists():
  tf.keras.utils.get_file(
      'mini_speech_commands.zip',
      origin="http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip",
      extract=True,
      cache_dir='.', cache_subdir='data')
Downloading data from http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip
182083584/182082353 [==============================] - 5s 0us/step
182091776/182082353 [==============================] - 5s 0us/step

डेटासेट के बारे में बुनियादी आँकड़ों की जाँच करें।

commands = np.array(tf.io.gfile.listdir(str(data_dir)))
commands = commands[commands != 'README.md']
print('Commands:', commands)
Commands: ['stop' 'yes' 'no' 'right' 'down' 'go' 'up' 'left']

ऑडियो फ़ाइलों को एक सूची में निकालें और इसे फेरबदल करें।

filenames = tf.io.gfile.glob(str(data_dir) + '/*/*')
filenames = tf.random.shuffle(filenames)
num_samples = len(filenames)
print('Number of total examples:', num_samples)
print('Number of examples per label:',
      len(tf.io.gfile.listdir(str(data_dir/commands[0]))))
print('Example file tensor:', filenames[0])
Number of total examples: 8000
Number of examples per label: 1000
Example file tensor: tf.Tensor(b'data/mini_speech_commands/right/0132a06d_nohash_1.wav', shape=(), dtype=string)

फ़ाइलों को क्रमशः 80:10:10 अनुपात का उपयोग करके प्रशिक्षण, सत्यापन और परीक्षण सेट में विभाजित करें।

train_files = filenames[:6400]
val_files = filenames[6400: 6400 + 800]
test_files = filenames[-800:]

print('Training set size', len(train_files))
print('Validation set size', len(val_files))
print('Test set size', len(test_files))
Training set size 6400
Validation set size 800
Test set size 800

ऑडियो फ़ाइलें और उनके लेबल पढ़ना

ऑडियो फ़ाइल को शुरू में एक बाइनरी फ़ाइल के रूप में पढ़ा जाएगा, जिसे आप एक संख्यात्मक टेंसर में बदलना चाहते हैं।

एक ऑडियो फ़ाइल लोड करने के लिए, आप का उपयोग करेगा tf.audio.decode_wav है, जो एक टेन्सर और नमूना दर के रूप में WAV एन्कोड ऑडियो देता है।

एक WAV फ़ाइल में प्रति सेकंड नमूनों की एक निर्धारित संख्या के साथ समय श्रृंखला डेटा होता है। प्रत्येक नमूना उस विशिष्ट समय पर ऑडियो सिग्नल के आयाम का प्रतिनिधित्व करता है। एक 16-बिट प्रणाली में, में फ़ाइलों की तरह mini_speech_commands , मूल्यों की सीमा -32,768 से 32767. को यह डेटासेट के लिए नमूना दर 16kHz है। ध्यान दें कि tf.audio.decode_wav रेंज [-1.0, 1.0] के लिए मूल्यों को सामान्य होगा।

def decode_audio(audio_binary):
  audio, _ = tf.audio.decode_wav(audio_binary)
  return tf.squeeze(audio, axis=-1)

प्रत्येक WAV फ़ाइल का लेबल उसकी मूल निर्देशिका है।

def get_label(file_path):
  parts = tf.strings.split(file_path, os.path.sep)

  # Note: You'll use indexing here instead of tuple unpacking to enable this 
  # to work in a TensorFlow graph.
  return parts[-2]

आइए एक ऐसी विधि को परिभाषित करें जो WAV फ़ाइल के फ़ाइल नाम में ले लेगी और पर्यवेक्षित प्रशिक्षण के लिए ऑडियो और लेबल युक्त एक टपल आउटपुट करेगी।

def get_waveform_and_label(file_path):
  label = get_label(file_path)
  audio_binary = tf.io.read_file(file_path)
  waveform = decode_audio(audio_binary)
  return waveform, label

अब आप लागू होगी process_path अपने प्रशिक्षण सेट ऑडियो-लेबल जोड़े निकालने और परिणामों की जांच करने के लिए बनाने के लिए। आप बाद में इसी तरह की प्रक्रिया का उपयोग करके सत्यापन और परीक्षण सेट तैयार करेंगे।

AUTOTUNE = tf.data.AUTOTUNE
files_ds = tf.data.Dataset.from_tensor_slices(train_files)
waveform_ds = files_ds.map(get_waveform_and_label, num_parallel_calls=AUTOTUNE)

आइए कुछ ऑडियो तरंगों को उनके संगत लेबल के साथ देखें।

rows = 3
cols = 3
n = rows*cols
fig, axes = plt.subplots(rows, cols, figsize=(10, 12))
for i, (audio, label) in enumerate(waveform_ds.take(n)):
  r = i // cols
  c = i % cols
  ax = axes[r][c]
  ax.plot(audio.numpy())
  ax.set_yticks(np.arange(-1.2, 1.2, 0.2))
  label = label.numpy().decode('utf-8')
  ax.set_title(label)

plt.show()

पीएनजी

spectrogram

आप तरंग को एक स्पेक्ट्रोग्राम में बदल देंगे, जो समय के साथ आवृत्ति परिवर्तन दिखाता है और इसे 2D छवि के रूप में दर्शाया जा सकता है। यह ऑडियो को टाइम-फ़्रीक्वेंसी डोमेन में बदलने के लिए शॉर्ट-टाइम फूरियर ट्रांसफ़ॉर्म (STFT) को लागू करके किया जा सकता है।

एक फूरियर रूपांतरण ( tf.signal.fft ) अपने घटक आवृत्तियों के लिए एक संकेत बदलता है, लेकिन हर समय जानकारी खो देता है। STFT ( tf.signal.stft ) समय की खिड़कियों में संकेत विभाजित है और एक फूरियर प्रत्येक विंडो पर बदलना, कुछ समय के बारे में जानकारी के संरक्षण, और एक 2 डी टेन्सर है कि आप पर मानक convolutions चला सकते लौटने चलाता है।

एसटीएफटी परिमाण और चरण का प्रतिनिधित्व करने वाली जटिल संख्याओं की एक सरणी उत्पन्न करता है। हालांकि, अगर आप केवल इस ट्यूटोरियल है, जो लागू करके प्राप्त किया जा सकता के लिए परिमाण की आवश्यकता होगी tf.abs के उत्पादन पर tf.signal.stft

चुनें frame_length और frame_step मापदंडों ऐसी है कि उत्पन्न spectrogram "छवि" लगभग वर्ग है। STFT मापदंडों विकल्प के बारे में अधिक जानकारी के लिए आप का उल्लेख कर सकते इस वीडियो ऑडियो सिग्नल प्रोसेसिंग पर।

आप यह भी चाहते हैं कि तरंगों की लंबाई समान हो, ताकि जब आप इसे स्पेक्ट्रोग्राम छवि में परिवर्तित करें, तो परिणाम समान आयाम होंगे। यह केवल एक सेकंड से छोटे ऑडियो क्लिप को शून्य पैडिंग द्वारा किया जा सकता है।

def get_spectrogram(waveform):
  # Padding for files with less than 16000 samples
  zero_padding = tf.zeros([16000] - tf.shape(waveform), dtype=tf.float32)

  # Concatenate audio with padding so that all audio clips will be of the 
  # same length
  waveform = tf.cast(waveform, tf.float32)
  equal_length = tf.concat([waveform, zero_padding], 0)
  spectrogram = tf.signal.stft(
      equal_length, frame_length=255, frame_step=128)

  spectrogram = tf.abs(spectrogram)

  return spectrogram

इसके बाद, आप डेटा का पता लगाएंगे। डेटासेट से एक उदाहरण के तरंग, स्पेक्ट्रोग्राम और वास्तविक ऑडियो की तुलना करें।

for waveform, label in waveform_ds.take(1):
  label = label.numpy().decode('utf-8')
  spectrogram = get_spectrogram(waveform)

print('Label:', label)
print('Waveform shape:', waveform.shape)
print('Spectrogram shape:', spectrogram.shape)
print('Audio playback')
display.display(display.Audio(waveform, rate=16000))
Label: right
Waveform shape: (16000,)
Spectrogram shape: (124, 129)
Audio playback

def plot_spectrogram(spectrogram, ax):
  # Convert to frequencies to log scale and transpose so that the time is
  # represented in the x-axis (columns). An epsilon is added to avoid log of zero.
  log_spec = np.log(spectrogram.T+np.finfo(float).eps)
  height = log_spec.shape[0]
  width = log_spec.shape[1]
  X = np.linspace(0, np.size(spectrogram), num=width, dtype=int)
  Y = range(height)
  ax.pcolormesh(X, Y, log_spec)


fig, axes = plt.subplots(2, figsize=(12, 8))
timescale = np.arange(waveform.shape[0])
axes[0].plot(timescale, waveform.numpy())
axes[0].set_title('Waveform')
axes[0].set_xlim([0, 16000])
plot_spectrogram(spectrogram.numpy(), axes[1])
axes[1].set_title('Spectrogram')
plt.show()
/home/kbuilder/.local/lib/python3.7/site-packages/ipykernel_launcher.py:9: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3.  Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading'].  This will become an error two minor releases later.
  if __name__ == '__main__':

पीएनजी

अब वेवफॉर्म डेटासेट को स्पेक्ट्रोग्राम इमेज और उनके संबंधित लेबल को पूर्णांक आईडी के रूप में रूपांतरित करें।

def get_spectrogram_and_label_id(audio, label):
  spectrogram = get_spectrogram(audio)
  spectrogram = tf.expand_dims(spectrogram, -1)
  label_id = tf.argmax(label == commands)
  return spectrogram, label_id
spectrogram_ds = waveform_ds.map(
    get_spectrogram_and_label_id, num_parallel_calls=AUTOTUNE)

डेटासेट के विभिन्न नमूनों के लिए स्पेक्ट्रोग्राम "छवियों" की जांच करें।

rows = 3
cols = 3
n = rows*cols
fig, axes = plt.subplots(rows, cols, figsize=(10, 10))
for i, (spectrogram, label_id) in enumerate(spectrogram_ds.take(n)):
  r = i // cols
  c = i % cols
  ax = axes[r][c]
  plot_spectrogram(np.squeeze(spectrogram.numpy()), ax)
  ax.set_title(commands[label_id.numpy()])
  ax.axis('off')

plt.show()
/home/kbuilder/.local/lib/python3.7/site-packages/ipykernel_launcher.py:9: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3.  Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading'].  This will become an error two minor releases later.
  if __name__ == '__main__':

पीएनजी

मॉडल बनाएं और प्रशिक्षित करें

अब आप अपने मॉडल का निर्माण और प्रशिक्षण कर सकते हैं। लेकिन ऐसा करने से पहले, आपको सत्यापन और परीक्षण सेट पर प्रशिक्षण सेट प्रीप्रोसेसिंग को दोहराना होगा।

def preprocess_dataset(files):
  files_ds = tf.data.Dataset.from_tensor_slices(files)
  output_ds = files_ds.map(get_waveform_and_label, num_parallel_calls=AUTOTUNE)
  output_ds = output_ds.map(
      get_spectrogram_and_label_id,  num_parallel_calls=AUTOTUNE)
  return output_ds
train_ds = spectrogram_ds
val_ds = preprocess_dataset(val_files)
test_ds = preprocess_dataset(test_files)

मॉडल प्रशिक्षण के लिए बैच प्रशिक्षण और सत्यापन सेट।

batch_size = 64
train_ds = train_ds.batch(batch_size)
val_ds = val_ds.batch(batch_size)

डाटासेट जोड़े cache() और prefetch() संचालन पढ़ने प्रतीक्षा अवधि कम करने, जबकि मॉडल प्रशिक्षण।

train_ds = train_ds.cache().prefetch(AUTOTUNE)
val_ds = val_ds.cache().prefetch(AUTOTUNE)

मॉडल के लिए, आप एक साधारण दृढ़ तंत्रिका नेटवर्क (सीएनएन) का उपयोग करेंगे, क्योंकि आपने ऑडियो फ़ाइलों को स्पेक्ट्रोग्राम छवियों में बदल दिया है। मॉडल में निम्नलिखित अतिरिक्त केरस प्रीप्रोसेसिंग परतें भी हैं:

  • tf.keras.layers.Resizing : तेजी से प्रशिक्षित करने के लिए मॉडल सक्षम करने के लिए इनपुट downsample करने के लिए।
  • tf.keras.layers.Normalization : अपनी माध्य और मानक विचलन के आधार पर छवि में प्रत्येक पिक्सेल को सामान्य बनाने में।

के लिए Normalization परत, इसके adapt विधि पहले के आदेश में कुल आंकड़े (यानी माध्य और मानक विचलन) की गणना करने के क्षेत्र में प्रशिक्षण के आंकड़ों पर कहा जा करने की आवश्यकता होगी।

for spectrogram, _ in spectrogram_ds.take(1):
  input_shape = spectrogram.shape
print('Input shape:', input_shape)
num_labels = len(commands)

norm_layer = layers.Normalization()
norm_layer.adapt(spectrogram_ds.map(lambda x, _: x))

model = models.Sequential([
    layers.Input(shape=input_shape),
    layers.Resizing(32, 32), 
    norm_layer,
    layers.Conv2D(32, 3, activation='relu'),
    layers.Conv2D(64, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Dropout(0.25),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(num_labels),
])

model.summary()
Input shape: (124, 129, 1)
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resizing (Resizing)          (None, 32, 32, 1)         0         
_________________________________________________________________
normalization (Normalization (None, 32, 32, 1)         3         
_________________________________________________________________
conv2d (Conv2D)              (None, 30, 30, 32)        320       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 28, 28, 64)        18496     
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 64)        0         
_________________________________________________________________
dropout (Dropout)            (None, 14, 14, 64)        0         
_________________________________________________________________
flatten (Flatten)            (None, 12544)             0         
_________________________________________________________________
dense (Dense)                (None, 128)               1605760   
_________________________________________________________________
dropout_1 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 8)                 1032      
=================================================================
Total params: 1,625,611
Trainable params: 1,625,608
Non-trainable params: 3
_________________________________________________________________
model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy'],
)
EPOCHS = 10
history = model.fit(
    train_ds, 
    validation_data=val_ds,  
    epochs=EPOCHS,
    callbacks=tf.keras.callbacks.EarlyStopping(verbose=1, patience=2),
)
Epoch 1/10
100/100 [==============================] - 14s 41ms/step - loss: 1.7739 - accuracy: 0.3600 - val_loss: 1.3077 - val_accuracy: 0.5838
Epoch 2/10
100/100 [==============================] - 0s 4ms/step - loss: 1.2051 - accuracy: 0.5766 - val_loss: 0.9049 - val_accuracy: 0.7000
Epoch 3/10
100/100 [==============================] - 0s 4ms/step - loss: 0.9100 - accuracy: 0.6825 - val_loss: 0.7509 - val_accuracy: 0.7525
Epoch 4/10
100/100 [==============================] - 0s 4ms/step - loss: 0.7684 - accuracy: 0.7316 - val_loss: 0.6925 - val_accuracy: 0.7688
Epoch 5/10
100/100 [==============================] - 0s 4ms/step - loss: 0.6551 - accuracy: 0.7711 - val_loss: 0.5822 - val_accuracy: 0.8112
Epoch 6/10
100/100 [==============================] - 0s 4ms/step - loss: 0.5601 - accuracy: 0.8050 - val_loss: 0.5667 - val_accuracy: 0.8062
Epoch 7/10
100/100 [==============================] - 0s 4ms/step - loss: 0.5201 - accuracy: 0.8169 - val_loss: 0.5552 - val_accuracy: 0.8263
Epoch 8/10
100/100 [==============================] - 0s 4ms/step - loss: 0.4643 - accuracy: 0.8405 - val_loss: 0.4698 - val_accuracy: 0.8338
Epoch 9/10
100/100 [==============================] - 0s 4ms/step - loss: 0.4156 - accuracy: 0.8583 - val_loss: 0.4831 - val_accuracy: 0.8350
Epoch 10/10
100/100 [==============================] - 0s 4ms/step - loss: 0.3903 - accuracy: 0.8630 - val_loss: 0.4545 - val_accuracy: 0.8425

आइए प्रशिक्षण और सत्यापन हानि वक्रों की जाँच करें कि प्रशिक्षण के दौरान आपके मॉडल में कैसे सुधार हुआ है।

metrics = history.history
plt.plot(history.epoch, metrics['loss'], metrics['val_loss'])
plt.legend(['loss', 'val_loss'])
plt.show()

पीएनजी

परीक्षण सेट प्रदर्शन का मूल्यांकन करें

आइए मॉडल को परीक्षण सेट पर चलाएं और प्रदर्शन की जांच करें।

test_audio = []
test_labels = []

for audio, label in test_ds:
  test_audio.append(audio.numpy())
  test_labels.append(label.numpy())

test_audio = np.array(test_audio)
test_labels = np.array(test_labels)
y_pred = np.argmax(model.predict(test_audio), axis=1)
y_true = test_labels

test_acc = sum(y_pred == y_true) / len(y_true)
print(f'Test set accuracy: {test_acc:.0%}')
Test set accuracy: 84%

एक भ्रम मैट्रिक्स प्रदर्शित करें

एक भ्रम मैट्रिक्स यह देखने में सहायक होता है कि परीक्षण सेट में प्रत्येक कमांड पर मॉडल ने कितना अच्छा प्रदर्शन किया।

confusion_mtx = tf.math.confusion_matrix(y_true, y_pred) 
plt.figure(figsize=(10, 8))
sns.heatmap(confusion_mtx, xticklabels=commands, yticklabels=commands, 
            annot=True, fmt='g')
plt.xlabel('Prediction')
plt.ylabel('Label')
plt.show()

पीएनजी

ऑडियो फ़ाइल पर अनुमान चलाएँ

अंत में, "नहीं" कहने वाले किसी व्यक्ति की इनपुट ऑडियो फ़ाइल का उपयोग करके मॉडल के पूर्वानुमान आउटपुट को सत्यापित करें। आपका मॉडल कितना अच्छा प्रदर्शन करता है?

sample_file = data_dir/'no/01bb6a2a_nohash_0.wav'

sample_ds = preprocess_dataset([str(sample_file)])

for spectrogram, label in sample_ds.batch(1):
  prediction = model(spectrogram)
  plt.bar(commands, tf.nn.softmax(prediction[0]))
  plt.title(f'Predictions for "{commands[label[0]]}"')
  plt.show()

पीएनजी

आप देख सकते हैं कि आपके मॉडल ने ऑडियो कमांड को "नहीं" के रूप में बहुत स्पष्ट रूप से पहचाना।

अगला कदम

इस ट्यूटोरियल में दिखाया गया है कि आप TensorFlow और Python के साथ कन्वेन्शनल न्यूरल नेटवर्क का उपयोग करके सरल ऑडियो वर्गीकरण कैसे कर सकते हैं।