Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""app.ipynb
|
| 3 |
+
|
| 4 |
+
Automatically generated by Colab.
|
| 5 |
+
|
| 6 |
+
Original file is located at
|
| 7 |
+
https://colab.research.google.com/drive/1oMJ02G_2BU5UAUhlQvk2s3Uvbu2YgDSG
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import pandas as pd
|
| 11 |
+
import numpy as np
|
| 12 |
+
from sklearn.model_selection import train_test_split
|
| 13 |
+
from sklearn.preprocessing import StandardScaler, LabelEncoder
|
| 14 |
+
from sklearn.neural_network import MLPClassifier
|
| 15 |
+
from sklearn.metrics import accuracy_score, confusion_matrix
|
| 16 |
+
import gradio as gr
|
| 17 |
+
|
| 18 |
+
# ==========================================
|
| 19 |
+
# (A) Data Loading & Preprocessing
|
| 20 |
+
# ==========================================
|
| 21 |
+
|
| 22 |
+
# 1. Load the dataset
|
| 23 |
+
# Using the URL directly from the quiz
|
| 24 |
+
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/ionosphere/ionosphere.data"
|
| 25 |
+
|
| 26 |
+
# The dataset has 34 numerical features and 1 class label at the end.
|
| 27 |
+
# It does not have a header row, so we use header=None.
|
| 28 |
+
df = pd.read_csv(url, header=None)
|
| 29 |
+
|
| 30 |
+
# Separate Features (X) and Target (y)
|
| 31 |
+
X = df.iloc[:, :-1] # All columns except the last one
|
| 32 |
+
y = df.iloc[:, -1] # The last column (labels: 'g' or 'b')
|
| 33 |
+
|
| 34 |
+
# Encode the labels: 'g' (Good) -> 1, 'b' (Bad) -> 0
|
| 35 |
+
le = LabelEncoder()
|
| 36 |
+
y_encoded = le.fit_transform(y)
|
| 37 |
+
|
| 38 |
+
# 2. Split the dataset (80% train, 20% test, random_state=42)
|
| 39 |
+
X_train, X_test, y_train, y_test = train_test_split(
|
| 40 |
+
X, y_encoded, test_size=0.20, random_state=42
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# 3. Standardize the features
|
| 44 |
+
scaler = StandardScaler()
|
| 45 |
+
# Fit on training set only to prevent data leakage, then transform both
|
| 46 |
+
X_train_scaled = scaler.fit_transform(X_train)
|
| 47 |
+
X_test_scaled = scaler.transform(X_test)
|
| 48 |
+
|
| 49 |
+
print("Data loaded and preprocessed successfully.")
|
| 50 |
+
print(f"Training shape: {X_train_scaled.shape}")
|
| 51 |
+
print(f"Testing shape: {X_test_scaled.shape}")
|
| 52 |
+
print("-" * 30)
|
| 53 |
+
|
| 54 |
+
# ==========================================
|
| 55 |
+
# (B) Build an ANN in scikit-learn
|
| 56 |
+
# ==========================================
|
| 57 |
+
|
| 58 |
+
# 4. Build the ANN (MLPClassifier) [cite: 15, 16, 17, 19]
|
| 59 |
+
# Architecture: Hidden layers (32, 16), Activation 'relu', Solver 'adam'
|
| 60 |
+
ann_model = MLPClassifier(
|
| 61 |
+
hidden_layer_sizes=(32, 16),
|
| 62 |
+
activation='relu',
|
| 63 |
+
solver='adam',
|
| 64 |
+
max_iter=500, # Setting > 300 as requested
|
| 65 |
+
random_state=42
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
# 5. Train the model [cite: 20]
|
| 69 |
+
ann_model.fit(X_train_scaled, y_train)
|
| 70 |
+
|
| 71 |
+
# 6. Evaluate the model [cite: 21, 22, 23]
|
| 72 |
+
y_pred = ann_model.predict(X_test_scaled)
|
| 73 |
+
|
| 74 |
+
accuracy = accuracy_score(y_test, y_pred)
|
| 75 |
+
conf_matrix = confusion_matrix(y_test, y_pred)
|
| 76 |
+
|
| 77 |
+
print(f"Model Accuracy on Test Set: {accuracy:.4f}")
|
| 78 |
+
print("Confusion Matrix:")
|
| 79 |
+
print(conf_matrix)
|
| 80 |
+
print("-" * 30)
|
| 81 |
+
|
| 82 |
+
# ==========================================
|
| 83 |
+
# (C) Build a GUI with Gradio
|
| 84 |
+
# ==========================================
|
| 85 |
+
|
| 86 |
+
def predict_radar_signal(input_str):
|
| 87 |
+
"""
|
| 88 |
+
Function to process input from Gradio and return prediction.
|
| 89 |
+
Expects a comma-separated string of 34 numbers.
|
| 90 |
+
"""
|
| 91 |
+
try:
|
| 92 |
+
# Convert string input to numpy array
|
| 93 |
+
# This handles the user pasting a row of data
|
| 94 |
+
input_list = [float(x.strip()) for x in input_str.split(',')]
|
| 95 |
+
|
| 96 |
+
if len(input_list) != 34:
|
| 97 |
+
return f"Error: Expected 34 values, but got {len(input_list)}."
|
| 98 |
+
|
| 99 |
+
# Reshape for a single sample (1, 34)
|
| 100 |
+
input_data = np.array(input_list).reshape(1, -1)
|
| 101 |
+
|
| 102 |
+
# IMPORTANT: Scale the input using the SAME scaler trained above
|
| 103 |
+
input_scaled = scaler.transform(input_data)
|
| 104 |
+
|
| 105 |
+
# Predict class and probability
|
| 106 |
+
prediction_idx = ann_model.predict(input_scaled)[0]
|
| 107 |
+
prediction_prob = ann_model.predict_proba(input_scaled)[0]
|
| 108 |
+
|
| 109 |
+
# Decode prediction back to 'Good' or 'Bad'
|
| 110 |
+
# Since we know 'g' is usually 1 and 'b' is 0, but let's use the encoder classes
|
| 111 |
+
# le.classes_ usually ['b', 'g']. So 0 -> 'b', 1 -> 'g'
|
| 112 |
+
predicted_label_code = le.inverse_transform([prediction_idx])[0]
|
| 113 |
+
label_text = "Good" if predicted_label_code == 'g' else "Bad"
|
| 114 |
+
|
| 115 |
+
# Get probability of the predicted class
|
| 116 |
+
# prob array is [prob_class_0, prob_class_1]
|
| 117 |
+
confidence = prediction_prob[prediction_idx]
|
| 118 |
+
|
| 119 |
+
# Format output as requested [cite: 28, 29]
|
| 120 |
+
return f"Prediction: {label_text}\nProbability of {label_text}: {confidence:.4f}"
|
| 121 |
+
|
| 122 |
+
except Exception as e:
|
| 123 |
+
return f"Error processing input: {str(e)}"
|
| 124 |
+
|
| 125 |
+
# Define the Gradio Interface [cite: 25, 30]
|
| 126 |
+
# We use a Textbox for input to handle the large number of features (34) easily.
|
| 127 |
+
iface = gr.Interface(
|
| 128 |
+
fn=predict_radar_signal,
|
| 129 |
+
inputs=gr.Textbox(
|
| 130 |
+
label="Input Features",
|
| 131 |
+
placeholder="Paste 34 comma-separated values here (e.g., 1,0,0.9,...)",
|
| 132 |
+
lines=3
|
| 133 |
+
),
|
| 134 |
+
outputs=gr.Textbox(label="Result"),
|
| 135 |
+
title="Ionosphere Radar Signal Predictor",
|
| 136 |
+
description="Enter the 34 features of the radar signal to predict if it is Good or Bad."
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
+
# Launch the app
|
| 140 |
+
print("Launching Gradio Interface...")
|
| 141 |
+
iface.launch(share=True) # Set share=True to create a public link
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
|