Kumar Shubham commited on
Commit
2c2f868
·
1 Parent(s): 271a1c7

Adding all files

Browse files
app.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import joblib
4
+ from sound_classifier import SoundClassifier
5
+ import numpy as np
6
+
7
+ # Get list of available models and their friendly names
8
+ MODELS_DIR = 'models'
9
+ MODEL_NAMES = {
10
+ 'lr_sound_classifier_model.joblib': 'Logistic Regression',
11
+ 'nn_sound_classifier_model.joblib': 'Neural Network',
12
+ 'rf_sound_classifier_model.joblib': 'Random Forest',
13
+ 'svm_sound_classifier_model.joblib': 'Support Vector Machine'
14
+ }
15
+
16
+ model_files = [f for f in os.listdir(MODELS_DIR) if f.endswith('_model.joblib')]
17
+ model_choices = {MODEL_NAMES[file]: file for file in model_files}
18
+
19
+ def load_model(model_file):
20
+ """Load a saved model and its associated scaler and label encoder"""
21
+ model_path = os.path.join(MODELS_DIR, model_file)
22
+ saved_data = joblib.load(model_path)
23
+ return saved_data['model'], saved_data['scaler'], saved_data['label_encoder']
24
+
25
+ def format_issue(issue_text):
26
+ """Format the issue text to be more readable"""
27
+ # Replace underscores with spaces and title case the text
28
+ formatted = issue_text.replace('_', ' ').title()
29
+ return formatted
30
+
31
+ def predict_sound(audio_file, model_name):
32
+ """
33
+ Function to make predictions on uploaded audio files using the selected model
34
+ """
35
+ # Get the actual model filename from the friendly name
36
+ model_file = model_choices[model_name]
37
+
38
+ # Load the selected model
39
+ model, scaler, le = load_model(model_file)
40
+
41
+ # Initialize classifier for feature extraction only
42
+ classifier = SoundClassifier(data_dir='data')
43
+
44
+ # Extract features and predict
45
+ features = classifier.extract_features(audio_file)
46
+ features = features.reshape(1, -1)
47
+ features_scaled = scaler.transform(features)
48
+ prediction = model.predict(features_scaled)
49
+
50
+ # Get the predicted label and format it
51
+ predicted_label = le.inverse_transform(prediction)[0]
52
+ formatted_label = format_issue(predicted_label)
53
+
54
+ return f"Predicted Issue: {formatted_label}"
55
+
56
+ # Create Gradio interface
57
+ iface = gr.Interface(
58
+ fn=predict_sound,
59
+ inputs=[
60
+ gr.Audio(type="filepath", label="Upload Sound File"),
61
+ gr.Dropdown(choices=list(model_choices.keys()), label="Select Model Type", value=list(model_choices.keys())[0])
62
+ ],
63
+ outputs=gr.Textbox(label="Prediction"),
64
+ title="Engine Sound Issue Classifier",
65
+ description="Upload an audio file of engine sound to identify potential issues. Choose from different machine learning models.",
66
+ examples=[
67
+ [os.path.join("test_data", "air_filter_sample_5.wav"), list(model_choices.keys())[0]],
68
+ [os.path.join("test_data", "cd_sample_16.wav"), list(model_choices.keys())[1]],
69
+ [os.path.join("test_data", "vl_sample_4.wav"), list(model_choices.keys())[2]]
70
+ ]
71
+ )
72
+
73
+ if __name__ == "__main__":
74
+ iface.launch()
75
+
models/lr_sound_classifier_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e6cbd07e39ac1508901942b63bb123f3e11a69bc0fb6080a4cb30df2f9ca75bb
3
+ size 3363
models/nn_sound_classifier_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8357223fcdbc7ac1cddcc6179a7ac7a5dca08c27af719e6627b62e1d0ec52976
3
+ size 272851
models/rf_sound_classifier_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f36dac57d6ebcec562dd1e5dc6b10526e54c9a820f46781ed24951088670ab87
3
+ size 119043
models/svm_sound_classifier_model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f8706f20c6742817c9b095fe7de9d6698516d344dc2fddb9e8bd072d80581429
3
+ size 8564
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ numpy>=1.20.0
2
+ librosa>=0.9.0
3
+ scikit-learn>=0.24.0
4
+ joblib>=1.0.0
5
+ pandas>=1.3.0
6
+ matplotlib>=3.4.0
7
+ seaborn>=0.11.0
8
+ scipy>=1.7.0
9
+ gradio>=4.0.0
10
+ onnx>=1.15.0
11
+ skl2onnx>=1.14.0
12
+ onnxruntime>=1.16.0
sound_classifier.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import librosa
4
+ from sklearn.model_selection import train_test_split
5
+ from sklearn.preprocessing import LabelEncoder, StandardScaler
6
+ from sklearn.ensemble import RandomForestClassifier
7
+ from sklearn.linear_model import LogisticRegression
8
+ from sklearn.svm import SVC
9
+ from sklearn.neural_network import MLPClassifier
10
+ from sklearn.metrics import classification_report
11
+ import joblib
12
+
13
+
14
+ class SoundClassifier:
15
+ def __init__(self, data_dir, model_type='rf', sr=22050, duration=20):
16
+ self.data_dir = data_dir
17
+ self.sr = sr
18
+ self.duration = duration
19
+ self.model = None
20
+ self.le = LabelEncoder()
21
+ self.scaler = StandardScaler()
22
+ self.model_type = model_type
23
+
24
+ def extract_features(self, file_path):
25
+ # Load audio file
26
+ y, _ = librosa.load(file_path, sr=self.sr, duration=self.duration)
27
+
28
+ # Pad or truncate to fixed length
29
+ if len(y) < self.sr * self.duration:
30
+ y = np.pad(y, (0, self.sr * self.duration - len(y)))
31
+ else:
32
+ y = y[:self.sr * self.duration]
33
+
34
+ # Extract features
35
+ mfccs = librosa.feature.mfcc(y=y, sr=self.sr, n_mfcc=13)
36
+ spectral_centroid = librosa.feature.spectral_centroid(y=y, sr=self.sr)
37
+ spectral_rolloff = librosa.feature.spectral_rolloff(y=y, sr=self.sr)
38
+
39
+ # Compute statistics
40
+ features = np.concatenate([
41
+ mfccs.mean(axis=1),
42
+ mfccs.std(axis=1),
43
+ spectral_centroid.mean(axis=1),
44
+ spectral_rolloff.mean(axis=1)
45
+ ])
46
+
47
+ return features
48
+
49
+ def prepare_data(self):
50
+ X = []
51
+ y = []
52
+
53
+ # Iterate through each issue folder
54
+ for issue in os.listdir(self.data_dir):
55
+ issue_path = os.path.join(self.data_dir, issue)
56
+ if os.path.isdir(issue_path):
57
+ # Process each audio file in the folder
58
+ for audio_file in os.listdir(issue_path):
59
+ if audio_file.endswith('.wav'):
60
+ file_path = os.path.join(issue_path, audio_file)
61
+ features = self.extract_features(file_path)
62
+ X.append(features)
63
+ y.append(issue)
64
+ print(len(X))
65
+ print(len(y))
66
+ X = np.array(X)
67
+ y = self.le.fit_transform(y)
68
+
69
+ return X, y
70
+
71
+ def train(self):
72
+ # Prepare data
73
+ X, y = self.prepare_data()
74
+
75
+ # Split data
76
+ X_train, X_test, y_train, y_test = train_test_split(
77
+ X, y, test_size=0.2, random_state=42
78
+ )
79
+
80
+ # Scale features
81
+ X_train_scaled = self.scaler.fit_transform(X_train)
82
+ X_test_scaled = self.scaler.transform(X_test)
83
+
84
+ # Train model based on model_type
85
+ if self.model_type == 'rf':
86
+ self.model = RandomForestClassifier(n_estimators=100, random_state=42)
87
+ elif self.model_type == 'lr':
88
+ self.model = LogisticRegression(random_state=42, max_iter=1000)
89
+ elif self.model_type == 'svm':
90
+ self.model = SVC(kernel='rbf', random_state=42)
91
+ elif self.model_type == 'nn':
92
+ self.model = MLPClassifier(hidden_layer_sizes=(100, 50), max_iter=1000, random_state=42)
93
+ else:
94
+ raise ValueError("Invalid model type. Choose 'rf', 'lr', 'svm', or 'nn'.")
95
+
96
+ self.model.fit(X_train_scaled, y_train)
97
+
98
+ # Evaluate
99
+ y_pred = self.model.predict(X_test_scaled)
100
+ print(f"\nModel Performance ({self.model_type}):")
101
+ print(classification_report(y_test, y_pred,
102
+ labels=np.unique(y),
103
+ target_names=self.le.classes_[np.unique(y)]))
104
+
105
+ return self.model
106
+
107
+ def predict(self, audio_file):
108
+ # Extract features from new audio
109
+ features = self.extract_features(audio_file)
110
+
111
+ # Scale features
112
+ features_scaled = self.scaler.transform([features])
113
+
114
+ # Make prediction
115
+ prediction = self.model.predict(features_scaled)[0]
116
+
117
+ # Return the issue name
118
+ return self.le.inverse_transform([prediction])[0]
119
+
120
+ def save_model(self, model_path='sound_classifier_model.joblib'):
121
+ """Save the trained model, label encoder, and scaler"""
122
+ if self.model is None:
123
+ raise ValueError("Model hasn't been trained yet!")
124
+
125
+ model_data = {
126
+ 'model': self.model,
127
+ 'label_encoder': self.le,
128
+ 'scaler': self.scaler,
129
+ 'model_type': self.model_type
130
+ }
131
+ joblib.dump(model_data, model_path)
132
+
133
+ @classmethod
134
+ def load_model(cls, model_path='sound_classifier_model.joblib'):
135
+ """Load a trained model"""
136
+ classifier = cls(data_dir=None) # Create instance without data dir
137
+ model_data = joblib.load(model_path)
138
+ classifier.model = model_data['model']
139
+ classifier.le = model_data['label_encoder']
140
+ classifier.scaler = model_data['scaler']
141
+ classifier.model_type = model_data['model_type']
142
+ return classifier