Data Funk
247 subscribers
192 photos
2 videos
1 file
68 links
Download Telegram
У картинок оставил три цветовых канала, но сами цвета, как и в предыдущем случае уменьшил до 2, что бы в итоге остались 0 и 1. Смесь распределений Бернулли сформировала несколько размытых кластеров, но некоторые кластера-картинки получились довольно четкие
🔥1
Прочитал статью на Хабре о решении уравнения Эйконала методом быстрого марша (Fast Marching Method - FMM) и вспомнил, что когда-то занимался решением уравнений Максвелла, а уравнение Эйконала как раз получается из уравнений Максвелла в приближении, когда длина волны очень мала. Оно связывает геометрическую оптику с волновой и считает, что световые лучи перпендикулярны волновому фронту, а модуль градиента фазы волны в каждой точке пространства равен показателю преломления в этой точке. Сам же FMM является алгоритмом Дейкстры (поиск кратчайших путей) заточенным под сеточные графы, что позволяет ему работать за O(N*log(N)) от числа вершин.
🔥1
Я взял картинки (простите Вермеер и Уорхол) и с помощью FMM рассчитал волновой фронт от источника (красная точка) в трёх RGB каналах, приняв яркость пикселя в каждом канале за степень оптической вязкости (чем светлее пиксель, тем медленнее через него движется волна). Это похоже на неравномерно растекающееся по поверхности масло. В итоге каждому пикселю сопоставляется время, за которое до него дошла волна от источника: чем светлее, тем больше потребовалось времени. Растекшееся масло заиграло радужными переливами.
🔥1
Привет. Визуализация больших графов - большая проблема (подробнее тут), визуализация даже небольших, но динамических графов (когда ребра и вершины то появляются, то исчезают) - проблема не меньше, но информации в сети об этом не так много, ровно, как и доступных инструментов. Парочка найденных библиотек работает крайне медленно. Один из выходов использовать статические укладки (я использовал multidimensional scaling - алгоритм оценивает кратчайшие пути между вершинами и пытается сохранить их в 2d проекции) в каждый момент времени + нормировку и экспоненциальное сглаживание, что бы изменения в укладках были хоть немного сглажены, впрочем, это все равно не исключает дрожания и прыжки между соседними укладками.
This media is not supported in your browser
VIEW IN TELEGRAM
Тут, в динамике по дням, представлен граф постов с reddit топика - r/TikTokCringe, собранных с июня 2023. Я формировал ребро между двумя вершинами - постами топика, только если как минимум 5 одних и тех же пользователей оставили комментарии под обоими постами. Цветом показаны основные теги постов.

Датасет взят тут -> https://www.kaggle.com/datasets/curiel/rtiktokcringe-post-and-comments
🔥1
Привет, всякий раз, когда приходится иметь дело с рисками (прогноз погоды, медицинская диагностика, финансы, беспилотные авто и тд) возникает задача прогнозирования не просто точечного значения, а целого диапазона, в идеале всего условного распределения F(Y|X). Среди доступных для этого инструментов: Байесовские методы, квантильная регрессия, конформные предсказания и ансамблевые методы. К последним относится модификация случайного леса - Distributional Random Forest. Отличие от классического леса только в конце - для выбранного X оценивается близость со всеми точками из train набора по тому, как часто X попадает с ними в одни и те же листья в деревьях. Полученные меры близости используются в качестве весов для соответствующих значений Y из обучающей выборки, что в итоге дает непараметрическую оценку условного распределения F(Y|X).
Для toy-примера я взял сглаженные данные подневной температуры в Longyearbyen (Лонгйир - город на Шпицбергене, где на глубине 130 метров расположено всемирное семенохранилище), и выкинул часть данных в виде лемнискаты Бернулли.
Обученный (на фичах - год и номер дня в году) Distributional Random Forest заполнил пропущенную область визуально близкими к фону значениями.
А тут DRF дает оценку стандартного отклонения для предсказаний по всем точкам (где была заполнена температура и где нет). Видно, что в вырезанной области дисперсия заметно возрастает. Модель подсказывает нам что, менее уверена в своих ответах на данных, которых не видела при обучении. Это полезное качество - при некотором пороге дисперсии не доверять предсказаниям модели.

