#!/usr/bin/env python3 """ Gradio App for NBA Performance Predictor on Hugging Face Spaces """ import gradio as gr import pandas as pd import numpy as np import os import sys # Initialize the model MODEL_DIR = "nba_model" model = None model_error = None try: # Try to import the huggingface model from huggingface_model import NBAPerformancePredictorHF if os.path.exists(MODEL_DIR): model = NBAPerformancePredictorHF(MODEL_DIR) print("✅ Model loaded successfully!") else: model_error = f"Model directory '{MODEL_DIR}' not found. Please upload the trained model." print(f"⚠️ {model_error}") except ImportError as e: model_error = f"Cannot import huggingface_model: {e}" print(f"❌ {model_error}") except Exception as e: model_error = f"Error loading model: {e}" print(f"❌ {model_error}") # Fallback prediction function if model fails to load def simple_prediction_fallback(pts_last_season, age, minutes_played): """Simple fallback prediction when model is not available""" # Basic heuristic based on age and last season performance age_factor = 1.0 if age <= 27 else (0.95 if age <= 32 else 0.9) minutes_factor = min(minutes_played / 35.0, 1.0) # Normalize to 35 minutes prediction = pts_last_season * age_factor * minutes_factor return max(prediction, 0.0) # Ensure non-negative def predict_player_performance( age, games, games_started, minutes_played, field_goals, field_goal_attempts, field_goal_percentage, position, pts_last_season, pts_two_seasons_ago, rebounds_last_season, assists_last_season, points_per_minute_last_season ): """ Predict NBA player performance based on input statistics """ if model is None: # Use fallback prediction prediction = simple_prediction_fallback(pts_last_season, age, minutes_played) result_text = f""" 🏀 **Predicted Points Per Game: {prediction:.1f}** *(Fallback Mode)* ⚠️ **Note**: Using simplified prediction model because: {model_error} 📊 **Input Summary:** - Player Age: {age} - Games: {games} (Started: {games_started}) - Minutes per Game: {minutes_played:.1f} - Field Goal %: {field_goal_percentage:.1f}% - Position: {position} 📈 **Historical Performance:** - Last Season PPG: {pts_last_season:.1f} - Two Seasons Ago PPG: {pts_two_seasons_ago:.1f} 🔧 **Fallback Method**: Basic heuristic using age and last season performance """ # Performance category for fallback if prediction < 8: category = "🔵 Role Player (Estimated)" elif prediction < 15: category = "🟢 Solid Contributor (Estimated)" elif prediction < 20: category = "🟡 Good Scorer (Estimated)" elif prediction < 25: category = "🟠 Star Player (Estimated)" else: category = "🔴 Superstar (Estimated)" return result_text, category try: # Position encoding (simplified) position_encoding = { "Point Guard": 0, "Shooting Guard": 1, "Small Forward": 2, "Power Forward": 3, "Center": 4 } # Age category encoding age_category = 0 if age <= 23 else (1 if age <= 27 else (2 if age <= 32 else 3)) # Create input dictionary player_stats = { 'Age': age, 'G': games, 'GS': games_started, 'MP': minutes_played, 'FG': field_goals, 'FGA': field_goal_attempts, 'FG_1': field_goal_percentage / 100.0, # Convert percentage to decimal 'Pos_encoded': position_encoding.get(position, 2), 'Team_encoded': 15, # Default team encoding 'Age_category_encoded': age_category, 'PTS_lag_1': pts_last_season, 'PTS_lag_2': pts_two_seasons_ago, 'TRB_lag_1': rebounds_last_season, 'AST_lag_1': assists_last_season, 'Points_per_minute_lag_1': points_per_minute_last_season, 'Efficiency_lag_1': (pts_last_season + rebounds_last_season + assists_last_season) / minutes_played if minutes_played > 0 else 0 } # Make prediction prediction = model.predict(player_stats) # Create detailed output result_text = f""" 🏀 **Predicted Points Per Game: {prediction:.1f}** 📊 **Input Summary:** - Player Age: {age} - Games: {games} (Started: {games_started}) - Minutes per Game: {minutes_played:.1f} - Field Goal %: {field_goal_percentage:.1f}% - Position: {position} 📈 **Historical Performance:** - Last Season PPG: {pts_last_season:.1f} - Two Seasons Ago PPG: {pts_two_seasons_ago:.1f} - Last Season RPG: {rebounds_last_season:.1f} - Last Season APG: {assists_last_season:.1f} 🎯 **Prediction Confidence:** {"High" if abs(prediction - pts_last_season) < 3 else "Medium" if abs(prediction - pts_last_season) < 6 else "Low"} """ # Performance category if prediction < 8: category = "🔵 Role Player" elif prediction < 15: category = "🟢 Solid Contributor" elif prediction < 20: category = "🟡 Good Scorer" elif prediction < 25: category = "🟠 Star Player" else: category = "🔴 Superstar" return result_text, category except Exception as e: return f"❌ Error making prediction: {str(e)}", "" def load_example_player(player_name): """Load example player data""" examples = { "LeBron James (Prime)": [27, 75, 75, 38.0, 9.5, 19.0, 50.0, "Small Forward", 27.1, 25.3, 7.4, 7.4, 0.71], "Stephen Curry (Peak)": [28, 79, 79, 34.0, 10.2, 20.2, 50.4, "Point Guard", 30.1, 23.8, 5.4, 6.7, 0.88], "Rookie Player": [22, 65, 15, 18.0, 3.2, 7.8, 41.0, "Shooting Guard", 8.5, 0.0, 2.8, 1.5, 0.47], "Veteran Role Player": [32, 70, 25, 22.0, 4.1, 9.2, 44.6, "Power Forward", 11.2, 12.8, 5.2, 1.8, 0.51] } if player_name in examples: return examples[player_name] return [25, 70, 50, 30.0, 6.0, 13.0, 46.0, "Small Forward", 15.0, 14.0, 5.0, 3.0, 0.50] # Create status message status_message = "" if model is None: status_message = f""" ⚠️ **Status**: Running in fallback mode **Issue**: {model_error} **Current Mode**: Using simplified prediction based on age and last season performance. For full ML model predictions, ensure the trained model files are available. """ else: status_message = "✅ **Status**: Full ML model loaded and ready!" # Create Gradio interface with gr.Blocks(title="NBA Performance Predictor", theme=gr.themes.Soft()) as demo: gr.Markdown(f""" # 🏀 NBA Player Performance Predictor {status_message} Predict a player's points per game (PPG) using machine learning trained on historical NBA data. **How to use:** 1. Enter the player's current season statistics 2. Provide historical performance data (last 1-2 seasons) 3. Click "Predict Performance" to get the PPG prediction *Note: The model works best with players who have at least 1-2 seasons of NBA experience.* """) with gr.Row(): with gr.Column(): gr.Markdown("### 📋 Current Season Stats") age = gr.Slider(18, 45, value=25, step=1, label="Age") games = gr.Slider(1, 82, value=70, step=1, label="Games Played") games_started = gr.Slider(0, 82, value=50, step=1, label="Games Started") minutes_played = gr.Slider(5.0, 45.0, value=30.0, step=0.1, label="Minutes Per Game") with gr.Row(): field_goals = gr.Number(value=6.0, label="Field Goals Made Per Game") field_goal_attempts = gr.Number(value=13.0, label="Field Goal Attempts Per Game") field_goal_percentage = gr.Slider(20.0, 70.0, value=46.0, step=0.1, label="Field Goal Percentage (%)") position = gr.Dropdown( choices=["Point Guard", "Shooting Guard", "Small Forward", "Power Forward", "Center"], value="Small Forward", label="Position" ) with gr.Column(): gr.Markdown("### 📈 Historical Performance") pts_last_season = gr.Number(value=15.0, label="Points Per Game (Last Season)") pts_two_seasons_ago = gr.Number(value=14.0, label="Points Per Game (Two Seasons Ago)") rebounds_last_season = gr.Number(value=5.0, label="Rebounds Per Game (Last Season)") assists_last_season = gr.Number(value=3.0, label="Assists Per Game (Last Season)") points_per_minute_last_season = gr.Slider(0.1, 1.5, value=0.50, step=0.01, label="Points Per Minute (Last Season)") with gr.Row(): predict_btn = gr.Button("🔮 Predict Performance", variant="primary", size="lg") clear_btn = gr.Button("🗑️ Clear", variant="secondary") with gr.Row(): with gr.Column(): prediction_output = gr.Markdown(label="Prediction Result") with gr.Column(): category_output = gr.Markdown(label="Player Category") # Example players section gr.Markdown("### 👥 Try Example Players") example_buttons = [] example_names = ["LeBron James (Prime)", "Stephen Curry (Peak)", "Rookie Player", "Veteran Role Player"] with gr.Row(): for name in example_names: btn = gr.Button(name, variant="outline") example_buttons.append(btn) # Event handlers predict_btn.click( fn=predict_player_performance, inputs=[ age, games, games_started, minutes_played, field_goals, field_goal_attempts, field_goal_percentage, position, pts_last_season, pts_two_seasons_ago, rebounds_last_season, assists_last_season, points_per_minute_last_season ], outputs=[prediction_output, category_output] ) # Example player loading for i, btn in enumerate(example_buttons): btn.click( fn=lambda name=example_names[i]: load_example_player(name), outputs=[ age, games, games_started, minutes_played, field_goals, field_goal_attempts, field_goal_percentage, position, pts_last_season, pts_two_seasons_ago, rebounds_last_season, assists_last_season, points_per_minute_last_season ] ) # Clear button clear_btn.click( fn=lambda: [25, 70, 50, 30.0, 6.0, 13.0, 46.0, "Small Forward", 15.0, 14.0, 5.0, 3.0, 0.50], outputs=[ age, games, games_started, minutes_played, field_goals, field_goal_attempts, field_goal_percentage, position, pts_last_season, pts_two_seasons_ago, rebounds_last_season, assists_last_season, points_per_minute_last_season ] ) gr.Markdown(""" --- ### ℹ️ About the Model - **Model Type**: XGBoost Regressor - **Training Data**: Historical NBA player statistics - **Performance**: RMSE ~3-5 points, R² ~0.6-0.8 - **Features**: Uses 50+ features including lag variables, rolling averages, and efficiency metrics **Limitations**: - Works best for players with NBA history - May be less accurate for rookies or players with significant role changes - Predictions are based on historical patterns and may not account for injuries or team changes """) # Launch the app if __name__ == "__main__": demo.launch()