惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
小众软件
小众软件
博客园_首页
博客园 - 聂微东
V
V2EX
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 司徒正美
博客园 - 三生石上(FineUI控件)
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
S
SegmentFault 最新的问题
J
Java Code Geeks
Last Week in AI
Last Week in AI
The Cloudflare Blog
月光博客
月光博客
雷峰网
雷峰网
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
博客园 - Franky
腾讯CDC
Jina AI
Jina AI
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
量子位
爱范儿
爱范儿
美团技术团队
T
Tailwind CSS Blog
博客园 - 【当耐特】
D
Docker
IT之家
IT之家
V
Visual Studio Blog
P
Proofpoint News Feed
L
LangChain Blog
Engineering at Meta
Engineering at Meta
C
Check Point Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
Recorded Future
Recorded Future

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Своими руками: как посчитать квази-биномиальную логистическую регрессию и зачем это вообще нужно
Darth_Masko · 2026-05-16 · via Все публикации подряд на Хабре

Своими руками: как посчитать квази-биномиальную логистическую регрессию и зачем это вообще нужно

Уровень сложностиСредний

Время на прочтение9 мин

Охват и читатели403

Туториал

Всем привет!

Я вычислительный биолог, изучаю молекулярные механизмы старения и возрастных заболеваний и работаю с данными секвенирования одиночных клеток (сингл‑селл). Это очень интересный тип данных, поскольку он позволяет смотреть не на «кашу» из органа, а видеть индивидуальные популяции клеток. В частности, можно наблюдать популяции, которых становится больше в старении, или которые наоборот исчезают, или просто что‑то редкое и прикольное. В последние лет 5 сингл‑селл данные дают очень много инсайтов в науке, которые будут безумно полезны для биомедицины. Но как показать, что содержание той или иной популяции меняется при старении или болезни? Давайте разберем.

Итак, допустим, мы отковыряли куски тканей (сердце, легкие, мозг, сосуды, печень — подставьте что нравится) от 10 молодых (или здоровых) и 10 старых (или больных) доноров и хотим сравнить их между собой. Мы провели сингл‑селл, нашли интересующий тип клеток (например, макрофаги или фибробласты) и видим, что они бывают двух «видов»: 

  • «Хорошие», которые экспрессируют нормальные гены и явно пребывают в нормальном, гомеостатическом состоянии; 

  • «Плохие» — например, хронически воспаленные.

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

Тут можно даже глазами увидеть, что процент плохих как будто бы больше при старении или болезни. Но как это измерить и доказать?

И когда я только начинал работать с сингл‑селл, наивным и самым «логичным» способом сравнить группы мне показался Z‑тест на пропорции (почитать можно тут). Идея простая: суммарно у нас 353 + 461 + … = 2797 хороших клеток у молодых доноров, 2157 хороших клеток у старых доноров, 284 плохих клеток у молодых доноров и 1283 плохих клеток у старых доноров. То есть, если считать пропорции, то pyoung = 284 / (2797 + 284) = 0.0922 и pold = 1283 / (2157 + 1283) = 0.3730. То есть, из всех «молодых» клеток 9.22% — плохие, из всех «старых» — целых 37.30%. Просто проспойлерю, что в конце расчетов Z‑score получается 26.49, а p‑value = 1.24*10-154. Запредельная достоверность!!! 

Только к сожалению, так делать нельзя. Это проблема носит название псевдорепликация: у нас 6521 клеток, но это псевдореплики — мы наскребли их со всего 20 реальных доноров, биологических повторов. И результаты получаются завышенные, ложноположительные. По противоположной причине тут не стоит использовать тест Манна‑Уитни, чтобы сравнить этих доноров — он слишком слабый. Грубо говоря, информацию «100 из 10000» он будет видеть как «1 из 100», хотя по информативности это небо и земля. Поэтому я посмотрел, как делают в статьях, и нашел, что сейчас такие штуки считают при помощи квази‑биномиальной логистической регрессии. Ну а идея этой статьи у меня родилась из того, что ни на русскоязычных, ни в англоязычных источниках не объяснено нормально, как её считать — обычно объясняют либо простые тесты (t‑критерий, Фишер), либо совсем уже ML модельки, либо это что‑то ультрасложное для математиков. 

Итак, как доказать, что плохих клеток становится больше при старении?

Шаг 1. Сформулируем уравнение модели

Наша модель — это регрессия. То есть функция вида y = kx + b.

В нашем случае y — это логарифм шансов, он же логит (поэтому регрессия называется логистическая), то есть y = ln(p / (1-p)), где p — теоретическая доля (от 0 до 1) плохих клеток для этого вида донора (молодого или старого). Мы строим линейный тренд не для самих долей, а для логарифма шансов, благодаря чему реальные проценты клеток будут красиво укладываться в плавную S‑образную кривую (сигмоиду) и никогда не вылетят за рамки от 0 до 1.

Регрессия называется биномиальной, потому что природа нашего отклика бинарна: каждая отсеквенированная клетка может быть либо «хорошей», либо «плохой».