Датасет -> https://www.kaggle.com/datasets/guillemservera/global-daily-climate-data
🔥2
Провел небольшой воркшоп коллегам по переходу с pandas на polars. Основные операции с табличками polars проворачивает на 1-2 порядка быстрее чем 🐼 (в основном из appache arrow в качестве бэкенда, отказа от индексов и Rust под капотом для управления памятью). Ниже небольшая тетрадка, которую собрал для того, что бы показать как привычные решения на pandas выглядят в polars:

https://www.kaggle.com/code/alexbenzik/polars-101-by-abenzik
🔥8
Несмотря на большое количество теории в математике/статистике, практика решений аналитических/DS задачек как сито просеивает методы, оставляя несколько проверенных трюков в личном "швейцарском ноже". Одним из таких первых трюков, который легко запомнить и применять, для меня стало логарифмическое преобразование с сохранением знака. Когда фичу сильно шатает, удобно сжать ее логарифмом, если она шатается в отрицательных значениях то нужно преобразование Йео-Джонсона, но я часто делаю так:

y = sign(x) * log(abs(x) + 1)
и если нужно обратное, то:
x = sign(y) * (exp(abs(y)) - 1)
Одним из недавних таких трюков для меня стала новая версия ранговой корреляции. Что бы быстро прикинуть есть ли связь между векторами X и Y часто применяется корреляция Пирсона (хотя эта связь редко бывает линейной, но кого это смущало) и реже корреляции Спирмена, Кендалла. Если важно увидеть не столько монотонные отношения Y~X, сколько вобще наличие/отсутствие связи, вот то, что нужно:

import polars as pl

u = pl.DataFrame({'Y':[-7, 4, -3, 7, 4],'X':[-6, 0, 2, -9, 3]})
n = len(u)
u = u.sort(['Y','X'])
u = u.with_columns(pl.Series(values = range(n),name = 'rank_Y'))
u = u.sort(['X','Y'])
S = u['rank_Y'].diff().abs().sum()

NewCorr = 1 - 3 * S / (n^2 - 1)
S - сумма абсолютных разностей рангов Y вдоль оси X. NewCorr ~ 0 когда Y это шум, и ~ 1, когда ранги Y плавно меняются вдоль оси X, также открывается полезное свойство NewCorr(X,Y) != NewCorr(Y,X). Единственное, мне не понравилось, что она никогда не достигает 1, даже для идеальной прямой (если Y(X) - монотонная функция, то S = n - 1), а т.к максимальное значение S не привышает n^2 / 2 - 1, то NewCorr можно перенормировать:

NewCorr* = 1 - 3*(S - n + 1) / (n^2 - 2*n)
🔥3
В продолжении темы про новую ранговую корреляцию. Ее способность улавливать зависимости, которые часто недоступны для корреляций Пирсона, Спирмана, Кендалла и легкость расчета (пара сортировок), делает ее удобным инструментом первичного EDA. Для примера я взял несколько датасетов почти без предобработки, отправляя в NewCorr*(X,Y) все фичи как есть (категориальные, числовые, datetime) расстояние между колонками считал как D = 1 - max{NewCorr*(X,Y),NewCorr*(Y,X)} и поверх матрицы расстояний иерархическую complete кластеризацию, собирая кластеры для D < 0.5.
Датасет со статистикой по топ 10 Youtube образовательным каналам. Количество просмотров/тегов/лайков/комментариев собрались в один кластер, там же день недели публикации и название канала, похоже по статистике просмотров можно точно идентифицировать каждый канал из списка. Доля лайков связана с длительностью роликов, также видно, что данный подход располагает уникальный идентификатор видео на уровне колонки с нормальным шумом.
IMDB. Название фильма оказалось сопоставимо с шумовой колонкой, imdb_id завязан на дату выхода фильма, остальные характеристики оказались в одном кластере, хотя популярность фильма расположена от остальных дальше всех.