<filename>pothole_predictor.py
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from keras.models import Input, load_model
from keras.layers import Dense
from keras import Model
from keras.callbacks import ModelCheckpoint
import matplotlib.pyplot as plt
import argparse
from keras import regularizers

parser = argparse.ArgumentParser(description='Choice-based ML model to find potholes along the road.')

parser.add_argument('--input', type=str, metavar='File path', help='path to .csv file generated by standardiser.py')

parser.add_argument('--mode', type=int, metavar='N', help='1 to train and validate on accelerometer data, 2 for '
                                                          'gyroscope, 3 for both')

args = parser.parse_args()
args_dictionary = vars(args)

model_choice = args_dictionary['mode']

RANDOM_SEED = 7
nb_epochs = 500
# increase batch size in case too many false positives are observed
batch_size = 9

df = pd.read_csv(args_dictionary['input'], error_bad_lines=False)

# determining dataframe dimensions and model filepath depending on choice of required predictions

model_filepath = None
predictions_filepath = None
if model_choice == 1:
    df.drop('GyrX', axis=1, inplace=True)
    df.drop('GyrY', axis=1, inplace=True)
    df.drop('GyrZ', axis=1, inplace=True)
    model_filepath = './model_accelerometer.h5'
    predictions_filepath = './data/predictions_accelerometer.csv'
elif model_choice == 2:
    df.drop('AccX', axis=1, inplace=True)
    df.drop('AccY', axis=1, inplace=True)
    df.drop('AccZ', axis=1, inplace=True)
    model_filepath = './model_gyroscope.h5'
    predictions_filepath = './data/predictions_gyroscope.csv'
elif model_choice == 3:
    predictions_filepath = './data/predictions_accelerometer_and_gyro.csv'
    model_filepath = './model_accelerometer_and_gyro.h5'

df.drop('GeoHash', axis=1, inplace=True)
# converting pandas dataframe to a numpy array
data = df.values
# TODO: ACCURACY MAY BE BETTER IF DATA IS NORMALISED
# data will be shuffled before splitting
# this is required so that the model learns pothole-free signatures, not driving style
X_train, X_test = train_test_split(
    data, test_size=0.2)
print('Shape = ' + str(X_train.shape[0]) + ', ' + str(X_train.shape[1]))
# input_dim contains number of columns in X_train
input_dim = X_train.shape[1]
timesteps = X_train.shape[0]
latent_dim = 1
hidden_layers = int(input_dim/2)
code_size = int(hidden_layers/2)

input_layer = Input(shape=(input_dim, ))
encoder = Dense(hidden_layers, activation='relu')(input_layer)
encoder = Dense(code_size, activation='relu', activity_regularizer=regularizers.l1(1e-7))(encoder)
decoder = Dense(hidden_layers, activation='relu')(encoder)
decoder = Dense(input_dim, activation='linear')(decoder)

autoencoder = Model(inputs=input_layer, outputs=decoder)
# mean_squared_error required for measuring error reconstruction
autoencoder.compile(
    optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])

checkpointer = ModelCheckpoint(
    filepath=model_filepath, verbose=1, save_best_only=True)
history = autoencoder.fit(x=X_train, y=X_train, epochs=nb_epochs, batch_size=batch_size,
                          shuffle=True, verbose=1, callbacks=[checkpointer], validation_data=(X_test, X_test)).history
plt.plot(history['loss'])
plt.plot(history['val_loss'])
plt.title('Model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right')
plt.show()

autoencoder = load_model(model_filepath)
predictions = autoencoder.predict(X_test)
mse = np.mean(np.power(X_test - predictions, 2), axis=1)
error_df = pd.DataFrame({'reconstruction_error': mse})
predictions_file = open(predictions_filepath, 'w')
error_df.to_csv(predictions_file)
print(error_df.describe())

# TODO: using labeled data, find out what the precision-recall metrics are

<filename>pothole_predictor.py
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from keras.models import Input, load_model
from keras.layers import Dense
from keras import Model
from keras.callbacks import ModelCheckpoint
import matplotlib.pyplot as plt
import argparse
from keras import regularizers

parser = argparse.ArgumentParser(description='Choice-based ML model to find potholes along the road.')

parser.add_argument('--input', type=str, metavar='File path', help='path to .csv file generated by standardiser.py')

parser.add_argument('--mode', type=int, metavar='N', help='1 to train and validate on accelerometer data, 2 for '
                                                          'gyroscope, 3 for both')

args = parser.parse_args()
args_dictionary = vars(args)

model_choice = args_dictionary['mode']

RANDOM_SEED = 7
nb_epochs = 500
# increase batch size in case too many false positives are observed
batch_size = 9

df = pd.read_csv(args_dictionary['input'], error_bad_lines=False)

# determining dataframe dimensions and model filepath depending on choice of required predictions

model_filepath = None
predictions_filepath = None
if model_choice == 1:
    df.drop('GyrX', axis=1, inplace=True)
    df.drop('GyrY', axis=1, inplace=True)
    df.drop('GyrZ', axis=1, inplace=True)
    model_filepath = './model_accelerometer.h5'
    predictions_filepath = './data/predictions_accelerometer.csv'
elif model_choice == 2:
    df.drop('AccX', axis=1, inplace=True)
    df.drop('AccY', axis=1, inplace=True)
    df.drop('AccZ', axis=1, inplace=True)
    model_filepath = './model_gyroscope.h5'
    predictions_filepath = './data/predictions_gyroscope.csv'
elif model_choice == 3:
    predictions_filepath = './data/predictions_accelerometer_and_gyro.csv'
    model_filepath = './model_accelerometer_and_gyro.h5'

df.drop('GeoHash', axis=1, inplace=True)
# converting pandas dataframe to a numpy array
data = df.values
# TODO: ACCURACY MAY BE BETTER IF DATA IS NORMALISED
# data will be shuffled before splitting
# this is required so that the model learns pothole-free signatures, not driving style
X_train, X_test = train_test_split(
    data, test_size=0.2)
print('Shape = ' + str(X_train.shape[0]) + ', ' + str(X_train.shape[1]))
# input_dim contains number of columns in X_train
input_dim = X_train.shape[1]
timesteps = X_train.shape[0]
latent_dim = 1
hidden_layers = int(input_dim/2)
code_size = int(hidden_layers/2)

input_layer = Input(shape=(input_dim, ))
encoder = Dense(hidden_layers, activation='relu')(input_layer)
encoder = Dense(code_size, activation='relu', activity_regularizer=regularizers.l1(1e-7))(encoder)
decoder = Dense(hidden_layers, activation='relu')(encoder)
decoder = Dense(input_dim, activation='linear')(decoder)

autoencoder = Model(inputs=input_layer, outputs=decoder)
# mean_squared_error required for measuring error reconstruction
autoencoder.compile(
    optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])

checkpointer = ModelCheckpoint(
    filepath=model_filepath, verbose=1, save_best_only=True)
history = autoencoder.fit(x=X_train, y=X_train, epochs=nb_epochs, batch_size=batch_size,
                          shuffle=True, verbose=1, callbacks=[checkpointer], validation_data=(X_test, X_test)).history
plt.plot(history['loss'])
plt.plot(history['val_loss'])
plt.title('Model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right')
plt.show()

autoencoder = load_model(model_filepath)
predictions = autoencoder.predict(X_test)
mse = np.mean(np.power(X_test - predictions, 2), axis=1)
error_df = pd.DataFrame({'reconstruction_error': mse})
predictions_file = open(predictions_filepath, 'w')
error_df.to_csv(predictions_file)
print(error_df.describe())

# TODO: using labeled data, find out what the precision-recall metrics are

# increase batch size in case too many false positives are observed # determining dataframe dimensions and model filepath depending on choice of required predictions # converting pandas dataframe to a numpy array # TODO: ACCURACY MAY BE BETTER IF DATA IS NORMALISED # data will be shuffled before splitting # this is required so that the model learns pothole-free signatures, not driving style # input_dim contains number of columns in X_train # mean_squared_error required for measuring error reconstruction # TODO: using labeled data, find out what the precision-recall metrics are