Галоўная / Артыкулы

Гра ў волейбол з AI-агентамі для прыкметкавання обороту рэстарана.

Хакатон з підвышэння обороту рэстарана, створаны на базе AI-агентоў з людскім кераваннем: аўдыт дадзеных, пераканальванне з урахоўваннем спецыфікі, інжынерыя функцый, стварэнне комбінацый і аналіз разліку з рэкордамі лідарборда.

Выдавец: REACTAPP.TOP18 хв чытання4112 слоў

Крыніцы: **How ‘Playing Volleyball’ with AI Agents Helped Me Predict Restaurant Turnover —**and Win a Hackathon

Уявіце хакатон, у якому сама мадэль ёсць ліш часткаю задачы. Іншая частка — гэта падзірэнне за некалькамі агентамі ШЫ, які працуют над конкуруючымі ідэямі, не дазволяючы жаднаму з іх здзейсніць дзвянак, які належыць чалавеку. У цам напісе опісваецца адны такі практык, з хакатона па прагнозаванне обороту рэстарана, які адбыўся пад эгідай Great Learning са спавярэнням UT Austin і яго бізнес-школы McCombs. У ём упомінаецца проста рабочая схема машыннаго навчання, строгая перакананне рэзультатаў і ансамбль, які, за словамі самага праекту, добра практыкуўся на конкурсе.

Слой кантролю быў фрамворк пад назвай DontPanic. Яго рабочыя працэсы адпавядаюць логіке рэлюйшчаў у волейбале. Агент прымець заданне, плануе наступны крок, перадае працу спецыялізаваным ролям і нарэшце перэдае рэзультат, пры чым мяч завжды вяртаецца да чалавека, які прымець рашэнне. Агенты прышвартаваюць выкананне, але не ўжо несу адпаведнасці за рашэння.

1. Заданне

Учаснікіям было неабходна працаваць над прыказаннем годоваго обороту рэстаранаў у всій Індыі на аднойчынку з 3,493 пазначаных трэнінгавых дадзенняў і 500 непазначаных тэставых дадзенняў. Існавалі прыбліжна 32 фактычныя праметы, якія включалі месца распадзелу, стыль кухні, фармат рэстарана, додатковыя умеласці, популярнасць у соцыяльных меражах і рэйтынгі якосці адносінаў з кліентамі. Пад «оборатам» тут разумеюцца годовыя прыбыткі, а не паказванне спецавікаў. Метрыкай быў RMSE, які вырахоўвае квадраты памылак перш чым зробіць сярэднюе значэнне, таму калькі вельмі большых памылак могу знецэніць загальны рэзультат.

Метай не было стварэння найболей складнага мадэлі. Што было неабходна — гэта ўстановка сістэмы прогназавання, якую можна было б апрацаваць: пераглянуць дадзення, зрозумець эканамічныя аспекты цэльвай галузі, стварыць сігналы, якія маюць сэнс з пункту гляду бізнесу, пераканацца ў правядзімасці кандыдатаў за дапамогою стабільнага крос-валідавання, апусціць тыя паследнія змены, якія не маглі б быць падтверджаныя, і нарэшце выдэліць справжнюя узагальненасць мадэлі ад налашоўкаў, спецыфічных для конкрэтнай канкурэнціі.

2. Артыкулы

Усе функцыяны знаходзіліся ў VS Code як модульны пакет на Python у катэгорыі src/, замест адзінаго набора несувязаных эксперыментаў у фармаце нотбук. Гэты выбар парадыжна сабрал своія плоды, адколі чышчэнне, стварэнне функцыянаў, перакананне ў ўсасненосці даных і вырашэнне задач выканваліся за дапамогою аднаго і тога ж коду, які можна было перадыстрыхтуваць. Такім чынам функцыя не могла спакойна працаваць аднакова пад час навчання і інакш — калі трэба было прэдставіць рэзультаты.

3. Оркестрацыя агентам

DontPanic быў інструментам, які кераваў праектам. Полная автонамія ніколі не была метай. Мэта заключалася ў тым, каб кілька агентаў моглі швытко працаваць, адночасна чытка візначаючы структуру прыняцьбы рашэння: хто дзіяе, хто стварае, хто крытыкуе, які элемент ёсць автаномным і калі работа павінна вернуцца да чалавека для падтверджэння або адхілення.

Гэта мае значэнне, таму што эксперыменты з машынным навучэнням прыводзяць да адной за адной правдападобных наступных крокаў. Агент, які працуе самастойна, будзе продовжваць оптымізаваць той сігнал, які ён бачыў неякраз недзеўна, а чалавек можа забыць, чы не змянілася гіпотэза, протакол паўтарной перапрацоўкі чы крэтынія прызначэння. Уявіце DontPanic як правіла, пад якімі велісь эксперымент: агенты маглі свабодна працаваць, але не маглі перапісваць правіла без таго, каб хтось гэта не зазначыў.

Кожны перыод працы агента быў опісаны маніфестам. Напрыклад, маніфест для працы Claude CLI пераказвае команды і файлы, якія ён трэбуе, як пераканацца ў готовасці, калькі часткі належаюць фрэймворку, што павінен зрабіць аператар і якія дзеяння забораны:

