PowerPlay-Score-Prediction / Mymodelfile.py
gurumurthy3's picture
Upload Mymodelfile.py
1d272c7 verified
Raw
History Blame Contribute Delete
16.2 kB
import pandas as pd
import numpy as np
from sklearn.svm import SVR
SEASON_MAP = {
"2007/08": 1, "2009": 2, "2009/10": 3, "2011": 4, "2012": 5, "2013": 6, "2014": 7, "2015": 8, "2016": 9, "2017": 10,
"2018": 11, "2019": 12, "2020/21": 13, "2021": 14, "2022": 15, "2023": 16, "2024": 17, "2025": 18, "2026": 19,
}
VENUE_NORM = {
"ma chidambaram stadium": "MA Chidambaram Stadium","ma chidambaram stadium, chepauk": "MA Chidambaram Stadium", "ma chidambaram stadium, chepauk, chennai": "MA Chidambaram Stadium",
"m chinnaswamy stadium": "M Chinnaswamy Stadium","m.chinnaswamy stadium": "M Chinnaswamy Stadium","m chinnaswamy stadium, bengaluru": "M Chinnaswamy Stadium",
"wankhede stadium": "Wankhede Stadium","wankhede stadium, mumbai": "Wankhede Stadium",
"narendra modi stadium": "Narendra Modi Stadium, Ahmedabad","narendra modi stadium, ahmedabad": "Narendra Modi Stadium, Ahmedabad",
"sardar patel stadium, motera": "Narendra Modi Stadium, Ahmedabad","sardar patel stadium": "Narendra Modi Stadium, Ahmedabad","motera stadium": "Narendra Modi Stadium, Ahmedabad",
"eden gardens": "Eden Gardens","eden gardens, kolkata": "Eden Gardens",
"sawai mansingh stadium": "Sawai Mansingh Stadium","sawai mansingh stadium, jaipur": "Sawai Mansingh Stadium",
"barsapara cricket stadium": "Barsapara Cricket Stadium, Guwahati","barsapara stadium, guwahati": "Barsapara Cricket Stadium, Guwahati","barsapara cricket stadium, guwahati": "Barsapara Cricket Stadium, Guwahati",
"arun jaitley stadium": "Arun Jaitley Stadium","arun jaitley stadium, delhi": "Arun Jaitley Stadium",
"feroz shah kotla": "Arun Jaitley Stadium","feroz shah kotla ground": "Arun Jaitley Stadium",
"dr. y.s. rajasekhara reddy aca-vdca cricket stadium": "Dr. Y.S. Rajasekhara Reddy ACA-VDCA Cricket Stadium","dr. y.s. rajasekhara reddy aca-vdca cricket stadium, visakhapatnam": "Dr. Y.S. Rajasekhara Reddy ACA-VDCA Cricket Stadium",
"punjab cricket association is bindra stadium": "Punjab Cricket Association IS Bindra Stadium","punjab cricket association is bindra stadium, mohali": "Punjab Cricket Association IS Bindra Stadium","punjab cricket association is bindra stadium, mohali, chandigarh": "Punjab Cricket Association IS Bindra Stadium","punjab cricket association stadium, mohali": "Punjab Cricket Association IS Bindra Stadium",
"himachal pradesh cricket association stadium": "Himachal Pradesh Cricket Association Stadium", "himachal pradesh cricket association stadium, dharamsala": "Himachal Pradesh Cricket Association Stadium",
"rajiv gandhi international stadium": "Rajiv Gandhi International Stadium","rajiv gandhi international stadium, uppal": "Rajiv Gandhi International Stadium","rajiv gandhi international stadium, uppal, hyderabad": "Rajiv Gandhi International Stadium","rajiv gandhi international cricket stadium": "Rajiv Gandhi International Stadium",
"bharat ratna shri atal bihari vajpayee ekana cricket stadium": "Bharat Ratna Shri Atal Bihari Vajpayee Ekana Cricket Stadium","bharat ratna shri atal bihari vajpayee ekana cricket stadium, lucknow": "Bharat Ratna Shri Atal Bihari Vajpayee Ekana Cricket Stadium",
"brabourne stadium": "Brabourne Stadium","brabourne stadium, mumbai": "Brabourne Stadium",
"dr dy patil sports academy": "Dr DY Patil Sports Academy","dr dy patil sports academy, mumbai": "Dr DY Patil Sports Academy",
"maharashtra cricket association stadium": "Maharashtra Cricket Association Stadium","maharashtra cricket association stadium, pune": "Maharashtra Cricket Association Stadium",
"maharaja yadavindra singh international cricket stadium, mullanpur": "Maharaja Yadavindra Singh International Cricket Stadium","maharaja yadavindra singh international cricket stadium, new chandigarh": "Maharaja Yadavindra Singh International Cricket Stadium",
}
def _norm_venue(name: str) -> str:
key = str(name).strip().lower()
return VENUE_NORM.get(key, str(name).strip())
ACTIVE_TEAMS = {
"Chennai Super Kings", "Delhi Capitals", "Gujarat Titans", "Kolkata Knight Riders",
"Lucknow Super Giants", "Mumbai Indians", "Punjab Kings", "Rajasthan Royals",
"Royal Challengers Bengaluru", "Sunrisers Hyderabad",
}
TEAM_NORM = {
"royal challengers bangalore": "Royal Challengers Bengaluru","royal challengers bengaluru": "Royal Challengers Bengaluru",
"delhi daredevils": "Delhi Capitals","delhi capitals": "Delhi Capitals",
"kings xi punjab": "Punjab Kings","punjab kings": "Punjab Kings",
"rising pune supergiant": "Rising Pune Supergiants","rising pune supergiants": "Rising Pune Supergiants",
"sunrisers hyderabad": "Sunrisers Hyderabad",
}
def _norm_team(name: str) -> str:
key = str(name).strip().lower()
canonical = TEAM_NORM.get(key, str(name).strip())
return canonical if canonical in ACTIVE_TEAMS else "Other"
def _parse_wickets(player_id_str) -> int:
if pd.isna(player_id_str) or str(player_id_str).strip() == "":
return 0
ids = [p.strip() for p in str(player_id_str).split(",") if p.strip()]
return int(np.clip(len(ids) - 2, 0, 10))
def _ceil_to_5(x: float) -> int:
x = int(x)
return x if x % 5 == 0 else int(np.ceil(x / 5.0) * 5)
class MyModel:
def __init__(self):
self.model = None
self.global_mean = 50
self.venue_map = {}
self.team_columns = []
self._v_wkt_mean = {}
self._v_inn_mean = {}
self._v_six_mean = {}
self._v_six_season_mean = {}
self._v_season_mean = {}
self._h2h_venue_mean = {}
self._bat_venue_mean = {} # venue x bat_team — h2h fallback level 2
self._bat_season_mean = {} # bat_team x season — bat_form fallback level 2
self._bat_form = {}
self._v_trend = {}
self._global_v_wkt = 50.0
self._global_v_inn = 50.0
self._global_six_mean = 3.0
def _build_features(self, agg: pd.DataFrame) -> pd.DataFrame:
gm = self._global_v_wkt # global run mean — last resort fallback
last_s = max(self._v_season_mean.keys(), key=lambda x: x[1], default=(0, 0))[1]
# v_wkt_mean: venue x wickets → venue x inning → global
agg["v_wkt_mean"] = [
self._v_wkt_mean.get((v, w),
self._v_inn_mean.get((v, i),
gm))
for v, w, i in zip(agg["v_enc"], agg["wickets"], agg["inning"])
]
# v_inn_mean: venue x inning → global
agg["v_inn_mean"] = [
self._v_inn_mean.get((v, i), gm)
for v, i in zip(agg["v_enc"], agg["inning"])
]
# v_six_season_mean: venue x season → venue all-time → global six mean
agg["v_six_mean"] = [
self._v_six_mean.get(v, self._global_six_mean)
for v in agg["v_enc"]
]
agg["v_six_season_mean"] = [
self._v_six_season_mean.get((v, s),
self._v_six_mean.get(v, self._global_six_mean))
for v, s in zip(agg["v_enc"], agg["season"])
]
# v_season_mean: venue x season → venue x last known season → venue x inning → global
agg["v_season_mean"] = [
self._v_season_mean.get((v, s),
self._v_season_mean.get((v, last_s),
self._v_inn_mean.get((v, i),
gm)))
for v, s, i in zip(agg["v_enc"], agg["season"], agg["inning"])
]
# h2h_venue_mean: venue x bat x bowl → venue x bat → venue x inning → global
agg["h2h_venue_mean"] = [
self._h2h_venue_mean.get((v, bt, bw),
self._bat_venue_mean.get((v, bt),
self._v_inn_mean.get((v, i),
gm)))
for v, bt, bw, i in zip(agg["v_enc"], agg["batting_team"], agg["bowling_team"], agg["inning"])
]
# bat_form_3: team rolling form → team last-season avg → venue x inning → global
agg["bat_form_3"] = [
self._bat_form.get(bt,
self._bat_season_mean.get((bt, last_s),
self._v_inn_mean.get((v, i),
gm)))
for bt, v, i in zip(agg["batting_team"], agg["v_enc"], agg["inning"])
]
agg["v_trend"] = [
self._v_trend.get(v, 0.0) for v in agg["v_enc"]
]
return agg
def fit(self, deliveries_df, players_df=None, matches_df=None):
df = deliveries_df.copy()
df["over"] = pd.to_numeric(df["over"], errors="coerce")
df["inning"] = pd.to_numeric(df["inning"], errors="coerce").astype("int32")
run_cols = ["batsman_runs", "extras", "isWide", "isNoBall", "Byes", "LegByes"]
run_cols = [c for c in run_cols if c in df.columns]
df[run_cols] = df[run_cols].apply(pd.to_numeric, errors="coerce").fillna(0)
df = df[df["over"] < 6].copy()
df["ball_runs"] = df[run_cols].sum(axis=1)
df["is_wicket"] = df.get("player_dismissed", pd.Series()).notna().astype(int)
df["is_six"] = (
(df["batsman_runs"] == 6) &
(df.get("isWide", pd.Series(0, index=df.index)).fillna(0) == 0) &
(df.get("isNoBall", pd.Series(0, index=df.index)).fillna(0) == 0)
).astype(int)
agg = (
df.groupby(["matchId", "inning"])
.agg(
runs=("ball_runs", "sum"),
wickets=("is_wicket", "sum"),
sixes=("is_six", "sum"),
batting_team=("batting_team", "first"),
bowling_team=("bowling_team", "first"),
)
.reset_index()
)
agg["batting_team"] = agg["batting_team"].apply(_norm_team)
agg["bowling_team"] = agg["bowling_team"].apply(_norm_team)
meta_cols = ["matchId", "venue", "season"]
for opt in ["toss_winner", "toss_decision"]:
if opt in matches_df.columns:
meta_cols.append(opt)
meta = matches_df[meta_cols].drop_duplicates("matchId").copy()
meta["venue"] = meta["venue"].astype(str).apply(_norm_venue)
agg = agg.merge(meta, on="matchId", how="left")
agg["venue"] = agg["venue"].fillna("Unknown")
agg["season"] = (
agg["season"].fillna("Unknown").astype(str)
.map(lambda x: SEASON_MAP.get(x.strip(), 0)).astype("int16")
)
if "toss_winner" in agg.columns and "toss_decision" in agg.columns:
agg["toss_bat"] = (
(agg["batting_team"] == agg["toss_winner"]) &
(agg["toss_decision"].str.lower().str.strip() == "bat")
).astype(int)
else:
agg["toss_bat"] = 0
self.venue_map = {v: i for i, v in enumerate(sorted(agg["venue"].unique()))}
agg["v_enc"] = agg["venue"].map(self.venue_map).fillna(-1).astype(int)
gm = float(agg["runs"].mean())
self._global_v_wkt = gm
self._global_v_inn = gm
self._global_six_mean = float(agg["sixes"].mean())
self.global_mean = int(round(gm))
self._v_wkt_mean = agg.groupby(["v_enc", "wickets"])["runs"].mean().to_dict()
self._v_inn_mean = agg.groupby(["v_enc", "inning"]) ["runs"].mean().to_dict()
self._v_six_mean = agg.groupby("v_enc")["sixes"].mean().to_dict()
self._v_six_season_mean = agg.groupby(["v_enc", "season"])["sixes"].mean().to_dict()
self._v_season_mean = agg.groupby(["v_enc", "season"])["runs"].mean().to_dict()
self._h2h_venue_mean = agg.groupby(["v_enc", "batting_team", "bowling_team"])["runs"].mean().to_dict()
self._bat_venue_mean = agg.groupby(["v_enc", "batting_team"])["runs"].mean().to_dict()
self._bat_season_mean = agg.groupby(["batting_team", "season"])["runs"].mean().to_dict()
agg_sorted = agg.sort_values(["season", "matchId"])
bat_form_series = (
agg_sorted.groupby("batting_team")["runs"]
.transform(lambda x: x.shift(1).rolling(3, min_periods=1).mean())
)
form_df = agg_sorted.copy()
form_df["bat_form_3"] = bat_form_series.reindex(agg_sorted.index).fillna(gm)
self._bat_form = form_df.groupby("batting_team")["bat_form_3"].last().to_dict()
vsm = agg.groupby(["v_enc", "season"])["runs"].mean().reset_index()
def _slope(grp):
if len(grp) < 2:
return 0.0
x = grp["season"].values.astype(float)
return float(np.polyfit(x, grp["runs"].values, 1)[0])
self._v_trend = vsm.groupby("v_enc").apply(_slope).to_dict()
agg = self._build_features(agg)
bat_ohe = pd.get_dummies(agg["batting_team"], prefix="bat")
bowl_ohe = pd.get_dummies(agg["bowling_team"], prefix="bowl")
self.team_columns = list(bat_ohe.columns) + list(bowl_ohe.columns)
base_features = [
"v_enc", "inning", "wickets", "season",
"v_wkt_mean", "v_inn_mean",
"v_six_mean", "v_six_season_mean",
"h2h_venue_mean",
"v_season_mean",
"bat_form_3",
"v_trend",
"toss_bat",
]
X = pd.concat([
agg[base_features].reset_index(drop=True),
bat_ohe.reset_index(drop=True),
bowl_ohe.reset_index(drop=True),
], axis=1)
y = agg["runs"].values.astype("float32")
self.model = SVR(kernel='rbf', gamma='scale', C=113.084, epsilon=3.418)
self.model.fit(X.values.astype("float32"), y)
self._feature_names = list(X.columns)
return self
def predict(self, test_df):
records = []
for i, row in test_df.iterrows():
inning = int(row.get("innings", 1))
venue = _norm_venue(str(row.get("venue", "Unknown")))
season = int(SEASON_MAP.get(str(row.get("season", "2026")), 19))
wickets = _parse_wickets(row.get("Batsman's Player Id", ""))
v_enc = self.venue_map.get(venue, -1)
batting_team = _norm_team(str(row.get("batting_team", "Unknown")))
bowling_team = _norm_team(str(row.get("bowling_team", "Unknown")))
toss_winner = str(row.get("toss_winner", ""))
toss_decision = str(row.get("toss_decision", "")).strip().lower()
toss_bat = int(batting_team == toss_winner and toss_decision == "bat")
row_df = pd.DataFrame([{
"v_enc": v_enc,
"inning": inning,
"wickets": wickets,
"season": season,
"batting_team": batting_team,
"bowling_team": bowling_team,
"toss_bat": toss_bat,
}])
row_df = self._build_features(row_df)
base_features = [
"v_enc", "inning", "wickets", "season",
"v_wkt_mean", "v_inn_mean",
"v_six_mean", "v_six_season_mean",
"v_season_mean", "h2h_venue_mean", "bat_form_3", "v_trend", "toss_bat",
]
base = row_df[base_features].reset_index(drop=True)
team_row = pd.DataFrame([[0] * len(self.team_columns)], columns=self.team_columns)
bat_col = f"bat_{batting_team}"
bowl_col = f"bowl_{bowling_team}"
if bat_col in team_row.columns: team_row[bat_col] = 1
if bowl_col in team_row.columns: team_row[bowl_col] = 1
x = pd.concat([base, team_row], axis=1).values.astype("float32")
if self.model:
raw = float(self.model.predict(x)[0])
pred = _ceil_to_5(raw)
else:
pred = self.global_mean
records.append({"id": row.get("id", i), "predicted_score": pred})
return pd.DataFrame(records)