main.py 7.18 KB
Newer Older
Hotwani's avatar
Hotwani committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import librosa.feature
import pandas as pd
import numpy as np
from pathlib import Path
from os import chdir
import os
import csv
from tensorflow import keras
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler
from keras import models
from keras import layers
from sklearn.metrics import classification_report
import constants
Hotwani's avatar
Hotwani committed
15
import sys
Hotwani's avatar
Hotwani committed
16
17
18


def create_csv_header():
Hotwani's avatar
Hotwani committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    if os.path.isfile(constants.TRAINED_MODEL):
        sys.exit("Trained model file already exists, "
                 "remove/move trained_model.h5 to another location and start training again")
    if os.path.isfile(constants.FEATURES_CSV_NAME):
        sys.exit("features.csv already exist, please remove/move the file to another location and run main.py again")
    else:
        header = 'filename '
        for i in range(constants.MFCC_RANGE_START, constants.MFCC_RANGE_END):
            header += f' mfcc{i}'
        header += ' label'
        header = header.split()
        file = open(constants.FEATURES_CSV_NAME, 'x', newline='')
        with file:
            writer = csv.writer(file)
            writer.writerow(header)
Hotwani's avatar
Hotwani committed
34
35
36
37
38
39


def extract_features(trainingDataDir, trainingDataSubDirs):
    create_csv_header()
    # Looping over every file inside the subdirectories for feature extraction
    for trainingDataSubDir in trainingDataSubDirs:
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
        if os.path.isdir(trainingDataSubDir):
            for audio_file_name in os.listdir(trainingDataDir/f'{trainingDataSubDir}'):
                if audio_file_name.endswith(".wav"):
                    audio_file = trainingDataDir/f'{trainingDataSubDir}/{audio_file_name}'
                    print("Extracting Features from Directory "+trainingDataSubDir+" and file "+audio_file.name)
                    y, sr = librosa.load(audio_file, mono=True)
                    mfcc_features = librosa.feature.mfcc(y=y, sr=sr,
                                                         n_mfcc=(constants.MFCC_RANGE_END - constants.MFCC_RANGE_START))
                    to_append = f'{audio_file.name}'
                    for mfcc_segment in mfcc_features:
                        to_append += f' {np.mean(mfcc_segment)}'
                    if trainingDataSubDir == constants.CAR:
                        to_append += f' {constants.LIGHT_WEIGHT}'
                    elif trainingDataSubDir == constants.BUS:
                        to_append += f' {constants.MEDIUM_WEIGHT}'
                    elif trainingDataSubDir == constants.TRUCK:
                        to_append += f' {constants.HEAVY_WEIGHT}'
                    elif trainingDataSubDir == constants.MOTORCYCLE:
                        to_append += f' {constants.TWO_WHEELED}'
                    elif trainingDataSubDir == constants.TRAM:
                        to_append += f' {constants.RAIL_BOUND}'

                    file = open(constants.FEATURES_CSV_NAME, 'a', newline='')
                    with file:
                        writer = csv.writer(file)
                        writer.writerow(to_append.split())
Hotwani's avatar
Hotwani committed
66
67
68


def preprocessing_csv_data():
Hotwani's avatar
Hotwani committed
69
70
    features_data = pd.read_csv(constants.FEATURES_CSV_NAME)
    features_data.head()
Hotwani's avatar
Hotwani committed
71
    # Dropping unnecessary columns (Column Filename is dropped)
Hotwani's avatar
Hotwani committed
72
73
74
    updated_features_data = features_data.drop(['filename'], axis=1)
    updated_features_data.head()
    return updated_features_data
Hotwani's avatar
Hotwani committed
75
76


Hotwani's avatar
Hotwani committed
77
def encode_labels(processedFeaturesData):
Hotwani's avatar
Hotwani committed
78
    # Extracting classes/label column as y from csv and converting string labels to numbers using LabelEncoder
Hotwani's avatar
Hotwani committed
79
80
81
82
    audio_labels_list = processedFeaturesData.iloc[:, -1]
    encode_object = LabelEncoder()
    encoded_target_audio_labels = encode_object.fit_transform(audio_labels_list)
    return encoded_target_audio_labels, encode_object
Hotwani's avatar
Hotwani committed
83
84


Hotwani's avatar
Hotwani committed
85
def normalize_data(processedData):
Hotwani's avatar
Hotwani committed
86
    # normalizing - Extracting Remaining Columns as X and normalizing them to a common scale
Hotwani's avatar
Hotwani committed
87
88
89
    scale_object = StandardScaler()
    X_normalized_features = scale_object.fit_transform(np.array(processedData.iloc[:, :-1], dtype=float))
    return X_normalized_features
