Эволюция шахматных фигур: от слона до епископа | 2026-02-14T16:24:38

Все началось с вопроса — а зачем этот вырез у слона ♗? И вообще, где он — слон, а где — бишоп, и вырез это про слона или бишопа? В общем, слушайте что нарыл, тут много интересного.

Шахматы родом из Индии. Там эту фигуру изначально называли верблюдом. А слон у них было то, что у нас ладья — что если задуматься, то ладья — вообще лодка такая — или в английском rook, что если задуматься на персидском, то это колесница.

Название «Тура», которое мы часто слышим в разговорной речи, — это чистый импорт из Европы. Во французском — tour. В итальянском — torre. В латыни — turris. Все они означают одно и то же: башня. Когда шахматы попали в Европу, рыцари и монахи не очень понимали, что такое «боевая колесница» (они к тому времени уже вышли из моды), зато отлично знали, что такое осадная башня.

Так вот, возвращаясь к слону и вырезу.

Короткий ответ — чтобы отличать от пешки. Но есть длинный.

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

Еще интересно, что во французском это le fou — шут. А в немцком Läufer — бегун. А на греческом — офицер (Αξιωματικός). Почему офицер? Не знаю, но накопал, что в китайских шахматах сянци (象棋) фигура «слон» обозначается и произносится как xiàng (象). Этот иероглиф действительно означает «слон». Но в истории Китая существовала высшая государственная должность, называемая xiàng (相), которая обычно переводится как «канцлер», «премьер-министр» или «главный министр». Это другой иероглиф, хотя произношение совпадает. Наверное, как-то офицер отсюда же.

Шахматный конь почти во всех языках конь, вот только в английском и еще нескольких — рыцарь (правда, в немецком например, это Springer — прыгун, а на Сицилии — осел).

То есть, в немецком есть прыгун и бегун. А коник в немецком вообще король.

А еще узнал, что оказывается, есть готовые решения ЛЮБОГО шахматного эндшпиля, в котором на доске остаётся семь или меньше фигур, независимо от позиции, состава оставшихся фигур или возможных ходов. Эта информация, известная как таблицы эндшпиля, в настоящее время занимает 18,4 терабайта.

из комментариев: «Самое интересное, что на этой неделе закончилась многолетняя работа, и есть готовое решение для любой позиции с 8 фигурами и меньше (7 фигур было уже 12 лет назад примерно, но там очень большая разница)»

Планы на 2026: от Галапагосских островов до PhD | 2026-01-20T04:44:36

Мой план на 2026:

— Уехать на неделю на Галапагоссы, в Эквадор (лето)

— Дописать и выпустить книжку по Information Retrieval (тоже лето, идет медленно, пара первых глав уже написана. Уже потратил на эту тему часов 50-100, то, что шло легко)

— Выпустить как минимум одну научную статью, видимо по Data Mining (весна). В идеале засабмиттить куда-нибудь в журнал (сложно). Уже потратил на эту тему часов 30, осталось еще дохрена.

— Сделать шаг к PhD. Найти профессоров, посетить универы, понять цену вопроса и оценить свои возможности и ресурсы.

— Продолжить изучать фундаментальную математику и не умереть (линейная алгебра, матанализ, тервер, статистика, классическое ML). В 2025 потратил на эту тему часов 200-400.

— Продолжить изучать Deep Learning и дойти до уровня «могу преподавать». В 2025 потратил на эту тему часов 100-200.

— Продолжить изучать Data Mining/NLP.

— Актуализировать мою книжку по RecSys, выпустив версию 2.0 включив обновления и исправления (осень 2026)

— Добиться видимого прогресса в живописи и игре на фортепиано. Конкретно, доучить серенаду Шуберта (Ständchen, D 889) и сделать хотя бы один холст, который не стыдно подарить.

Разработка 3D-редактора волейбольных стратегий в полете | 2026-01-01T21:21:21

Чем я занимался в самолете в/из отпуска и иногда между и после: 3D-визуализация и редактор волейбольных схем для Нади (она — тренер). Этот корт на приложенном изображении свободно вращается, на нем могут быть поставлены игроки, и указан путь мяча и игрока — все в 3D.

Траектория мяча рассчитывается так, чтобы мяч не пересекал сетку при движении из A в B (формула Безье). Игроки могут принимать несколько поз — прямо сейчас есть наспех сделанные позы serve, attack, block, pass/receive. Кстати, из интересного в коде: пришлось прописать немного «волейбольных мозгов». Система сама считает траекторию мяча через кривые Безье так, чтобы он всегда проходил над сеткой. Причем высота вылета зависит от типа действия: для атаки мяч «вылетает» с более высокой точки, чем а для паса. Еще добавил авто-разворот: 3D-моделька сама поворачивается лицом туда, куда она по схеме должна пасовать или бежать.

Дольше и сложнее всего было сделать 3D-модель волейболистки. Для генерации реалистичной волейболистки я использовал сервис tripo3D. Он мне выдал модель в нейтральной позе (бесплатно выдал). Теоретически дальше с помощью Blender и плагина Rigify можно прицепить к ней armature и двигать руки-ноги, за которыми будет пересчитываться модель.

Однако в реальности такой подход не срабатывает: сгенерированная ИИ модель содержит большое количество геометрических ошибок, которые прощает рендер, но не прощает Rigify. Их можно условно разделить на два вида — неверные нормали полигонов и проблемы с немногообразной (non-manifold) геометрией, которые исправлять значительно сложнее. Внутри корпуса могут «плавать» невидимые кластеры полигонов или пересекающиеся поверхности. Когда Rigify пытается рассчитать веса (какая кость на какую часть кожи влияет), этот внутренний шум сбивает алгоритм с толку, и в итоге веса распределяются хаотично (например, движение руки может начать тянуть за собой сетку на животе). Плюс модель немного не симметрична.

Non-manifold — это ошибка геометрии, при которой топология объекта перестаёт быть корректной с точки зрения трёхмерного тела: рёбра могут принадлежать более чем двум полигонам, полигоны могут соприкасаться только вершинами или рёбрами без общего объёма, внутри модели появляются «висящие» поверхности или нулевая толщина. Такая геометрия формально не описывает замкнутый объём, из-за чего возникают проблемы с риггингом и деформациями. Кроме этого, нужно упростить модель, потому что для рендера в реальном времени в браузере миллионы полигонов не нужны.

Я исправлял это с помощью MashLab, попутно дорабатывая «напильником» (руками). В итоге получается модель, чуть-чуть отличающающаяся от исходной почти везде. На исходной же модели нацеплена «кожа» в виде текстуры — лицо, майка, шорты должны быть раскрашены. Как все это перенести на упрощенную модель? Для этого есть специальная операция в Blender, называется Baking. Там тоже шаманство. В итоге неидеально перенеслось, но идеально пока и не нужно.

Дальше привязываем арматуру к «суставам», и через часа три разбирательств, почему все работает не так, как должно, оно все-таки заработало. Я сделал четыре позы, и теперь каждому кружочку (игроку) можно указывать в какой позе он стоит.

Еще нужно будет сделать динамическую смену раскраски формы — это не должно быть сложно. Есть еще идея переносить позу с фотографии — это посложнее, но в целом реалистично. С помощью MediaPipe/AlphaPose можно детектировать ключевые точки в 2D, затем с помощью каких-нибудь моделей типа HMR/HybrIK можно «поднять» плоские координаты в 3D-пространство, выдавая относительные углы поворота суставов. Полученные данные можно попробовать спроецировать на Rigify-скелет. Поскольку пропорции сгенерированной волейболистки и человека на фото могут не совпадать, как раз и используется Inverse Kinematics (IK). Это довольно сложная часть, но в целом она уже не очень обязательная — просто интересно разобраться и сделать что-то работающее.

Видео в комментах

Разгадывая лабиринт запросов: как я превратил хаос в четкий код | 2025-12-17T03:25:38

Ух какую я прикольную задачку только что решил. Хрен только объяснишь. Ну я попробую.

Короче, у клиента есть 10 сайтов с поиском. Они все используют один индекс, но кидают разные запросы к нему. К тому, что вводит пользователь, прибавляется очень длинный и сложный query, который генерирует модуль на сайткоре. Он содержит айдишники шаблонов и страниц, которые нужно включать или исключать. В итоге понять, что там происходит, вообще невозможно. Там может быть десять открывающих скобок и где-то рандомно закрывающие, но с Coveo работало. Реформаттинг помогал, но не сильно.

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

В итоге вот что я сделал:

Написал скрипт, который разбирает эту текстовую «кашу» в абстрактное синтаксическое дерево (AST). Это позволило превратить нечитаемую строку в структурированный JSON-объект, где четко видно: вот тут AND, тут OR, а тут — конкретное условие.

Дальше я превратил эти условия в формулы булевой алгебры. С помощью библиотеки SymPy я «скормил» эти формулы алгоритмам упрощения. Математика сама выкинула дубликаты, схлопнула лишние вложенности и убрала условия, которые логически поглощаются другими. В результате «деревья» стали плоскими и понятными.

В аттаче — оригинальное дерево и упрощенное.

Чтобы быть уверенным, что я ничего не сломал при упрощении, я написал генератор тестов. Он берет упрощенную логику, собирает её обратно в рабочий curl и проверяет, совпадает ли количество найденных документов (totalCount) с оригинальным запросом. Цифры сошлись — значит, логика сохранена на 100%.

Имея на руках упрощенные и стандартизированные структуры для каждого сайта, я построил матрицу сравнения. Скрипт проанализировал их и выделил Common Core — условия, которые гарантированно требуются (или запрещены) на всех сайтах без исключения, и Specifics — уникальные «хвосты», которые отличают один сайт от другого.

На приложенном скриншоте: REQ означает, что условие гарантированно выполняется для любого документа, который пройдет через этот запрос. NOT — гарантированно не выполняется. OPT — условие присутствует в запросе, но оно не является строгим само по себе. Оно работает только в связке с чем-то еще. «.» — условие вообще не упоминается в запросе.

Для 3 сайтов моментально отвечает, для 10 работает минут 30.

Ну и конечно, все данные на всех скриншотах тщательно обфусцированы.

От идеи к игровому AI: разработка шахматного алгоритма | 2025-12-15T04:33:13

Пока разбирался с нейросетями, решил придумать себе игровую задачку. А что если я найду где-то готовые партии, и обучу нейросетку предсказывать ход по ситуации на доске. Сказано — сделано. Конечно, код быстрее генерить с помощью LLM, но задание подробное писал сам и архитектуру придумывал сам. Через 40 минут (!) от идеи до результата: у меня уже было работающее решение, которое ну по крайней мере в первой половине партии не очень сильно косячит.

На скриншоте CuteChess — он работает с любым шахматным движком, и в моем случае это простой скрипт на питоне. Скрипт берет ситуацию на доске и скармливает ее модели. Выбирает топ 5 ходов, и только эти топ 5 просматривает вглубь на несколько ходов вперед и оценивает позицию. То есть, нейросеть у меня предлагает возможные ходы на основе анализа 20000 партий (534453 позиций). Из того, что получается, выбирается лучшее. Там используется для этого алгоритм minimax, если это кому-то что-то говорит (мне не очень говорило, поэтому Gemini тут мне помог)

Как тренируется модель. На сайте lichess можно скачать партии, там сотни гигабайт. Я взял файлик с 800000 сыгранными партиями за 2014 год. Из этих 800000 я отбираю 20000, а именно скриптом ищу партии, где результат не ничья (1-0 или 0-1). Далее считаю разницу (Рейтинг_Победителя минус Рейтинг_Проигравшего). Это не самая лучшая метрика, но лучше, чем ничего. Чем больше эта разница, тем «увереннее» должен быть выигрыш (сильный наказывает слабого). Итого получается 20000 таких партий.

«Игнорирование ходов слабого» (чтобы модель не учить плохому) реализуется на этапе тренировки модели. Фактически, логика такая: «Если сейчас ход белых, и белые выиграли эту партию — учимся. Если сейчас ход черных, и черные проиграли — пропускаем и не учим сеть этому ходу» .

Нейросеть тренируется батчами по 128 позиций за раз. Сеть получает на вход позицию на доске и выдает 4096 — оценку вероятности для каждого возможного хода.

Отбор партий занимает минут 5. Тренировка модели у меня на компе занимает минут 10 для 20000 игр. Можно оставить как-нибудь потренироваться на 100К или на миллионе, будет точно лучше. Только уже не надо — я разобрался 🙂

Партию можно посмотреть тут:

Магия искусственных нейронных сетей: разделение гласных и согласных | 2025-12-14T23:35:00

Сейчас экспериментирую с обучением простых нейросетей — главным образом для доведение до автоматизма имеющегося инструментария и некоторые штуки просто создают впечатление магии.

Есть база из 32000 имен. Есть нейросеть, заполеннная случайными числами. Запускаю тренировку, на входе — только этот список имен. Первый слой нейросети — эмбеддинги, и я выставляю число измерений 2, чтобы было легко визуализировать. И после 200000 итераций обучения система четко разделяет гласные от согласных, и почему-то чуть в стороне от других согласных ставит букву «q». Похоже, это потому, что буква ‘q’ почти исключительно предсказывает букву ‘u’ (Queen, Quincy, Quentin).

На русских именах тоже очень надежно разделяет гласные и согласные. В русских именах буквы б и л почему-то поодаль от остальных согласных, как и мягкий и твердый знаки (ну с ними понятно).

Интересно, как ж оно работает. Если на нормальном корпусе текстов натренировать, разница будет совсем четкая. Почему отделяются гласные от согласных? Видимо, с точки зрения математики сети, ‘а’ и ‘о’ выполняют одинаковую функцию: они «триггерят» предсказание согласной, следующей за ними, то есть виной всему чередование гласных и согласных. Но черт побери интересно 🙂

Ну и поскольку моделька умеет предсказывать следующие буквы, можно попробовать запустить ее на русском. На модели с эмбеддингами 30 измерений вот такие имена придумывает: бякетта, афсена, еракей, засбат, дарая, гайомахад, раин, ражул, гжаций, ребен, вуреб, дуродира, туружул, регравгава, разсан, габила, авганжа, рахси, халебкохорта, ратхер. Модель — для тех, кто разбирается — такая: вход 6х33 символа (потому что берем до 6 символов контекста), закодированных эмбеддингами в 60, идут на слой в 100 нейронов, а с них обратно на 33 символа. Фигня какая-то, но по крайней мере понятно как это все работает на всех уровнях.

Математические нотации: хаос под строгим порядком | 2025-12-02T15:30:20

Если вам кто-то говорит, что математика это точная наука — не верьте. Поскольку у меня сейчас хобби data science, я изучаю всякое разное из разных книжек и у меня взрывается мозг, как вообще может такое происходить в науке, где каждая мелочь должна укладываться в систему, иначе она идет лесом. Пока дело не доходит до нотаций. С ними там какой-то дикий бардак. Набор диалектов.

Взять, например, обычные логарифмы. «Стандарт» как обозначать логарифм зависит от того, в какой комнате университета вы находитесь. В матанализе и теории чисел log(x) почти всегда означает натуральный логарифм ln(x) база e. Производная от e^x равна e^x. Это «естественно». Писать ln им лень. Там, же где могут вылезти дясятичные логарифмы (computer science тот же), log(x) внезапно становится десятичным, а ln(x) — по основанию e.

Матожидание E имеет аргумент в квадратных скобках. При этом те же квадратные скобки в computer science используются для степ-фукции 0/1.