x бывает двух видов: 0 для молодых, 1 для старых.

b — это интерцепт, свободный член. Это базовый логарифм шансов найти плохую клетку у молодого донора, когда x = 0.

k — это коэффициент возраста. Он показывает, как изменяется этот логарифм шансов при старении или болезни.

Тогда функция для молодого донора (x = 0) будет иметь вид: ln( pyoung / (1 — pyoung) ) = b.

А для старого (x = 1) такой: ln( pold / (1 — pold) ) = b + k.

Шаг 2. Найдем коэффициенты k и b

Это сделать не очень сложно. Шансы (odds) считаются так: 

Oddsyoung = pyoung / (1 - pyoung) = 284 / 2797 = 0.1015. 

Oddsold = pold / (1 - pold) = 1283 / 2157 = 0.5948.

То есть тогда как у молодых на одну плохую клетку приходится почти 10 хороших, у старых — меньше 2 хороших. 

Далее b = ln(Oddsyoung) = -2.2873. Ну а k = ln(Oddsold) - b = -0.5185 + 2.2873 = 1.7678.

То есть, мы вывели тот самый закон природы, как % плохих клеток изменяется при старении. А именно: 

ln( p / (1-p) ) = -2.2873 + 1.7678 * x, где x = 0 для молодых и x = 1 для старых. Простыми словами, для молодого донора шансы найти старую клетку равны e-2.2873 = 0.1015 (мы это уже считали), а при старении эти шансы растут в e1.7678 = 5.8580 раз! 

Ну, осталось самое сложное – доказать статистическую значимость наших находок. 

Шаг 3. Расчет ожидаемых значений и хи-квадратов для всех образцов

Партия сказала надо, в следующем шаге поймете, зачем.

Для каждого донора мы считаем ожидаемое количество плохих и хороших клеток. Процент плохих клеток у молодых = pyoung = 0.0922, процент хороших = 1 - pyoung = 0.9078. У стариков процент плохих клеток pold = 0.3730, процент хороших = 1 - pold = 0.6270.

Для расчета ожидаемого количества плохих и хороших клеток мы общее число клеток каждого донора умножаем на его проценты, при этом до целого не округляем. То есть для первого молодого донора (Y1) мы ждем 370 * 0.0922 = 34.114 плохих и 370 * 0.9078 = 335.886 хороших клеток, для Y2 489 * 0.0922 = 45.086 плохих и 489 * 0.9078 = 443.914 хороших клеток; для первого старого (O1) 334 * 0.3730 = 124.582 плохих и 334 * 0.6270 = 209.418 хороших клеток. И так далее, масштабировать можно в экселе или похожих программах.

Далее считаем хи-квадраты. В данном случае для каждого образца χ² = ((реальные плохие - ожидаемые плохие)2) / (ожидаемые плохие * доля хороших в группе). То есть для Y1 будет χ² = ((17 - 34.114)2) / (34.114 * 0.9078) = 9.458, а для O1 верно χ² = ((115 - 124.582)2) / (124.582 * 0.6270) = 1.175. Опять-таки, масштабируется экселем.

Шаг 4. Оценка параметра сверхдисперсии

Теперь просуммируем получившиеся хи‑квадраты по всем 20 образцам. У меня получилось 682.093 по значениям экселя, если считать на калькуляторе, будет чуть по‑другому из‑за округления.

И прикинем число степеней свободы. Для этого надо из числа доноров (20) вычесть число параметров (их два, k и b), которые мы считаем. То есть, df = 20 — 2 = 18.

Из этого можно посчитать параметр (или коэффициент) сверхдисперсии φ = сумма хи‑квадратов / df = 682.093 / 18 = 37.894.

Что это вообще такое? Тут раскрывается смысл ещё одного магического термина «квази‑биномиальная». В обычной биномиальной регрессии дисперсия = (p * (1-p)) / n. Ну то есть если бы мы подбрасывали абсолютно сферических коней в вакууме, а все наши 20 доноров были бы идеальными биологическими роботами. В реальности же у кого‑то скрытый воспалительный процесс, у кого‑то генетика кривая, какой‑то образец просто на столе протух — в биологии всё сложно.

И поэтому из 682.093 единиц разброса только 18 (по центральной предельной теореме) может объяснить технический шум. Остальные — это биология, и наша модель, которая теперь называется квази‑биномиальная регрессия, определяет дисперсию как φ * (p * (1-p)) / n. И собственно, этот φ мы нашли.

Шаг 5. Раздувание стандартной ошибки и финальная оценка p-value

Доказать статистическую значимость в регрессии — это значит, доказать, что коэффициент b или k не равен нулю. И собственно, этим мы сейчас займемся. Сначала для b. 

Посчитаем информационный вес для молодых доноров: Wyoung = общее число клеток молодых доноров * процент плохих * процент хороших = 3081 * 0.0922 * 0.9078 = 257.81. Старые нам тут не нужны, так как b работает для x = 0. 

