Search code examples
pythonarraystensorflowdeep-learningneural-network

Input to the Neural Network using an array


I am writing a neural network to take the Mel frequency coefficients as inputs and then run the model. My dataset contains 100 samples - each sample is an array of 12 values corresponding to the coefficients. After splitting this data into train and test sets, I have created the X input corresponding to the array and the y input corresponding to the label.

Data array containing the coefficients

Here is a small sample of my data containing 5 elements in the X_train array:

['[107.59366 -14.153783 24.799461 -8.244417 20.95272\n -4.375943 12.77285 -0.92922235 3.9418116 7.3581047\n -0.30066165 5.441765 ]' '[ 96.49664 2.0689797 21.557552 -32.827045 7.348135 -23.513977\n 7.9406714 -16.218931 10.594619 -21.4381 0.5903044 -10.569035 ]' '[105.98041 -2.0483367 12.276348 -27.334534 6.8239 -23.019623\n 7.5176797 -21.884727 11.349695 -22.734652 3.0335162 -11.142375 ]' '[ 7.73094559e+01 1.91073620e+00 6.72225571e+00 -2.74525508e-02\n 6.60858107e+00 5.99264860e-01 1.96265772e-01 -3.94772577e+00\n 7.46383286e+00 5.42239428e+00 1.21432066e-01 2.44894314e+00]']

When I create the Neural network, I want to use the 12 coefficients as an input for the network. In order to do this, I need to use each row of my X_train dataset that contains these arrays as the input. However, when I try to consider the array index as an input it gives me shape errors when trying to fit the model. My model is as follows:

def build_model_graph():
model = Sequential()
model.add(Input(shape=(12,)))
model.add(Dense(12))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('relu'))
model.add(Dense(num_labels))
model.add(Activation('softmax'))
# Compile the model
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
return model

Here, I want to use every row of the X_train array as an input which would correspond to the shape(12,). When I use something like this:

num_epochs = 50
num_batch_size = 32
model.fit(x_train, y_train, batch_size=num_batch_size, epochs=num_epochs, 
validation_data=(x_test, y_test), verbose=1)

I get an error for the shape which makes sense to me. For reference, the error is as follows:

ValueError: Exception encountered when calling layer "sequential_20" (type Sequential).

Input 0 of layer "dense_54" is incompatible with the layer: expected min_ndim=2, found ndim=1. Full shape received: (None,)

But I am not exactly sure how I can extract the array of 12 coefficients present at each index of the X_train and then use it in the model input. Indexing the x_train and y_train did not work either. If anyone could point me in a relevant direction, it would be extremely helpful. Thanks!

Edit: My code for the dataframe is as follows:

clapdf = pd.read_csv("clapsdf.csv")
clapdf.drop('Unnamed: 0', inplace=True, axis=1)
clapdf.head()
nonclapdf = pd.read_csv("nonclapsdf.csv")
nonclapdf.drop('Unnamed: 0', inplace=True, axis=1)
sound_df = clapdf.append(nonclapdf)
sound_df.head()
d=sound_data.tolist()
df=pd.DataFrame(data=d)
data = df[0].to_numpy()
print("Before-->", data.shape)
dat = np.array([np.array(d) for d in data])
print('After-->', dat.shape)

Here, the shape remains the same as the values of each of the 80 samples are not in a comma separated format but instead in the form of a series.


Solution

  • If your data looks like this:

    samples = 2
    features = 12
    x_train = tf.random.normal((samples, 1, features))
    
    tf.Tensor(
    [[[-2.5988803  -0.629626   -0.8306641  -0.78226614  0.88989156
       -0.3851106  -0.66053045  1.0571191  -0.59061646 -1.1602987
        0.69124466 -0.04354193]]
    
     [[-0.86917496  2.2923143  -0.05498986 -0.09578358  0.85037625
       -0.54679644 -1.2213608  -1.3766612   0.35416105 -0.57801914
       -0.3699728   0.7884727 ]]], shape=(2, 1, 12), dtype=float32)
    

    You will have to reshape it to (2, 12) in order to fit your model with the input shape (batch_size, 12):

    import tensorflow as tf
    
    def build_model_graph():
      model = tf.keras.Sequential()
      model.add(tf.keras.layers.Input(shape=(12,)))
      model.add(tf.keras.layers.Dense(12))
      model.add(tf.keras.layers.Activation('relu'))
      model.add(tf.keras.layers.Dense(10))
      model.add(tf.keras.layers.Activation('relu'))
      model.add(tf.keras.layers.Dense(2))
      model.add(tf.keras.layers.Activation('softmax'))
      # Compile the model
      model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
      return model
    
    model = build_model_graph()
    
    samples = 2
    features = 12
    x_train = tf.random.normal((samples, 1, features))
    x_train = tf.reshape(x_train, (samples, features))
    y = tf.random.uniform((samples, 1), maxval=2, dtype=tf.int32)
    y_train = tf.keras.utils.to_categorical(y, 2)
    model.fit(x_train, y_train, batch_size=1, epochs=2)
    

    Also, you usually need to convert your labels to one-hot encoded vectors if you plan to use categorical_crossentropy. y_train looks like this:

    [[0. 1.]
     [1. 0.]]
    

    Update 1: If your data is coming from a dataframe, try something like this:

    import numpy as np
    import pandas as pd
    
    d = {'features': [[0.18525402, 0.92130125, 0.2296906,  0.75818471, 0.69813222, 0.47147329,
                       0.03560711, 0.06583931, 0.90921289, 0.76002148, 0.50413995, 0.36099004], 
                      [0.18525402, 0.92130125, 0.2296906,  0.75818471, 0.69813222, 0.47147329,
                       0.03560711, 0.06583931, 0.90921289, 0.76002148, 0.50413995, 0.36099004]]}
    df = pd.DataFrame(data=d)
    
    data = df['features'].to_numpy()
    print('Before -->', data.shape)
    data = np.array([np.array(d) for d in data])
    print('After -->', data.shape)
    
    Before --> (2,)
    After --> (2, 12)