{
  "schema_version": "1.0.0",
  "id": "agent-claude-cli",
  "title": "Claude CLI agent runtime",
  "kind": "agent_cli",
  "category": "agent-cli",
  "summary": "External agent CLI used by DontPanic as an implementer, auditor, or goal-auditor runtime.",
  "setup_required": true,
  "setup_doc": "docs/GETTING_STARTED.md#setup-tracks--pick-yours",
  "default_in_profiles": ["core"],
  "use_cases": ["U1", "U3", "U4", "U5", "U6", "U7"],
  "requires": {
    "commands": ["claude"],
    "env": [],
    "files": ["~/.dontpanic/config.json"],
    "services": ["Claude account / Claude Code or CLI runtime"],
    "auth": ["Claude CLI authenticated by operator"],
    "config": [
      "roles.implementer",
      "roles.auditor",
      "roles.goal_auditor"
    ]
  },
  "verify": {
    "doctor_profiles": ["core"],
    "probes": ["cli:claude", "agent_role_config"],
    "readiness": "Ready when the claude command is present and the selected DontPanic role points at claude."
  },
  "owner_boundary": {
    "dontpanic_core": [
      "agent registry entry",
      "dispatch envelope",
      "audit/signoff capture",
      "quota and breaker handling",
      "role configuration"
    ],
    "adapter": [
      "subprocess executor for claude",
      "stream/output parsing",
      "timeout and envelope normalization"
    ],
    "operator": [
      "Claude CLI installation",
      "account authentication",
      "model/quota management",
      "local CLI updates"
    ]
  },
  "mutation_boundary": {
    "writes_dontpanic_state": true,
    "external_mutation": "agent_subprocess_execution",
    "allowed_path": "DontPanic supervisor invokes claude through the governed executor and captures artifacts through audit/signoff writers.",
    "forbidden": [
      "Bypassing supervisor gates",
      "Untracked agent writes outside declared plan scope",
      "Treating Claude account configuration as DontPanic-owned state"
    ]
  },
  "notes": [
    "Claude is an external runtime, not bundled by DontPanic.",
    "Core profile may also support other agent CLIs; this manifest records the Claude-specific path."
  ],
  "setup_steps": [
    {
      "id": "install_claude_cli",
      "what": "Install the Claude CLI so DontPanic can spawn agent runs through the governed executor.",
      "automatable": true,
      "command_template": "npm install -g @anthropic-ai/claude-cli",
      "verify_probe": "cli:claude",
      "human_required_reason": null
    },
    {
      "id": "authenticate_claude",
      "what": "Authenticate the Claude CLI against the operator's Claude account or API key.",
      "automatable": false,
      "command_template": "claude auth login --token <YOUR_CLAUDE_API_TOKEN>",
      "verify_probe": "agent_role_config",
      "human_required_reason": "Operator must approve scopes for their Claude account and treat the API token as a secret; DontPanic does not provision Claude credentials on the operator's behalf."
    }
  ]
}

