рандомизация действий pokerbot-a

Для определения текущего действия бота используется tree-search (перепиленный и доведенный до ума MCTS). Как известно, алгоритмы поиска по дереву на выходе дают оценку матожидания для каждого действия

                   { EV[fold], EV[call], EV[raise] } 
Каким образом нужно выбирать текущее действие, чтобы:
  • a. максимизировать матожидание нашего выйгрыша
  • b. оставаться максимально нечитаемым для оппонента

    Какие варианты я нашла к настоящему времени:

  • 1. играть действие с max EV (action = argmax(EV[fold/call/raise]))
    Очевидно, что это "вааще не вариант", поскольку оппонент все равно приспособится, как ни моделируй
  • 2. нормализовать EV "по-тупому" и играть действие из дискретного распределения
    Т.е. допустим поиск нам дал (0, 3, 6) => нормализуем => (fold = 0%, call = 33%, raise = 66%)
    Несмотря на простоту реализации, этот метод не удовлетворяет (b), поскольку EV и вероятности связаны нелинейно
  • 3. нормализовать EV "по-умному"
    Любая функция ядра с радостью преобразует какое-нибудь число в какую-нибудь вероятность
    Возьмем, к примеру, гауссиан (6, 1) => нормализуем (0, 3, 6) => (fold = 0%, call = 1%, raise = 98.9%)
    Проблема этого метода в том, что все эти хорошие функции являются параметрическими, т.е. встает задача оценки параметра(-ов)
  • 4. прекратить, наконец, заниматься идиотизмом и подойти к проблеме по-научному. Одеваем белый халат, стильные очки... Формализуем задачу:

    у нас есть модель оппонента (т.к. поиск по дереву мы как-то делали) => мы можем замоделировать себя с точки зрения оппонента (используя эту же самую модель) => к моменту, когда был запущен поиск по дереву, у нас имелся априорный диапазон "наших" рук с точки зрения оппонента => соответственно, когда мы выберем какое-нибудь действие, у нас будет апостериорный диапазон (спасибо дяде Байесу:

        P(hand|action) ~ P(action|hand)*P(hand))
    => максимальная "нечитаемость" обеспечивается, когда с точки зрения оппонента наш спектр выглядит равномерно (вероятность каждой руки одинакова) и в нем максимальное количество рук с вероятностью > 0 => равномерность обеспечивается минимальной дисперсией => для определения вероятности действия используем softmax:
        P(action) = exp ( EV[action] / lambda ) / Σ (exp (EV[i] / lambda)
            где i = fold,call,raise
                lambda - управляющий параметр 
    => значит мы можем построить наш обобщенный взвешенный спектр из 3-х разных диапазонов (для каждого действия по отдельности) => получили стандартную задачу оптимизации:
    -- дисперсия рук -> 0
    -- количество рук -> max
    -- P(fold)*EV(fold) + P(call)*EV(call) + P(raise)*EV(raise) -> max
    оптимизируем по lambda

    Вот такие мысли у меня. В настоящий момент использую 4-ый вариант, но он весьма "тяжеловат" для вычисления. Хотела бы выслушать ваши подходы к решению сей задачи


    Насколько я понимаю, в задаче оптимизации мы все равно будем пытаться сбалансировать между максимизацией нашего взвешенного выигрыша и выдачей сопернику информации - мы не можем одновременно достичь обоих целей. Соответственно, параметр балансировки придется подбирать вручную Я бы искал решение в виде
            P(fold)*EV(fold) + P(call)*EV(call) + P(raise)*EV(raise) >= coeff * max(EV[f/c/r])
    где coeff от 0 до 1 (подбираем правилом от балды, ну, скажем, 0.7 - ну вот готов я потерять 30% от профита сейчас, чтобы замаскироваться, но если теряю совсем дофига, то идет лесом маскировка), а вероятности распределяются по какому-нибудь простенькому закону наподобие atan(ev * p) на пространстве от min(ev) до max(ev)

    Да, кстати, есть подозрение, что то, что мы не выдаем информацию оппоненту в текущий ход может не значить, что мы не даем ему информацию, которую он может учесть в будущих раздачах. Так что, не уверен в том, что формальный подход нас спасает. Если уж очень хочется, можно restricted nash response использовать =)

    Я бы искал решение в виде ....
    Мне кажется, Вы не совсем верно поняли: никаких коэффициентов дополнительно не потребуется, потому что этот самый несчастный коэффициент (lambda) уже подбирается в задаче оптимизации, т.е. имеем:
              EV[fold], EV[call], EV[raise] - константы 
    априорный спектр - константа
    3 апостериорных спектра - константы
    лямбда - свободный параметр системы
    И задача оптимизации как раз и заключается в том, чтобы максимально сбалансировать спектр наших рук с точки зрения соперника и то, что мы можем с него поиметь
    Фактически, эта лямбда эквивалентна p - константе RNR (только в RNR она задается априорно, а здесь оценивается). А с точки зрения пространства exploitation/exploitability - этот алгоритм дает такие же сильно выпуклые кривульки, как и RNR
    Да, кстати, есть подозрение, что то, что мы не выдаем информацию оппоненту в текущий ход может не значить, что мы не даем ему информацию, которую он может учесть в будущих раздачах. Так что, не уверен в том, что формальный подход нас спасает. Если уж очень хочется, можно restricted nash response использовать
    Так моделька все равно подстраивается под оппонента, так что если принимать оптимальное решение каждый ход + учесть bias/variance модельки как шум системы = получаем какой-то best responce на best responce. А RNR в моем случае не подойдет, поскольку подсчет NE для >= 6 игроков весьма затруднителен

    Я дико извиняюсь, но в задаче оптимизации мы вроде как оптимизируем одну целевую функцию. Здесь же система функций:

    -- дисперсия рук -> 0
    -- количество рук -> max
    -- P(fold)*EV(fold) + P(call)*EV(call) + P(raise)*EV(raise) -> max
    По идее, мы в итоге должны получить что-то вида
          w1 * (1/дисперсия) + w2 * количество рук + w3 * взвешенный EV -> max
    где w(i) показывает важность для нас каждой функции в оптимизации. Ну, или может я все не так понял (хотя, на самом деле все предельно ясно, кроме того, какую именно функцию оптимизируем-то). Можно формальное определение целевой функции?
    Я дико извиняюсь, но в задаче оптимизации мы вроде как оптимизируем одну целевую функцию
    Multi-Objective Optimization
    По идее, мы в итоге должны получить что-то вида w1 * (1/дисперсия) + w2 * количество рук + w3 * взвешенный EV -> max, где w(i) показывает важность для нас каждой функции в оптимизации
    Это то, что называется aggregate objective function. Я сделала немножко по-другому:

    1. Конструируем фронт Парето (т.е. каждая координата оптимизируется согласно собственному критерию)
    2. Выбираем из него оптимальное решение

    Очевидная проблема шага (2) в том, что мы, вообще говоря, не знаем какое решение выбрать, потому что все они хороши. Вообще говоря, одномерное пространство поиска не может дать многомерное пространство решений (см. топологию). Значит наше пространство решений на самом деле одномерное, а многомерным оно получилось потому что исследователь (я) оказалась недостаточно умной =). Делаем пас руками:

  • сортируем в порядке убывания наш фронт оптимальных решений по наиболее важной координате (я выбрала взвешенную сумму EV, потому что в первую очередь нужно выиграть максимум денег)
  • выбираем середину отсортированного фронта
  • параметр lambda принадлежащий выбранной точке и есть решение задачи оптимизации

    Почему это работает: много жестокой топологии и дифуров. Если простым языком, то когда какое-нибудь EV большое, то взвешенная сумма тоже получается большой и фронт "забивается" большим количеством решений которые максимально эксплоитят оппонента + граничное решение для полностью рандомного действия. Когда все EV примерно одинаковы, то во фронте присутствуют много решений с минимальной дисперсией, соответственно мы выбираем действие максимально эксплоитящее оппонента

    А, ну собственно мой пойнт в том и был, что если решаем многокритериальную задачу оптимизации, то множество решений имеет частичный порядок, и для выбора единственного доминирующего решения нужно этот порядок свернуть в полный. Что касается пассов руками, то без строгого доказательства (дифуры не страшны) мне сложно понять, чем

    A -- сортируем в порядке убывания наш фронт оптимальных решений по наиболее важной координате -- выбираем _середину_ отсортированного фронта -- параметр lambda принадлежащий выбранной точке и есть решение задачи оптимизации
    лучше чем
    B -- w1 * (1/дисперсия) + w2 * количество рук + w3 * взвешенный EV -> max
    В варианте A есть параметры 1) наиболее важной координаты 2) середины фронта (почему, например, именно середина, а не 40% - строгое доказательство докажет это?). В варианте B есть параметры w1, w2, w3 (ну, если поделить на w1, то останется всего два параметра). Возможно, для каких-то алгоритмов A лучше конечно (reinforcement learning? )

    Как я бы решал задачу, я уже писал:

    P(fold)*EV(fold) + P(call)*EV(call) + P(raise)*EV(raise) >= coeff * max(EV[f/c/r])
    Если рассмотреть этот алгоритм, то если одно EV сильно больше остальных, то оно будет важнее, и мы редко будем выбирать другие решения (т.к. иначе будем терять больше чем (1-coeff)*max(EV)); если EV примерно похожи, то мы будем выбирать их примерно равновероятно и давать минимум информации оппоненту
    Я бы искал решение в виде ...
    Проблема этого подхода в том, что он не учитывает информацию о нашем спектре с точки зрения оппонента. Т.е. представим ситуацию, когда наш спектр уже смещен в сторону сильных рук, EV[call] << EV[raise] и рейз позволит оппоненту сократить наш спектр до очень маленького количества рук. В таком случае, этот алгоритм все равно вернет рейз. Это плохо
    чем A лучше B
    Середина выбирается потому что "медиана отрезка отсортированных решений является точкой бифуркации для распределений вероятности построенных внутри топологии порожденной полуметрикой функции координаты по которой производилась сортировка". *выдохнула* :-)
    Возможно, atan можно заменить на softmax, возможно, нужно будет что-то сделать с фолдом, но общая идея такая
    Страшная тайна: в этой задаче не важно, каким образом выбирать функцию f:EV[action] -> P[action], достаточно, чтобы преобразование было монотонным

    А можно узнать, сам алгоритм поиска макс EV у тебя уже есть и работает, а осталась только такая мелочь как рандомизация решений для балансировки?

    перепиленный и доведенный до ума MCTS
    И есть, и работает. А рандомизация действий это вовсе не мелочь, поскольку на mid/high stakes без этого никуда
    Середина выбирается потому что медиана отрезка отсортированных решений является точкой бифуркации для распределений вероятности построенных внутри топологии порожденной полуметрикой функции координаты по которой производилась сортировка
    Не уверен, что осилил, но, иными словами, ты имеешь в виду, что такой алгоритм получения вероятностей будет давать оппоненту минимум информации из всех возможных, я правильно понял?
    Проблема этого подхода в том, что он не учитывает информацию о нашем спектре с точки зрения оппонента
    С одной стороны, что-то в этом есть, и нужно это обдумать. С другой стороны, у нас есть предсказатели, которые, если они были бы круто построены, предскажут, что оппонент будет делать в конкретной раздаче после нашего действия. Т.е. мы рейз - он с какими-то вероятностями FCR, мы колл - он с другими вероятностями FCR. Эти самые FCR уже учитываются при расчете EV, т.к. мы строим MCTS дерево, используя эти предсказатели. Т.е., наш постериорный спектр чувак уже в каком-то роде может учитывать. Проблема в таком видении только в том, что в предсказателе нужно учитывать наш спектр как параметр. И философия подхода, о котором говорю я, пытается лишь уменьшить информацию, доступную оппоненту, в последующих раздачах, а не в текущей. В текущей раздаче, наверное, можно принять стратегию оппа статической
    Страшная тайна: в этой задаче не важно, каким образом выбирать функцию f:EV[action] -> P[action], достаточно, чтобы преобразование было монотонным
    В твоем подходе, да, наверное. В подходе попроще это такой же параметр, подбираемый интуитивно, как и coeff
    Не уверен, что осилил, но, иными словами, ты имеешь в виду, что такой алгоритм получения вероятностей будет давать оппоненту минимум информации из всех возможных, я правильно понял?
    Ага, все так. В теории. На практике, проблема этого алгоритма заключается в том, что для оценки апостериорного спектра он использует модель оппонента для собственного моделирования, т.е. имеем все "вкусные" косяки machine learning - overfitting/prediction noise/bias/etc..
    С другой стороны, у нас есть предсказатели, которые, если они были бы круто построены, предскажут, что оппонент будет делать в конкретной раздаче после нашего действия. Т.е. мы рейз - он с какими-то вероятностями FCR, мы колл - он с другими вероятностями FCR. Эти самые FCR уже учитываются при расчете EV, т.к. мы строим MCTS дерево, используя эти предсказатели. Т.е., наш постериорный спектр чувак уже в каком-то роде может учитывать
    В этом, конечно, есть смысл. Имея абсолютно идеальную модель оппонента у нас нет нужды в математических заклинаниях, т.к. игра best response уже учтет все это на стопицот шагов вперед. Проблема как раз в отсутствии идеальной модели. Поэтому мы переключаемся на более высокий уровень абстрации: "как мы моделируем его как он моделирует нас как мы моделируем его"
    в предсказателе нужно учитывать наш спектр как параметр. И философия подхода, о котором говорю я, пытается лишь уменьшить информацию, доступную оппоненту, в последующих раздачах, а не в текущей
    И как можно учесть в предсказателе наш спектр? Брать с EM-алгоритма как у дядьки Ван-дер-Клейя?
    Имея абсолютно идеальную модель оппонента у нас нет нужды в математических заклинаниях, т.к. игра best response уже учтет все это на стопицот шагов вперед
    (Из серии разговоров за пивом) фик знает, все-таки мы строим модель оппонента исходя из того, что он будет себя вести сейчас согласно той статистике, что мы на него наблюдали, и мы именно против этой модели подбираем ответ. Если уж совсем фантазировать, оппонент себя может вести таким образом, что даже идеальный предсказатель (который смотрит только на ммм параметры оппонента, параметры игры, но не на наши(херо) параметры) не будет его нормально предсказывать
    проблема этого алгоритма заключается в том, что для оценки апостериорного спектра он использует модель оппонента для собственного моделирования, т.е. имеем все "вкусные" косяки machine learning - overfitting/prediction noise/bias/etc..
    Да ладно, все может быть еще проще - оппонент пользуется каким-то сильно урезанной информацией из той, что ты ему выдаешь
    И как можно учесть в предсказателе наш спектр? Брать с EM-алгоритма как у дядьки Ван-дер-Клейя?
    Ну, не знаю, как на высоких лимитах, а на мелких наверное пойдет ручное разложение спектра на параметры типа наша линия игры, наши(херо) статы, и т.д. Можно придумать какой-то комбинированный параметр получше. Собственно, это чем-то перекликается с машинным обучением - можно, конечно, пытаться подобрать какую-то kernel function, чтобы она скомбинировала нам параметры, но порой проще - и вычислительно, и в реализации, - задать комбинацию параметров руками
    оппонент себя может вести таким образом, что даже идеальный предсказатель ... не будет его нормально предсказывать
    Не, под идеальной моделью я имею ввиду заспиртованный мозг оппонента к которому подключены электроды для сбора информации. =) Ну и вдобавок, построение модели по статистике - это всего лишь один из многих способов machine learning. А есть еще много advanced способов (ну хотя бы моделька с фильтром частиц + RVM + HyperNEAT, которая умеет предсказывать смену поведения оппонента еще до того как он его сменил фактически)
    Ну, не знаю, как на высоких лимитах, а на мелких наверное пойдет ручное разложение спектра на параметры типа наша линия игры, наши(херо) статы, и т.д
    Это опять же фит данных. Просто он делается руками. И даже на мид-стеках такой подход проканает максимум против рейк-машин

    Лучше побольше расскажи как работает твой текущий алгоритм поиска макс EV. если он у тебя выдает результаты при которых твой спектр получается очень четкий, то есть грубо плохие руки фолд, средние колл, лучшие рейз, то может проблема как раз в твоем алгоритме, а не в рандомизации действий. К примеру у меня алгоритм который считает EV может блефовать, полублефовать, слоуплеить. И в итоге мои действия с одинаковыми руками могут быть разными и это все идет от макс EV, а не потому что я что то рандамизирую. А то что ты хочешь это в конечном итоге полный отказ от эксплуатации слабостей опонента и переход к оптимальной игре, когда даже если подробно всем расскажешь, как ты играешь, то это не даст никому преимущества перед тобой

    Я пока это не проверял но у меня есть мысль, что если перед нами будет игрок с нечетким спектром (то есть не понятно какая у него рука что бы он не делал), то поиск макс ЕВ против такого игрока и даст нам оптимальную игру или рандомизацию действий. Но против тех кто имеет слабости нет смысла играть оптимально. То есть в итоге алгоритм поиска макс EV должен дать ответы на все вопросы

    Лучше побольше расскажи как работает твой текущий алгоритм поиска макс EV
    Да в общем-то никаких загадок:
    - есть модель оппонента (см. топик который я вела) - одна из лучших на сегодняшнее время. Модель дает вектор вероятностей действий оппонента при каждом возможном развитии игры
    - используем модель оппонента для конструирования best-response - т.е. строим дерево возможных развитий игры, считаем EV (подробнее см. MCTS, работы дядек Ван-ден-Брока и Ван-дер-Клейя)
    Алгоритм обхода дерева даст тройку матожиданий: EV[fold], EV[call], EV[raise]
    Вопрос: что с ней делать потом? Различные подходы я уже описала
    К примеру у меня алгоритм который считает EV может блефовать, полублефовать, слоуплеить И в итоге мои действия с одинаковыми руками могут быть разными и это все идет от макс EV, а не потому что я что то рандамизирую
    Различные advanced-тактики уже учитываются просто по природе game-tree, т.е. нет нужды специально описывать случаи когда мы слоуплеим, блефуем, чек-рейзим - это все уже заключено в дереве. Вопрос заключается как раз в балансе тактик
    А то что ты хочешь это в конечном итоге полный отказ от эксплуатации слабостей опонента и переход к оптимальной игре, когда даже если подробно всем расскажешь как ты играешь не даст никому преимущества перед тобой
    Ну, с оптимальной игрой пока все сложно - различные абстракции/bucketing'и довольно сильно херят множество стратегий
    Я пока это не проверял но у меня есть мысль, что если перед нами будет игрок с нечетким спектром, то есть не понятно какая у него рука что бы он не делал, то поиск макс ЕВ против такого игрока и даст нам оптимальную игру или рандомизацию действий
    Best-response в таком случае даст RNR-стратегию
    Но против тех кто имеет слабости нет смысла играть оптимально. То есть в итоге алгоритм поиска макс EV должен дать ответы на все вопросы
    Даже у тех, кто имеет слабости, хватит мозгов смоделировать тебя. Поэтому задача post-processing'а матожиданий весьма важна
    Алгоритм обхода дерева даст тройку матожиданий: EV[fold], EV[call], EV[raise]
    Почему тройку, а как же ситуации когда перед тобой выбор чек или бет. Вообще пока у меня такая мысль, максимум что можно сделать это запрашивать статы оппа при игре конкретно с тобой, тогда можно узнать как он играет конкретно против тебя, но сам поиск макс EV останется тем же. То есть вместо рандомизации действий - если ты видишь проблемы при игре против какого то оппа, то моделируй его действия конкретно против тебя. Потом конечно может вылезти проблема, что он подстроится под твои изменения и опять надо что то делать. В итоге против сложных опов игра должна быть близка к оптимальной, и я думаю что она должна сразу получиться после моделирования оппа по его общим статам, ведь все сложные и умные оппы должны иметь полярные спектры

    Не знаю, как braenn (хотя думаю скорее всего), а мы это делали. Проблема была в том, что это несколько помогает, когда опп медленно меняет свою стратегию, и статистика успевает это отследить (особенной проблемой являются редкие случаи, типа действия оппа после нашей ставки на ривере, где статов вообще мало). Но опп может менять свою стратегию быстро, как только он раскусил нас. Ну да еще проблема будет если опп очень быстро меняет игру, но это скорее для HU покера, на 6-макс думаю представления оппа о нас будет меняться не так быстро

    Действительно, в game tree блеф-полублеф уже заложен в самом дереве игры (не уверен насчет слоуплея). А какой техникой пользуешься ты, можешь рассказать?
    Все покерные приемы должны иметь отражения в EV, слоуплей не исключение если он выгоден это должно отразиться в EV. Что за техника вопрос не понял

    Все покерные приемы должны иметь отражения в EV, слоуплей не исключение если он выгоден это должно отразиться в EV

    Ну, со слоуплеем проблема вот в чем. Если мы строим дерево, то мы считаем EV только на текущую раздачу, но не на следующие (собственно, это называется myopic best response). Предположим, что у тебя монстр, и ты смотришь, что лучше - рейзнуть его или вколоть. Так вот, (это правда зависит и от того, как опп сдается на рейз), рейзнуть монстра, если смотришь EV только на текущую раздачу, выгоднее, чем вколоть - банк быстрее разгоняется. А вот если бы мы считали EV + impact на последующие раздачи, заслоуплеить монстра порой было бы выгоднее - в будущих раздачах опп, если бы кольнули, не думал бы, что у нас только слабые руки, но еще и боялся бы заслоупленного монстра. Но мы так сделать не можем, и в итоге получается EV(рейза с монстром)>EV(колла с монстром)

    Поясню вопрос про технику - расскажи, как ты вычисляешь EV/принимаешь решение/етц

    Так вот, (это правда зависит и от того, как опп сдается на рейз)
    Опп это набор каких то стат итд и если перед нами чел который может легко сделать фолд, то имеет смысл слоуплеить монстра чисто математически и будущие раздачи тут не при чем
    расскажи, как ты вычисляешь EV/принимаешь решение/етц
    EV считаю моделируя конкретного опа и прогоняя возможные действия оппа через дерево решений считая вероятности для каждого решения и итоговый показатель EV нашего конкретного действия. Ну то есть я думаю все так делают, как еще по другому можно считать EV?
    Опп это набор каких то стат итд и если перед нами чел который может легко сделать фолд, то имеет смысл слоуплеить монстра чисто математически и будущие раздачи тут не при чем
    Согласен, с тем что с легко сдающимся оппом имеет смысл медленно разыгрывать, чтобы не спугнуть. Но, в тех ХА, что мы играли, оппы хреново сдавались на рейз с SB (он же BT в ХА). В итоге с силой было выгоднее рейзить, а с гавном - колоть. Ну, а это уж очень легко читалось в ХА в дальнейшем. Так что, будущие раздачи тоже важны, получается. Ну, в ХА, как минимум

    Ну так опп моделируется по раздачам что он уже показал и EV может основываться только на информации что уже есть, какая разница что будет потом, если при текущей модели оппа и нашей текущей руке нам выгодно слоуплеить, то надо так и делать и будущие раздачи тут не при чем

    Согласен

    Таким образом, у нас есть - моделирование оппа по прошлым статам, у оппа есть - моделирование нас по прошлым статам и умение скрывать/быстро менять свою стратегию от нас. Похоже, что опп в чем-то лучше нас, нет? Имеет смысл добавить скрытие своей стратегии и себе

    Ну вообще насчет скрытия инфы от оппа, во первых нужно определить что перед нами опп против которого стоит балансировать свои линии и во вторых что наша ситуция попадает под балансировку. То есть возмем слоуплей, допустим у нас монстр, а вероятность что опп ответит на нашу ставку почти нулевая и тут балансировка не будет играть роль нужно слоуплеить. И как я говорил играя по макс ЕВ постоянно получаю разные решения с похожими руками, то есть может получиться так что простой макс ЕВ всегда лучше. Но это надо проверять. Допустим у нас есть умный опп, какие ситуации требуют балансировки? Если есть примеры можно дальше порассуждать. Я пока думаю что кроме макс ЕВ ничего и не нужно

    Ну вообще насчет скрытия инфы от оппа, во первых нужно определить что перед нами опп против которого стоит балансировать свои линии и во вторых что наша ситуция попадает под балансировку
    +100500, с этим люто согласен, но блин, вот ту фигню с рейзами гавна в 2бб, в 3бб - это даже тупица заметит в ХА. В 6макс хз, может и нет, но мы только делаем 6макс сейчас. Ну и какбе, это человеку легко определить, что опп, против которого надо балансить, а для компа надо париться дополнительно
    И как я говорил играя по макс ЕВ постоянно получаю разные решения с похожими руками
    У нас такое было, когда дерево хреново сходилось - с одной и той же рукой при разных расчетах(оппы те же, все то же самое, просто несколько раз подряд считали одно и то же) получались сильно разные цифры. Дерево исправили - перестало

    у меня нет такой проблемы, если все одинаково то и результат будет такой же

    Итак, подведем итоги:
    1caramba играет argmax(EV) и у него все работает
    2kanopush играет argmax(EV) и/или монотонную трансформацию f:EV[action] -> P[action] и у него все работает
    Не очень большая статистика, конечно, но основной тренд в принципе прослеживается: KISS. Уже неплохо

    a) нестационарность распределений уже заложена в природе PF, достаточно сделать Predict-шаг несколько раз вперед. Что-то подобное делал skydriver на покераи - искал кроссовер скользящих средних по VPIP'у, просто у меня PF вместо moving average
    б) одно из самых хороших свойств моей модельки - это глобальная оптимальность. Т.е. она может и не очень хорошо фиттить тестовые данные, зато гарантированно не оверфичена

    Мы тоже занимаемся работой со скользящими средними, но только как с критерием соответствия оппа глобальной модели, без предсказания тренда. Надо будет подумать =)

    Тестовые данные же - это, ммм, критерий качества модели. Если у тебя модель не очень хорошо их предсказывает, ты говоришь, что она не оверфичена, тогда, стало быть, она андерфичена, и тогда я не понимаю, почему модель глобально оптимальна

    Не совсем так: тестовые данные являются конечным локальным аппроксиматором ошибки модели, т.е. теоретически в тестовых данных может появиться кусок где моделька будет не очень хорошо себя показывать. Однако, это не значит, что модель плохая - на бесконечных данных ошибка генерализации моей модельки ~ минимальная байесовская ошибка + не сильно большой эпсилон (2-3%)

    Даже очень хорошие модели не всегда предсказывают правильно. А если все же результаты нужны "честные" - милости просим считать RNR/DBR. Вот там все корректно получится

    Не то что я, даже великий Гугл считает что RNR/DBR - это шведский музыкант

    Потому что порядок операций все-таки менять не стоит: сначала голова - потом гугл

    Под словом "модель" я имела ввиду именно модель machine learning

        f : R -> R
    Может быть стоит освежить и реструктурировать знания по данной теме? Например, почитать публикации. Классика же

    Я знаю два подхода к написанию бота
    1. Сделать как-то что-то, что реагирует как-то на игровую ситуацию - по правилам. То есть написать бота который не нарушает правил игры при ходах. Логика же его внутренняя - это чисто полёт нашей фантазии (как если девочке 2 года дать карандаши и обои)
    2. Сделать модель противника (противников). Если у нас есть модель - то из неё однозначно вытекает наш лучший ход чисто математическими методами (надеюсь это доказывать не стоит). Ключевое слово: однозначно
    В виду вышенаписанного изначальный вопрос ТС звучит так:

  • Есть модель игрока (условие) из неё мы находим лучший ход (следствие)
  • Но нам наш ход не нравится, давайте изменим наш ход (следствие)
    Но ведь следствие следует однозначно из условия! Надо менять условие (модель) если не устраивает следствие (ходы). Нам некогда проверять нравится нам ход бота или нет - раз он его выбрал, значит этот ход лучший! Мы ж боту правила сами задали
    И маленький пс для ТС (да я поэт прям): Если модель основана на стеке, блайндах, ходах в данной сдаче, картах и глобальных коэфициентах типа префлоп рейз - то никогда оптимальный ход не будет прыгать случайно при равных условиях. Попробуй ввести в модель что-то типа "реакция соперника на наш стиль игры последние пару ходов"

    Оказывается как легко написать бота!
    1. Сделать как-то, что-то и т.д., а оно само полетит
    2. Сделать модель противника. Тоже легко
    1. Вопрос ТС на самом деле звучал маленько по-другому: best-response поиск даже с хорошей моделью не всегда будет давать хорошо-играбельные результаты, потому что BR увеличивает шум модели просто по природе алгоритма; как нам снизить собственную exploitability не прибегая ко всяким штукам вроде RNR?
    2. Если уж охота давать советы, то лучше делать это в формализованном виде. Пробовать "ввести в модель чтото типа", т.е. неизвестно что (тем более так сформулированное) - бессмысленно

    Что вы понимаете под шумом модели?. У модели есть вход (информация) и выход(как ходить) - где тут шум я не понимаю. Про Бест респонз. У нас есть модель игрока или игроков. Игроки (реальные) что-то там походили. Мы 100500 раз сдаём им (моделям) карты и если модели походили как в жизни - рассматриваем дальше варианты ответов и считаем те самые еквити. Другой вопрос что в жизни так посчитать не просто. Но есть методы решения
    Про формализованое предложение: Для этого надо формализованая модель. Полагаю это функция ( к примеру на С++:)

            Otvet = Model(Karty_v_rukah, karty_na_stole, hodi_protivnika, parametr_modeli)
    Это грубо для 1 на 1. Так вот само интересное тут parametr_modeli у тебя он считается как
            parametr_modeli = GetParametr(Vpip, pfr)
    А я предлагаю его считать
            parametr_modeli = GetParametr(Vpip, pfr, otnoshenie_k_protivniku)
            otnoshenie_k_protivniku = GetOtnoshenie(naskolko_agressiven_opponent)
    Вобщем в модель заложить чтоб она не тупо ходила "как робот хи хи" а пыталась как то подстроится под ситуацию. И это имхо логично - так как модель мы для того и пишем чтоб смоделировать противника. А игроки в покер, насколько я знаю, не тупо ходят оно и тоже в стандартных ситуациях

    Например, я люблю играть ХА с незнакомцами. 1500 стек 10/20 блины. Первая ставка 5блинов с типа K7 оп пас (хотя некоторые и колят) - показываю карты. И потом мне приходит АК, а я 100 - оп потирает руки с АД и попадает на стек (чего б он ни в жизни не сделал не покажи я ему 5бб с К7). Люди играют порой ну очень адаптивно, и пытаться их смоделировать настолько деревянной моделью - имхо наивно. Так что это не "бест респонз неиграбельный", а модель надо улучшать

    я бы хотел задать уточняющий вопрос: Если мы хотим равномерный спектр, то зачем нам маленькая дисперсия? Судя по всему дисперсия и равномерность вообще слабо связаны, но если уж привязываться к дисперсии то нам по идее нужна именно большая (если случайная величина "наши руки с точки зрения оппонента после действия" имеет большУю дисперсию, значит он обладает скудной информацией по поводу наших рук). Но, если я нигде не ошибся в выкладках, это ни к чему не приводит - максимизация дисперсии дискретного распределения просто выберет две самые удалённые точки и положит им вероятность 1/2 (в вырожденном случае когда РОВНО между ними есть ещё несколько точек, то их тоже можно добавить не меняя дисперсию). Почему бы например не минимизировать расстояние между равномерным и нашим распределением? Тогда не придётся добавлять третий objective о том, что мы хотим много рук с ненулевой верятностью.. P.S. Пользуясь случаем, хочу сказать спасибо за публикацию cutting edge technologies в этом консервативном покер-мире)

    если мы хотим равномерный спектр, то зачем нам маленькая дисперсия?
    Здесь я рассказала лишь общую концепцию: если мы хотим получить распределение на действиях, то придется решать многокритериальную задачу оптимизации между нашими "внешними" (external - т.е. с точки зрения оппонента) распределениями рук. Целевые функции были выбраны самые простые, чтобы сохранить прозрачность изложения изначальной идеи (если бы это направление получило развитие, то я бы поделилась информацией, как заставить это работать корректно). Так что на этот метод сначала нужно больше смотреть в философском аспекте (т.е. схватить общую концепцию), а уже только потом - в техническом (т.е. маленько подумать, порисовать на листочке и понять, что, собственно, мы хотим получить от задачи оптимизации). Так что Вы сделали абсолютно верные замечания и функции оптимизации там нужно выбрать похитрее, чем описанные мной. Просто идея поста была не в этом