Spaces:
Sleeping
Sleeping
| """ | |
| Gradio application for Game of Thrones House Prediction | |
| Interactive web interface for character house prediction | |
| Deployed on HuggingFace Spaces | |
| """ | |
| import gradio as gr | |
| import pandas as pd | |
| import joblib | |
| import json | |
| import os | |
| # Model paths (HuggingFace structure) | |
| MODEL_PATH = "model.pkl" | |
| FEATURE_NAMES_PATH = "feature_names.json" | |
| # Load model and features | |
| model = None | |
| feature_columns = None | |
| def load_model(): | |
| """Load the trained model and feature columns""" | |
| global model, feature_columns | |
| if not os.path.exists(MODEL_PATH): | |
| return False, f"Model not found at {MODEL_PATH}" | |
| try: | |
| model = joblib.load(MODEL_PATH) | |
| # Load feature columns from JSON | |
| if os.path.exists(FEATURE_NAMES_PATH): | |
| with open(FEATURE_NAMES_PATH, 'r') as f: | |
| feature_data = json.load(f) | |
| feature_columns = feature_data.get('features', []) | |
| return True, "Model loaded successfully" | |
| except Exception as e: | |
| return False, f"Error loading model: {str(e)}" | |
| def preprocess_input(region, primary_role, alignment, status, species, | |
| honour, ruthlessness, intelligence, combat_skill, | |
| diplomacy, leadership, trait_loyal, trait_scheming): | |
| """Preprocess input data to match training format""" | |
| # Create input dictionary | |
| input_dict = { | |
| "honour_1to5": [honour], | |
| "ruthlessness_1to5": [ruthlessness], | |
| "intelligence_1to5": [intelligence], | |
| "combat_skill_1to5": [combat_skill], | |
| "diplomacy_1to5": [diplomacy], | |
| "leadership_1to5": [leadership], | |
| "trait_loyal": [1 if trait_loyal else 0], | |
| "trait_scheming": [1 if trait_scheming else 0], | |
| "trait_strategic": [0], | |
| "trait_impulsive": [0], | |
| "trait_charismatic": [0], | |
| "trait_vengeful": [0], | |
| "feature_set_version": [1], | |
| "region": [region], | |
| "primary_role": [primary_role], | |
| "alignment": [alignment], | |
| "status": [status], | |
| "species": [species] | |
| } | |
| # Create DataFrame | |
| df = pd.DataFrame(input_dict) | |
| # One-hot encode categorical features | |
| categorical_cols = ["region", "primary_role", "alignment", "status", "species"] | |
| df_encoded = pd.get_dummies(df, columns=categorical_cols, drop_first=False) | |
| # Align with training features | |
| if feature_columns is not None: | |
| # Add missing columns with 0 | |
| for col in feature_columns: | |
| if col not in df_encoded.columns: | |
| df_encoded[col] = 0 | |
| # Reorder columns to match training | |
| df_encoded = df_encoded[feature_columns] | |
| return df_encoded | |
| def predict_house(region, primary_role, alignment, status, species, | |
| honour, ruthlessness, intelligence, combat_skill, | |
| diplomacy, leadership, trait_loyal, trait_scheming): | |
| """ | |
| Predict house affiliation for a character | |
| Returns: | |
| str: Prediction result with house name and confidence | |
| """ | |
| if model is None: | |
| return "โ Error: Model not loaded. Please contact the administrator." | |
| try: | |
| # Preprocess input | |
| input_df = preprocess_input( | |
| region, primary_role, alignment, status, species, | |
| honour, ruthlessness, intelligence, combat_skill, | |
| diplomacy, leadership, trait_loyal, trait_scheming | |
| ) | |
| # Make prediction | |
| prediction = model.predict(input_df)[0] | |
| # Get prediction probability if available | |
| result = f"๐ฐ **Predicted House: {prediction}**\n\n" | |
| if hasattr(model, 'predict_proba'): | |
| proba = model.predict_proba(input_df)[0] | |
| confidence = max(proba) | |
| result += f"๐ Confidence: {confidence:.2%}\n\n" | |
| # Show top 3 probabilities | |
| classes = model.classes_ | |
| proba_dict = dict(zip(classes, proba)) | |
| sorted_proba = sorted(proba_dict.items(), key=lambda x: x[1], reverse=True)[:3] | |
| result += "**Top 3 Predictions:**\n" | |
| for house, prob in sorted_proba: | |
| result += f"- {house}: {prob:.2%}\n" | |
| return result | |
| except Exception as e: | |
| return f"โ Error during prediction: {str(e)}" | |
| # Character attribute options | |
| regions = [ | |
| "The North", "Crownlands", "Dorne", "Essos", "Iron Islands", | |
| "King's Landing", "The Reach", "The Riverlands", "The Stormlands", | |
| "The Vale", "The Westerlands", "Beyond the Wall" | |
| ] | |
| roles = [ | |
| "Commander", "Ruler", "Knight/Warrior", "Advisor", "Noble", | |
| "Merchant/Noble", "Scholar/Healer", "Assassin/Spy", "Religious leader", | |
| "Mage/Seer", "Commoner" | |
| ] | |
| alignments = [ | |
| "Lawful Good", "Neutral Good", "Chaotic Good", | |
| "Lawful Neutral", "True Neutral", "Chaotic Neutral", | |
| "Lawful Evil", "Neutral Evil", "Chaotic Evil" | |
| ] | |
| statuses = ["Alive", "Deceased", "Unknown/Varies"] | |
| species_list = ["Human", "Warg", "White Walker"] | |
| # Load model on startup | |
| success, message = load_model() | |
| if not success: | |
| print(f"โ ๏ธ Warning: {message}") | |
| # Create Gradio interface | |
| with gr.Blocks(title="Game of Thrones House Predictor", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown( | |
| """ | |
| # ๐ฐ Game of Thrones House Predictor | |
| Enter a character's attributes to predict which house they belong to! | |
| This model was trained on Game of Thrones character data using **Azure Machine Learning** with **MLFlow tracking**. | |
| The Decision Tree classifier analyzes character attributes, roles, and traits to predict house affiliation. | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### ๐ Basic Information") | |
| region = gr.Dropdown(choices=regions, label="Region", value="The North") | |
| primary_role = gr.Dropdown(choices=roles, label="Primary Role", value="Commander") | |
| alignment = gr.Dropdown(choices=alignments, label="Alignment", value="Lawful Good") | |
| status = gr.Dropdown(choices=statuses, label="Status", value="Alive") | |
| species = gr.Dropdown(choices=species_list, label="Species", value="Human") | |
| with gr.Column(): | |
| gr.Markdown("### ๐ Attributes (1-5)") | |
| honour = gr.Slider(minimum=1, maximum=5, step=1, value=4, label="Honour") | |
| ruthlessness = gr.Slider(minimum=1, maximum=5, step=1, value=2, label="Ruthlessness") | |
| intelligence = gr.Slider(minimum=1, maximum=5, step=1, value=3, label="Intelligence") | |
| combat_skill = gr.Slider(minimum=1, maximum=5, step=1, value=4, label="Combat Skill") | |
| diplomacy = gr.Slider(minimum=1, maximum=5, step=1, value=3, label="Diplomacy") | |
| leadership = gr.Slider(minimum=1, maximum=5, step=1, value=4, label="Leadership") | |
| with gr.Row(): | |
| gr.Markdown("### ๐ญ Character Traits") | |
| with gr.Row(): | |
| trait_loyal = gr.Checkbox(label="Loyal", value=True) | |
| trait_scheming = gr.Checkbox(label="Scheming", value=False) | |
| predict_btn = gr.Button("๐ฎ Predict House", variant="primary", size="lg") | |
| output = gr.Markdown(label="Prediction Result") | |
| # Examples | |
| gr.Markdown("### ๐ Example Characters") | |
| gr.Examples( | |
| examples=[ | |
| ["The North", "Commander", "Lawful Good", "Alive", "Human", 4, 2, 3, 4, 3, 4, True, False], | |
| ["King's Landing", "Ruler", "Neutral Evil", "Deceased", "Human", 2, 5, 4, 2, 3, 3, False, True], | |
| ["The Reach", "Knight/Warrior", "Lawful Neutral", "Alive", "Human", 4, 3, 2, 5, 2, 3, True, False], | |
| ["Essos", "Ruler", "Chaotic Good", "Alive", "Human", 3, 4, 4, 3, 4, 5, True, False], | |
| ["The Westerlands", "Noble", "Lawful Evil", "Alive", "Human", 2, 5, 5, 3, 4, 4, False, True], | |
| ], | |
| inputs=[region, primary_role, alignment, status, species, honour, ruthlessness, | |
| intelligence, combat_skill, diplomacy, leadership, trait_loyal, trait_scheming], | |
| ) | |
| # Connect prediction function | |
| predict_btn.click( | |
| fn=predict_house, | |
| inputs=[region, primary_role, alignment, status, species, honour, ruthlessness, | |
| intelligence, combat_skill, diplomacy, leadership, trait_loyal, trait_scheming], | |
| outputs=output | |
| ) | |
| gr.Markdown( | |
| """ | |
| --- | |
| ### ๐ About This Model | |
| **Training Pipeline:** | |
| - Data source: Game of Thrones character dataset (100 characters) | |
| - Algorithm: Decision Tree Classifier (scikit-learn) | |
| - Training platform: Azure Machine Learning | |
| - Experiment tracking: MLFlow | |
| - Pipeline: Automated data preparation, training, and model registration | |
| **Features Used:** | |
| - **Geographic**: Region (12 regions across Westeros and Essos) | |
| - **Role**: Primary character role (11 types) | |
| - **Alignment**: D&D-style alignment (9 categories) | |
| - **Attributes**: 6 numeric scores (honour, ruthlessness, intelligence, combat skill, diplomacy, leadership) | |
| - **Traits**: Personality traits (loyal, scheming) | |
| **Model Performance:** | |
| - Trained with stratified train/test split | |
| - Metrics logged: accuracy, precision, recall, F1-score (overall and per-class) | |
| - Model registered and versioned in Azure ML Model Registry | |
| --- | |
| *Developed as part of an MLOps exam project demonstrating end-to-end ML pipeline deployment.* | |
| """ | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |