Spaces:
Sleeping
Sleeping
Commit ·
46e4a69
1
Parent(s): e85ad1a
init model
Browse files- .gitignore +2 -0
- app.py +185 -0
- requirements.txt +10 -0
- saved_model/best_cat_model.pkl +0 -0
- saved_model/best_lgbm_model.pkl +3 -0
- saved_model/best_model.keras +3 -0
- saved_model/l1_model.pkl +3 -0
- saved_model/lr_model_selected.pkl +3 -0
- saved_model/rf_model.pkl +3 -0
- saved_model/rfe_svm.pkl +3 -0
- saved_model/scaler_xgb_lgbm.pkl +3 -0
- saved_model/xgb_model.pkl +3 -0
.gitignore
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
| 2 |
+
flagged
|
app.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import numpy as np
|
| 3 |
+
import joblib
|
| 4 |
+
import lightgbm
|
| 5 |
+
|
| 6 |
+
import librosa
|
| 7 |
+
import numpy as np
|
| 8 |
+
import tensorflow as tf
|
| 9 |
+
from tensorflow.keras.models import load_model
|
| 10 |
+
import pickle
|
| 11 |
+
from tensorflow.keras.models import Model
|
| 12 |
+
from tensorflow.keras.layers import (
|
| 13 |
+
Input,
|
| 14 |
+
Conv1D,
|
| 15 |
+
LSTM,
|
| 16 |
+
Bidirectional,
|
| 17 |
+
Dense,
|
| 18 |
+
Dropout,
|
| 19 |
+
Concatenate,
|
| 20 |
+
Layer,
|
| 21 |
+
BatchNormalization,
|
| 22 |
+
)
|
| 23 |
+
from tensorflow.keras.utils import get_custom_objects
|
| 24 |
+
from tensorflow.keras.saving import register_keras_serializable
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# 🔹 Attention Layer
|
| 28 |
+
@register_keras_serializable()
|
| 29 |
+
class Attention(Layer):
|
| 30 |
+
def __init__(self, **kwargs):
|
| 31 |
+
super(Attention, self).__init__(**kwargs)
|
| 32 |
+
self.attention_dense = Dense(1, activation=None)
|
| 33 |
+
|
| 34 |
+
def call(self, inputs):
|
| 35 |
+
attention_scores = self.attention_dense(inputs)
|
| 36 |
+
attention_weights = tf.nn.softmax(attention_scores, axis=1)
|
| 37 |
+
return tf.reduce_sum(inputs * attention_weights, axis=1)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
# ✅ Register the custom object manually
|
| 41 |
+
get_custom_objects()["Attention"] = Attention
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# 🔹 Normalize Data Properly
|
| 45 |
+
def normalize(X):
|
| 46 |
+
return (X - np.min(X, axis=0)) / (np.max(X, axis=0) - np.min(X, axis=0) + 1e-8)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# Load the trained model
|
| 50 |
+
lr_model = joblib.load("saved_model/best_lgbm_model.pkl")
|
| 51 |
+
with open("saved_model/scaler_xgb_lgbm.pkl", "rb") as s:
|
| 52 |
+
scaler = pickle.load(s)
|
| 53 |
+
|
| 54 |
+
# Define the feature list based on the dataset (excluding 'id' and target column)
|
| 55 |
+
feature_names = [
|
| 56 |
+
"Age",
|
| 57 |
+
"Cough",
|
| 58 |
+
"WeightLoss",
|
| 59 |
+
"Gender_Male",
|
| 60 |
+
"Gender_Other",
|
| 61 |
+
"Fever_Yes",
|
| 62 |
+
"NightSweats_Yes",
|
| 63 |
+
"ChestPain_Yes",
|
| 64 |
+
"Hemoptysis_Yes",
|
| 65 |
+
"Breathlessness_Moderate",
|
| 66 |
+
"Breathlessness_Severe",
|
| 67 |
+
"ContactHistory_Yes",
|
| 68 |
+
"TravelHistory_Yes",
|
| 69 |
+
"HIVStatus_Positive",
|
| 70 |
+
"PreviousTB_Yes",
|
| 71 |
+
]
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# Define the prediction function
|
| 75 |
+
def predict_tuberculosis(*features):
|
| 76 |
+
try:
|
| 77 |
+
# Convert inputs to a NumPy array and reshape for model prediction
|
| 78 |
+
features_array = np.array(features, dtype=float).reshape(1, -1)
|
| 79 |
+
print(features_array)
|
| 80 |
+
features_array_scaled = scaler.transform(features_array)
|
| 81 |
+
print(features_array_scaled)
|
| 82 |
+
prediction = lr_model.predict(features_array_scaled)
|
| 83 |
+
print(prediction)
|
| 84 |
+
|
| 85 |
+
return (
|
| 86 |
+
"Tuberculosis Positive" if prediction[0] == 1 else "Tuberculosis Negative"
|
| 87 |
+
)
|
| 88 |
+
except Exception as e:
|
| 89 |
+
return f"Error: {e}"
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
# Load the trained model
|
| 93 |
+
model = load_model("saved_model/best_model.keras")
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
# Function to extract audio features
|
| 97 |
+
def extract_features(audio_path, sr=22050, max_len=157):
|
| 98 |
+
try:
|
| 99 |
+
# Load the audio file
|
| 100 |
+
y, sr = librosa.load(audio_path, sr=sr)
|
| 101 |
+
|
| 102 |
+
# Extract features
|
| 103 |
+
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=20) # (20, time)
|
| 104 |
+
chroma = librosa.feature.chroma_stft(y=y, sr=sr) # (12, time)
|
| 105 |
+
mel = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128) # (128, time)
|
| 106 |
+
spec_contrast = librosa.feature.spectral_contrast(y=y, sr=sr) # (7, time)
|
| 107 |
+
|
| 108 |
+
# Transpose and pad/crop to max_len
|
| 109 |
+
def pad_or_truncate(feature, target_shape):
|
| 110 |
+
if feature.shape[1] > target_shape:
|
| 111 |
+
return feature[:, :target_shape]
|
| 112 |
+
else:
|
| 113 |
+
return np.pad(
|
| 114 |
+
feature,
|
| 115 |
+
((0, 0), (0, target_shape - feature.shape[1])),
|
| 116 |
+
mode="constant",
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
mfcc = pad_or_truncate(mfcc, max_len).T # (157, 20)
|
| 120 |
+
chroma = pad_or_truncate(chroma, max_len).T # (157, 12)
|
| 121 |
+
mel = pad_or_truncate(mel, max_len).T # (157, 128)
|
| 122 |
+
spec_contrast = pad_or_truncate(spec_contrast, max_len).T # (157, 7)
|
| 123 |
+
|
| 124 |
+
# Normalize
|
| 125 |
+
def normalize(X):
|
| 126 |
+
return (X - np.min(X)) / (np.max(X) - np.min(X) + 1e-8)
|
| 127 |
+
|
| 128 |
+
mfcc = normalize(mfcc)
|
| 129 |
+
chroma = normalize(chroma)
|
| 130 |
+
mel = normalize(mel)
|
| 131 |
+
spec_contrast = normalize(spec_contrast)
|
| 132 |
+
|
| 133 |
+
return (
|
| 134 |
+
np.array([mfcc]),
|
| 135 |
+
np.array([chroma]),
|
| 136 |
+
np.array([mel]),
|
| 137 |
+
np.array([spec_contrast]),
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
except Exception as e:
|
| 141 |
+
print(f"Error processing audio: {e}")
|
| 142 |
+
return None, None, None, None
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
# Function to predict from audio
|
| 146 |
+
def predict_from_audio(audio_path):
|
| 147 |
+
mfcc, chroma, mel, spec = extract_features(audio_path)
|
| 148 |
+
if mfcc is None:
|
| 149 |
+
return "Error processing audio file."
|
| 150 |
+
|
| 151 |
+
# Predict
|
| 152 |
+
prediction = model.predict([mfcc, chroma, mel, spec])
|
| 153 |
+
predicted_class = np.argmax(prediction, axis=1)[0]
|
| 154 |
+
|
| 155 |
+
return (
|
| 156 |
+
"Tuberculosis Detected" if predicted_class == 1 else "No Tuberculosis Detected"
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
# Create the Gradio interface
|
| 161 |
+
with gr.Blocks() as demo:
|
| 162 |
+
gr.Markdown("# Tuberculosis Prediction Model")
|
| 163 |
+
|
| 164 |
+
with gr.Tab("Predict with Numeric Features"):
|
| 165 |
+
inputs = [
|
| 166 |
+
(
|
| 167 |
+
gr.Number(label=feature)
|
| 168 |
+
if feature in ["Age", "Cough", "WeightLoss"]
|
| 169 |
+
else gr.Radio([0, 1], label=feature)
|
| 170 |
+
)
|
| 171 |
+
for feature in feature_names
|
| 172 |
+
]
|
| 173 |
+
predict_button = gr.Button("Predict Tuberculosis")
|
| 174 |
+
output_text = gr.Textbox(label="Prediction Result")
|
| 175 |
+
predict_button.click(predict_tuberculosis, inputs, output_text)
|
| 176 |
+
|
| 177 |
+
with gr.Tab("Predict with Audio File"):
|
| 178 |
+
audio_input = gr.Audio(type="filepath", label="Upload Audio File")
|
| 179 |
+
predict_audio_button = gr.Button("Predict from Audio")
|
| 180 |
+
audio_output = gr.Textbox(label="Audio Prediction Result")
|
| 181 |
+
predict_audio_button.click(predict_from_audio, audio_input, audio_output)
|
| 182 |
+
|
| 183 |
+
# Run Gradio
|
| 184 |
+
if __name__ == "__main__":
|
| 185 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
python-multipart
|
| 2 |
+
gradio
|
| 3 |
+
numpy
|
| 4 |
+
joblib
|
| 5 |
+
scikit-learn
|
| 6 |
+
librosa
|
| 7 |
+
tensorflow
|
| 8 |
+
ffmpeg-python
|
| 9 |
+
xgboost
|
| 10 |
+
lightgbm
|
saved_model/best_cat_model.pkl
ADDED
|
File without changes
|
saved_model/best_lgbm_model.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1dfc58d78d32d32e18f0e722458dcbb826cbf901fa40b0ab1aad5ed281a1cc42
|
| 3 |
+
size 330094
|
saved_model/best_model.keras
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5fbafe813834eb3d50fa78ebd17d16a8d590dba030634dea5733687ee7113921
|
| 3 |
+
size 20165288
|
saved_model/l1_model.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f69c047a778e5ffc75a271025f101bdf9ffed84709a115957b73c9205c8f918c
|
| 3 |
+
size 821
|
saved_model/lr_model_selected.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:86d550f7fbccb6b8dd871adb1aa2f6e3d5bbecb3be52f243ac8a163b7b833d3d
|
| 3 |
+
size 777
|
saved_model/rf_model.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9bd92ee375718cca2f8360e69c0f2a190f880ab04ecd9e471bcd3c7d603769d2
|
| 3 |
+
size 37029516
|
saved_model/rfe_svm.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:31d9bc253d84dcd1cb08139933a6f1b2802753b89a3eeaf61e053cc3f16a50c4
|
| 3 |
+
size 1210
|
saved_model/scaler_xgb_lgbm.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:476cbd66b7c4eaf18047ab84aab05abda62a31779e9007f49451d6c976687d81
|
| 3 |
+
size 1144
|
saved_model/xgb_model.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3b4b8c92dea1d682612c703eb023561857254e5f8f66ec48df4089071c3a1532
|
| 3 |
+
size 776
|