Hotwani's avatar
Hotwani committed
90
91


Hotwani's avatar
Hotwani committed
92
def train_test_data_split(XInput, yLabels):
Hotwani's avatar
Hotwani committed
93
    # splitting of dataset into train and test dataset
Hotwani's avatar
Hotwani committed
94
95
96
    X_split_train, X_split_test, y_split_train, y_split_test = train_test_split(XInput, yLabels,
                                                                                test_size=constants.TEST_DATA_SPLIT)
    return X_split_train, X_split_test, y_split_train, y_split_test
Hotwani's avatar
Hotwani committed
97
98
99
100


def create_and_compile_model():
    print("Creating a Model")
Hotwani's avatar
Hotwani committed
101
102
103
104
105
106
    model_instance = models.Sequential()
    model_instance.add(layers.Dense(constants.HIDDEN_LAYER_1_DIMENSIONS, activation=constants.ACTIVATION_RELU,
                                    input_shape=(X_input_features.shape[1],)))
    model_instance.add(layers.Dense(constants.HIDDEN_LAYER_2_DIMENSIONS, activation=constants.ACTIVATION_RELU))
    model_instance.add(layers.Dense(constants.HIDDEN_LAYER_3_DIMENSIONS, activation=constants.ACTIVATION_RELU))
    model_instance.add(layers.Dense(constants.OUTPUT_LAYER_DIMENSIONS, activation=constants.ACTIVATION_SOFTMAX))
Hotwani's avatar
Hotwani committed
107
108

    print("Compiling a Model")
Hotwani's avatar
Hotwani committed
109
110
111
112
    model_instance.compile(optimizer=constants.OPTIMIZER_ADAM,
                           loss=constants.LOSS_FUNCTION_SPARSE,
                           metrics=[constants.ACCURACY_METRICS])
    return model_instance
Hotwani's avatar
Hotwani committed
113
114


Hotwani's avatar
Hotwani committed
115
116
117
118
def train_and_save_model(compiledModel, X_train, y_train, X_test, y_test):
    log_directory = constants.LOG_DIR_PATH
    tensorboard_callback = keras.callbacks.TensorBoard(log_dir=log_directory)

Hotwani's avatar
Hotwani committed
119
    print("Start Training...")
Hotwani's avatar
Hotwani committed
120
121
122
123
    training_history = compiledModel.fit(X_train, y_train, epochs=35,
                                         validation_data=(X_test, y_test),
                                         callbacks=[tensorboard_callback])

Hotwani's avatar
Hotwani committed
124
    # Saving the trained model to avoid re-training
Hotwani's avatar
Hotwani committed
125
126
    compiledModel.save(constants.TRAINED_MODEL)
    return training_history
Hotwani's avatar
Hotwani committed
127
128


129
def predict(X_test, y_test, encoder):
Hotwani's avatar
Hotwani committed
130
    print("Predictions.....")
Hotwani's avatar
Hotwani committed
131
132
133
    final_predictions = np.argmax(compiled_model.predict(X_test), axis=-1)
    target_names = [constants.LIGHT_WEIGHT, constants.MEDIUM_WEIGHT, constants.HEAVY_WEIGHT, constants.TWO_WHEELED,
                    constants.RAIL_BOUND]
134
135
    test_labels = encoder.inverse_transform(y_test)
    output_labels = encoder.inverse_transform(final_predictions)
Hotwani's avatar
Hotwani committed
136
    print(classification_report(y_test, final_predictions, target_names=target_names))
137
138
    df = pd.DataFrame({"Actual Output": test_labels, "Predicted Output": output_labels})
    df.to_csv(r'prediction_report.csv', index=False)
Hotwani's avatar
Hotwani committed
139
140
141
142


# Changing Directory to Training Dataset Folder
chdir(constants.TRAINING_DATA_DIRECTORY_NAME)
Hotwani's avatar
Hotwani committed
143
144
145
146
147
148
149
150
151
training_data_directory = Path.cwd()
training_data_sub_directories = os.listdir(training_data_directory)
extract_features(training_data_directory, training_data_sub_directories)
processed_features_data = preprocessing_csv_data()
target_audio_labels, encoder_object = encode_labels(processed_features_data)
X_input_features = normalize_data(processed_features_data)
X_train_data, X_test_data, y_train_data, y_test_data = train_test_data_split(X_input_features, target_audio_labels)
compiled_model = create_and_compile_model()
model_training_history = train_and_save_model(compiled_model, X_train_data, y_train_data, X_test_data, y_test_data)
152
predict(X_test_data, y_test_data, encoder_object)