Variable Input for a classification neural network

Viewed 99

I am currently working on a project, where I have a sensor in a shoe which records the XYZ from an acceleration and gyroscope sensor. Every millisecond I get 6 data points. Now the goal is, if I do an action, such a jumping or kicking, I would use the sensor's output to predict that action being done.

Here is the issue: if I jump, for example, one time I may get 1000 data points, but in another, I get 1200 amounts, meaning the size of the input is different. The Neural Network’s I’ve studied so far require the input size to be constant to predict a Y value, however, in this case, it isn’t. I've done some research on how to make a neural network with variable sizes, but haven't been able to find one which works. It's not a good idea to crop the input to a certain size, because then I am losing data. In addition, if I just resize the smaller trials by putting extra 0s, it skews the model. Any suggestions on a model that would work or how to better clean the data?

1 Answers

What you need is here is RNNs. Most of my code uses TensorFlow but the same is available in most other DL libraries as well. RNNs can handle variable-length data and are used in many things such as speech detection. (Speech can be of variable length and like you said, we cant shorten it or break it into smaller boxes either). Below is a small example that implements a simple NN that fits your model requirements.

We also have to use ragged tensors with RNNs for your task. Ragged tensors, as the name suggests have variable internal shape and are perfect for representing cases where the time duration is variable.

import tensorflow as tf
import numpy as np


x = []
# Your action sequences stored as one-hot encoding.
y = tf.one_hot(np.array([np.random.randint(0, 4) for _ in range(100)]), 5)
# Your input data, each row is a np array of shape (random value between 600 and 1200, 5)
for i in range(100):
    temp = np.random.randint(600, 1200)
    x.append(np.random.rand(temp, 5))

x = tf.ragged.constant(x)

keras_model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=[None, 5], dtype=tf.float64, ragged=True),
    tf.keras.layers.LSTM(32),
    tf.keras.layers.Dense(32),
    tf.keras.layers.Activation(tf.nn.relu),
    tf.keras.layers.Dense(5)
])

keras_model.compile(optimizer='rmsprop', loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True))
keras_model.fit(x, y, epochs=100)

I have kept the internal model complexity to a minimum, which I hope with further testing you can expand upon. The best architecture will require testing. My recommendation is to use multiple Bidirectional GRUs and end with a couple of small dense layers.

Related