Интересное что-то
517 subscribers
2.72K photos
253 videos
139 files
4.52K links
Материалы и мысли, понадерганные отовсюду
Блог: https://t.me/asisakov_channel
Чат: https://t.me/youknowds_chat
Download Telegram
AB-тесты: наблюдаемый эффект и MDE

"А как такое может быть?" — спрашивает продакт, когда мы, подводя итоги AB-теста, получили статзначимый аплифт в 0.8%, когда во время дизайна закладывали MDE = 1%.

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

Нужно разделить три понятия:

▶️Реальный эффект - это тот реальный эффект от нашей фичи, который мы не знаем и который хотим оценить
▶️MDE - это наше предположение о реальном эффекте, который мы сможем задетектить с заданным размером выборки и с заданной вероятностью. Эта вероятность, она же мощность, как правило фиксируется на 80%.
▶️Наблюдаемый эффект - этот тот эффект, который мы уже своими глазами видим между тестовой и контрольной группой по завершении теста. Наблюдаемый эффект не равняется реальному эффект хотя бы в силу того, что в данных всегда имеется шум, который будет толкать наш наблюдаемый эффект либо в плюс, либо в минус от реального.

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

Мы можем в наблюдаемом эффекте получить и меньшее значение, чем в MDE и этот эффект может быть статзначимым. Такое происходит нередко. Как в нашем примере с наблюдаемым статзначимым эффектом в 0.8%, а MDE = 1%. Финальное слово здесь за наблюдаемым эффектом.

А откуда могла взяться разница между ними? Здесь много вариантов. Возможно, реальный эффект на самом деле ниже, чем вы закладывали в MDE. Возможно, реальный эффект на самом деле равен MDE, но из-за флуктуации в данных, наш наблюдаемый эффект оказался ниже. Все равно важно помнить, что MDE — это про дизайн теста, а наблюдаемый эффект — про результаты теста.

Если хотите почитать подробнее и посмотреть на симуляции с графичками, то можете глянуть вот эти статьи)

📌What if the Observed Effect is Smaller Than the MDE?
📌Как же мощно я провел А/В-тест, или почему не стоит сравнивать наблюдаемый аплифт с MDE
Please open Telegram to view this post
VIEW IN TELEGRAM
Technology Radar 2024

Год потихоньку подходит к концу. Пришло время посмотреть, какие технологии появились, какие устаканились и какие ушли на второй план.

Довольно много LLM и разных ML штук. Но поскольку я в них не шарю, вот список того, что отметил на свой вкус:
1% canary
Component testing
Domain storytelling
Bruno
K9s
Devbox
pgvector
Unleash
GitButler
JetBrains AI Assistant
Mise
ReadySet
uv
Zed
Pingora
PGLite

https://www.thoughtworks.com/radar
Anthropic Sonnet 3.5 1022 - это очень классная модель

(1) Она поддерживает хорошо работу с PDF
(2) У этой модели есть кэширование промптов
(3) делать structured data extraction с checklist и custom chain of thought на ней одно удовольствие.

Хотя Anthropic пока и не завел structured outputs на базе constrained decoding (как это сделали в OpenAI), но их модели понимают JSON схему без каких-то нареканий. А выход у них пока без ошибок (если не перегружать контекст и соблюдать signal-noise ratio).

Что я делаю для извлечения данных из сложных PDF недорого:

(1) загружаю системный промпт со схемой в первое сообщение. Помечаю для кэширования через "cache_control": {"type": "ephemeral"},. Схему конвертирую в строку (см ниже) и добавляю к общему описанию задачи:


json.dumps(Model.model_json_schema(), indent=2, ensure_ascii=False)


(2) загружаю PDF напрямую во второе сообщение модели. Также помечаю для кэширования.

У меня PDF достается из CAS, но можно грузить хоть откуда. Главное - сконвертировать бинарную начинку в base64 для добавления в API запрос (так сделана работа с документами в бете):