Или вот если вы видите вектор — это столбец или строка? В классической математике вектор — это всегда столбец. Чтобы умножить его на веса, мы пишем T после вектора и потом w для весов. Но во многих пейперов векторы мыслятся как строки. И если вы видите y = xW+b , то x — это не столбец, потому что иначе размерности не сойдутся. x тут — строка. но в следующей статье пишут Wx+b. И тут x — столбец 🙂

Угловые скобки . Для скалярного произведения (dot product) используется знак «⋅», но его плохо видно, особенно на доске, и я очень часто вижу, что математики используют угловые для dot product. Вообще по науке угловые используются для обобщенного (generalized) понятия inner product, где скалярное произведение частный случай. означает некий абстрактный способ перемножить a и b и получить число. Причем в квантовой механике это бы записывалось как . А еще для скалярного произведения некоторые используют кружок с точкой или x в кружочке.

Ну и для кучи еще в России тангенс — это tg, а в США — tan. А есть еще tan^-1 и arctan, что одно и то же, хотя x^-1 вообще означает 1/x

Алхимия данных: размышления об алгоритмах RecSys | 2025-11-16T04:02:08

Заумный пост сегодня. Пока писал книгу по RecSys, поймал себя на мысли, что современный data science — это, по сути, алхимия 21 века. За половиной «лучших практик» в алгоритмах нет хорошего математического аппарата. Это набор эвристик, которые «просто работают». Причем как в 17 веке смешивали все подряд, так и сейчас смешивают, и если что-то сработало лучше, все остальные начинают делать так же. Ответа на вопрос «почему» просто нет.

Возьмем, к примеру, алгоритм NCF/NeuMF (Neural Collaborative Filtering). Там такая логика. Есть, скажем, миллион оценок пользователями фильмов. И 100 миллионов оценок пользователями еще на даны — пользователи ж не могут посмотреть все фильмы на свете. Но из этих 100 миллионов для конкретного пользователя надо выбрать кандидатов для рекламы. У алгоритма, конечно, есть фаза тренировки, когда рассчитываются веса, и стадия предсказания, когда эти веса используются на входящих данных.

(Что делает алгоритм. Там по сути ансамбль из три подалгоритмов, два из которых генерят каждый свое заключение, а потом их решения поступают на новую нейронку, третий алгоритм, который дает финальную рекомендацию. По-умному это гибрид GMF (матричная факторизация) и MLP (многослойный персептрон) Первый из этих двух основан на разложении матриц, а второй представляет собой нейронную сеть из нескольких слоев. На тренировочных данных подбираются веса.)

На один позитивный пример он берет 4 негативных. Потому четыре? Да просто это «не много и не мало». Будет ли 8 лучше? Неизвестно, но учиться будет точно дольше.

Почему размерность эмбеддингов 32? или 64? Нет никакой формулы. Это «золотая середина» между «тупой» моделью (мало k) и «переобученной» (много k).

Теперь про нейронку. Почему MLP-блок строят «башней» (64 -> 32 -> 16)? Почему не (50 -> 25 -> 10)? Почему между ними ReLU (а не tanh например)? Чистая эмпирика. Число слоев в башне тоже подбирается.

Почему у GMF и MLP-частей разные эмбединги на входе? Потому что авторы статьи попробовали, и так «получилось лучше». Мат. доказательства нет. Почему на финальный слой они идут с равными весами? Потому что потому.

Почему выходы двух путей «склеиваются» (concat), а не складываются или перемножаются? «Опыт показал, что так результат точнее».

И так во всем, вплоть до выбора оптимизатора Adam или «магического» learning_rate=0.001, хотя с этими по крайней мере понятен матаппарат.

То есть, у одного алгоритма как минимум с десяток параметров подобрано эмпирически, при этом однозначной уверенности, что они независимые друг от друга — нет. Зато многие из них зависят от датасета, но никто не знает как 😉

В общем, алхимия.