Теперь стандартная ошибка для b. SEbinomial(b) = sqrt( 1 / Wyoung ) = 0.0623. И вот теперь мы вспоминаем, что наши данные упоротые, имеют сверхдисперсию, и стандартную ошибку нам придется раздуть. Это плохо для стат. значимости, но зато очень хорошо для честности и адекватной оценки того, что происходит в образце. А поможет нам тут как раз коэффициент φ. SEquasi(b) = SEbinomial(b) * sqrt(φ) = 0.3834.

Теперь считаем t‑критерий по формуле коэффициент делить на стандартную ошибку: t = b / SEquasi(b) = -2.2873 / 0.3834 = -5.9658. Это много по модулю, скажу я Вам, и по таблице/экселю/питону t = -5.9658 при 18 степенях свободы дает p‑value = 1.2*10-5.

То есть, b прошел порог статистической значимости. Если бы не прошел, то это значило бы, что логарифм шансов для молодого донора найти плохую и хорошую клетку достоверно не отличается от нуля, и pyoung достоверно не отличается от 0.5. Ну а у нас отличается: всё‑таки у молодых доноров, как мы помним, только 10% клеток — плохие.

Теперь то же самое для k. Нам ещё понадобится Wold = общее число клеток старых доноров * процент плохих * процент хороших = 3440 * 0.3730 * 0.6270 = 804.49. Wyoung берем из предыдущих расчетов.

SEbinomial(k) = sqrt( [1 / Wyoung] + [1 / Wold] ) = 0.0716. Снова раздуваем ошибку: SEquasi(k) = SEbinomial(k) * sqrt(φ) = 0.4406. 

Аналогично считаем t = k / SEquasi(k) = 1.7678 / 0.4406 = 4.0127, что при 18 степенях свободы дает нам p-value = 8.177*10-4. Снова достоверно! 

Это уже доказывает, что при старении действительно статистически значимо меняется процент плохих клеток. Но обратите внимание – p-value = 0.0008 это уже почти “на грани”, особенно если будут ещё какие-то поправки на множественное сравнение (ведь обычно мы тестируем не одну, а десятки популяций!).

Вот только если бы мы не раздували стандартные ошибки, а использовали SEbinomial(b) и SEbinomial(k), то для b мы бы получили p-value 2.68*10-295, а для k — 1.02*10-134. То есть как будто бы супер круто и биологически достоверно, но на деле — тотальный научный терроризм и так считать нельзя. А раздувание ошибок позволяет нам не получить ложноположительный результат и выдать его за реальную биологию.

Решение в гугл таблицах смотреть тут. В питоне - тут.

Если отрисовать в Seaborn, выглядеть это будет вот так:

Итоги и применение

Ну а теперь о том, где это применяется. Как и обещал в начале, приведу два хороших примера из мира сингл‑селл биологии.

В первой статье Раймондо и соавторы изучали механизм развития псориатического артрита, правда, у мышей. Это когда оно начинается на коже как псориаз, а дальше болезнь поражает суставы и развивается уже как артрит. В общем, выделили «плохую» популяцию CD2+MHC‑II+CCR2+ миелоидных предшественников (плюсики означают экспрессию соответствующих генов), которая увеличивается в коже, в крови и в синовиальной ткани сустава при болезни. В суставах эти ребята превращаются в макрофагов и начинают стимулировать Т лимфоциты производить всякие провоспалительные молекулы (интерлейкин 17, например), что и приводит к печально известным последствиям [1].

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

Во второй в лаборатории Манолиса Келлиса отсеквенировали больше миллиона ядер клеток мозга в здоровом состоянии и при болезни Альцгеймера. При помощи квази‑биномиальной регрессии обнаружили, что селективно умирают именно те нейроны, в которых активен сигнальный путь Reelin (а именно гены RELN и DAB1). То есть тут ситуация обратная: нашли «хорошую» популяцию, которая исчезает при заболевании [2].

Зачем нам эта информация? Путь Reelin — как минимум молекулярная сигнатура, а может быть, и причина уязвимости. Зная это, мы можем пытаться воздействовать на него, чтобы такие нейроны умирали медленнее, и пытаться тормозить развитие болезни Альцгеймера. Конечно, в составе комплексной терапии, но данные очень ценные.

P. S. Картинка в начале статьи собрана из этих двух публикаций.

Ссылки

[1] Raimondo, Maria G., Hashem Mohammadian, Mario R. Angeli, Stefano Alivernini, Vladyslav Fedorchenko, Kaiyue Huang, Richard Demmler et al. “Skin‑derived myeloid precursors and joint‑resident fibroblasts spread psoriatic disease from skin to joints.” Nature Immunology (2026): 1–13.

[2] Mathys, Hansruedi, Carles A. Boix, Leyla Anne Akay, Ziting Xia, Jose Davila‑Velderrain, Ayesha P. Ng, Xueqiao Jiang et al. “Single‑cell multiregion dissection of Alzheimer”s disease.’ Nature 632, no. 8026 (2024): 858–868.