def read_pdf_as_base64(env: Env, hash: str):
with env.storage.read_cas(hash) as file:
return base64.standard_b64encode(file.read()).decode('utf-8')

Кстати, под капотом Anthropic не просто распарсит PDF в текст, но и приложит картинки страниц к этому тексту. Это заметно повышает качество ответов.

(3) помещаю задачу из чеклиста в третье сообщение, уже не кэширую.
(4) в последнее сообщение добавляю


{
"role": "assistant",
"content": "Here is the JSON requested:\n{"
}

(5) к ответу модели добавляю { и валидирую загрузкой в исходную pydantic model

И потом все будет работать так:


results = []
for pdf in pdfs:
for question in checklist:
result = extract_data(schema, pdf, question)
results.append(result)


Причем schema кэшируется на все запросы, а содержимое pdf (самое большое) переиспользуется на все вопросы из чеклиста.

Такой процесс в итоге работает точнее и проще, чем комбайн из openAI GPT-4o со structured outputs и предобработкой PDF в отдельных специализированных моделях.

Ваш, @llm_under_hood 🤗

PS: Бенчмарк модели будет попозже
Паттерны работы с базами данных

В большинстве проектов мы храним какие-то данные. Для этого используются разные виды баз данных: реляционные, nosql или даже специализированные HTTP API. Такие хранилища имеют специфическое API, которое мы обычно хотим скрыть от основного кода за некоторой абстракцией. Вот стандартные варианты, описанные, в частности, Мартином Фаулером.

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

DAO - наиболее простой вариант, он представляет собой достаточно тупой класс, который просто выполняет операции с хранилищем и возвращает данные в том или ином виде. Он не должен содержать какого-то своего состояния (будь то кэши или IdentityMap). Он получает и возвращает только данные в виде неких абстрактных RecordSet или простых DTO, то есть структур, не содержащих логики. Плюсы такого паттерна: простота реализации, возможность точечного тюнинга запросов. Паттерн описан в "Core J2EE Patterns", а у Фаулера встречается очень близкое описание под именем Table Data Gateway.

Data Mapper - в отличие от DAO занимается не просто передачей данных, а двусторонней синхронизацией моделей бизнес логики с хранилищем. То есть он может получать какие-то сущности и потом сохранять их обратно. Внутри он может содержать IdentityMap для исключения дублей модели с одним identity или создания лишних запросов на загрузку. Каждый маппер работает с моделью определенного типа, но в случае составных моделей он иногда может обращаться к другим мапперам (например, при использовании select-in load). При использовании Unit Of Work, тот обращается именно к мапперу для сохранения данных.

Repository - фактически вариант Data Mapper, предназначенный для работы с корневыми сущностями. Для прикладной бизнес логики репозиторий выглядит как коллекция, содержащая корни агрегатов. Он может использоваться для получения полиморфных моделей, а также может возвращать некоторую сводно-статистическую информацию (например, количество элементов или сумму полей) или даже выполнять какие-то расчеты, не выходящие за пределы общей компетенции хранилища данных. Это основной паттерн при использовании богатых доменных моделей. Паттерн описан у Эрика Эванса, а у Фаулера встречаются некоторые варианты его реализации.

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

Raw Data Gateway - предлагает каждой строке таблицы поставить в соответствие экземпляр класса. Мы получаем отдельный класс Finder для загрузки строк и собственно класс шлюза строки, который предоставляет доступ к загруженным данным и обладает методами сохранения себя в БД.

Active Record - вариант RDG, но содержащий бизнес логику. По факту, мы имеем богатые доменные модели не абстрагированные от хранилища. Часто методы загрузки данных реализованы просто как static-методы в этом же классе вместо выделения отдельного Finder.

Строит отметить, что многие ORM в Python реализуют Active Record и активно используют при этом неявный контроль соединений и транзакций. В отличие от них SQLAlchemy реализует паттерн Data Mapper и может дать больший уровень абстракции над хранилищем (обратите внимание на подход с map_imperatively).

Дополнительные материалы:
http://www.corej2eepatterns.com/Patterns2ndEd/DataAccessObject.htm
https://martinfowler.com/eaaCatalog/identityMap.html
https://docs.sqlalchemy.org/en/20/orm/dataclasses.html#applying-orm-mappings-to-an-existing-dataclass-legacy-dataclass-use
Forwarded from ИИгорь R&D
О наивной схеме Эйлера

Герметическое броуновское движение (ГБМ) — стандартная модель для цены базового актива в финансах, начиная со статьи Блэка и Шоулза. В ней предполагается, что приращения логарифма цены распределены нормально. У этой модели есть 3 существенных преимущества. Первое — цена не может быть отрицательной. Второе — в ней все легко и явно считается. Третье — она отражает наше восприятие долгосрочного изменения цен акций, то есть, что акции растут на сколько-то процентов каждый год, а не на сколько-то тугриков. Другими словами, мы лучше воспринимаем относительное изменение (в %), а не абсолютное (в $). И ГБМ как раз про постоянное в некотором смысле относительное изменение цен.

Сэмплировать в этой модели очень просто: есть явное решение. Однако часто на ней иллюстрируют некоторые техники для численного интегрирования стохастических диффуров, типа интегрировать по схеме Эйлера не саму цену, а ее логарифм. Там сходимость получше (для ГБМ даже точное решение получается), и отрицательные цены не вылезают. А про наивную схему Эйлера (dS_t = S_t[mu dt + sigma dW_t]) говорят что-то типа: смотрите какой уродец, забудьте про него. Но мы к ней еще вернемся.

Есть и другая модель — арифметическое броуновское движение (АБМ). В ней предполагается нормальное распределение абсолютных приращений, а не логарифмических. Ее изначально предложил Башелье за 70 лет до Блэка и Шоулза, потом про нее все забыли, а потом снова вспомнили в 20 году, когда фьючи на нефть минусанулись. В ГБМ отрицательных цен не бывает, а когда они все-таки случились, то пришлось всем бодренько корректировать модели и вспоминать классику. Но базовой все еще остается модель ГБМ. Также АБМ вспоминают часто в контексте всяких моделей микроструктуры рынка, так как там она естественно возникает при переходе с микро- на макроуровень (см. работы Cont).

А я про это все задумался вот в каком контексте. В недавних работах на основе Deep Hedging'а и оптимизации полезности в целом отмечается, что экспоненциальная функция полезности проблемна. В качестве основной проблемы Buehler называет отсутствие оптимальной стратегии на ГБМ-рынке с отрицательным дрифтом (оптимально шортить, но там тупо интеграл расходится). И дальше предлагаются всякие уродские и костыльные фукнции полезности, про которые я даже писать не хочу. Но может быть проблема не в функции полезности, а в ГБМ? Может лучше что-то типа АБМ использовать? Там оптимальная стратегия всегда существует. А еще улыбки волатильности в АБМ менее скошенные для акций. И с микроструктурной точки зрения получше.

Я сейчас ковыряю Deep Hedging и мне нужно оптимизировать экспоненциальную полезность в какой-то простой модели для цены. С одной стороны, хочется чего-то, что похоже на традиционную модель ГБМ, чтобы быть в контексте всех исследований и нормально сравниваться, с другой стороны, хочется чтобы при этом и полезность оптимизировалась. То есть хочется какую-то модель, в которой на коротких интервалах цена ведет себя как АБМ, а на длинных — как в ГБМ. При этом меня не волнует, как там все считается, потому что все равно нейронки сами разберутся и стохастическим исчислением я тут не занимаюсь. И вот тут-то как раз и всплыла наивная схема Эйлера для ГБМ. На длинных горизонтах — это все-таки схема для моделирования именно ГБМ, так что все норм. А инкременты цены имеют нормальное распределение, а не лог-нормальное, так что все интегралы сходятся и полезность всегда существует даже чисто математически. Ну а чтобы отрицательных цен не получить, тупо воткнем absorbing barrier на 0.01 и полетели.
Forwarded from Aspiring Data Science (Anatoly Alekseev)
#pricing #mabs

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


https://towardsdatascience.com/dynamic-pricing-with-multi-armed-bandit-learning-by-doing-3e4550ed02ac

https://towardsdatascience.com/dynamic-pricing-with-contextual-bandits-learning-by-doing-b88e49f55894
Привет всем!👋

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

На помощь приходят различные методы интерпретируемости моделей, не зависящие от типов моделей. Сегодня разберем их поподробнее.

- Какая существует интерпретируемость?
Прежде всего, разделяют локальную и глобальную интерпретируемость.

Локальная - в разрезе одного наблюдения, глобальная в разрезе всего набора данных.

-Какие есть методы?
1️⃣Feature Importances
Обычно применимо к "деревянным" моделям, где важность признака оценивается как изменение критерия разбиения. Для ансамблей важность признака усредняется по всем деревьям.
2️⃣SHAP (SHapley Additive exPlanations) [Реализация]
Для вычисления вклада каждого признака анализируется, как изменяется предсказание, если этот признак добавляется к набору уже учтенных признаков. Для начала считается базовое значение - это среднее предсказание модели на всем наборе данных, так, будто признаков нет. Вклад i-го признака рассчитывается как разница между предсказаниями модели с учётом и без учёта i-го признака. Чтобы учесть зависимость между признаками, SHAP вычисляет вклад признака как среднее значение влияния по всем возможным порядкам добавления.

Часто используем в работе в рамках кредитования клиентов для ответа на вопрос о клиенте и факторах выбора его кредитного рейтинга.


На примере:
Модель по клиенту показала на 3 признаках 80% вероятность дефолта по модели на 3-х признаках. 60% базовое значение, 1 признак дает +15%, второй +5%, а третий -10%. Таким образом, предсказание по признакам 60%+15%+5%−10%=80%.

3️⃣LIME [Реализация]
Метод, который объясняет предсказания модели на основе простых, интерпретируемых моделей, построенных в окрестности конкретного предсказания.
LIME создает интерпретируемую модель (например, линейную или решающее дерево), которая аппроксимирует поведение сложной модели (черного ящика) только в окрестности одного конкретного объекта.

Метод создает множество синтетических объектов, которые похожи на исходный, но с небольшими изменениями путем рандомизации или перестановки признаков объекта. Сгенерированные объекты передаются в модель для предсказания. Таким образом, LIME получает набор данных (новые объекты и их предсказания), которые отображают поведение модели в окрестности выбранного объекта. С использованием полученных данных в LIME обучается интерпретируемая модель (например, линейную модель или решающее дерево), которая аппроксимирует поведение сложной модели только в окрестности интересующего нас объекта. Мы можем анализировать её коэффициенты или правила для объяснения, как она делает предсказания. Это позволяет понять, какие признаки повлияли на предсказание для объекта.

Аналогичный метод обоснования сложной модели линейной также применял в работе


4️⃣Permutation Importances
Для каждого признака случайным образом перемешиваем его значения в тестовой выборке. Это изменяет только этот признак, но сохраняет зависимость между другими признаками. Важность признака определяется как разница между производительностью модели на исходных данных и на данных с перемешанным признаком. Чем больше эта разница, тем более важен признак.
💡Реализация в sklearn.inspection как permutation_importance.

5️⃣ICE (Individual Conditional Expectation)
Метод локальной интерпретации, основанный на визуализации. Для объекта меняется один признак, остальные фиксированы. По оси x строится значение изменяемого признака, по оси y - результирующее предсказание модели. Так можно понять и оценить влияние конкретного признака.
💡Реализация в sklearn.inspection как plot_ice.


6️⃣Partial Dependence Plot (PDP)
Визуальный метод глобальной интерпретации. В отличие от ICE учитывает изменения на всем наборе данных, а не на отдельном объекте.
💡Реализация в sklearn.inspection как plot_partial_dependence

Ставь 🔥, если понравилось!

#ds_лайфхаки
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Data Blog
💥 Список библиотек для XAI

Хочу зафиналить год useful постом, который лежит у меня дольше, чем ..... ладно, просто долго!

💫Основные библиотеки для моделей ML (и DL)

LIME https://github.com/marcotcr/lime
— ELI5 https://eli5.readthedocs.io/en/latest/
— SHAP https://github.com/slundberg/shap
— DICE ML https://interpret.ml/DiCE/dice_ml.html#
— Pdpbox https://pdpbox.readthedocs.io/en/latest/

☄️Для моделей Deep Learning и LLM

* Captum (pytorch) https://github.com/pytorch/captum
* Anchors https://github.com/marcotcr/anchor
* DALEX https://github.com/ModelOriented/DALEX
* AIX360 https://github.com/IBM/AIX360
* ALIBI https://github.com/SeldonIO/alibi
* Quantus https://github.com/understandable-machine-intelligence-lab/Quantus
* OmniXAI https://github.com/salesforce/OmniXAI
* pytorch_explain https://github.com/pietrobarbiero/pytorch_explain
* DeepExplain https://github.com/marcoancona/DeepExplain
* Grad-CAM https://github.com/ramprs/grad-cam
* Integrated Gradients https://github.com/ankurtaly/Integrated-Gradients
* DeepLIFT https://github.com/kundajelab/deeplift
* interpret-text https://github.com/interpretml/interpret-text?ysclid=ldebiwr4jr824513795
* ExBERT https://github.com/bhoov/exbert
* ExplainaBoard (NLP) https://github.com/neulab/ExplainaBoard
* CARLA https://github.com/carla-recourse/CARLA

Никому не верьте, и всегда сомневайтесь в моделях!
Forwarded from Machinelearning
🌟 noise_step: алгоритм тернарного обучения без использования градиентной памяти.


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

Noise_step обходится без обратного распространения ошибки, а также может работать параллельно с инференсом и хранит тернарные значения в бинарном представление, которое позволяет упаковать 5 тернов в 1байт.

Алгоритм оценивает градиент, используя произведение Якобиана на вектор возмущения, которые генерируются с помощью распределения Бернулли и равномерного распределения {-1, +1}. Для оценки градиента нужен только знак выравнивания, а не его величина. Чтобы улучшить сходимость, Noise_step отбрасывает возмущения со слишком маленькой величиной выравнивания.

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

Таким образом, модель можно представить как последовательность шагов, что кардинально уменьшает её размер. Теоретически, основываясь на расчетах, размер модели, подобной GPT-3 175B, можно уменьшить до 19MB.

Noise_step использует дискретные шаги из-за тернарного пространства, что добавляет шума в кривую обучения, но алгоритм сходится примерно как Adam, хотя и требует большего батч-сайза. Сходимость, аналогичная Adam, была подтверждена эмпирически на единственном прикладном эксперименте с простым MLP на наборе MINST и, очевидно, требует большей вариативности практических тестов.

Несмотря на то, что ранее тернарная точность уже была реализована в фреймворке Microsoft и модели Nous Research, которые не имеют таких ограничений, как в Noise_step , он может стать в будущем альтернативой квантованию и встать в один ряд с другими методами оптимизации обучения и инференса.

⚠️ Обучение трансформерных моделей с noise_step пока остается отрытым вопросом, так как для этого необходимо написать ядро, в котором шум будет виртуализирован (генерироваться по мере использования).

⚠️ Для больших моделей с большим количеством шагов реконструкция становится непрактичной, поскольку каждый вес должен обновляться с учетом каждого вектора возмущений на каждом шаге. Полная реконструкция тернарной модели с количеством параметров 175B, потребовала бы примерно 10 в 19 степени операций.


🟡Исследование
🟡Google Collab простого MLP c MINST
🖥GitHub

@ai_machinelearning_big_data

#AI #ML #NoiceStep #TernaryPresision
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM