Розробка AI-системи аналізу поведінки гравців Player Analytics

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка AI-системи аналізу поведінки гравців Player Analytics
Середній
~1-2 тижні
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1286
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1122
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    859

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 — пріоритет при скорингу критичних.