3.1 Ралі за пяцьх крокаў

  1. Падача: прычаму жоднага эксперымента не пачалася, чалавек сформулюваў бізнес-запіт, абмежэння, метрыку, крытарыя прыйняцьбы і нынішньага лідэра.
  2. Прыемка: агент для аналізу пераканалы падтверджэння, выявіў анамаліі і запропанаваў гіпотэзы, якія можна было б перапрацаваць, замест таго каб адразу перапісваць мадэль.
  3. Настройка: калі гіпотэза была затверджана, агент для рэалізацыі запісваў яе у вачынку модульнага коду, дэтэрміністычных артыфактаў і вачынку эксперымента, які можна было перадзеяць.
  4. Атака: агент-рэвізор пераглядаў наявнасць вытэкання інфармацыі, памылак у крос-валідазіі, нестабільных значэннях і незрозумелага походжання дадзэнняў, а таксама спытваўся, чы рэальная выгода застаецца пасля пораўнання з нынішнім лідэрам.
  • Рашыранне да чалавеку: выбір, адхоўкі, пашырэнне чы гэтыя змяны стратэгіі застаўаліся на рашынку чалавека. Агенты моглі запрасіць певны падход, але адпаведныя рашынкі застаўаліся у чалавека.
  • Праўыя выгоды крыліся ў кантролюемай паралелізацыі, а не ў простай швальнасці кодавання. Разныя агенты моглі сфокусавацца на разных спосабах падчынення целей, тады калі чалавекскі элемент захоўваў намеры продукту, ўзгоднасць з бізнес-практыкамі і адпаведнае адпраўданне. Рэзультат быў бліжы да маленькай команды, якая працуе над продуктам, чым да адной сесіі чат-бота.

    3.2 Lean ML delivery

    Працэс працы агента таксама був прыв’язаній до ефектывного цыклу жытця продукту, з метою здэшэвлення експерыментыв у рэжымі DEV, ускладнення підробкі даных під час тэстування в рэжымі UAT і запобігання віпадковім змінам у станах віробніцтва. Чым більшэ експерыментыв проводылося, тым ціннішою ставала падзелу на DEV/UAT/PROD. Новій агент міг прыеднатыся без необхідносты покладатыся на памяць про поперэдні розмові, оскількі авторытэтні даныя зберыгаліся у вігляды файлів, маніфестыв, прогнозів поза структурою (OOF), рэестру перэможців і запісаніх рышэнь шчодо просування. Ключовій прынцып: нехай агенты забезпечуюць швідкісць, а arteфакты і механізмі контролю — достовірнісць даных.

    4. Перэвірка даных перад тым, як ім вірыты

    Перад стварэннем модэлі файлы для навчання і тэставання былі аналізаваны за дапамою SHA-256, пры чым пераглядаліся колонкі по аднай. Гэта не была бюракратыя. Некалькі особеннасцей моглі змяніць прастор характэрыстыкаў пад час выканання прыкладоў і пашкадзіць прыкладныя рэзультаты, не ствараючы жадных відчутных памылак.

    • У наборэ дадзеных для навчання было 3,493 радкаў і 34 колонкі, тады як у наборэ для тэставання — 500 радкаў і 33 колонкі, адтуды ў яго не было меты.
    • У колонках Ambience і Restaurant Tier у наборах для навчання і тэставання былі разныя тыпы дадзеных, таму для таго, каб модэлі отрымалі ідэнтычныя характэрыстыкі, была неабходна явная прымусовая канвертацыя.
    • У наборэ для навчання адна з колонак мела назву Endorsed By, а ў наборэ для тэставання — Endoresed By. Без праверкі супараднення, практыка могла стварыць характэрыстыку тэсту, якая бы зовсім не існавала.
  • Не было ні дублікатных радоў, ні дублікатных вектараў-прадзектароў, таму даныя на рывень радоў былі чыстымі.
  • Номер рэгістрацыі выканаў ролю ідэнтыфікатора, а не прадзектара для бізнесу (Pearson — або -0,017, Spearman — або -0,022). Яго не включалі ў модэлі, а заставілі толькі для супарабоцавання радоў у канцы.
  • 5. Анаіз даных

    5.1 Цэль з сільным правым співпаданнем

    Годовыя выручкі мелі дзейнавае правае хвоста. 90-й перцентыль станавіўся адносна ₹48 млн, 95-й — адносна ₹57 млн, 99-й — адносна ₹100 млн, а максімум — ₹400 млн; первасны пакосьванне дыстрыбуцыі станавіўся адносна 6,65. Пры выкарыстоўванні трансфарматыроўкі log1p дыстрыбуцыя стала практычна сіметрычной, і былі пораўнаны первасныя, log1p-і тэлекі Yeo-Johnson, пры чым пазней была перапрацавана версія, заснованая на плошчы за квадратны фут. З пункту зору бізнесу, большасць рэстаранаў знаходзіцца ў досыта вузкай дыяпазоне выручкі, тады як незначная група вельмі большых закладоў стварае значныя фінансавыя адхылення, калі іх не врачымаць.

    Хвостаў не было проста візуальна незвычайным — ён домінаваў у падазрах. Аналіз адхыленняў паказваў, што незначная група рэстаранаў з найгоршымі прагнозамі стварала значную частку аб’ёму квадратных адхыленняў, таму дыягнастыка хвостаў стала ключовай часткой ацэнкі.

    5.2 Для недастатковых дадзенняў патрэбны больш за адна правіла

    Значэнні, які не былі заданы, не расследваліся як адна ўзеякая проблема. Дзеяныя з іх выражалі звычныя недастаткі ў якасці дадзэнняў. Іншыя паказвалі структуру бізнесу — напрыклад, порожняя ацэнка розважальных прыемнасцей таму, што заклад не праслугавае розважальнымі практыкамі. Адна і тая ж правіла заполнення моглы знішчыць корысную інфармацыю.

    Звычныя віпадкі нехваткі дадзэнняў, такія як популярнасць у соцыяльных меражах, загальная ацэнка, атмасфера і клас, адмахваліся за дапамою метода заполнення, адпрацаванага на навчальных дадзэннях, плюс явных адзначэнняў пра нехватку. Гэта дазволяе модэлю розразліцаваць оцененыя значэння ад сітуацыі, калі нічога не было зафіксавана. Структурныя віпадкі нехваткі дадзэнняў, якія стосуюцца жывай музыкі, камедыйных выступаў, выгодных прыемнасцей і жывых спортавых практык, ператвараліся на флагі доступнасці, такія як has_live_music і has_comedy. Порожняя ацэнка можа значыць, што такой сервіс не існуе, што ўжо ёсць іншым станам бізнесу, чым невядомая ацэнка.

    ORDINARY_MISSINGNESS_FLAGS = {
        "facebook_popularity_quotient": "facebook_missing",
        "instagram_popularity_quotient": "instagram_missing",
        "overall_restaurant_rating": "overall_rating_missing",
        "ambience": "ambience_missing",
        "restaurant_tier": "tier_missing",
    }
    
    STRUCTURAL_AVAILABILITY_FLAGS = {
        "live_music_rating": "has_live_music",
        "comedy_gigs_rating": "has_comedy",
        "value_deals_rating": "has_value_deals",
        "live_sports_rating": "has_live_sports",
    }
    
    
    def add_missingness_features(df: pd.DataFrame) -> pd.DataFrame:
        """Add ordinary-null and structural-availability indicators before imputation."""
        required_columns = set(ORDINARY_MISSINGNESS_FLAGS) | set(
            STRUCTURAL_AVAILABILITY_FLAGS
        )
        missing_columns = sorted(required_columns - set(df.columns))
        if missing_columns:
            raise KeyError(f"Missing required columns for missingness features: {missing_columns}")
    
        df = df.copy()
        for column, flag in ORDINARY_MISSINGNESS_FLAGS.items():
            df[flag] = df[column].isna().astype("int8")
        for column, flag in STRUCTURAL_AVAILABILITY_FLAGS.items():
            df[flag] = df[column].notna().astype("int8")
        return df
    

    5.3 Кацэгародныя плямы: 297 варыянтавання назв горадоў

    У столцы «Горад» было 297 первасобных варыянтавання назв для значна меньшага калекцыі рэальных рынкаў. Разлічвалася верхня і ніжня велічыні літароў, былі просторы і спецыяльныя знакі, з’являліся памылкі і альтэрнатыўныя назвы, а дзеякі запісы былі складнымі строкамі, якія называлі кальколь горадоў. Для чысткі паказаных даных была выкарыстана комбінацыя перагляду з вікорыстаннем алгорытма fuzzy-matching (rapidfuzz), дыктарыю альтэрнатыўных назв і явнага парсінгу складных запісаў. Флажкі рэдкіх горадоў і паказнікі частоты з’явлення горадоў засталіся, таму што як розмер рынка, так і наявнасць дадзэнняў можа вплываць на адлікі обороту. Крок падбору проста прызначае кандыдатаванні для перагляду чалавекам і ніколі сам не зменяе значэнняў:

    def generate_city_candidate_matches(
        city: pd.Series,
        minimum_similarity: float = 80.0,
    ) -> pd.DataFrame:
        """Return nearest fuzzy matches for review; this never changes city values."""
        normalized = normalize_city_values(city, aliases={})
        counts = normalized.value_counts()
        names = [name for name in counts.index if name != "unknown"]
        rows = []
        for raw_city in names:
            candidates = [candidate for candidate in names if candidate != raw_city]
            match = process.extractOne(raw_city, candidates, scorer=fuzz.ratio)
            if match is not None and match[1] >= minimum_similarity:
                rows.append(
                    {
                        "Raw City": raw_city,
                        "Candidate": match[0],
                        "Similarity": float(match[1]),
                        "Count": int(counts[raw_city]),
                    }
                )
        return pd.DataFrame(
            rows,
            columns=["Raw City", "Candidate", "Similarity", "Count"],
        ).sort_values(["Similarity", "Count", "Raw City"], ascending=[False, False, True])
    

    5.4 Пары зменных

    Тып рэсторана і ранг горада абсалютна разныя характэрыстыкі, якія значыцынны спосабом вплываюць на обсяг выручкі. Фармат рэсторана вплывае на сярэжню цену століка, швыдкасць обслужвання і мадэль кампаніі, тады як ранг горада ўособлівае ў сябе ступень попытку, купоўную спроможнасць і розмеры рынку. Адзінкавыя атрыбуты былі корыстнымі, але мелі вельмі большую плямавасць. Іжа, гігіяена, спакойна цэна за прыемлівасць, адказнасць персоналу і атмасфера — гэта не незалежныя факторы. Яны взаімаюцца з фарматам, віком рэсторана, рынкам, суспяльным паводзе і позіцыяванням, што стала прычыной як нелінейных методаў аналізу, так і рэгульавання взаімадзеяў.

    5.5 Шырэй картанае

    Корляцыя Pearson і Spearman паказалі разныя рэзультаты. Некалькі фактора мелі набліжна сільнейшую монотонную, а не лінейную зв’язку з колькасцю персоналу, таму існавалі корыстныя сігналы нават там, дзе прама лінія пасходзіла па-разным чынам. Былі дадзены пераконтрольванні парных зв’язкаў, каб экстрэмальныя корляцыі, якія базаваліся на вельмі маляй колькасці перакрываючыхся спостарэнняў, не былі пацярплены за стойкую структуру.

    5.6 Атрыбуты, заснованыя на часе

    Даты адкрывання былі раздэлены на календарныя складовыя і атрыбуты віку. Рэстараны з большым векам часта зараблялі больш, але гэта спрацоўвалася як асоціяцыя, а не як каузальны факт, адкуль ўжо вік можа выступаць заместнікам для розпазнаўання маркі, выжывання адзелень, падтрымкі з боку кліянтаў чы ўсага масштабу. Фіксаваная дата-рэферэнс памагала зберагчы воспавядомленасць атрыбутаў.

    6. Проблема дзісбалансу ў задачы рэгрэсіі

    У рэгрэсіі няма дзіявання дзіўнай распадзелкі класаў у сэнсе класыфікаціі, але для гэтага цялявога показніка існавала аналагічная сітуацыя: высокія значэння былі рэдкіснымі і карыстычнымі з точкі зору аналізу. Пад парадкам RMSE калькуляцыя сумарнай памеры квадратных адхылэнняў можа быць занята калькуляцыямі калькулаваных адхылэнняў з вялікімі значэннямі. У працэсе дыягностыкі найгоршыя прыклады займалі непропарцыйна большую частку, таму модэль могла выглядаць нормальна для большасці рэстаранаў, але ўсё равна паказваць слабыя рэзультаты, калі ўпускала калькуляцыю кількох прыкладаў з вялікімі значэннямі.

    Таму для параболення была выкарыстоўвана 5-кратная крос-параболення з стратыфікацыяю па цялявым показніку. Контынуальны цялявы показнік быў раздзелены на 10 квантыльных дыястэроў толькі для пазначэння груп у крос-параболенні, тады як модэлі продовжвалі трэнавацца і оцэнювацца на аднойчыных даных пра выручку. Фінальныя перагляды булі паўтараны на незалежных прыкладах (17, 42 і 101). Гэта зменіла шансы таго, што кандыдат стане чэмпіонам проста таму, што якаясь ўдачная раздзелка падае экстрэмальныя значэнняя ў лёгкіяя групы.

    7. Адлегчэнне характэрыстыкаў

    Функцыі былі роздзелены на безстановыя трансформаціі і статыстыку падходжання. Безстановая логіка працавала ідэнтычна як на навчальных, так і на тэстовых даных. Усе параметры, які булі падобраны — чы то медыяны, карты частоты або кодування — булі отрыманы вэськама з навчальных дадзеных, версіонаваны і перывжываны пад час інферэнсу. Гэта дазволіла зберагчы працэс у контрольным стане і запобігло непазначальному зсуву між навчальнымі і тэстовымі дадзеннямі, які можа быць спрычынены прадзеяванням.

    • Флагі відсутнасці і доступнасці, як опісана вышэй.
    • Характэрыстыкі календара: дата пачатку (год, месяц, квартал, дзень тыжня), а таксама вік у месяцах і гадах, а таксама катэгорыя «эра пачатку» з чотырма групамі.
    • Колькісна інформацыя пра кухню, отрыманая шляхом аналізу спіску кухонь, роздзеленага комамі.
    • Іўерархія горадоў: вачыманы горад → чыставаны горад → асновны горад → штат, з флагамі для складных елементаў, рэгіонаў і аліясоў, а таксама показатэлямі частоты і рэдкісных горадоў на трох рубежах.
  • Катагарычныя взаімадзеянні, які фіксуюць камбінацыі з іншай эканомічной цэннаю, чым яе складовыя: тэма і тып рэсторана, тэма і месца распадзелу, алкагольны напой і яго тып, а таксама дзеякі пары разважанняў і фармата.
  • Чыслаўскія взаімадзеянні для рэгулярызаванай лінейной семьі: ранг рэсторана і ранг гароду, сацыяльная відкрытасць і ранг, досвід кліента і сацыяльная відкрытасць, а таксама возраст і популярнасць. Чырвоныя ператворылі певныя нелінейныя бізнес-вазаеўнасці на форму, якую могла выкарыстоўваць метода Ridge.
  • Кодаванні частоты і парадку для кожнага катагарычнага столбца, якія выучваліся на дадзенах для навчання і перыяктываліся на дадзенах для тэставання.
  • Главны фіксаваны пайплайн выкарыстоўваў 71 прыкметнік. Дадатковыя створаныя сем’і тэставаліся за дапамою метода абляцыі, а не прымножваліся автаматычна; кожны функцыйны элемент займаў свае месца завяршэнням інкрэментальнай праверкі, а не завяршэнням інтуўітывнага адбору.

    8. Адчыненне зовнішняй дадзейнай для апрацоўкі

    Адзін з дапаможных направленняў даследжэння спынуўся на супарабоце даных пра мяста і штаты з публічнымі геаграфічнымі і эканамічнымі дадзеннямі. Пытанне заключалася у тым, чы розмах местнага рынку, ступень урбанізацыі, інтэнсывнасць турызму і аб’ём населення даўаюць дапаможную інфармацыю паўза сабеіндывыя характэрыстыкі рэстарану.

    • Для кожнага мяста: населенне, колькісна і аб’ёмная структура домоў, логарыфм населення, коордынаты, а таксама пазнакі «так/нет» для мегапалэц, рэгіону століцы, прыбрэжных мяст, сталіц штатаў і мяст з населеннем паўза мільйон чалавек.
    • На рэгіональнам лэвеле: населенне, урбанізаванае населенне і яго частка, ўтрамленасць, ВВП на душу населення, а таксама колькісна і вартасовая структура турызму, адносна да колькіснага показніка турызму.

    Рэзультат быў навмесна консерватывны. Некалькі зовнішняях характэрыстыкаў паказалі сігнал у ізольаваных тэстах, але група не паспела пакрашчыць фінальную сумку на адпаведны протакол замены і падняць яе качэнне, таму ёй так і не удалося стаць чэмпіонам. Бсць корыстны урок для бізнес-мадэлявання: зменная можа быць правдападобной і прыносіць прогназы сама па сабе, але даўа мало корысты, калі ёсць сільнейшыя, корэляваныя сігналы.

    9. Мадэлі і прычыны

    Даныя складаліся заўсёды з рэйтынгоў, рыхлых і структурных прыняжэнняў, а таксама катэгорыяў з высокай кардынальнасцю, таму калькuluваліся канкурэнтныя мадэльныя сем’і як гіпатэзы, замест таго каб прыймаць, што адны алгорытмы будуць домінаваць. Ridge і ElasticNet апынуліся неспадзевана конкурэнтнымі з CatBoost. Гэта не было параду для метода boosting. Гэта адбілася ад таго, насколькі структуры ўвайшла ў створаныя характэрыстыкі і насколькі корысная ёсць рэгулярызацыя, калі існуе многа супакоўзлых прычыннікаў. Мадэлі на базе дрэва застаўся важнымі, адтолькі якія можаюць зафіксаваць нелінейныя взаімадзеянні, якія лінейныя мадэлі не можаюць выразіць безпосерэдна.

    10. Налагоджэнне

    У перадзеі стварэння кожная група мела свае адзінае даследжэння з Optuna, якое ацэнівалася за показнікам RMSE за межамі фолдаў, атрымленая праз парадоўжаныя, стратыфікованыя па цэлі фолды. Выбір кандыдаў і ўзнесенне іх на вышэйшыя пазіцыі здольгвалася на внутраній верыфікацыі, а не на табелі лідэраў; гэта важна, калі бо пазнейшы этап оптымізацыі для змаганняў не трэба плутаць з працэсам генералізацыі.

    Найэфектывнейшая чыстая сумешчаная мадэль аб’еднала CatBoost, Ridge, ElasticNet і варыянт Ridge з стабілізаваным за дапамою квадратнага корана паказнікам варыянцы (WR01) у співважаннях працоўнае 30%, 10%, 6% і 54%. Іё парадоўжаныя показнікі RMSE за межамі фолдаў станавілі адпаведна працоўнае ₹20.10M. Вялікі вага WR01 быў значным сігналам: трансфармаваная лінейная мадэль не была найкрашчым самастойным алгорытам, але ўнаследак іншай геометрыі яе памылак яна стала вельмі ценной ў складзе ансамбля.

    11. Чы гэта дапамагало, чы ні

    Кожны эксперымент быў задафісаваны з інформацыяй пра семью яго функцый, настройкі модэлю, прыметы паўтарной перапрацоўкі, прагнозы па зразку OOF і рашэнне пра ўжыванне. Прагрэс адбываўся за счыткам адхоўленняя слабых ідэй так жорстка, як і падтрымкі сільных.

    • Спачатку была задана базовая лінія. Серэйны і медыянны прагнозавальнікі задалі ніжнюю межу RMSE адпаведна 21,6 да 21,7 мільйонаў, што дапамагало лёгка адзначыць модэлі, якія былі проста складныя.
    • Рэгулярызацыя мела важнае значэнне. Методы Ridge і ElasticNet перамагалі звычны OLS за вялікай размой, таму што створаны простор містыў корэляваныя сігналы і взаімадзеяння.
    • CatBoost даваў нелінейную і катагарычную сілу, але не падазроўвалася, што настройкі дапаможу. Адны перспектывны рэзультат з CatBoost павысіў эфектывнасьць оптымізацыі прыбліжна на 258 тысяч, але пасля таго не працаваў пад час паўтарной перапрацоўкі на незалежных дадзенах і быў адмовлены як прыклад перэадаптавання.
  • Інжыніерыя характэраў залежала ад мадэлі. Кодаванні цэлі, взаімадзеяння, частоты катэгарыяў і характэрыстыкы трымкі былі сярод найболей корыстных груп, тады як калькуляцыі на адчутныя показнікі давалі мало корысты, калі існавалі болей сільныя фактары прычыны.
  • Дадзенні з зовнішніх істочнікаў пра горад і штат былі корыстным, але негатыўным фактам: дзеякія тэсты складовых падняліся, а эфект ад замены на каскадныя мадэлі пагорчыўся, і гэты падход не увайшоў у тыя найлепшыя рашэння.
  • Каскадныя мадэлі далі найбольш надзеючы эфект, адколі CatBoost і рэгулярызаваныя лінейныя варыянты давалі разныя рэзультаты. Метай была мінімальная квадратовая памята, атрыбутаваная допаможнымі мадэлямі, а не максымальная складнасць.
  • Класіфікаторы для рэгіонаў з малым колькасцю дадзенняў і мадэлі корэкцыі заляшковых памят выказалі перспектывныя дыягностычныя эфекты, але не даўалі достатньго падняцья значэння RMSE, каб праверыць ўзнесенне іх у прыорытэт. Корыстнасць для дыягназы і корыстнасць для прогнозавання расследваліся як аднае самастоятэльныя пытанні.
  • 12. Рэйтынгі для разных чампіёнаў

    У праекце былі створаны два тыпу чампіёнаў: чыстая мадэль, выбраная праз парадную перапрацоўку даных, і чампіён з сораўнання, налаштаваны для сераўнічання ў конкрэтным аптэкранавальным сераўе. Трэці пункт перапрацоўкі, S08, паказвае, як вплывае намерна мала корэкцыя на рэзультаты, прычым гэта адбываецца да болей значных этапаў, прызначаных для сораўнання. Шырыя рэйтынгі адпаведзаюць на разныя запытанні і не ўсуненліва паказваюць ступень узнавамасці мадэлі.

    У частыне сораўнання, версія LB05 дапамогла зменшыць публічны RMSE на 9,195,461.72 рупіяў у пораўнаны з S08, тое ў 76.1% раза. Гэта рэзультат табелі лідэраў, а не доказ таго, што мадэль, якая можа быць адправлена ў прыменэнне, раптам пакажае высокую узнавамасць з RMSE 2.89 мільйона рупіяў. Ёсць скрыпт, які выкарыстоўвае зафіксаваныя компоненты і запішае першую сумаваную версію мадэлі:

    from __future__ import annotations
    
    from datetime import datetime, timezone
    from pathlib import Path
    import time
    import json
    
    import joblib
    import numpy as np
    import pandas as pd
    
    from src import config, data, models, submission
    from src.pipeline import FeaturePipeline
    from main import _prepare_catboost_matrices, _prepare_model_matrices
    
    
    S01_ID = "S01"
    S01_WEIGHTS = {"catboost": 0.50, "ridge": 0.45, "elasticnet": 0.05}
    
    
    def run(output_dir: Path | None = None) -> tuple[Path, Path]:
        output_dir = output_dir or config.SUBMISSIONS_DIR
        output_dir.mkdir(parents=True, exist_ok=True)
        manifest_path = config.EXPERIMENTS_DIR / "frozen_v1_manifest.json"
        if not manifest_path.exists():
            raise FileNotFoundError(f"Frozen V1 manifest is required: {manifest_path}")
        manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
        if manifest.get("feature_pipeline") != "processed_v1" or manifest.get("predictor_count") != 71:
            raise ValueError("Frozen V1 manifest does not describe the processed_v1 71-predictor contract")
    
        train_raw = data.load_train()
        test_raw = data.load_test()
        pipeline = FeaturePipeline().fit(train_raw)
        train = pipeline.transform(train_raw)
        test = pipeline.transform(test_raw)
        target = config.INTERNAL_TARGET
    
        X_train = train.drop(columns=[target, config.INTERNAL_ID_COL], errors="ignore")
        X_test = test.drop(columns=[config.INTERNAL_ID_COL], errors="ignore")
        y = train[target].astype(float).to_numpy()
        X_numeric, X_test_numeric = _prepare_model_matrices(X_train, X_test)
        X_cat, X_test_cat = _prepare_catboost_matrices(X_train, X_test)
    
        predictions = {}
        timings = {}
    
        start = time.perf_counter()
        catboost = models.get_catboost(**{
            key: value for key, value in manifest["catboost_config"].items()
            if key != "native_categorical"
        })
        cat_features = [
            index for index, dtype in enumerate(X_cat.dtypes)
            if str(dtype) in {"object", "string", "category"}
        ]
        catboost.fit(X_cat, y, cat_features=cat_features, verbose=False)
        predictions["catboost"] = catboost.predict(X_test_cat)
        timings["catboost_seconds"] = time.perf_counter() - start
    
        start = time.perf_counter()
        ridge = models.get_ridge(**manifest["ridge_config"])
        ridge.fit(X_numeric, y)
        predictions["ridge"] = ridge.predict(X_test_numeric)
        timings["ridge_seconds"] = time.perf_counter() - start
    
        start = time.perf_counter()
        elasticnet = models.get_elasticnet(**manifest["elasticnet_config"])
        elasticnet.fit(X_numeric, y)
        predictions["elasticnet"] = elasticnet.predict(X_test_numeric)
        timings["elasticnet_seconds"] = time.perf_counter() - start
    
        weights = manifest["ensemble_weights"]
        blend_prediction = sum(weights[name] * predictions[name] for name in weights)
        submission_df = submission.build_submission(test_raw, blend_prediction)
        submission_path = output_dir / "S01_frozen_v1_blend.csv"
        submission.write_submission(submission_df, submission_path, expected_rows=len(test_raw))
    
        component_paths = {}
        for name, prediction in predictions.items():
            component_paths[name] = output_dir / f"S01_{name}_predictions.csv"
            pd.DataFrame({config.ID_COL: test_raw[config.ID_COL].to_numpy(), config.TARGET: prediction}).to_csv(
                component_paths[name], index=False
            )
    
        metadata = {
            "submission_id": S01_ID,
            "model": "Frozen V1 Blend",
            "feature_version": "frozen production",
            "oof_rmse": 20097389.205713525,
            "catboost_weight": S01_WEIGHTS["catboost"],
            "ridge_weight": S01_WEIGHTS["ridge"],
            "elasticnet_weight": S01_WEIGHTS["elasticnet"],
            "public_leaderboard_rmse": None,
            "leaderboard_rank": None,
            "timestamp_utc": datetime.now(timezone.utc).isoformat(timespec="seconds"),
            "submission_file": str(submission_path),
            "component_files": {name: str(path) for name, path in component_paths.items()},
            "fit_method": "fit_each_frozen_component_on_all_3493_processed_v1_training_rows",
            "catboost_production_iterations_rule": "fixed_manifest_value_no_early_stopping",
            "manifest_path": str(manifest_path),
            **timings,
        }
        metadata_path = output_dir / "S01_metadata.json"
        metadata_path.write_text(json.dumps(metadata, indent=2), encoding="utf-8")
        return submission_path, metadata_path
    
    
    if __name__ == "__main__":
        for path in run():
            print(path)
    

    13. Рэзультаты ў супернікаўскіх змаганнях проты гэналізацыі

    Калі была створэна чыстая мадэль і ўзначаны протакол яе праверкі, аддзельны этап оптымізаціі для супернікаўскіх змаганняў палягчыў прыкладзенні прогнозаў да конкрэтнага незайманага набора дадзенняў для ацэнкі. Дэталі гэтага працэсу не ў межах данай тэмы. Методолагічна важлівае — гэты этап выкарыстоўваў інфармацыю з супернікаўскага сераўера, а не новыя пазначаныя даны для навчання.

    Таму канечны показнік RMSE у рэйтынгу, які станавіць адпоўна ₹2,893 млн, трэба спрыймаць як характэрны толькі для супернікаўскіх змаганняў і, можліва, як наследак перэадаптавання мадэлі да гэтага набора дадзенняў. Адпаведныя показнікі для новых рэстаранаў застаюцься рэзультатамі павторных тэстаў CV, якія станавляць адпоўна ₹20,10 млн. Разлік гэтых двух цыфр ўскладненне для науковай і бізнес-інтэрпрэтацыяў.

    У рэальным застосаванні прогназавання шар, оптымізаваны для канкурэнціі, быў бы адмовлены, якбы не было доступна эквівалентнага сігналу калібравання. Сістэма, якая можа быць запусканая, выкарыстоўвае зафіксаваныя каналы апрацоўкі дадзэнняў і альянсы модэляў, сочыць за залішкамі і змянамі ў распадзе дадзэнняў, і перэнашвачае мадэль, калі прыходзяць рэальныя даныя.

    14. Прыяўкі

    • Працавалася з гадзенням, што працэсы навчання і тэставання выйшлі з дастаткова схожых бізнес-процэсаў, каб перакрытая верыфікацыя мела сэнс. Жадных формальных корэкцый з-за змян коварыятав не было, за выключэнням перакрыцання структуры і распаду дадзэнняў.
    • Номер рэгістрацыі быў строго ідэнтыфікаторам і не ўключаўся у чыстую мадэль, адтолькі ў яе не было жаднага пераконвалюючага зв’язку з показнікамі дзейнасці.
    • Прыпускалася, што вакуумныя ацэнкі канаў зручнасцей несу структурную інфармацыю, калі адпаведныя послугі відсутніе, што стала падставай для дызайну флага доступнасці.
  • Усі статыстыкі прадзеяўнай обработкы, якія былі выкарыстоўваны, павінны быць взятыя з дадзенаў навчання і без змян быць перыяктыя пад час аналізу, — гэта правіло сама працэсная лінія прыменяе, таму ёна ніколі не залежала ад памяці аналітыка.
  • Зовнішнія рыночныя дадзеныя зарахоўваліся як прыемныя толькі тады, калі яны павышалі рэзультаты паўтарной праверкі і працы ансамбля. Аднальна правдападобнасць не была достатняй.
  • 15. Рэкамендацыі

    • Спрыяйце якосты дадзенаў, як і выкарыстоўванню модэля. Несувярэннасці схемы, фрагментаваныя назвы гарадоў і неоднаковыя катэгарыі можу знішчыць сігнал прытаманны модэлю, перш чым алгорытм яго пазнае.
    • Раздзеляйце „выключанне з-за невядомасці“ ад „выключання з-за вялікага“; гэта другое часта ёсцца функцыяй, а не проблемай.
    • Для несаўершэнных цэляў падаючых доходаў трэба сочыць за значэннем RMSE, канцентрацыяй квадратных падбягоў, а таксама за аб’ёмным показнікам. Кальколькі вялікіх кліентаў можу вялікі вплыв на тое, чы розрахунак будзе фінансава практычны.
    • Ўжывайце чыста выражаныя крэтыніяры пры прымененні акцыяў: адыскаванне кандыдатаў, паўтарная перакананасць на незалежных прыкладах і замена альянсаў. Гэта не дазволяе, каб выгода, атрыманая на аднай з груп, па чыяй-небудзь памылцы стала найкрашчай.
    • Спрыяйце вікорыстоўванню AI-агентаў як частыні модэлу адработы, а не як ліцэнзыі на самастойнае прыменення акцыяў. Нека агенты прыметліяюць, ствараюць і крытыкуюць, тады калі важлівыя рашэнні ўжо стосаваныя да модэляў і продуктав застаюцца у руках людзей.
    • Зберагаюце фактычныя даныя не ў вікні чату, а ў іншым месцы. Наборы дадзеных, маніфесты, прыклады прыменення за межамі модэля, журналы эксперыментаў, найлепшыя рэшынкі і рашэнні пра ўзнесенне іх у прыорытэтны статус трэба застаўляць, каб новы агент могаў выкарыстоўваць гэтыя доказы, а не толькі прадышлыя паведамленні.
    • Пры гэнерыяцыі эксперыментаў з МЛ неабходна раздзеляць асяроддзя DEV, UAT і PROD. Свабодная творчасць прабывае ў асяроддзі DEV, тады як рэплікацыя і крытычны аназіс выконваюцца ў асяроддзі UAT, а асяроддзе PROD павінна быць дэтэрміністычной, зафіксаванай і можлівай да адворачэння.

    16. Урокі

    Главны урок не ў тым, што якісь алгорытм выграў. Дысцыплінована формулявацыя задачы, аўдыт дадзэнняў, пераканальванне з урахоўваннем атыповых сітуацый, інжынерыя характэрных параметраў, разнаобразныя залішкі і кантролюемы працэс выканання задач создалі лепшую сістэму прагнозавання, чым сама толькі складнасць модэлю. За дапамогою DontPanic агенты працавалі як команда, што спрыяла прышвартованню і рэалізацыі рашэнняў, тады як чысткія людзкія крокі запобеглі таму, каб швальба заменіла собой разумнае суджэнне.

    Чэмпіон фінальнага змагання пасягнуў прыблізна да 2,893 мільйона RMSE пасля этапу оптымізацыі, прызначанага для сяродавішняе атмасферы ацэнкі. Гэты рэзультат заканчыў змаганне, але яго паводлівае аддзельна, таму што ён можа быць наследкам перэадаптавання і не павінен спрыяць ацэнцы паказніка для будучых рэстаранаў.

    Большая наука — гэта практычная. Абавяжыце практыку атэстацыі ўсё раней, чым прыступіце да налаштавання, зберагуйце неудачныя эксперыменты, прызнаюце успехі толькі пасля таго, як яны паўтарыюцца, і ніколі не плутайце мадэль, якая павышае паказнік, з той, якой можна было бы даверыць у рэальных умовах. А якшо участвуюць калькі AI-агентаў, нехай яны граюць у волейбал: нехай агрэсыўна ведуць гру, але старайцеся, каб важлівыя рашэнні вярталіся да чалавека першым, чым будзе зафіксаваны гол.