AI-система аналітики поведінки гравців
Аналітика гравців — ключовий інструмент монетизації та утримання у грах. Коли гравець припиняє прогресувати, злиться або нудьгує — це поведінкові сигнали, видимі в даних за хвилини до відтоку. AI-система детектує їх у реальному часі та запускає персоналізовані інтервенції.
Профілювання гравця та сегментація
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import GradientBoostingClassifier
class PlayerProfiler:
"""Багатовимірне профілювання гравця"""
def extract_behavioral_features(self, sessions: pd.DataFrame,
player_id: str,
window_days: int = 30) -> dict:
"""Ознаки з ігрових сесій за період"""
player_sessions = sessions[
(sessions['player_id'] == player_id) &
(sessions['date'] >= pd.Timestamp.now() - pd.Timedelta(days=window_days))
]
if player_sessions.empty:
return {}
return {
# Активність
'sessions_per_week': len(player_sessions) / (window_days / 7),
'avg_session_minutes': player_sessions['duration_minutes'].mean(),
'total_play_hours': player_sessions['duration_minutes'].sum() / 60,
'days_active': player_sessions['date'].dt.date.nunique(),
# Прогрес
'avg_level_gain_per_session': player_sessions['level_gained'].mean(),
'completion_rate': player_sessions['objective_completed'].mean(),
'win_rate': player_sessions['wins'].sum() / max(player_sessions['games_played'].sum(), 1),
# Монетизація
'total_spent_usd': player_sessions['purchase_usd'].sum(),
'purchase_count': (player_sessions['purchase_usd'] > 0).sum(),
'avg_purchase_usd': player_sessions[player_sessions['purchase_usd'] > 0]['purchase_usd'].mean() or 0,
# Соціальність
'social_interactions': player_sessions['chat_messages'].sum() + player_sessions['party_plays'].sum(),
'guild_member': int(player_sessions['guild_id'].notna().any()),
# Різноманітність
'game_modes_played': player_sessions['game_mode'].nunique(),
'avg_frustration_events': player_sessions.get('rage_quits', pd.Series([0])).mean(),
}
def segment_players(self, player_features: pd.DataFrame,
n_segments: int = 6) -> pd.DataFrame:
"""K-Means сегментація гравців"""
feature_cols = [c for c in player_features.columns if c != 'player_id']
X = player_features[feature_cols].fillna(0)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
kmeans = KMeans(n_clusters=n_segments, random_state=42, n_init=10)
player_features['segment'] = kmeans.fit_predict(X_scaled)
# Інтерпретація сегментів за центроїдами
centroids = pd.DataFrame(
scaler.inverse_transform(kmeans.cluster_centers_),
columns=feature_cols
)
segment_labels = self._label_segments(centroids)
player_features['segment_label'] = player_features['segment'].map(segment_labels)
return player_features
def _label_segments(self, centroids: pd.DataFrame) -> dict:
"""Автоматичне маркування сегментів за характеристиками"""
labels = {}
for i, row in centroids.iterrows():
spend = row.get('total_spent_usd', 0)
sessions = row.get('sessions_per_week', 0)
social = row.get('social_interactions', 0)
if spend > 50 and sessions > 10:
labels[i] = 'whale'
elif spend > 20:
labels[i] = 'dolphin'
elif sessions > 14:
labels[i] = 'hardcore_f2p'
elif social > 100:
labels[i] = 'social_player'
elif sessions < 2:
labels[i] = 'casual_at_risk'
else:
labels[i] = 'regular'
return labels
class ChurnPredictor:
"""Прогнозування відтоку гравців"""
def __init__(self):
self.model = GradientBoostingClassifier(
n_estimators=200, learning_rate=0.05, max_depth=4, random_state=42
)
def build_churn_features(self, player_history: pd.DataFrame) -> pd.DataFrame:
"""Ознаки, що передбачають відток протягом 14 днів"""
features = pd.DataFrame()
features['sessions_last_7d'] = player_history['sessions_7d']
features['sessions_prev_7d'] = player_history['sessions_prev_7d']
features['session_trend'] = (
(features['sessions_last_7d'] - features['sessions_prev_7d']) /
(features['sessions_prev_7d'] + 1)
)
features['days_since_last_login'] = player_history['days_since_last_login']
features['avg_session_drop_min'] = player_history['avg_session_drop_minutes']
features['level_progression_rate'] = player_history['level_gain_per_hour']
features['win_rate_last_10'] = player_history['win_rate_last_10_games']
features['frustration_events'] = player_history['rage_quits_7d']
features['purchase_recency_days'] = player_history['days_since_last_purchase']
features['social_activity_trend'] = player_history['social_activity_trend']
return features.fillna(0)
def predict_churn_risk(self, players: pd.DataFrame) -> pd.DataFrame:
"""Оцінка ризику відтоку для кожного гравця"""
X = self.build_churn_features(players)
churn_probabilities = self.model.predict_proba(X)[:, 1]
result = players[['player_id']].copy()
result['churn_probability_14d'] = churn_probabilities
result['churn_risk'] = pd.cut(
churn_probabilities,
bins=[0, 0.2, 0.5, 0.75, 1.0],
labels=['low', 'medium', 'high', 'critical']
)
return result
class PlayerInterventionEngine:
"""Персоналізовані інтервенції для утримання"""
INTERVENTIONS = {
'whale': {
'critical': {'type': 'vip_outreach', 'channel': 'personal_manager'},
'high': {'type': 'exclusive_content', 'channel': 'in_game_popup'},
},
'regular': {
'critical': {'type': 'comeback_bonus', 'channel': 'push_notification'},
'high': {'type': 'limited_offer', 'channel': 'email'},
},
'hardcore_f2p': {
'critical': {'type': 'challenge_event', 'channel': 'in_game'},
'high': {'type': 'new_content_unlock', 'channel': 'push_notification'},
},
'casual_at_risk': {
'critical': {'type': 'simplified_quest', 'channel': 'push_notification'},
'high': {'type': 'social_invite', 'channel': 'email'},
}
}
def select_intervention(self, player_segment: str,
churn_risk: str,
player_context: dict) -> dict:
segment_interventions = self.INTERVENTIONS.get(player_segment, self.INTERVENTIONS['regular'])
intervention = segment_interventions.get(churn_risk, {'type': 'generic_reminder', 'channel': 'push'})
# Персоналізація контенту інтервенції
intervention['personalized_offer'] = self._create_offer(
player_segment, player_context
)
return intervention
def _create_offer(self, segment: str, context: dict) -> dict:
offers = {
'whale': {'type': 'exclusive_skin', 'value': 'Limited Edition Character'},
'dolphin': {'type': 'currency_bonus', 'value': '50% bonus gems'},
'hardcore_f2p': {'type': 'xp_boost', 'value': '2x XP for 3 days'},
'casual_at_risk': {'type': 'starter_pack', 'value': 'Welcome back pack'},
}
return offers.get(segment, {'type': 'general_bonus', 'value': 'Daily reward'})
Прогнозування відтоку у іграх досягає AUC 0.82-0.88 з 7-денним горизонтом. Персоналізовані інтервенції для сегменту "високий ризик" утримують 25-35% потенційно відійти гравців. Whale-сегмент (5-10% гравців) генерує 50-70% revenue — пріоритет при скорингу критичних.







