• The TensorFlow tutorials are written as Jupyter notebooks and run directly in Google Colab—a hosted notebook environment that requires no setup. Click the Run in Google Colab button.


  • Colab link - Open colab


  • **Understanding the Problem Statement for our Speech-to-Text Project**


  • Let’s understand the problem statement of our project before we move into the implementation part.


  • We might be on the verge of having too many screens around us. It seems like every day, new versions of common objects are “re-invented” with built-in wifi and bright touchscreens. A promising antidote to our screen addiction is voice interfaces.


  • TensorFlow recently released the Speech Commands Datasets. It includes 65,000 one-second long utterances of 30 short words, by thousands of different people. We’ll build a speech recognition system that understands simple spoken commands.


  • You can download the dataset from [here](https://www.kaggle.com/c/tensorflow-speech-recognition-challenge).


  • Implementing the Speech-to-Text Model in Python


  • First, import all the necessary libraries into our notebook. LibROSA and SciPy are the Python libraries used for processing audio signals.


  • 
    import os
    import librosa
    import IPython.display as ipd
    import matplotlib.pyplot as plt
    import numpy as np
    from scipy.io import wavfile
    import warnings
    
    warnings.filterwarnings("ignore")
      
    
  • #Download dataset


  • 
    !wget 'http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip'
    !unzip mini_speech_commands.zip
    !rm '/content/mini_speech_commands/README.md'
      
    
  • Data Exploration and Visualization - Data Exploration and Visualization helps us to understand the data as well as pre-processing steps in a better way.


  • Visualization of Audio signal in time series domain - Now, we’ll visualize the audio signal in the time series domain.


  • 
    train_audio_path = '/content/mini_speech_commands/'
    samples, sample_rate = librosa.load(train_audio_path+'yes/004ae714_nohash_0.wav', sr = 16000)
    fig = plt.figure(figsize=(14, 8))
    ax1 = fig.add_subplot(211)
    ax1.set_title('Raw wave of ' + '/content/mini_speech_commands/yes/004ae714_nohash_0.wav')
    ax1.set_xlabel('time')
    ax1.set_ylabel('Amplitude')
    ax1.plot(np.linspace(0, sample_rate/len(samples), sample_rate), samples)
      
    
  • Sampling rate - Let us now look at the sampling rate of the audio signals


  • 
    ipd.Audio(samples, rate=sample_rate)
    
    print(sample_rate)
    
      
    
  • Resampling - From the above, we can understand that the sampling rate of the signal is 16000 hz. Let us resample it to 8000 hz since most of the speech related frequencies are present in 8000z


  • 
    samples = librosa.resample(samples, sample_rate, 8000)
    ipd.Audio(samples, rate=8000)
      
    
  • Now, let’s understand the number of recordings for each voice command:


  • 
    labels=os.listdir(train_audio_path)
    
    #find count of each label and plot bar graph
    no_of_recordings=[]
    for label in labels:
        waves = [f for f in os.listdir(train_audio_path + '/'+ label) if f.endswith('.wav')]
        no_of_recordings.append(len(waves))
        
    #plot
    plt.figure(figsize=(30,5))
    index = np.arange(len(labels))
    plt.bar(index, no_of_recordings)
    plt.xlabel('Commands', fontsize=12)
    plt.ylabel('No of recordings', fontsize=12)
    plt.xticks(index, labels, fontsize=15, rotation=60)
    plt.title('No. of recordings for each command')
    plt.show()
    
    labels=["yes", "no", "up", "down", "left", "right", "stop", "go"]
      
    
  • Duration of recordings - What’s next? A look at the distribution of the duration of recordings.


  • 
    duration_of_recordings=[]
    for label in labels:
        waves = [f for f in os.listdir(train_audio_path + '/'+ label) if f.endswith('.wav')]
        for wav in waves:
            sample_rate, samples = wavfile.read(train_audio_path + '/' + label + '/' + wav)
            duration_of_recordings.append(float(len(samples)/sample_rate))
        
    plt.hist(np.array(duration_of_recordings))
      
    
  • Preprocessing the audio waves - In the data exploration part earlier, we have seen that the duration of a few recordings is less than 1 second and the sampling rate is too high. So, let us read the audio waves and use the below-preprocessing steps to deal with this.


  • Here are the two steps we’ll follow: Resampling, Removing shorter commands of less than 1 second.


  • Let us define these preprocessing steps in the below code snippet:


  • 
    train_audio_path = '/content/mini_speech_commands'
    
    all_wave = []
    all_label = []
    for label in labels:
        print(label)
        waves = [f for f in os.listdir(train_audio_path + '/'+ label) if f.endswith('.wav')]
        for wav in waves:
            samples, sample_rate = librosa.load(train_audio_path + '/' + label + '/' + wav, sr = 16000)
            samples = librosa.resample(samples, sample_rate, 8000)
            if(len(samples)== 8000) : 
                all_wave.append(samples)
                all_label.append(label)
      
    
  • Convert the output labels to integer encoded:


  • 
    from sklearn.preprocessing import LabelEncoder
    le = LabelEncoder()
    y=le.fit_transform(all_label)
    classes= list(le.classes_)
      
    
  • Now, convert the integer encoded labels to a one-hot vector since it is a multi-classification problem:


  • 
    from keras.utils import np_utils
    y=np_utils.to_categorical(y, num_classes=len(labels))
      
    
  • Reshape the 2D array to 3D since the input to the conv1d must be a 3D array:


  • 
    all_wave = np.array(all_wave).reshape(-1,8000,1)
      
    
  • Split into train and validation set - Next, we will train the model on 80% of the data and validate on the remaining 20%:


  • 
    from sklearn.model_selection import train_test_split
    x_tr, x_val, y_tr, y_val = train_test_split(np.array(all_wave),np.array(y),stratify=y,test_size = 0.2,random_state=777,shuffle=True)
    
      
    
  • Model Architecture for this problem - We will build the speech-to-text model using conv1d. Conv1d is a convolutional neural network which performs the convolution along only one dimension.

  • Model building - Let us implement the model using Keras functional API.


  • 
    from keras.layers import Dense, Dropout, Flatten, Conv1D, Input, MaxPooling1D
    from keras.models import Model
    from keras.callbacks import EarlyStopping, ModelCheckpoint
    from keras import backend as K
    K.clear_session()
    
    inputs = Input(shape=(8000,1))
    
    #First Conv1D layer
    conv = Conv1D(8,13, padding='valid', activation='relu', strides=1)(inputs)
    conv = MaxPooling1D(3)(conv)
    conv = Dropout(0.3)(conv)
    
    #Second Conv1D layer
    conv = Conv1D(16, 11, padding='valid', activation='relu', strides=1)(conv)
    conv = MaxPooling1D(3)(conv)
    conv = Dropout(0.3)(conv)
    
    #Third Conv1D layer
    conv = Conv1D(32, 9, padding='valid', activation='relu', strides=1)(conv)
    conv = MaxPooling1D(3)(conv)
    conv = Dropout(0.3)(conv)
    
    #Fourth Conv1D layer
    conv = Conv1D(64, 7, padding='valid', activation='relu', strides=1)(conv)
    conv = MaxPooling1D(3)(conv)
    conv = Dropout(0.3)(conv)
    
    #Flatten layer
    conv = Flatten()(conv)
    
    #Dense Layer 1
    conv = Dense(256, activation='relu')(conv)
    conv = Dropout(0.3)(conv)
    
    #Dense Layer 2
    conv = Dense(128, activation='relu')(conv)
    conv = Dropout(0.3)(conv)
    
    outputs = Dense(len(labels), activation='softmax')(conv)
    
    model = Model(inputs, outputs)
    model.summary()
      
    
  • Define the loss function to be categorical cross-entropy since it is a multi-classification problem:


  • 
    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
      
    
  • Early stopping and model checkpoints are the callbacks to stop training the neural network at the right time and to save the best model after every epoch:


  • 
    es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=10, min_delta=0.0001) 
    mc = ModelCheckpoint('best_model.hdf5', monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
      
    
  • Let us train the model on a batch size of 32 and evaluate the performance on the holdout set:


  • 
    history=model.fit(x_tr, y_tr ,epochs=100, callbacks=[es,mc], batch_size=32, validation_data=(x_val,y_val))
      
    
  • Diagnostic plot - I’m going to lean on visualization again to understand the performance of the model over a period of time:


  • 
    from matplotlib import pyplot
    pyplot.plot(history.history['loss'], label='train')
    pyplot.plot(history.history['val_loss'], label='test')
    pyplot.legend()
    pyplot.show()
      
    
  • Loading the best model


  • 
    from keras.models import load_model
    model=load_model('best_model.hdf5')
      
    
  • Define the function that predicts text for the given audio:


  • 
    def predict(audio):
        prob=model.predict(audio.reshape(1,8000,1))
        index=np.argmax(prob[0])
        return classes[index]
      
    
  • Prediction time! Make predictions on the validation data:


  • 
    import random
    index=random.randint(0,len(x_val)-1)
    samples=x_val[index].ravel()
    print("Audio:",classes[np.argmax(y_val[index])])
    ipd.Audio(samples, rate=8000)
    
    print("Text:",predict(samples))