Русский
Русский
English
Статистика
Реклама

Big data

Паша Финкельштейн о Big Data, Apache Spark и DevRel

15.06.2021 10:13:02 | Автор: admin

Паша Финкельштейн разработчик, серийный спикер, автор и ведущий нескольких подкастов. На конференции Java Meeting Point он сделает доклад Spark: let's touch it, на котором познакомит участников с миром больших данных.

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


Расскажи, чем ты занимаешься?

Я Developer Advocate в JetBrains, занимаюсь темой Big Data и дата-инжиниринга. Я пытаюсь рассказывать людям о том, как устроен мир Big Data, что там интересного, какие есть инструменты.

О чем будет твой доклад на Java Meeting Point?

Я расскажу, что такое большие данные и как они отличаются от маленьких. Разберемся, как работает Apache Spark, как устроен его API, и поймем, что ничего принципиально сложного в этом нет.

Кому будет полезно посмотреть доклад?

Полезно будет Java или JVM-разработчикам ровня Middle+ и тем, кому интересно узнать, как работает Apache Spark. Мы научимся писать простенькие пайплайны на этом фреймворке. Станет понятно как, например, взять и написать пайплайн обработки данных на Apache Spark или проанализировать данные в датасете.

Ты много занимаешься DevRel-активностями: выступаешь с докладами, вел подкасты. Как ты начал этим заниматься?

Мой друг Слава Семушин уехал работать в Чехию. Я не особенно умею поддерживать отношения на расстоянии, но Слава очень классный, с ним хотелось продолжать общаться. Однажды он написал: Слушай, давай запишем подкаст. Решили попробовать, и так родился подкаст Паша+Слава.

Раз в пару недель мы созванивались и говорили на околотехнические темы. Потом к нам присоединился еще один Слава Артемьев, с которым я работал в компании Домклик. Очень удобно не пришлось менять название подкаста. Так возникла моя первая публичность.

Потом появилась идея выступить на сцене, и я сделал доклад на Joker. В последствии этот доклад я переделывал 3 раза и выступил с ним 14 раз.

С тех пор я подсел на этот крючок и сделал десятки докладов. Со временем мне стало намного проще их готовить. Я могу подготовить выступление по теме, в которой я не разбираюсь за неделю, а теме, в которой разбираюсь за 2-4 дня.

Можешь посоветовать, как научиться так же быстро готовить выступления?

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

Что должно быть в хорошем докладе?

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

Альтернативный вариант, это если доклад полностью теоретический. На такой люди придут вывернуть мозги. Так тоже можно, но сложно. Я один раз сделал доклад про внутренности Kotlin, людям не зашло.

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

Какой формат будет у твоего доклада на Java Meeting Point?

Это будет демо, на котором Java или JVM-разработчик на примере не очень больших данных сможет посмотреть, как работают большие. Мы посмотрим 5-6 слайдов и перейдем к программированию.

Подробнее..

Recovery mode Создаём компанию мечты нет хайпу

01.06.2021 00:14:15 | Автор: admin
Наверняка в вашей компании уже не раз появлялись ребята в дорогих костюмах и с хорошо подвешенным языком, увлекательно рассказывающие, что без современных айти-штучек компания не проживет и несколько лет!

Все эти data lake (болото данных), КХД (корпоративное кладбище данных), data mining (смотри, не подорвись), data governance (стань рабом своих данных) и им подобные не исчезают из их рассказов, периодически сменяя друг друга. Срок жизни очередного хайпа редко превышает год-два, но при желании для вас с большим удовольствием откопают любую почти забытую технологию.

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

В этой статье я постараюсь рассказать о старых-добрых технологиях, которые всё ещё работают. О том, что можно извлечь из перечисленных выше хайповых технологий и как всем этим пользоваться простым смертным, типа нас, не нанимая толпу дата-сайентологов с зарплатами >10 тысяч $ в месяц.

image


Статья продолжает цикл:
Создаём компанию мечты: мастер-данные и интеграция
Создаём компанию мечты: управление качеством данных

Содержание


1. Big data: постановка проблемы
2. Мастер-данные: бессмертная классика
3. Как хранить данные: нужны ли КХД
4. Нормализация, или зачем вам болота данных
5. Почему дата-сайентист получает больше аналитика, а делает меньше?
6. Шина данных vs микросервисы
7. Как вообще не попасть на хайп?

1. Big data: постановка проблемы


Роль big data в развитии современной цивилизации впечатляющая. Но не по той причине, которая вам кажется.

Если интернет в каждой деревне и каждом телефоне появился благодаря порно и соцсетям (мессенджерам), то big data подарила триллионы долларов производителям жёстких дисков и оперативной памяти.

Проблема в том, что реальная польза от современной big data (в широком смысле слова) для всего человечества близка к пользе от порнографии, т.е. за несколькими исключениями нулевая!

Как же так, удивитесь вы. Ведь любой консультант и продажник рассказывает целую дюжину примеров, начиная с General Electric с их диагностикой состояния авиадвигателей, заканчивая таргетированной рекламой от Гугла!

Проблема, если быть точнее, в повторяемости результатов. Скажу по секрету, что скамейка запасных у продажников big data короткая. Если вы попросите их привести ещё несколько примеров, список закончится на втором десятке. Уверен, что мессенджеров и порносайтов они смогут назвать куда больше :) потому что их просто физически больше.

Результат от работы дата-сайентистов, конечно, есть, только он редко когда удовлетворяет заказчиков. Потому что, потратив год работы и несколько миллионов на оборудование и зарплату, на выходе они дают совершенно тривиальные выводы и закономерности, очевидные для любого линейного менеджера или специалиста на местах. Например, что лучше всего продаётся товар, размещённый на уровне человеческого глаза.

А General Electric сформировала своё конкурентное преимущество основываясь на методах математического анализа и статистики, которые можно найти в любом курсе математики для университета. Понятия big data тогда ещё не было.

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

Что же делать? Работать! Долго, скучно и уныло, стараясь создать такую атмосферу, которая поощряла бы активное думание. Как в канонических примерах от Bell Labs или той же GE. Это вполне возможно, более того, на это способны самые обычные люди, как вы и я, если их нужным образом замотивировать.

А начать нужно с

2. Мастер-данные: бессмертная классика


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

В среде дата-сайентистов младше 30 лет встречается убеждение, что окно для внедрения систем MDM началось примерно в 2008 и закончилось в районе 2012-15 годов. Что после этого появилось так много новых инструментов (всякие hadoop и spark), что заморачиваться с мастер-данными уже не нужно, не нужно ходить и договариваться с владельцами всех систем, думать о последствиях выбора архитектуры MDM и каждого конкретного реквизита в каждом справочнике.

К сожалению для них и к счастью для вас, это окно не закрылось. MDM-системы всё так же актуальны, как и системы бухучета или взаимодействия с клиентами. И думать и договариваться всё ещё нужно.

3. Как хранить данные: нужны ли КХД


Нет, корпоративные кладбища данных вам не нужны.

Идея, что для целей аналитики нужно иметь специальным образом подготовленные наборы всех данных (идеологи КХД не только выделяют это слово жирным, но и подчёркивают его двойной чертой) в вашей компании, абсурда. Коэффициент реального использования этих данных минимальный, 99% из них не используются никогда.

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

4. Нормализация, или зачем вам болота данных


Это раздел про data lake, или болото данных. Легенды гласят, что можно сваливать все данные без разбору в одну большую кучу. Не нужно приводить все данные к одному формату, не нужно нормализовать и вычищать их!

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

На практике самый ценный вывод, который вы сможете сделать из data lake что ваша компания почти не работает на январских каникулах.

И главный вопрос как какие-то жулики сумели убедить хоть кого-то в работоспособности этого подхода. Я склоняюсь к гипнозу :)

5. Почему дата-сайентист получает больше аналитика, а делает меньше?


Маркетинг, грамотная самопрезентация, максимум уверенности в себе. Не исключаю также гипноз :)

6. Шина данных vs микросервисы


Мой любимый пример использования технологии не по назначению. В любой достаточно крупной компании на определённом этапе развития возникает шина данных. Не обязательно единая и по науке, но сама функция реализуется успешно. Подробнее и системно о подходе можно прочитать в прошлой статье.

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

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

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

Уже на десяти системах прекрасно выглядевшая на старте архитектура, подход превращается в некий такой клубок, паутину, когда определённые потоки отваливаются и не работают месяцами.

image

На нескольких десятках систем (цифра только кажется внушительной, в любом энтерпрайзе используется куда больше информационных систем) подход хоронит сам себя. И спустя несколько лет возникает какая-то централизация и шина. Делают её, как правило, уже другие люди.

7. Как вообще не попасть на хайп?


Вы познакомились с несколькими примерами хайпа, когда какой-то подход или технология могут оказаться бесполезными. И это с учётом того, что, по мировой статистике, доля успешно выполненных проектов по разработке и внедрению в IT редко превышает 40%.

Послевкусие от проваленных или бесполезных проектов может оказаться таким, что компания на время вообще откажется от IT-инициатив до тех пор, пока очередной влиятельный менеджер не оседлает очередной хайп.

Чтобы не попасть на хайп, перед очередным внедрением нужно выяснить следующее:

у технологии есть большая скамейка запасных. Количество приводимых примеров успешного применения должно превышать пару десятков, и от них не должно возникать ощущения, что тут происходит какая-то магия;
технология должна проходить тест на бабушку (объяснение сути должны быть настолько понятным, что его осилит даже ваша бабушка повторю, никакой магии);
у технологии должен быть конкретный, оцифрованный список ачивок, которые в результате получит ваша компания. Внедренцы MDM, CRM или той же 1С-бухгалтерии могут часами рассказывать о пользе их решения на примере ваших конкретных задач. Внедренцы Big data вообще начинают рассказывать, что сначала соберём кучу данных, а потом посмотрим, что с ней делать;
и, наконец, технология должна быть фальсифицируемой (в смысле критерия Поппера), т.е. внедренец должен чётко понимать область её применения и актуальности и суметь привести доводы против (!) внедрения. Не нужно забивать гвозди микроскопом, и вообще, например, если у вас мало клиентов, нужна ли вам супер-пупер CRM?

По большому счёту, этого уже достаточно, чтобы продолжить просто работать и не отвлекаться на хайпы.

Можете предложить ещё какие-нибудь критерии?
Приглашаю к обсуждению!
Подробнее..

Перевод ТОП-10 трендов в сфере данных и аналитики 2021. Версия Gartner

15.06.2021 10:13:02 | Автор: admin
Оракул технологического мира Gartner регулярно и охотно делится с обществом своими наблюдениями относительно текущих трендов. Эксперты компании составили подборку из 10 трендов в сфере данных и аналитики, которые стоит учитывать ИТ-лидерам в 2021 году от искусственного интеллекта до малых данных и применения графовых технологий.

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

Источник

Коротко о трендах


В предложенном материале Gartner выделяет ряд трендов в индустрии, связанной с машинным обучением и искусственным интеллектом. Не стоит ожидать, что статья откроет новые горизонты: в ней собраны те особенности и тренды, которые уже прошли этап новаторства, а также этап привлечения ранних последователей, однако если не обратить должного внимания на отмеченные тенденции, то можно опоздать даже попасть в категорию отстающих последователей. Кроме того, в статье явно прослеживаются рекламные и побудительные элементы, нацеленные на аудиторию, влияющую на инновации в своей области бизнеса, т.е. на основную аудиторию Gartner. В процессе перевода не удалось уйти от упомянутых элементов, однако рекомендуется к ним относиться снисходительно, т.к. эти рекламные вставки перемежаются ценной информацией. Некоторые из трендов напрямую связаны с изменениями в индустрии, к которым привела эпидемиологическая обстановка. Другие с растущей популярностью систем автоматического принятия решений и использованию ИИ в бизнес-аналитике. Отдельно хочется отметить тренд, связанный с графовыми методами, которые быстро развиваются и набирают все большую популярность. Тем не менее, некоторые из них носят скорее номинальный характер. Одним из таких номинальных трендов на первый взгляд кажется термин XOps, в котором Gartner объединяет направления DataOps, ModelOps и DevOps, комментируя свое видение следующим образом: Умножение дисциплин Ops, вытекающих из лучших практик DevOps, вызвало значительную путаницу на рынке. Тем не менее, их согласование может принести значительные преимущества организациям, которые способны гармонизировать эти дисциплины Практики XOps объединяют разработку, развертывание и обслуживание, чтобы создать общее понимание требований, передачу навыков и процессов для мониторинга и поддержки аналитики и артефактов ИИ. В этом, казалось бы, номинальном тренде, прослеживается мысль, отсылающая к теме Франкенштейна: мало состыковать отдельные рабочие части компании, т.к. они будут функционировать хаотично и не согласовано, жизнь и полезная активность начнется после того, как эти разрозненные части будут синхронизированы и гармонизированы. Но не буду раскрывать все карты сразу, предлагаю читателю самостоятельно ознакомиться с находками Gartner далее.

Как изменилась работа data-специалистов


По словам экспертов Gartner, на фоне COVID-19 организации, использующие традиционные методы аналитики, которые в значительной степени полагаются на большие объемы исторических данных, осознали одну важную вещь: многие из этих моделей больше не актуальны. По сути, пандемия изменила все, сделав множество данных бесполезными. В свою очередь, прогрессивные команды, занимающиеся обработкой данных и аналитикой, все больше переходят от традиционных методов искусственного интеллекта, основанных на больших данных, к классу аналитики, использующей малые или более разнообразные данные.

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

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

Каждая из тенденций соответствует одной из трех основных тем:

  1. Ускорение изменений в данных и аналитике: использование инноваций в области искусственного интеллекта, улучшенная возможность по компоновке, а также более гибкая и эффективная интеграция разнообразных источников данных.
  2. Операционализация ценности бизнеса посредством более эффективного использования XOps: позволяет лучше принимать решения и превращать данные и аналитику в неотъемлемую часть бизнеса.
  3. Принцип все распределено: предполагает гибкое соотнесение данных и идей для расширения возможностей более широкой аудитории людей и объектов.

Тренд 1. Продвинутый, ответственный, масштабируемый ИИ


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

Хотя традиционные методы ИИ могут в значительной степени полагаться на исторические данные, учитывая, как COVID-19 изменил бизнес-ландшафт, исторические данные могут больше не иметь значения. Это означает, что технология ИИ должна быть способна работать с меньшим количеством данных с помощью методов малых данных и адаптивного машинного обучения. Эти системы ИИ также должны защищать приватность, соблюдать федеральные правила и минимизировать предвзятость для поддержки этичного ИИ.

Тренд 2. Составные данные и аналитика


Целью составных данных и аналитики является использование компонентов из множества данных, аналитики и решений ИИ для создания гибкого, удобного, адаптированного под потребности пользователей интерфейса, который позволит руководителям связывать аналитические данные с бизнес-действиями. Запросы клиентов Gartner показывают, что в большинстве крупных организаций имеется более одного стандартного корпоративного инструмента аналитики и бизнес-аналитики.

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

Тренд 3. Фабрика данных как основа


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

Фабрика данных сокращает время на проектирование интеграции на 30%, развертывание на 30% и поддержку на 70%, поскольку технологические разработки основаны на возможности использования / повторного использования и комбинирования различных стилей интеграции данных. Кроме того, фабрики данных могут использовать существующие навыки и технологии из data-хабов (data hubs), озер данных (data lakes) и хранилищ данных (data warehouses), а также внедрять новые подходы и инструменты для будущего.

Тренд 4. От больших данных к малым и широким данным


Малые и широкие данные, в отличие от больших данных, решают ряд проблем для организаций, которые сталкиваются со все более сложными вопросами, касающимися ИИ, и проблемами, связанными с редкими вариантами использования данных. Широкие данные с использованием методов X-аналитики позволяют анализировать и объединять многообразие малых и широких, неструктурированных и структурированных источников данных для повышения осведомленности о контексте и принимаемых решениях. Малые данные, как следует из названия, могут использовать модели данных, которые требуют меньше данных, но все же предлагают полезные инсайты.

Источник

Тренд 5. XOps


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

Тренд 5. XOps. Источник

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

Тренд 6. Проектирование интеллекта принятия решений


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

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

Тренд 7. Данные и аналитика как ключевая бизнес-функция


Руководители бизнеса начинают понимать важность использования данных и аналитики для ускорения инициатив цифрового бизнеса. Вместо того, чтобы быть второстепенной задачей, выполняемой отдельной командой, данные и аналитика переключаются на основную функцию. Однако руководители предприятий часто недооценивают сложность данных и в конечном итоге упускают возможности. Если директора по данным (CDO) участвуют в постановке целей и стратегий, они могут увеличить стабильное производство стоимости бизнеса в 2,6 раз.

Тренд 8. Графы в основе всего


Графовые подходы формируют основу современных данных и аналитики, предоставляя возможности для усиления и улучшения взаимодействия c пользователями, моделей машинного обучения и интерпретируемого ИИ. Хотя графические технологии не новы для данных и аналитики, произошел сдвиг в мышлении вокруг них, поскольку организации выявляют все больше вариантов их использования. Фактически, до 50% запросов клиентов Gartner о ИИ связаны с обсуждением использования graph-технологий.

Источник

Тренд 9. Расширение пользовательского опыта


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

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

Тренд 10. Данные и аналитика впереди планеты всей


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

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

В заключение


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

Нас, представителей компании CleverDATA, активно использующих ИИ в повседневной работе, отчасти уже коснулись упомянутые в статье тренды: мы пришли к аналогичным выводам через собственный опыт. Благодаря выделенным в статье тенденциям, у читателей есть возможность подготовиться к переменам в индустрии ИИ, например, освоить методы работы с графовыми нейронными сетями или взяться за освоение элементов профессии Data Engineer. Предусмотрительный работник готовит не только сани летом, но и актуальные в будущем навыки уже сейчас.
Подробнее..

Инструменты для алготрейдинга на Python. SMA Полосы Боллинджера на акциях Северстали код готовой стратегии

31.05.2021 18:12:13 | Автор: admin

Внимание! Если данная статья наберет 1000 положительных голосов, то я организую хакатон по алготрейдингу с ценными призами.

Предыдущая статья о "Расчете дневного изменения цены"

Когда я писал прошлую статью (она была первой из цикла) я не предполагал, что читатели разделятся на 2 категории:
1. Те, кто верят, что в алготрейдинг
2. Те, кто верят, что я шарлатан

Для обоих групп я напоминаю, что цель алготрейдинга - это увеличить вероятность получить прибыль от сделки
Или же, как говорят в "теории игр" - сделать математическое ожидание от игры положительным

Поэтому, предлагаю аудитории договориться о следующем:
1. Если ваш комментарий несет научный смысл, то пишите его под постом в Хабре.
2. Если ваш комментарий несет дискуссионный посыл, то прошу задавать его в специально созданном канале в телеге:

Собственно, здесь я перехожу к сути данной статьи.

SMA (Simple Moving Average, Скользящее среднее) - индикатор, основанный на подсчете среднего значения цены закрытия ценной бумаги.

Для тех, кто не знает что такое SMA, приведу алгоритм его подсчета:
1. Взять цену закрытия "close" ценной бумаги за период от t1 до t2 и отсортировать ее от t1 к t2.
2. Взять таймфрейм из первых N значений цены close.
3. Посчитать среднее арифметическое значение таймфрейма (simple average).
4. Сдвинуть таймфрейм вперед на одно значение (происходит moving) и выполнить пункт 3
5. Пункт 4 проводить до тех пор, пока таймфрейм не дойдет до точки t2

Отрисуем график SMA (N=20) для цены close акций Северсталь (тикер CHMF) за 27 мая 2021г.:

По графику видно, что SMA является сглаженной версией цены Close с временным лагом в 20 периодов.

Полосы Боллинджера (Bollinger Bands)

В 1980х годах Джон Боллинджер предложил рассчитывать не только SMA, но и STD (standart deviation, среднеквадратическое отклонение). Таким образом, мы будем видеть не только график изменения средней цены, но и ее волатильность.

Обычно, значения std устанавливают равным 2. В таком случае, с вероятностью в 95% следующее значение цены close будет лежать внутри полосы Боллинджера и только в 5% случаях оно будет выходить из этой полосы.

В тех местах, где цена close близка к нижней грани полосы Боллинджера, стоимость акций считается низкой. И, наоборот, если цена close близка к верхней грани полосы Боллинджера, стоимость акций считается высокой.

И тут у трейдера срабатывает чуйка: покупаем на низах, продаем на хаях (никак не наоборот).

Весь код с использованием полос Боллинджера привел на Google Colab. Данная стратегия принесла +1,7% за 1 день (но это не точно).

В следующей статье поговорим об RSI

Подробнее..

MEX (Minimum EXcluded) Алгоритм поиска минимального отсутствующего числа

13.06.2021 20:13:49 | Автор: admin
Добрый день. Сегодня хочется поговорить о том, как найти MEX (минимальное отсутствующие число во множестве).


Мы разберем три алгоритма и посмотрим на их производительность.

Добро пожаловать под cat

Предисловие


Перед тем как начать, хотелось бы рассказать почему я вообще за этот алгоритм взялся?
Всё началось с задачки на OZON.


Как видно из задачи, в математике результатом работы функции MEX на множестве чисел является наименьшим значением из всего набора, который не принадлежит этому множеству. То есть это минимальное значение набора дополнений. Название MEX является сокращением для Minimum EXcluded значение.

И покопавшись в сети, оказалось, что нет общепринятого алгоритма нахождения MEX

Есть решения в лоб, есть варианты с дополнительными массивами, графами, но, как-то всё это раскидано по разным углам интернета и нет единой нормальной статьи по этому поводу. Вот и родилась идея написать эту статью. В этой статье мы разберем три алгоритм нахождения MEX и посмотрим, что у нас получиться по скорости и по памяти.
Код будет на языке C#, но в целом там не будет специфичных конструкций.
Базовый код для проверок будет таким.

static void Main(string[] args)        {            //MEX = 2            int[] values = new[] { 0, 12, 4, 7, 1 };                        //MEX = 5            //int[] values = new[] { 0, 1, 2, 3, 4 };                        //MEX = 24            //int[] values = new[] { 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 0, 7, 6, 5, 27, 26, 25, 4, 31, 30, 28, 19, 18, 17, 16, 23, 22, 21, 20, 43, 1, 40, 47, 46, 45, 44, 35, 33, 32, 39, 38, 37, 36, 58, 57, 56, 63, 62, 60, 51, 49, 48, 55, 53, 52, 75, 73, 72, 79, 77, 67, 66, 65, 71, 70, 68, 90, 89, 88, 95, 94, 93, 92, 83, 82, 81, 80, 87, 86, 84, 107, 106, 104 };                        //MEX = 1000            //int[] values = new int[1000];            //for (int i = 0; i < values.Length; i++) values[i] = i;                        //Импровизированный счетчик итераций            int total = 0;            int mex = GetMEX(values, ref total);            Console.WriteLine($"mex: {mex}, total: {total}");            Console.ReadKey();        }

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

1) Решение в лоб


Как нам найти минимальное отсутствующие число? Самый простой вариант сделать счетчик и перебирать массив до тех пор, пока не найдем число равное счетчику.

  static int GetMEX(int[] values, ref int total)        {            for (int mex = 0; mex < values.Length; mex++)            {                bool notFound = true;                for (int i = 0; i < values.Length; i++)                {                    total++;                    if (values[i] == mex)                    {                        notFound = false;                        break;                    }                }                if (notFound)                {                    return mex;                }            }            return values.Length;        }    }


Максимально базовый случай. Сложность алгоритма составляет O(n*cell(n/2)) Т.к. для случая { 0, 1, 2, 3, 4 } нам нужно будет перебрать все числа т.к. совершить 15 операций. А для полностью заполного ряда из 100 числе 5050 операций Так себе быстродейственность.

2) Просеивание


Второй по сложности вариант в реализации укладывается в O(n) Ну или почти O(n), математики хитрят и не учитывают подготовку данных Ибо, как минимум, нам нужно знать максимальное число во множестве.
С точки зрения математики выглядит так.
Берется битовый массив S длинной m (где m максимально число в изначально массиве (V) + 1) заполненный 0. И в один проход исходному множеству (V) в массиве (S) ставятся 1. После этого в один проход находим первое пустое значение.
static int GetMEX(int[] values, ref int total)        {            //Не учитываем в сложности             var max = values.Max() + 1;            bool[] sieve = new bool[max];            for (int i = 0; i < values.Length; i++)            {                total++;                sieve[values[i]] = true;            }            for (int i = 0; i < sieve.Length; i++)            {                total++;                if (!sieve[i])                {                    return i;                }            }            return values.Length;        }

Т.к. математики хитры люди. То они говорят, что алгоритм O(n) ведь проход по массиву исходному массиву всего один
Т.к. математики хитры люди. И говорят, что алгоритм O(n) ведь проход по массиву исходному массиву всего один
Вот сидят и радуются, что такой крутой алгоритм придумали, но правда такова.
Первое нужно найти максимально число в исходном массиве O1(n)
Второе нужно пройтись по исходному массиву и отметить это значение в массиве S O2(n)
Третье нужно пройтись массиве S и найти там первую попавшеюся свободную ячейку O3(n)
Итого, т.к. все операции в целом не сложные можно упростить все расчеты до O(n*3)
Но это явно лучше решения в лоб Давайте проверим на наших тестовых данных:
1) Для случая { 0, 12, 4, 7, 1 }: В лоб: 11 итераций, просеивание: 13 итераций
2) Для случая { 0, 1, 2, 3, 4 }: В лоб: 15 итераций, просеивание: 15 итераций
3) Для случая { 11,}: В лоб: 441 итерация, просеивание: 191 итерация
4) Для случая { 0,,999}: В лоб: 500500 итераций, просеивание: 3000 итераций

Дело в том, что если отсутствующие значение является небольшим числом, то в таком случае решение в лоб оказывается быстрее, т.к. не требует тройного прохода по массиву. Но в целом, на больших размерностях явно проигрывает просеиванью, что собственно неудивительно.
С точки зрения математика алгоритм готов, и он великолепен, но вот с точки зрения программиста он ужасен из-за объема оперативной памяти, израсходованной впустую, да и финальный проход для поиска первого пустого значения явно хочется ускорить.
Давайте сделаем это, и оптимизируем код.
static int GetMEX(int[] values, ref int total)        {            total = values.Length;            var max = values.Max() + 1;            var size = sizeof(ulong) * 8;            ulong[] sieve = new ulong[(max / size) + 1];            ulong one = 1;            for (int i = 0; i < values.Length; i++)            {                total++;                sieve[values[i] / size] |= (one << (values[i] % size));            }            var maxInblock = ulong.MaxValue;            for (int i = 0; i < sieve.Length; i++)            {                total++;                if (sieve[i] != maxInblock)                {                    for (int j = 0; j < size; j++)                    {                        total++;                        if ((sieve[i] & (one << j)) == 0)                        {                            return i * size + j;                        }                    }                }            }            return values.Length;        }

Что мы тут сделали. Во-первых, в 64 раза уменьшили количество оперативной памяти, которая необходима.
var size = sizeof(ulong) * 8;ulong[] sieve = new ulong[(max / size) + 1];
Во-вторых, оптимизировали фальную проверку: мы проверяем сразу блок на вхождение первых 64 значений: if (sieve[i] != maxInblock) и как только убедились в том, что значение блока не равно бинарным 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111, только тогда ищем уже вхождение на уровне блока: ((sieve[i] & (one << j)) == 0
В итоге алгоритм просеивание нам дает следующие результат:
1) Для случая { 0, 12, 4, 7, 1 }: просеивание: 13 итераций, просеивание с оптимизацией: 13 итераций
2) Для случая { 0, 1, 2, 3, 4 }: В лоб: 15 итераций, просеивание с оптимизацией: 16 итераций
3) Для случая { 11,}: В лоб: 191 итерация, просеивание с оптимизацией: 191 итерации
4) Для случая { 0,,999}: В лоб: 3000 итераций, просеивание с оптимизацией: 2056 итераций

Так, что в итоге в теории по скорости?
O(n*3) мы превратили в O(n*2) + O(n / 64) в целом, чуть увеличили скорость, да еще объём оперативной памяти уменьшили аж в 64 раза. Что хорошо)

3) Сортировка


Как не сложно догадаться, самый простой способ найти отсутствующий элемент во множестве это иметь отсортированное множество.
Самый быстрый алгоритм сортировки это quicksort (быстрая сортировка), которая имеет сложность в O1(n log(n)). И итого мы получим теоретическую сложность для поиска MEX в O1(n log(n)) + O2(n)
static int GetMEX(int[] values, ref int total)        {            total = values.Length * (int)Math.Log(values.Length);            values = values.OrderBy(x => x).ToArray();            for (int i = 0; i < values.Length - 1; i++)            {                total++;                if (values[i] + 1 != values[i + 1])                {                    return values[i] + 1;                }            }            return values.Length;        }

Шикарно. Ничего лишнего)
Проверим количество итераций
1) Для случая { 0, 12, 4, 7, 1 }: просеивание с оптимизацией: 13, сортировка: ~7 итераций
2) Для случая { 0, 1, 2, 3, 4 }: просеивание с оптимизацией: 16 итераций, сортировка: ~9 итераций
3) Для случая { 11,}: просеивание с оптимизацией: 191 итерации, сортировка: ~356 итераций
4) Для случая { 0,,999}: просеивание с оптимизацией: 2056 итераций, сортировка: ~6999 итераций

Здесь указаны средние значения, и они не совсем справедливы. Но в целом: сортировка не требует дополнительной памяти и явно позволяет упростить последний шаг в переборе.
Примечание: values.OrderBy(x => x).ToArray() да я знаю, что тут выделилась память, но если делать по уму, то можно изменить массив, а не копировать его


Вот у меня и возникла идея оптимизировать quicksort для поиска MEX. Данный вариант алгоритма я не находил в интернете, ни с точки зрения математики, и уж тем более с точки зрения программирования. То код будем писать с 0 по дороге придумывая как он будет выглядеть :D

Но, для начала, давайте вспомним как вообще работает quicksort. Я бы ссылку дал, но нормально пояснения quicksort на пальцах фактически нету, создается ощущение, что авторы пособий сами разбираются в алгоритме пока его рассказывают про него
Так вот, что такое quicksort:
У нас есть неупорядоченный массив { 0, 12, 4, 7, 1 }
Нам потребуется случайное число, но лучше взять любое из массива, это называется опорное число (T).
И два указателя: L1 смотрит на первый элемент массива, L2 смотрит на последний элемент массива.
0, 12, 4, 7, 1
L1 = 0, L2 = 1, T = 1 (T взял тупа последние)

Первый этап итерации:
Пока работам только с указателем L1
Сдвигаем его по массиву вправо пока не найдем число больше чем наше опорное.
В нашем случае L1 равен 8

Второй этап итерации:
Теперь сдвигаем указатель L2
Сдвигаем его по массиву влево пока не найдем число меньше либо равное чем наше опорное.
В данном случае L2 равен 1. Т.к. я взял опорное число равным крайнему элементу массива, а туда же смотрел L2.

Третей этап итерации:
Меняем числа в указателях L1 и L2 местами, указатели не двигаем.
И переходим к первому этапу итерации.
Эти этапы мы повторяем до тех пор, пока указатели L1 и L2 не будет равны, не значения по ним, а именно указатели. Т.е. они должны указывать на один элемент.

После того как указатели сойдутся на каком-то элементе, обе части массива будут всё еще не отсортированы, но уже точно, с одной стороны объеденных указателей (L1 и L2) будут элементы, которые меньше T, а со второй больше T. Именно этот факт нам и позволяет разбить массив на две независимые группы, которые мы сортируем можно сортировать в разных потоках в дальнейших итерациях.
Статья на wiki, если и у меня непонятно написанно

Напишем Quicksort
static void Quicksort(int[] values, int l1, int l2, int t, ref int total)        {            var index = QuicksortSub(values, l1, l2, t, ref total);            if (l1 < index)            {                Quicksort(values, l1, index - 1, values[index - 1], ref total);            }            if (index < l2)            {                Quicksort(values, index, l2, values[l2], ref total);            }        }        static int QuicksortSub(int[] values, int l1, int l2, int t, ref int total)        {            for (; l1 < l2; l1++)            {                total++;                if (t < values[l1])                {                    total--;                    for (; l1 <= l2; l2--)                    {                        total++;                        if (l1 == l2)                        {                            return l2;                        }                        if (values[l2] <= t)                        {                            values[l1] = values[l1] ^ values[l2];                            values[l2] = values[l1] ^ values[l2];                            values[l1] = values[l1] ^ values[l2];                            break;                        }                    }                }            }            return l2;        }


Проверим реальное количество итераций:
1) Для случая { 0, 12, 4, 7, 1 }: просеивание с оптимизацией: 13, сортировка: 11 итераций
2) Для случая { 0, 1, 2, 3, 4 }: просеивание с оптимизацией: 16 итераций, сортировка: 14 итераций
3) Для случая { 11,}: просеивание с оптимизацией: 191 итерации, сортировка: 1520 итераций
4) Для случая { 0,,999}: просеивание с оптимизацией: 2056 итераций, сортировка: 500499 итераций

Попробуем поразмышлять вот над чем. В массиве { 0, 4, 1, 2, 3 } нет недостающих элементов, а его длина равно 5. Т.е. получается, массив в котором нет отсутствующих элементов равен длине массива 1. Т.е. m = { 0, 4, 1, 2, 3 }, Length(m) == Max(m) + 1. И самое главное в этом моменте, что это условие справедливо, если значения в массиве переставлены местами. И важно то, что это условие можно распространить на части массива. А именно вот так:
{ 0, 4, 1, 2, 3, 12, 10, 11, 14 } зная, что в левой части массива все числа меньше некого опорного числа, например 5, а в правой всё что больше, то нет смысла искать минимальное число слева.
Т.е. если мы точно знаем, что в одной из частей нет элементов больше определённого значения, то само это отсутствующие число нужно искать во второй части массива. В целом так работает алгоритм бинарного поиска.
В итоге у меня родилась мысль упростить quicksort для поиска MEX объединив его с бинарным поиском. Сразу скажу нам не нужно будет полностью отсортировывать весь массив только те части, в которых мы будем осуществлять поиск.
В итоге получаем код
static int GetMEX(int[] values, ref int total)        {            return QuicksortMEX(values, 0, values.Length - 1, values[values.Length - 1], ref total);        }        static int QuicksortMEX(int[] values, int l1, int l2, int t, ref int total)        {            if (l1 == l2)            {                return l1;            }            int max = -1;            var index = QuicksortMEXSub(values, l1, l2, t, ref max, ref total);            if (index < max + 1)            {                return QuicksortMEX(values, l1, index - 1, values[index - 1], ref total);            }            if (index == values.Length - 1)            {                return index + 1;            }            return QuicksortMEX(values, index, l2, values[l2], ref total);        }        static int QuicksortMEXSub(int[] values, int l1, int l2, int t, ref int max, ref int total)        {            for (; l1 < l2; l1++)            {                total++;                if (values[l1] < t && max < values[l1])                {                    max = values[l1];                }                if (t < values[l1])                {                    total--;                    for (; l1 <= l2; l2--)                    {                        total++;                        if (values[l2] == t && max < values[l2])                        {                            max = values[l2];                        }                        if (l1 == l2)                        {                            return l2;                        }                        if (values[l2] <= t)                        {                            values[l1] = values[l1] ^ values[l2];                            values[l2] = values[l1] ^ values[l2];                            values[l1] = values[l1] ^ values[l2];                            break;                        }                    }                }            }            return l2;        }

Проверим количество итераций
1) Для случая { 0, 12, 4, 7, 1 }: просеивание с оптимизацией: 13, сортировка MEX: 8 итераций
2) Для случая { 0, 1, 2, 3, 4 }: просеивание с оптимизацией: 16 итераций, сортировка MEX: 4 итераций
3) Для случая { 11,}: просеивание с оптимизацией: 191 итерации, сортировка MEX: 1353 итераций
4) Для случая { 0,,999}: просеивание с оптимизацией: 2056 итераций, сортировка MEX: 999 итераций

Итого


Мы получили разны варианты поиска MEX. Какой из них лучше решать вам.
В целом. Мне больше всех нравится просеивание, и вот по каким причинам:
У него очень предсказуемое время выполнения. Более того, этот алгоритм можно легко использовать в многопоточном режиме. Т.е. разделить массив на части и каждую часть пробегать в отдельном потоке:
for (int i = minIndexThread; i < maxIndexThread; i++)sieve[values[i] / size] |= (one << (values[i] % size));

Единственное, нужен lock при записи sieve[values[i] / size]. И еще алгоритм идеален при выгрузки данных из базы данных. Можно грузить пачками по 1000 штук например, в каждом потоке и всё равно он будет работать.
Но если у нас строгая нехватка памяти, то сортировка MEX явно выглядит лучше.

П.с.
Я начал рассказ с конкурса на OZON в котором я пробовал участвовал, сделав предварительный вариант алгоритма просеиванья, приз за него я так и не получил, OZON счел его неудовлетворительным По каким именно причин он так и не сознался До и кода победителя я не видел. Может у кого-то есть идеи как можно решить задачу поиска MEX лучше?
Подробнее..

Запросить 100 серверов нельзя оптимизировать код. Ставим запятую

15.06.2021 20:16:32 | Автор: admin

Можно выделить ряд алгоритмов, которые являются базовыми и лежат в основе практически каждой строчки программ, написанных на языках высокого уровня. Хорошо иметь под руками классический многотомный труд Дональда Кнута "The Art of Computer Programming", там детально разобраны многие базовые алгоритмы. Но прочесть и усвоить все задача, требующая много усилий и времени, которая должна как-то быть мотивирована.


Многие могут предположить, что нюансы необходимо было знать 50 лет назад, а сейчас можно пользоваться готовыми пакетами и функциями и не погружаться в детали. Однако, это далеко не так. Равно как никто не отменял важность понимания представления методов хранения данных в памяти и их обработки в процессоре.


Далее разберем нюансы на примере функций сортировки. Сортировка и поиск используются максимально часто во всех манипуляциях с данными. Экономия нескольких миллисекунд на операции может приводить к суммарному сокращению часов расчета на значительных данных.


Является продолжением серии предыдущих публикаций.


Введение


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


Допустим, что для алгоритмической отработки необходимо подготовить тестовый датасет, содержащий три колонки:


  • case_id уникальный идентификатор кейса/прецедента;
  • record журнальная запись события в кейсе;
  • start время регистрации.

Используемые библиотеки


library(tidyverse)library(data.table)library(rTRNG)

Наиболее интересной задачей является генерация временных меток. События должны идти последовательно во времени для каждого кейса в отдельности. Сначала подготовим простую "рыбу". В частном случае мы возьмем для демонстрации малое число кейсов. В продуктиве их может быть 10^5-10^n, что определяется задачами.


Пример кода
# определим число кейсовnn <- 100# создаем первичный набор кейсовrecords <- c("first", "one and a half", "second", "third", "fourth",              "fifth", "sixth")# готовим два варианта для экспериментовdf <- tibble(case_id = 1:nn, recs = list(records)) %>%  unnest(recs)dt <- as.data.table(df)[, case_id := as.numeric(case_id)]# указание ключа приводит к физической сортировке данныхsetkey(dt, case_id)head(df, 10)

  # A tibble: 10 x 2     case_id recs                 <int> <chr>            1       1 first            2       1 one and a half   3       1 second           4       1 third            5       1 fourth           6       1 fifth            7       1 sixth            8       2 first            9       2 one and a half  10       2 second  

Теперь приступим к интересному блоку генерации временных меток. Для простоты задачи сведем ее к распределению долей в интервале [0; 1] в рамках каждого кейса. Перевод в реальный unixtimestamp оставим за пределами, это неинтересно. Варианты с явными циклами также за пределами. Времена исполнения приведены на условном компьютере, главное, что выполняется все на одном.


Создание одной временнОй метки


Вариант 1. Прямолинейный


Этот вариант предлагается в большинстве случаев. А что, все просто и понятно.


Пример кода
f1 <- function(df) {  df %>%    group_by(case_id) %>%    mutate(t_idx = sort(runif(n(), 0, 1))) %>%    ungroup()}

Получаем такие условные показатели. Наверное, неплохо. Но не забываем, что тут всего 100 кейсов.


  median `itr/sec` mem_alloc 15.38ms      63.2   284.9KB

Подумаем, что можно улучшить?


Вариант 1+1/2. Прямолинейный + быстрый генератор чисел


Есть хорошая библиотека rTRNG. На больших объемах она дает существенное ускорение, в том числе, за счет параллельной генерации. Просто проверим:


Пример кода
f1_5 <- function(df) {  df %>%    group_by(case_id) %>%    mutate(t_idx = sort(runif_trng(n(), 0, 1))) %>%    ungroup()}

  median `itr/sec` mem_alloc 29.34ms      29.5   284.9KB

На малых объемах не получили никакого выигрыша. Это все? Конечно же нет. Мы знаем, что tidyverse медленнее data.table, попробуем применить его. Но здесь мы попробуем применить первую хитрость отсортировать вектор времен по индексам, а потом его переприсвоить.


Вариант 2. Однопроходный, через индексы data.table


Пример кода
f2 <- function(dt) {  # здесь полагаемся на то, что мы заранее отсортировали уже по `case_id``  # формируем случайные числа и сортируем их по кейсам  vec <- dt[, t_idx := runif_trng(.N, 0, 1)][order(case_id, t_idx), t_idx]  # возвращаем сортированный   dt[, t_idx := vec]}

Получается вполне неплохо, ускорение раз в 15-20 и памяти требуется почти в три раза меньше.


  median `itr/sec` mem_alloc   1.69ms     554.      109KB 

Останавливаемся? А почему да?


Вариант 3. Однопроходный, через композитный индекс


На самом деле, как только мы сваливаемся в цикл, явный, или через by, мы резко просаживаемся в производительности. Попробуем сделать все за один проход. Идея следующая сделать композитный индекс, который позволил бы нам отсортировать все события одним махом. Используем трюк. Поскольку у нас внутри кейса все временные метки будут в диапазоне [0; 1], то мы можем разделить индекс на две части. Целочисленная часть будет содержать case_id, дробная часть временнУю долю. Однократная сортировка одного такого индекса сохранит принадлежность строчек case_id, при этом мы одним махом отсортируем значения внутри каждого кейса


Пример кода
f3 <- function(dt) {  # делаем трюк, формируем композитный индекс из case_id, который является монотонным, и смещением по времени  # поскольку случайные числа генерятся в диапазоне [0, 1], мы их утаскиваем в дробную часть (за запятую)  # сначала просто генерируем случайные числа от 0 до 1 для каждой записи отдельно   # и масштабируем одним вектором  dt[, t_idx := sort(case_id + runif_trng(.N, 0, 1, parallelGrain = 10000L)) - case_id]}

Запускаем и получаем выигрыш еще в 2 раза против предыдущего варианта, как по времени, так и по памяти.


  median `itr/sec` mem_alloc 826.7us    1013.     54.3KB

Вариант 3+1/2. Однопроходный, через композитный индекс, используем set


Останавливаемся? Можно и остановиться, хотя поле для сжатия еще есть. Дело в том, что при таких малых временах исполнения накладные расходы на NSE становятся весьма ощутимыми. Если использовать прямые функции, то можно получить куда лучший результат.


Пример кода
f3_5 <- function(dt) {  set(dt, j = "t_idx",       value = sort(dt$case_id + runif(nrow(dt), 0, 1)) - dt$case_id)}

Ускорение еще в 5 раз, памяти потребляем в 4 раза меньше


  median `itr/sec` mem_alloc 161.5us    5519.     16.3KB

Промежуточное подведение итогов


Соберем все вместе.


Тестируем
bench::mark(  f1(df),  f1_5(df),  f2(dt),  f3(dt),  f3_5(dt),  check = FALSE)

  expression      min   median `itr/sec` mem_alloc  <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>1 f1(df)       14.3ms  15.38ms      63.2   284.9KB2 f1_5(df)    24.43ms  29.34ms      29.5   284.9KB3 f2(dt)       1.55ms   1.69ms     554.      109KB4 f3(dt)        722us  826.7us    1013.     54.3KB5 f3_5(dt)    142.5us  161.5us    5519.     16.3KB

Путем изучения принципов работы алгоритмов и пристального взгляда на задачу первичный наивный вариант удалось бесплатно улучшить по производительности в 90 раз, а потребление памяти сократить в 18 раз. Это показатели, которые слабо достижимы горизонтальным масштабированием серверов.


Создание временнОй метки начала записи и окончания


Усложним немного задачу. Теперь для каждой записи надо сформировать время начала и время окончания ("прием у врача"). При этом все записи должны соблюдать исходный порядок следования во времени и время окончания для каждой записи должно быть не раньше времени начала.


Количество рассматриваемых сценариев сократим, оставим только наиболее интересные. И всякие варианты с явными циклами тоже даже не упоминаем.


Вариант 1. Прямолинейный


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


Пример кода
# Cоздание ЧЕТРЕХ колонок -- case_id, record, start, finish# Все как в предыдущем, только для каждого записи finish > start # и для двух последовательных записей 1, 2 в одном кейсе start_2 > finish_1 dt[, t_idx := NULL] # очистим хвосты предыдущего упражненияf1 <- function(df) {  df %>%    group_by(case_id) %>%    mutate(ts_idx = sort(runif(n(), 0, 1))) %>%    ungroup() %>%    # еще раз пройдемся генератором, используя время начала следующей записи как границу    # чтобы избежать NaN при переходе между кейсами (в случае max < min),     # принудительно выставим порог 1 в таких переходах, NA в последней строке тоже заменим на 1    mutate(tf_idx = {lead(ts_idx, default = 1) %>% if_else(. > ts_idx, ., 1)}) %>%    mutate(tf_idx = map2_dbl(ts_idx, tf_idx, ~runif(1, .x, .y)))}

В целом меньше секунды, но, очевидно, что это ОЧЕНЬ далеко от оптимальности.


  median `itr/sec` mem_alloc  28.16ms      30.7    2.06MB 

Вариант 2. Однопроходный, через композитный индекс и матрицы


Идея следующая. Нам нужно получить 2 колонки, в которых значения будут отсортированы строчка за строчкой и значение первой колонки не превышает значение второй колонки для каждой строки. Но это же матрица! Матрица это единый кусок в памяти, который сопровождается атрибутами сегментирования. Работа с ними куда быстрее классических датафреймов.


Пример кода
f2 <- function(dt){  dt[, c("ts_idx", "tf_idx") := {    # используем принцип vector recycling    x <- case_id + runif(2 * .N, 0, 1);    m <- matrix(sort(x), ncol = 2, byrow = TRUE) - case_id;    list(m[, 1], m[, 2])  }]}

В легкую сократили время и память почти в 30 раз! Да и код стал существенно проще и прямолинейнее.


  median `itr/sec` mem_alloc   1.04ms     733.    74.38KB 

Вариант 2+1/2. Однопроходный, через композитный индекс, матрицы и set


Пример кода
f2_5 <- function(dt){  x <- dt$case_id + runif(2 * nrow(dt), 0, 1)  m <- matrix(sort(x), ncol = 2, byrow = TRUE) - dt$case_id  set(dt, j = "ts_idx", value = m[, 1])  set(dt, j = "tf_idx", value = m[, 2])}

Перфекционизм в действии. Еще в 4 раза ускорили.


  median `itr/sec` mem_alloc  278.1us    2781.    57.55KB 

Промежуточное подведение итогов


Соберем все вместе.


Тестируем
bench::mark(  f1(df),  f2(dt),  f2_5(dt),  check = FALSE)

  median `itr/sec` mem_alloc  28.16ms      30.7    2.06MB   1.04ms     733.    74.38KB  278.1us    2781.    57.55KB 

Первичный наивный вариант также удалось бесплатно улучшить по производительности в 90 раз, а потребление памяти сократить в 35 раз.


Заключение


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


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


Предыдущая публикация Оценка структуры кредитного портфеля с помощью R.

Подробнее..

Как упростить доработки и поддержку хранилища данных?

08.06.2021 12:19:01 | Автор: admin

1. Адаптированная методология Anchor modeling

Архитектура ядра хранилища данных должна соответствовать описанной ниже адаптированной (не оригинальной) методологии Anchor modeling (но не Data Vault).

Тип таблицы

Примеры имени таблицы (в скобках описание)

С таблицами каких типов может быть связана

Обязательный тип поля

Примеры имени поля

Сущности (Anchor, Entity type). Обозначается квадратом

TR_Transaction (полупроводка по дебету или по кредиту), AC_Account (синтетический счет)

Связи, Атрибут сущностей

Суррогатный ключ сущности

TR_ID, AC_ID

Атрибут сущностей (Attribute). Обозначается кругом

TR_TDT_TransactionDate (дата заключения сделки)

Сущности

Суррогатный ключ сущности (является первичным ключом в течение срока действия записи)

TR_ID

Дата и время начала срока действия записи

TR_TDT_FROM

Дата и время окончания срока действия записи (не включительно)

TR_TDT_BEFORE

Атрибут сущностей

TR_TDT

Связи (Tie, Relationship). Обозначается ромбом

TR_AC_DC_Transaction_Account_DrCr (счет главной книги в полупроводке)

Сущности

Суррогатные ключи каждой связанной сущности (вместе с некоторыми атрибутами связей, обозначающими тип связи, образуют составной ключ в течение срока действия записи)

TR_ID, AC_ID

Дата и время начала срока действия записи

TR_AC_DC_FROM

Дата и время окончания срока действия записи (не включительно)

TR_AC_DC_BEFORE

Опциональный атрибут или несколько атрибутов связей

DC (дебет/кредит)

Схема данных примераСхема данных примера

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

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

В ядре хранилища данных не должны использоваться значения NULL, за исключением тех атрибутов связей, которые не входят в составной ключ (обычно это наименования, обозначения, коды, ссылки, выбранные значения, флаги). Если неизвестны начало и/или окончание срока действия записи, то должны указываться принятые условные даты (например, '0001-01-01', '-infinity', '9999-12-31', 'infinity').

Для облегчения создания полиморфных связей двухсимвольный код в именах должен совпадать с двумя последними символами в соответствующих суррогатных ключах, которыми обозначается тип сущностей или атрибут связей (см. ниже). Поэтому в нем необходимо использовать символы алфавита Crockford's base32.

Таблицы типа узел (knot) исключены из адаптированной методологии Anchor modeling. Однако типовое обозначение узла на схеме в виде квадрата с закругленными углами удобно использовать для обозначения атрибутов связей.

Набросок БД может быть сделан (в том числе, офлайн) с помощью наглядных и удобных веб-инструментов Online Modeler или Online Modeler (test version), но сгенерированный ими SQL-код непригоден для использования. Для генерации SQL-кода (включая SQL-запросы) по методологии Anchor modeling все известные компании используют самостоятельно разработанные ими инструменты на основе языка программирования Python и Microsoft Excel.

2. Суррогатные ключи в адаптированном формате ULID

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

В качестве суррогатного ключа должна использоваться адаптированная (не оригинальная) версия ULID (но не UUID), имеющая любой из двух форматов:

  • ttttttttttrrrrrrrrrrrrrrxx (пример: 01F5B023PBG3C48TSBDQQ3V9TR)

  • ttttttttttsssrrrrrrrrrrrxx (пример: 01F5B023PB00448TSBDQQ3V5TR)

где

t дата и время генерации с точностью до миллисекунды (Timestamp) (10 символов или 48 бит), UNIX-time в миллисекундах (UTC)

s счетчик от 0 до 32768, сбрасываемый каждую миллисекунду, (Sequence) (3 символа или 15 бит)

r случайное число (Randomness) (14/11 символов или 65/55 бит)

x тип сущностей (Entity type) (2 символа или 10 бит)

Должна использоваться кодировка и алфавит Crockford's base32.

Генератор ULIDов должен удовлетворять следующим требованиям:

  1. Соблюдение требуемого формата ULIDов

  2. Однократное использование каждого генерируемого ULIDа в качестве суррогатного ключа сущности

  3. Использование (достаточно производительного) криптографически стойкого генератора псевдослучайных чисел или генератора истинно случайных чисел

  4. Монотонное возрастание ULIDов в интервале менее миллисекунды (за счет инкремента случайного числа для формата без счетчика, или за счет счетчика для формата со счетчиком)

  5. Генерация ULIDов в формате (текстовый, бинарный, UUID или целочисленный), наиболее производительном для операций поиска в применяемых СУБД и носителе данных (HDD или SSD)

  6. Пиковая (в течение 5 мс) производительность генерации ULIDов должна быть выше максимальной производительности записи в применяемых СУБД и носителе данных (HDD или SSD) (например, за счет буферизации заранее вычисленных частей ULIDа)

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

3. Указание начала и окончания срока действия записи

Для сохранения историчности данных должен применяться второй тип медленно меняющегося измерения SCD2 с добавлением двух унифицированных полей (столбцов): Дата и время начала срока действия записи (имя столбца с суффиксом _FROM) и Дата и время окончания срока действия записи (не включительно) (имя столбца с суффиксом _BEFORE).

Единственным условием связи записей в таблицах, помимо суррогатного ключа, должно быть одновременное действие (valid time) связанных записей, определяемое унифицированными полями начала и окончания срока действия записи, но не датой загрузки в систему или датой создания записи (transaction time). Данные не должны храниться в форме срезов на отчетные или на текущую дату или за календарный период (например, месяц).

4. Указание даты и времени создания записи

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

Примеры имени поля: TR_TIMESTAMP, TR_TDT_TIMESTAMP, TR_AC_DC_TIMESTAMP.

5. Только внешние источники пунктов классификаторов

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

Если при загрузке свежей версии классификатора изменился (исчез, появился) пункт классификатора, то должны автоматически рассчитываться и указываться окончание срока действия прежней запаси, а также начало и окончание действия новой записи.

6. Фасетная классификация

Необходимо по возможности использовать фасетную классификацию вместо иерархической классификации.

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

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

  • признак счета активный/пассивный,

  • глава,

  • раздел,

  • счет первого порядка,

  • тип контрагента,

  • срок.

7. Теги

Если есть большое количество атрибутов с логическими значениями true и false, то эти атрибуты удобнее заменить соответствующими тегами, которые можно хранить в одном поле типа array, типа hstore или типа jsonb.

8. Полиморфные связи

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

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

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

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

9. Устранение витрин данных

Каждый отчет должен формироваться непосредственно из реплики ядра хранилища данных.

Нежелательно использовать витрины данных, так как они сводят на нет все достоинства методологии Anchor modeling. Особенно большими недостатками обладают универсальные витрины данных, предназначенные для формирования любых видов отчетности.

10. Типовые SQL-запросы и материализованные представления

Разработка SQL-запросов к базе данных, соответствующей методологии Anchor modeling, трудоемка. Поэтому для облегчения работы системных аналитиков и SQL-программистов могут быть созданы типовые SQL-запросы или материализованные представления, соединяющие сущности с их атрибутами на задаваемую дату. Но использование таких SQL-запросов и материализованных представлений может привести к усложнению БД и снижению производительности. Поэтому для рабочей системы вместо них необходимо использовать автоматическую генерацию SQL-запросов (с использованием языка программирования Python и Microsoft Excel).

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

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

11. Вынесение логики из программного кода в таблицы решений

Логику необходимо по возможности выносить из программного кода на языках программирования, SQL и различных ORM в таблицы решений. Например, в таблице решений может быть закодирован выбор дебетуемого синтетического счета в зависимости от типа операции, категории контрагента и срока погашения финансового инструмента. Таблица решений может быть реализована двумя способами:

  • таблица сущностей правил, к которой привязаны входные атрибуты и один выходной атрибут,

  • таблица связей, соединяющая входные сущности и атрибуты с выходной сущностью либо с выходным атрибутом.

Первый способ очевидно более гибкий и упорядоченный.

Подробнее..

Как мы весь интернет сканировали

20.06.2021 16:11:04 | Автор: admin

Всем привет! Меня зовут Александр и я пишу код для 2ip.ru. За добрую половину сервисов можно пинать меня, готов отбиваться. Cегодня я хочу немного рассказать про переделку одного нашего старого сервиса. Это конечно не "big data", но всё равно довольно большие объемы информации, поэтому думаю будет интересно.

Речь пойдет про Сайты на одном IP, который как вы уже догадались, позволяет узнать все домены зарегистрированные на одном IP. Довольно удобно посмотреть кто присосался к вашему серверу (да, есть и такие), ну или чужому (например shared хостинг).

Как это всегда работало? Мы ходили в Bing с большого пула адресов и парсили выдачу по специальному запросу. Да, решение так себе, но что было то было. Было, потому что бинг прикрутил гайки и мы решили всё это сделать по человечески.

Своя база

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

Есть сервер с 12 ядрами и 64 гигами памяти, а в арсенале MySQL, PHP, golang и куча всяких фреймворков. Очевидно, что благодаря горутинам можно достичь неплохих результатов. Golang быстр и требует минимум ресурсов. По базе вопросы, потянет ли это все обычный MySQL?

Пробуем.

Делаем прототип

Собирать все домены дело неблагодарное, поэтому мы купили базу доменов размером в 260 миллионов записей. Сервисов, которые предоставляют свои услуги довольно много и стоит это копейки.

Итак на моем диске CSV файл размером 5 ГБ, дело за малым, написать масс ресолвер, который будет читать строку за строкой, а на выход в STDOUT, отдавать пару "домен - IP адрес"

Вопрос только в производительности, нужно делать это очень и очень быстро, мы не можем ждать результата месяц.

Несколько часов работы и мой демон на гоу готов. Мэйн получился примерно такой:

func main() {    file, err := os.Open("domains.txt")    if err != nil {        log.Fatal(err)    }    defer file.Close()    maxGoroutines := 500    guard := make(chan struct{}, maxGoroutines)    scanner := bufio.NewScanner(file)    for scanner.Scan() {        guard <- struct{}{}        host := scanner.Text()        go func(host string) {            resolve(host)            <-guard        }(host)    }    if err := scanner.Err(); err != nil {        log.Fatal(err)    }}

Суть в том, что мы можем набрать пул в 500 горутинов и непрерывно обрабатывать большое количество данных в единицу времени, подгружая равномерно все 12 ядер сервера.

Функция resolve опущена, но кратко это обычный ресолвер IP с выдачей результата в STDOUT. Обращаемся к DNS, получаем A записи, выдаем результат.

DNS

Прогуглив немного я понял, что большие DNS особо не лимитируют количество запросов с одного IP, но кто знает. Поэтому было принято решение поднять undbound из Docker.

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

Второй вариант Google DNS, тот который четыре восьмерки, оказался гораздо быстрее. У меня были опасения по лимитам в 500 запросов в секунду но по факту их нет.

Тестируем в localhost и на проде

Нельзя сказать что на тестовом ноутбуке граббер работал быстро. 500 горутинов машина не потянула, процесс падал через несколько секунд. Зато все кардинально поменялось на боевом сервере.

1000 горутинов упали на 12 ядрах, а вот 500 практически не грузили проц и работали стабильно. Мощность получилась на уровне ~2000 доменов в секунду.

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

В конечном счёте я оставил процесс в tmux и через трое суток получил CSV размером 10 Гб. Идём дальше.

Ура! Переходим к следующему шагу.

База данных

Я создал таблицу domain_ip, в которой всего два столбца домен и IP. Оба не уникальны, на один домен может приходиться несколько IP адресов.

IP - это обычный BIGINT domain - VARCHAR 255

Индексы

Очевидно, что выборка из 260 млн записей это довольно большая работа. Поэтому без индексов не обойтись, поиск у нас по IP адресу, значит его и индексируем.

20 минут импорта на тестовой машине и я понял что это фиаско, выборка работает медленно несмотря на индексы. 260 млн записей это очень много. Переходим к плану Б.

Партиципирование

Это метод разделения больших таблиц на мелкие и в дальнейшем уже обращение по нужному адресу сразу к конкретной таблице.

Я разделил весь пул IP адресов на 20 таблиц с шагом 200 млн. Получилось примерно так:

ALTER TABLE domain_ip PARTITION BY RANGE COLUMNS (ip)  (    PARTITION p0 VALUES LESS THAN (200000000),    PARTITION p1 VALUES LESS THAN (400000000),    PARTITION p2 VALUES LESS THAN (600000000),    PARTITION p3 VALUES LESS THAN (800000000),    PARTITION p4 VALUES LESS THAN (1000000000),    PARTITION p5 VALUES LESS THAN (1200000000),    PARTITION p6 VALUES LESS THAN (1400000000),    PARTITION p7 VALUES LESS THAN (1600000000),    PARTITION p8 VALUES LESS THAN (1800000000),    PARTITION p9 VALUES LESS THAN (2000000000),    PARTITION p10 VALUES LESS THAN (2200000000),    PARTITION p11 VALUES LESS THAN (2400000000),    PARTITION p12 VALUES LESS THAN (2600000000),    PARTITION p13 VALUES LESS THAN (2800000000),    PARTITION p14 VALUES LESS THAN (3000000000),    PARTITION p15 VALUES LESS THAN (3200000000),    PARTITION p16 VALUES LESS THAN (3400000000),    PARTITION p17 VALUES LESS THAN (3600000000),    PARTITION p18 VALUES LESS THAN (3800000000),    PARTITION p19 VALUES LESS THAN (4000000000),    PARTITION p20 VALUES LESS THAN (MAXVALUE) );

И как вы поняли это сработало, иначе зачем эта статья? :)

Импорт

Кто работал с MySQL знает, что вливать большие дампы данных это довольно долгая операция. За долгие годы работы я не нашел ничего лучше, чем импорт данных из CSV. Выглядит это примерно так:

LOAD DATA INFILE '/tmp/domains.csv' IGNORE INTO TABLE domain_ipFIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'

Машина переваривает CSV размером ~10 Гб за 30 минут.

Финал

Как результат получился вот такой милый сервис. Выборка из ~300 миллионов записей происходит мгновенно на довольно скромном по нынешним меркам сервере. Оперативной памяти нужно под это всё порядка 8 Гб.

Теперь можно узнать например, что к IP 8.8.8.8 человечество прицепило 8194 домена, ну или придумайте сами ... ;-)

Спасибо за внимание.

Подробнее..

Перевод Путеводитель по базам данных в 2021г

04.06.2021 20:14:20 | Автор: admin

Данные это один из наиболее важных компонентов геопространственных технологий и, пожалуй, любой другой отрасли. К управлению данными сейчас относятся серьезно во всех отраслях, поэтому знания по этой дисциплине имеют важное значение для карьеры ИТ-специалистов. Этот цикл статей задуман как универсальное руководство, в котором мы рассмотрим тему от и до, начиная с вопроса Что такое данные? и заканчивая изучением и применением геопространственных запросов.

Основные понятия баз данных

Что такое данные?

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

Что такое база данных?

Множество записей данных, собранных вместе, образуют базу данных. Базы данных обычно создаются для того, чтобы пользователи могли обращаться к большому количеству данных и массово выполнять с ними определенные операции.База данных может хранить что угодно: представьте себе, например, блокнот вашей бабушки со всеми ее вкусными рецептами, учетную книгу ваших родителей, куда они записывают все доходы и расходы, или свою страницу в Facebook со списком всех ваших друзей. Из этих примеров видно, что все данные в базе данных относятся более-менее к одному типу.

Зачем нужна база данных?

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

Система управления базами данных (СУБД)

Итак, мы уже знаем, что данные и базы данных важны, но как осуществляется работа с базами данных в компьютерных системах? Вот тут на сцену и выходит СУБД. СУБД это программное обеспечение, предоставляющее нам способ взаимодействия с базами данных на компьютере для выполнения различных операций, таких как создание, редактирование, вставка данных и т.д. Для этого СУБД предоставляет нам соответствующие API. Редко какие программы не используют СУБД для работы с данными, хранящимися на диске.Помимо операций с данными СУБД также берет на себя резервное копирование, проверку допуска, проверку состояния базы данных и т.д. Поэтому рекомендуется всегда использовать СУБД при работе с базами данных.

Пространственные данные и база данных

Особое внимание мы уделим обработке пространственных данных, поэтому я хотел бы обсудить здесь этот тип данных. Пространственные данные несколько отличаются от остальных. Координаты необходимо сохранять в особом формате, который обычно указан в документации на веб-сайте о базе данных. Этот формат позволяет базе считывать и правильно воспринимать координаты. Если обычно для поиска данных мы используем запросы типа Получить все результаты, где возраст>15, то пространственный запрос выглядит как-то так: Получить все результаты в радиусе 10км от определенной точки.Поэтому пространственные данные необходимо хранить в надлежащем формате.

Типы баз данных

Базы данных обычно делятся на два типа: реляционные и нереляционные. Оба типа имеют свои плюсы и минусы. Было бы глупо утверждать, что один лучше другого, поскольку это будет зависеть от варианта использования. Конкретно для пространственных данных я в 99% случаев использую реляционные базы данных, и вы скоро поймете почему.

Реляционные базы данных и РСУБД

Допустим, ваш начальник просит вас создать электронную таблицу с важной информацией, включающей имена, местонахождения, адреса электронной почты, номера телефонов и должности всех сотрудников. Вы сразу же откроете таблицу Excel или Google Spreadsheets, напишете все эти названия столбцов и начнете собирать информацию.

Образец таблицы с информациейОбразец таблицы с информацией

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

Связь между двумя столбцамиСвязь между двумя столбцами

Взаимосвязи в реляционных базах данных мы подробно рассмотрим позже.

По сравнению с базами данных NoSQL, недостатком реляционных баз данных является относительно медленное получение результатов, когда количество данных стремительно увеличивается (по мнению автора статьи прим. пер.). Еще один недостаток заключается в том, что при добавлении каждой записи нужно следовать определенным правилам (типы столбцов, количество столбцов и т.д.), мы не можем просто добавить отдельный столбец только для одной записи.В реляционных базах данных используется SQL(Structured Query Language язык структурированных запросов), с помощью которого пользователи могут взаимодействовать с данными, хранящимися в таблицах. SQL стал одним из наиболее широко используемых языков для этой цели. Мы подробнее поговорим об SQL чуть позже.Вот примеры некоторых известных и часто используемых реляционных баз данных: PostgreSQL, MySQL, MSSQL и т.д. У каждой крупной компании, занимающейся реляционными базами данных, есть собственная версия SQL. В большинстве аспектов они выглядят одинаково, но иногда требуется немного изменить какой-нибудь запрос, чтобы получить те же результаты в другой базе данных (например, при переходе из PostgreSQL в MySQL).

Нереляционные базы данных (NoSQL)

Все базы данных, не являющиеся реляционными, относятся к категории нереляционных баз данных. Обычно данные хранятся в нетабличном формате, например:

  1. Пара ключ-значение

  2. Формат JSON, XML

  3. Графовый формат

Основное преимущество баз данных NoSQL состоит в том, что все строки независимы и могут иметь разные столбцы. Как показано на изображении ниже, оба пользователя относятся к одной и той же таблице Core_user, но их записи содержат разную информацию.

База данных NoSQL реального времени в Google FirebaseБаза данных NoSQL реального времени в Google Firebase

База данных NoSQL реального времени в Google Firebase

При использовании баз данных NoSQL пользователям иногда приходится прописывать собственную логику, чтобы добавить уникальный ключ к каждой записи и тем самым обеспечить доступ к записям. В большинстве стандартных баз данных NoSQL, таких как Firebase и MongoDB, для хранения данных используется формат JSON. Благодаря этому очень легко и удобно выполнять операции с данными из веб-приложений, используя JavaScript, Python, Ruby и т.д.

Рекомендации по выбору типа базы для хранения пространственных данных

Очевидно, что нам хотелось бы сохранить точку, линию, многоугольник, растры и т.д. так, чтобы это имело смысл, вместо того чтобы сохранять просто координаты. Нам нужна СУБД, которая позволяет не только сохранять данные, но и запрашивать их пространственными методами (буфер, пересечение, вычисление расстояния и т.д.). На сегодняшний день для этого лучше всего подходят реляционные базы данных, поскольку в SQL есть функции, помогающие выполнять подобные операции. Использование таких дополнительных средств, как PostGIS для PostgreSQL, открывает разработчикам возможности для написания сложных пространственных запросов. С другой стороны, NoSQL тоже работает в области геопространственных технологий: например, MongoDB предоставляет кое-какие функции для выполнения геопространственных операций. Однако реляционные базы данных все же лидируют на рынке с большим отрывом.

Работа с РСУБД

Основное внимание мы уделим РСУБД, так как именно эти системы в большинстве случаев мы будем использовать для хранения пространственных данных и работы с ними. В качестве примера мы будем использовать PostgreSQL, поскольку это самая перспективная реляционная база данных с открытым исходным кодом, а ее расширение PostGIS позволяет работать и с пространственными данными. Вы можете установить PostgreSQL, следуя инструкциям из документации. Помимо PostgreSQL рекомендуется также загрузить и установить pgAdmin. Платформа pgAdmin предоставляет веб-интерфейс для взаимодействия с базой данных. Также для этого можно загрузить и установить какое-либо другое совместимое ПО или использовать командную строку.

pgAdmin4 на MacpgAdmin4 на Mac

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

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

Создание новой базы данных для проектаСоздание новой базы данных для проекта

В инструменте запросов (Query Tool) база данных создается следующим образом:

CREATE DATABASE <database_name>

Создание таблиц. Создание таблицы требует некоторых дополнительных соображений, поскольку именно здесь нам нужно определить все столбцы и типы данных в них. Все типы данных, которые можно использовать в PostgreSQL, вы найдете здесь.

pgAdmin позволяет нам выбрать в таблице различные ключи и ограничения, например Not Null (запрет на отсутствующие значения), Primary Key (первичный ключ) и т.д. Обсудим это подробнее чуть позже.

Создание таблицы пользователейСоздание таблицы пользователей

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

CREATE TABLE <table_name> (<column_1> <datatype>,<column_2> <datatype>,.....<column_n> <datatype>PRIMARY KEY (<column>));

CRUD-операции с данными в таблицах

CRUD-операции (создание, чтение, обновление и удаление Create, Retrieve, Update, Delete) это своего рода hello world в мире СУБД. Поскольку эти операции используются наиболее часто, команды для их выполнения одинаковы во всех РСУБД. Мы будем писать и выполнять запросы в инструменте запросов в pgAdmin, который вызывается следующим образом:

Инструмент запросов (Query Tool) в pgAdminИнструмент запросов (Query Tool) в pgAdmin

1. Создание новой записи

Для добавления новой записи в таблицу используйте следующую команду:

INSERT INTO <tablename> (column1, column2, column3,...) VALUES (value1, value2, value3,...);

INSERT, INTO, VALUE являются ключевыми словами в SQL, поэтому их нельзя использовать в качестве переменных, значений и т.д. Чтобы добавить новую запись в нашу таблицу пользователей, мы напишем в инструменте запросов следующий запрос:

INSERT INTO users(name, employed, address) VALUES ('Sheldon Cooper', true, 'Pasadena');

Обратите внимание: строки всегда следует заключать в'' (одинарные кавычки), а не в"" (двойные кавычки).

2. Получение записей (всех или нескольких)

Данные, хранящиеся в базе данных, можно извлечь и отобразить на экране. При этом мы можем получить все данные или ограниченное количество записей. Код для получения данных:

select <column1, column2 ,...> from <tablename> 

Этот код извлекает весь набор данных. Если вы хотите получить только 20записей, напишите:

select <column1, column2 ,...> from <tablename> limit 20

Если вы хотите получить данные из всех столбцов, то вместо перечисления названий всех столбцов можно написать:

select * from <tablename>

Если вы хотите получить результат с определенным условием, используйте ключевое слово WHERE, как показано ниже:

select * from <tablename> where <key> = <value>

Вы можете создавать даже сложные запросы, о которых мы поговорим позже.В нашем примере мы можем получить нужные нам данные:

--Retrieving Specific columns for all usersselect name,employed from users--Retrieving all columns for all usersselect * from users--Retrieving all columns for first 3 usersselect * from users limit 3--Retrieving all columns for all users where employed = trueselect * from users where employed = true

3. Обновление записей (всех или нескольких)РСУБД позволяет нам обновить все или только некоторые записи данных, указав новые значения для столбцов.

UPDATE <tablename> SET <column1> = <value1>, <column2> = <value2> 

Если вы хотите обновить определенные строки, добавьте условия с использованием ключевого слова WHERE:

UPDATE <tablename> SET <column1> = <value1>, <column2> = <value2>WHERE <column> = <value> 

В нашем случае мы обновим таблицы с помощью следующих запросов:

-- Make all rows as  employed = trueupdate users set employed = true-- change employed = false for entries with address = 'nebraska'update users set employed = false where address = 'nebraska'
Обновление записейОбновление записей

4. Удаление записей (всех или нескольких)Удалять записи в SQL легко. Пользователь может удалить либо все строки, либо только определенные строки, добавив условие WHERE.

-- Deleting all entries Delete from <tablename> -- Deleting entries based on conditionsDelete from <tablename> where <column> = <value> 
-- Deleting all entries Delete from users-- Deleting entries based on conditionsDelete from users where employed = false
Удаление записей из таблицыУдаление записей из таблицы

CRUD-операции используются очень часто, поскольку выполняют основные функции в базе данных.


Перевод подготовлен в рамках курса Базы данных. Все желающих приглашаем на бесплатный двухдневный онлайн-интенсив Бэкапы и репликация PostgreSQL. Практика применения. Цели занятия: настроить бэкапы; восстановить информацию после сбоя. Регистрация здесь.

Подробнее..

Перевод Сеть в bitly Linux tc для минимизации издержек и забавы ради

02.06.2021 20:09:34 | Автор: admin

Представьте, что вы, например, bitly то есть очень большой сервис сокращения ссылок. И вот, вы хотите скопировать свои 150 ТБ сжатых данных с одного физического кластера на другой, новый. Чтобы сделать это, вы запускаете distcp из набора инструментов hadoop и рады тому, насколько быстро он работает. Но, несколько позже, вы уже совсем не радуетесь жалобам обычных пользователей веб-сайта и API-клиентов случаются ошибки, задерживаются ответы, а данные их дата-центра только запутывают. К старту курса о DevOps мы перевели материал о том, что делать, если вы, как и bitly, оказались в подобной ситуации.


Мы в bitly очень любим работать с данными и устройствами, а если говорить точнее, то с устройствами для передачи данных. Сегодня расскажем историю о том, как мы пытались перекачать через устройства очень и очень много данных.

Важной частью инфраструктуры bitly и основным инструментом команды Data Science и рабочей группы обслуживания операций и инфраструктуры (Ops/Infra) в течение довольно долгого времени был физический кластер hadoop набор утилит, библиотек и фреймворк для разработки и выполнения распределённых программ, работающих на кластерах из сотен и тысяч узлов. Мы уже давно вынашивали идею подключения нового кластера, копирования и объединения данных старого кластера с данными нового.

И вот, были созданы ветки, проведена вся подготовительная работа, сгенерированы серверы и запущен новый кластер. Но, прежде чем приступить к изложению истории, приведём некоторые технические детали:

  • bitly работает с огромными объёмами данных: на момент миграции кластер hadoop занимал более 150 ТБ дискового пространства сжатых потоковых данных, то есть данных, полученных в результате работы наших различных приложений. Объёмы таких данных продолжали увеличиваться в результате дополнительной обработки другими приложениями;

  • физически инфраструктура bitly располагается в центре обработки данных нашего партнёра. Она состоит из трёх физических видов шасси (приложения, хранилище и база данных), расположенных в ряд в смежных стойках. На момент написания этой статьи каждое шасси имело три физических гигабитных Ethernet-канала (каждый логически изолирован посредством организации сети VLAN) прямой канал, обратный канал и схему удалённого управления (для внеполосного управления серверными шасси). Каждое соединение после прохождения через ряд патч-панелей и коммутаторов подключается к нашим главным коммутаторам через стеклянное оптоволокно 10 Gb по звездообразной схеме сети;

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

Вернёмся к нашей истории.

Для быстрого копирования данных с одного кластера на другой мы воспользовались инструментом distcp, поставляемом в комплекте с кластером hadoop. Говоря просто, инструмент distcp выдаёт задание программному фреймворку mapreduce (используемому для параллельных вычислений над очень большими наборами данных в компьютерных кластерах) на перемещение данных из одного кластера hdfs в другой при копировании узлов в режиме "многие ко многим". Инструмент distcp сработал быстро, и это нас порадовало.

Но тут сломался сервис bitly, и это не привело в восторг команду Ops/Infra.

Пользователи веб-сайта и API-клиенты стали жаловаться на ошибки и задержки в получении ответов. Нам удалось выяснить, что причиной ошибок было получение нашим сервисом ошибок от других сервисов, что приводило к превышению времени ожидания при вызове баз данных и даже сбоям при обработке DNS-запросов внутри нашей собственной сети. Мы выяснили, что копирование данных привело к необъяснимому увеличению нагрузки на сетевые устройства, особенно на устройства, передающие трафик через физические стойки. Мы надеялись решить проблему, получив информацию от нашего партнёра из центра обработки данных, но эта информация не только не помогла, но и ещё больше нас запутала: ни одно соединение и ни одна стойка не проявляли никаких признаков насыщения, перегруженности или ошибок.

Теперь нам нужно было решать сразу две противоречивые задачи: с одной стороны, надо было продолжать миграцию hadoop, а с другой устранить неполадки и понять, в чём же кроется наша сетевая проблема.

Мы ограничили количество диспетчеров mapreduce, которые инструмент distcp использовал для копирования данных между кластерами, что позволило искусственно снизить пропускную способность при копировании и кое-как возобновить миграцию. После завершения копирования нам, наконец, удалось установить новый кластер взамен старого.

В новом кластере было больше узлов, значит, по идее, hadoop должен был работать быстрее.

Мы, кажется, осчастливили команду Data Science.

Но, к сожалению, поскольку кластер hadoop стал крупнее и быстрее, во время работы mapreduce на большее количество узлов стало передаваться большее количество данных, и это привело к непредвиденному эффекту:

Сервис bitly опять сломался, на этот раз очень серьёзно. Команда Ops/Infra была от этого не в восторге.

Первым импульсивным действием было вообще отрубить hadoop.

Но такое решение очень не понравилось команде Data Science.

Отключение кластера hadoop самое плохое из возможных решений (по последствиям может сравниться разве что с поломкой bitly), поэтому мы вернули кластер в состояние 1995 года, заставив все сетевые карты перейти на 100 Мбит/с (с 1 Гбит/с) с помощью команды ethtool -s eth1 speed 100 duplex full autoneg on. Теперь можно было спокойно подключить hadoop, но какой же медленной стала его работа!

Команда Data Science по-прежнему не выказывала признаков восторга.

И действительно, работа кластера была настолько "тормозной", что при вводе данных, выполнении запланированных заданий ETL (извлечения, преобразования и загрузки) и выдаче отчётов стали часто возникать сбои, постоянно срабатывали аварийные сигналы, будившие среди ночи членов команды Ops/Infra.

Надо ли говорить, как это не нравилось команде Ops/Infra!

Поскольку мы были лишены возможности удовлетворительно контролировать состояние сети, работа по поиску и устранению неисправностей вместе с партнёром из центра обработки данных предстояла сложная и длительная. Нужно было что-то сделать, чтобы привести hadoop в пригодное для использования состояние, и одновременно сделать так, чтобы сервис bitly перестал выходить из строя.

Сделаем ещё одно небольшое отступление:

Что нам было доступно в bitly?

  • roles.json : список серверов (app01, app02, userdb01, hadoop01 и т. д.), ролей (userdb, app, web, monitoring, hadoop_node и т.д.), а также сведения об отображении серверов на роли (app01,02 -> app, hadoop01,02 -> hadoop_node и т. д.);

  • $datacenter/jsons/* : каталог, содержащий json-файл для каждого логического сервера с атрибутами, описывающими сервер, IP-адресами, именами, информацией конфигурирования и, что наиболее важно в нашей истории, расположением стоек.;

  • Linux : Linux.

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

Но команда Ops/Infra не проявляла признаков радости.

Её не устраивал синтаксис системы контроля сетевого трафика (Traffic Control, tc) в Linux, не говоря уже о совершенно неудобочитаемой документации. После напряжённого периода работы (с многочисленными проклятиями и разбиванием о стену клавиатур) мы смогли, наконец, создать не вызывающие отторжения работающие сценарии в tc. Были открыты ветви, написаны скрипты, выполнены развёртывания, проведены эталонные тестирования, и в результате было создано несколько тестовых узлов с таким кодом:

$ tc class show dev eth1class htb 1:100 root prio 0 rate 204800Kbit ceil 204800Kbit burst 1561b    cburst 1561bclass htb 1:10 root prio 0 rate 819200Kbit ceil 819200Kbit burst 1433b     cburst 1433bclass htb 1:20 root prio 0 rate 204800Kbit ceil 204800Kbit burst 1561b     cburst 1561b$ tc filter show dev eth1filter parent 1: protocol ip pref 49128 u32 filter parent 1: protocol ip pref 49128 u32 fh 818: ht divisor 1 filter parent 1: protocol ip pref 49128 u32 fh 818::800 order 2048 key     ht 818 bkt 0 flowid 1:20     match 7f000001/ffffffff at 16filter parent 1: protocol ip pref 49129 u32 filter parent 1: protocol ip pref 49129 u32 fh 817: ht divisor 1 filter parent 1: protocol ip pref 49129 u32 fh 817::800 order 2048 key     ht 817 bkt 0 flowid 1:10     match 7f000002/ffffffff at 16filter parent 1: protocol ip pref 49130 u32 filter parent 1: protocol ip pref 49130 u32 fh 816: ht divisor 1 filter parent 1: protocol ip pref 49130 u32 fh 816::800 order 2048 key     ht 816 bkt 0 flowid 1:20     match 7f000003/ffffffff at 16<snipped>$ tc qdisc showqdisc mq 0: dev eth2 root qdisc mq 0: dev eth0 root qdisc htb 1: dev eth1 root refcnt 9 r2q 10 default 100     direct_packets_stat 24

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

class htb 1:100 root prio 0 rate 204800Kbit ceil 204800Kbit burst 1561b cburst 1561b

Каждый класс это потолок пропускной способности исходящего трафика, агрегированного по всем подписанным на этот класс фильтрам.

Каждый фильтр это конкретное правило для конкретного IP (к сожалению, каждый IP выводится в шестнадцатеричном формате), поэтому фильтр:

filter parent 1: protocol ip pref 49128 u32 filter parent 1: protocol ip pref 49128 u32 fh 818: ht divisor 1 filter parent 1: protocol ip pref 49128 u32 fh 818::800 order 2048 key     ht 818 bkt 0 flowid 1:20     match 7f000001/ffffffff at 16

можно интерпретировать как "subscribe hadoop14 to the class 1:20", где "7f000001" можно интерпретировать как IP для hadoop14, а "flowid 1:20" класс для подписки. Затем запускаем команду qdisc, формирующую более или менее активную очередь для устройства eth1. Данная очередь по умолчанию помещает любой хост, не определённый в фильтре класса, в класс 1:100:

qdisc htb 1: dev eth1 root refcnt 9 r2q 10 default 100 direct_packets_stat 24

В такой конфигурации любой хост (hadoop или другой), находящийся в одной стойке с конфигурируемым хостом, получает фильтр, назначенный классу "1:10", разрешающий скорость передачи до ~800 Мбит/с для класса в целом. Аналогичным образом для предопределённого списка ролей, считающихся "ролями приоритетных узлов", создаётся фильтр по тому же правилу "1:100". Такие узлы выполняют довольно важные задачи, например запускают сервисы hadoop namenode или jobtracker, а также наши узлы мониторинга. Любой другой хост hadoop, не находящийся в той же стойке, подключается к классу "1:20", ограниченному более консервативным классом ~200 Мбит/с.

Как было сказано выше, любой хост, не определённый в фильтре, попадает в класс по умолчанию для eth1 qdisc, то есть в класс "1:100". Как это выглядит на практике? Вот хост, подпадающий под действие правила "1:100":

[root@hadoop27 ~]# iperf -t 30 -c NONHADOOPHOST------------------------------------------------------------Client connecting to NONHADOOPHOST, TCP port 5001TCP window size: 23.2 KByte (default)------------------------------------------------------------[  3] local hadoop27 port 35897 connected with NONHADOOPHOST port 5001[ ID] Interval       Transfer     Bandwidth[  3]  0.0-30.1 sec   735 MBytes   205 Mbits/sec

Теперь при подключении к другому хосту, расположенному в той же стойке или подпадающему под правило "1:10":

[root@hadoop27 ~]# iperf -t 30 -c CABINETPEER------------------------------------------------------------Client connecting to CABINETPEER, TCP port 5001TCP window size: 23.2 KByte (default)------------------------------------------------------------[  3] local hadoop27 port 39016 connected with CABINETPEER port 5001[ ID] Interval       Transfer     Bandwidth[  3]  0.0-30.0 sec  2.86 GBytes   820 Mbits/sec

Что произойдёт при подключении к двум серверам, подпадающим под правило "1:10"?

[root@hadoop27 ~]# iperf -t 30 -c CABINETPEER1------------------------------------------------------------Client connecting to CABINETPEER1, TCP port 5001TCP window size: 23.2 KByte (default)------------------------------------------------------------[  3] local hadoop27 port 39648 connected with CABINETPEER1 port 5001[ ID] Interval       Transfer     Bandwidth[  3]  0.0-30.0 sec  1.47 GBytes   421 Mbits/sec[root@hadoop27 ~]# iperf -t 30 -c CABINETPEER2------------------------------------------------------------Client connecting to 10.241.28.160, TCP port 5001TCP window size: 23.2 KByte (default)------------------------------------------------------------[  3] local hadoop27 port 38218 connected with CABINETPEER2 port 5001[ ID] Interval       Transfer     Bandwidth[  3]  0.0-30.0 sec  1.43 GBytes   408 Mbits/sec

Трафик уменьшится вдвое? Похоже на правду. Даже лучше стало относительно проще отслеживать тренды данных, анализируя статистические данные, выводимые на наши сервисы трендов:

$ /sbin/tc -s class show dev eth1 classid 1:100class htb 1:100 root prio 0 rate 204800Kbit ceil 204800Kbit     burst 1561b cburst 1561b Sent 5876292240 bytes 41184081 pkt (dropped 0, overlimits 0 requeues 0) rate 3456bit 2pps backlog 0b 0p requeues 0 lended: 40130273 borrowed: 0 giants: 0tokens: 906 ctokens: 906

После тестирования мы проверили хосты hadoop, подняв их скорости до первоначальных 1Gb после применения ролей traffic control. После всех описанных действий кластер hadoop вновь обрёл достаточно высокую производительность.

Мы осчастливили команду Data Science.

Команда Ops/Infra смогла приступить к устранению неполадок и поиску решений, при этом спокойно спать по ночам, зная, что сервис bitly будет вести себя нормально.

Мы осчастливили и команду Ops/Infra.

Выводы:

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

  • Не загоняйте себя в трудные ситуации: изучите все нюансы среды, в которой будете работать. В данном случае нам следовало лучше понять и оценить масштабы миграции hadoop и её возможные последствия.

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

  • Linux: Linux

И последнее

Эта история хорошая иллюстрация "закона Мерфи для девопсов":

Закон Мёрфи для девопсов: "Если что-то может пойти не так, значит, что-то уже идёт не так, просто Nagios ещё не предупредил".

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

Эта статья подчёркивает, что правильная, эффективная организация инфраструктуры не менее важна, чем данные и программное обеспечение. По мере развития информационных технологий, увеличения нагрузок, специалисты DevOps, возможно, станут называться иначе, а область станет ещё более самостоятельной. Если она вам интересна, вы можете обратить внимание на наш курс о DevOps, после которого будете иметь полное представление об этой профессии и сможете работать в DevOps.

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Перевод Линейная алгебра для исследователей данных

15.06.2021 14:10:21 | Автор: admin
Иллюстрация: UCIИллюстрация: UCI

Наша [Ирвинга Капланского и Пола Халмоша] общая философия в отношении линейной алгебры такова: мы думаем в безбазисных терминах, пишем в безбазисных терминах, но когда доходит до серьезного дела, мы запираемся в офисе и вовсю считаем с помощью матриц.

Ирвинг Капланский

Для многих начинающих исследователей данных линейная алгебра становится камнем преткновения на пути к достижению мастерства в выбранной ими профессии.

kdnuggetskdnuggets

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

Произведения векторов

Для двух векторов x, y их скалярным или внутренним произведением xy

называется следующее вещественное число:

Как можно видеть, скалярное произведение является особым частным случаем произведения матриц. Также заметим, что всегда справедливо тождество

.

x^Ty = y^Tx

Для двух векторов x , y (не обязательно одной размерности) также можно определить внешнее произведение xy . Это матрица, значения элементов которой определяются следующим образом: (xy) = xy, то есть

След

Следом квадратной матрицы A , обозначаемым tr(A) (или просто trA), называют сумму элементов на ее главной диагонали:

След обладает следующими свойствами:

  • Для любой матрицы A : trA = trA.

  • Для любых матриц A,B : tr(A + B) = trA + trB.

  • Для любой матрицы A и любого числа t : tr(tA) = t trA.

  • Для любых матриц A,B, таких, что их произведение AB является квадратной матрицей: trAB = trBA.

  • Для любых матриц A,B,C, таких, что их произведение ABC является квадратной матрицей: trABC = trBCA = trCAB (и так далее данное свойство справедливо для любого числа матриц).

TimoElliottTimoElliott

Нормы

Норму x вектора x можно неформально определить как меру длины вектора. Например, часто используется евклидова норма, или норма l:

Заметим, что x=xx.

Более формальное определение таково: нормой называется любая функция f : n , удовлетворяющая четырем условиям:

  1. Для всех векторов x : f(x) 0 (неотрицательность).

  2. f(x) = 0 тогда и только тогда, когда x = 0 (положительная определенность).

  3. Для любых вектора x и числа t : f(tx) = |t|f(x) (однородность).

  4. Для любых векторов x, y : f(x + y) f(x) + f(y) (неравенство треугольника)

Другими примерами норм являются норма l

и норма l

Все три представленные выше нормы являются примерами норм семейства lp, параметризуемых вещественным числом p 1 и определяемых как

Нормы также могут быть определены для матриц, например норма Фробениуса:

Линейная независимость и ранг

Множество векторов {x,x,...,x} называют линейно независимым, если никакой из этих векторов не может быть представлен в виде линейной комбинации других векторов этого множества. Если же такое представление какого-либо из векторов множества возможно, эти векторы называют линейно зависимыми. То есть, если выполняется равенство

для некоторых скалярных значений ,, - , то мы говорим, что векторы x,...,x линейно зависимы; в противном случае они линейно независимы. Например, векторы

линейно зависимы, так как x = 2x + x.

Столбцовым рангом матрицы A называют число элементов в максимальном подмножестве ее столбцов, являющемся линейно независимым. Упрощая, говорят, что столбцовый ранг это число линейно независимых столбцов A. Аналогично строчным рангом матрицы является число ее строк, составляющих максимальное линейно независимое множество.

Оказывается (здесь мы не будем это доказывать), что для любой матрицы A столбцовый ранг равен строчному, поэтому оба этих числа называют просто рангом A и обозначают rank(A) или rk(A); встречаются также обозначения rang(A), rg(A) и просто r(A). Вот некоторые основные свойства ранга:

  • Для любой матрицы A : rank(A) min(m,n). Если rank(A) = min(m,n), то A называют матрицей полного ранга.

  • Для любой матрицы A : rank(A) = rank(A).

  • Для любых матриц A , B np: rank(AB) min(rank(A),rank(B)).

  • Для любых матриц A,B : rank(A + B) rank(A) + rank(B).

Ортогональные матрицы

Два вектора x, y называются ортогональными, если xy = 0. Вектор x называется нормированным, если ||x|| = 1. Квадратная м

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

Непосредственно из определений ортогональности и нормированности следует, что

Другими словами, результатом транспонирования ортогональной матрицы является матрица, обратная исходной. Заметим, что если U не является квадратной матрицей (U , n < m), но ее столбцы являются ортонормированными, то UU = I, но UU I. Поэтому, говоря об ортогональных матрицах, мы будем по умолчанию подразумевать квадратные матрицы.

Еще одно удобное свойство ортогональных матриц состоит в том, что умножение вектора на ортогональную матрицу не меняет его евклидову норму, то есть

для любых вектора x и ортогональной матрицы U .

TimoElliottTimoElliott

Область значений и нуль-пространство матрицы

Линейной оболочкой множества векторов {x,x,...,x} является множество всех векторов, которые могут быть представлены в виде линейной комбинации векторов {x,...,x}, то есть

Областью значений R(A) (или пространством столбцов) матрицы A называется линейная оболочка ее столбцов. Другими словами,

Нуль-пространством, или ядром матрицы A (обозначаемым N(A) или ker A), называют множество всех векторов, которые при умножении на A обращаются в нуль, то есть

Квадратичные формы и положительно полуопределенные матрицы

Для квадратной матрицы A и вектора x квадратичной формой называется скалярное значение x Ax. Распишем это выражение подробно:

Заметим, что

  • Симметричная матрица A называется положительно определенной, если для всех ненулевых векторов x справедливо неравенство xAx > 0. Обычно это обозначается как

    (или просто A > 0), а множество всех положительно определенных матриц часто обозначают

    .

  • Симметричная матрица A называется положительно полуопределенной, если для всех векторов справедливо неравенство x Ax 0. Это записывается как

    (или просто A 0), а множество всех положительно полуопределенных матриц часто обозначают

    .

  • Аналогично симметричная матрица A называется отрицательно определенной

  • , если для всех ненулевых векторов x справедливо неравенство xAx < 0.

  • Далее, симметричная матрица A называется отрицательно полуопределенной (

    ), если для всех ненулевых векторов x справедливо неравенство xAx 0.

  • Наконец, симметричная матрица A называется неопределенной, если она не является ни положительно полуопределенной, ни отрицательно полуопределенной, то есть если существуют векторы x, x такие, что

    и

    .

Собственные значения и собственные векторы

Для квадратной матрицы A комплексное значение и вектор x будут соответственно являться собственным значением и собственным вектором, если выполняется равенство

На интуитивном уровне это определение означает, что при умножении на матрицу A вектор x сохраняет направление, но масштабируется с коэффициентом . Заметим, что для любого собственного вектора x и скалярного значения с справедливо равенство A(cx) = cAx = cx = (cx). Таким образом, cx тоже является собственным вектором. Поэтому, говоря о собственном векторе, соответствующем собственному значению , мы обычно имеем в виду нормализованный вектор с длиной 1 (при таком определении все равно сохраняется некоторая неоднозначность, так как собственными векторами будут как x, так и x, но тут уж ничего не поделаешь).


Перевод статьи был подготовлен в преддверии старта курса "Математика для Data Science". Также приглашаем всех желающих посетить бесплатный демоурок, в рамках которого рассмотрим понятие линейного пространства на примерах, поговорим о линейных отображениях, их роли в анализе данных и порешаем задачи.


Подробнее..

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

08.06.2021 18:13:14 | Автор: admin

Искусственный интеллект давно стал частью медицины. Его используют для сбора и обработки данных о пациентах, для регулярного наблюдения за состоянием их здоровья, для постановки диагнозов. Но перед современными технологиями стоит ещё более амбициозная задача побороть смерть.

О том, как искусственный интеллект помогает улучшить качество медицинского обслуживания, повысить градус эмпатии врачей и даже сделать человека бессмертным, рассказывает Антон Меркулов, сооснователь венчурной студии Лаборатория Долголетия.

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

Искусственный интеллект (ИИ) применяется во многих отраслях медицины и кажется, что его преимущества по сравнению с человеком очевидны. Но давайте разберёмся, так ли это.

В книге 0,05. Доказательная медицина от магии до поисков бессмертия автор Пётр Талантов описывает исследование, которое проводилось в США в 2004 году. Согласно этому исследованию, абстрактному врачу для беглого прочтения материалов обо всех последних исследованиях нужно 29 часов в сутки минус выходные, но с учётом времени на лечение пациентов, сон и еду. Это в принципе неразрешимая задача для врача работать и одновременно обновлять информацию с такой скоростью, держать у себя в голове все новые исследования и разработки. А вот ИИ с этим может справиться легко.

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

Согласно прогнозу McKinsey, к 2030 году с помощью ИИ будет автоматизировано 15% рабочего времени специалистов в сфере здравоохранения.

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

Подтверждение этому мы видели в 2020 году во время борьбы с пандемией. Например, ИИ использовался для анализа рентгеновских снимков, помогая быстрее выявлять ранние признаки пневмонии у пациентов с COVID-19. Также при помощи ИИ работали интерактивные голосовые помощники, чатботы и другие системы отбора и мониторинга пациентов, которые помогали определять, действительно ли человек болен COVID-19, и которые выявляли людей с температурой даже в толпе. Всё это позволило снизить нагрузку на врачей и количество потенциально опасных взаимодействий между пациентами.

Евгений Ковалёв, врач-психиатр, эксперт превентивной медицины и научный редактор первого в России переводного издания книги Биохакинг. Руководство по раскрытию потенциала организма

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

Например, сейчас, в эпоху пандемии, мы воочию видим ту революцию, которую сделал ИИ, в частности я говорю про автоматическую систему обработки изображений с рентгенологией. Огромное количество рентгеновских изображений анализируются ИИ и потом уже верифицируются врачом-рентгенологом, который может находиться за сотни километров, а не в соседнем кабинете, как мы привыкли. Часто рентгеновские снимки компьютерного томографа, МРТ и энцефалограммы пациентов из США расшифровываются в Индии с помощью ИИ.

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

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

Журнал Time в статье Google против смерти (Google vs. Death) ещё в 2013 году написал, что медицина постепенно превращается в информационную науку, когда ключевую роль играет объём данных и умение быстро и качественно их обрабатывать. Поэтому становится понятным, почему в игру включаются крупные технологические компании.

Из последних примеров: в апреле 2021 года Microsoft приобрела компанию Nuance Communications, которая предлагает программное обеспечение по переводу речи в текст и которая прочно закрепилась в сфере здравоохранения. Стоимость сделки составила $19,7 млрд значительная сумма даже для такого ИТ-гиганта, как Microsoft.

Существенную роль во внедрении искусственного интеллекта в сферу здравоохранения продолжает играть частный сектор: инвестиции венчурного капитала в проекты, связанные со здравоохранением, достигают $8,5 млрд. По прогнозам Research and Markets, к 2027 году объём мирового рынка ИИ в здравоохранении достигнет $51,3 млрд. Для сравнения: в 2016 году он составлял $1,1 млрд. Всё это свидетельствует о зарождающейся экосистеме ИИ в медицине.

Мнения экспертов: исчезнут ли рабочие места из-за автоматизации

(источник)

Эйлин Хаггерти, старший директор по корпоративному бизнесу компании Netscout:

Автоматизация в здравоохранении уже значительно влияет на качество медицинской помощи дальнейшая цифровая трансформация неизбежна.

Среди примеров:

  • умные кровати, которые отслеживают статистику состояния здоровья пациента и отправляют её медсестрам;

  • робототехника, которая помогает хирургам в операционной;

  • носимые устройства для людей с хроническими заболеваниями такими, как диабет или гипертония, которые напрямую связаны с медицинскими центрами для оказания своевременной помощи;

  • роботизированные тележки, которые доставляют еду, хирургическое оборудование и расходные материалы на нужные этажи больницы.

При этом автоматизация вовсе не означает, что медицинские работники станут лишним звеном. Врачи вместе с искусственным интеллектом работают для оптимального результата.

Дилан Макс, руководитель отдела роста и развития компании Foglogic:

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

Кейт Туленко, врач, эксперт по кадрам здравоохранения, генеральный директор Corvus Health:

Технологии в основном заменят медицинских работников, которые не имеют прямого контакта с пациентами или выполняют только рутинную работу. К ним относятся, например, работники лабораторий, специалисты по выставлению счетов и кодированию.

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

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

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

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

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

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

Рэй Курцвейл, писатель и футуролог, который работает над проектом машинного обучения Google, предсказывает, что к 2029 году человечество сможет значительно продлить жизнь или и вовсе сделать человека бессмертным. В качестве одного из примеров он указывает, что в будущем человеческий мозг будет усилен крошечными роботизированными имплантами, которые позволят отправлять электронные письма и фотографии непосредственно в мозг друг друга, а также создавать резервные копии наших мыслей и воспоминаний, что также откроет массу других возможностей.

Другой футуролог Ян Пирсон считает, что к 2050 году люди достигнут своего рода виртуального бессмертия: смогут сохранять свою личность в компьютерах, что позволит общаться с другими людьми даже после смерти.

Ещё один сторонник того, что искусственный интеллект может радикально продлить человеческую жизнь, латвийский учёный Александр Жаворонков, директор IARP (International Aging Research Portfolio; некоммерческой организации, занимающейся развитием естественных наук) и фонда исследований в сфере биогеронтологии, а также генеральный директор биоинформационной компании Insilico Medicine.

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

Евгений Ковалёв, врач-психиатр, эксперт превентивной медицины и научный редактор первого в России переводного издания книги Биохакинг. Руководство по раскрытию потенциала организма

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

На первый взгляд может показаться, что предсказать можно всё что угодно. Однако всё больше организаций проявляют интерес к ИИ как к способу продления жизни, инвестируют миллионы долларов в подобные исследования и разработку технологий.

Крупнейшие технологические компании вступили в гонку за прекращение старения. В 2013 году Google запустила Calico Labs для борьбы с возрастными заболеваниями и продления человеческой жизни. Компания Apple также занимается разработками в области здравоохранения. В интервью CNBC генеральный директор компании Тим Кук в 2019 году сказал: Если в будущем вы зададитесь вопросом, какой самый большой вклад в развитие человечества внесла компания Apple, ответ будет связан со здоровьем.

Джош Боканегра, генеральный директор австралийского стартапа Humai, верит, что в ближайшие 30 лет человечество придёт к тому, что сможет замораживать мозг человека, создавать новое искусственное тело, восстанавливать любые повреждения мозга и переносить его в новое тело. И этот процесс можно будет повторять бесконечно.

Компания Humai занимается тем, что использует искусственный интеллект и нанотехнологии для сбора и хранения данных о поведенческих паттернах человека, его уникальных мыслительных процессах и информации о том, как функционирует его тело изнутри. Это позволит сохранить идентичность личности, скопировать её и перенести в новое искусственное тело.

Одним из способов продления человеческой жизни исследователи считают создание цифровой копии жизни

Так, Национальный научный фонд, независимое агентство при правительстве США, которое отвечает за развитие науки и технологий, выделил около полумиллиона долларов университетам Центрального Орландо и Иллинойса в Чикаго для поддержки исследователей, которые изучают, как искусственный интеллект, компьютерная визуализация и архивирование данных помогут создавать дубликаты реальных людей.

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

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

С помощью ИИ стартап StoryFile создаёт видеоботов 3D-прототип человека, который похож на него не только внешне, но и манерой общения. Видеобот может общаться с родственниками и друзьями человека даже после его смерти. Правда, использование подобных технологий вызывает много этических вопросов, ответы на которые мы найдём со временем.

Амбассадором проекта стал 90-летний актёр Уильям Шетнер, звезда сериала Звёздный путь. Чтобы создать его видеобота, команда StoryFile записывала ответы актёра на самые разные вопросы в течение 45 часов на протяжении пяти дней. Использовали специальную 3D-камеру, с помощью которой впоследствии можно будет создать голограмму Шетнера, а большой набор его реплик позволит сконструировать ответы на самые разные вопросы и поддерживать диалог.

Уильям Шетнер так прокомментировал участие в проекте: Для моих детей, детей моих детей, близких моих детей и их близких. Это мой подарок вам сквозь время.

Евгений Ковалёв, врач-психиатр, эксперт превентивной медицины и научный редактор первого в России переводного издания книги Биохакинг. Руководство по раскрытию потенциала организма

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

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

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

В 2016 году генеральный директор SpaceX и Tesla Илон Маск основал нейротехнологическую компанию Neuralink, которая разрабатывает и производит нейрокомпьютерные интерфейсы. Эти устройства имплантируются в человеческий мозг, чтобы улучшить память и усилить интеллектуальные способности людей.

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

В июле 2019 года Маск провёл первую пресс-конференцию, посвящённую Neuralink, на которой представил технологию, позволяющую считывать информацию с мозга. В её основе шесть нитей толщиной в четыре микрометра, что в разы тоньше человеческого волоса. На каждой нити закреплено несколько десятков электродов, которые вживляются в мозг специальным роботом. Их задача мониторить активность мозга и передавать данные с помощью специального чипа, расположенного за ухом. В дальнейшем компания планирует создать систему, которая позволит работать по беспроводной сети.

Чип Neuralink размером с монету позволит людям управлять технологиями с помощью разумаЧип Neuralink размером с монету позволит людям управлять технологиями с помощью разума

В апреле 2021 года Neuralink анонсировала, что специалистам компании удалось вживить чип в мозг обезьяны, это позволило ей управлять компьютерной игрой только силой мысли. Испытания на людях, по словам Маска, Neuralink планирует начать в конце 2021 года.

Макака Пейджер контролировала игру в MindPong симулятор пинг-понга, передавая сигнал с помощью вживлённых нейронных нитей

Становится всё меньше сомнений в том, что цифровые версии человека и его ментальное бессмертие это только вопрос времени

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

Развитие технологий в целом и искусственного интеллекта в частности свидетельствует о том, что амбициозные идеи, высказанные нынешними исследователями и учёными, могут стать частью нашего будущего.

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


Если вас интересует обучение по направлению Data Science, посмотрите программы Нетологии:

  • Курс Старт в аналитике напишете первый код на языке Python, создадите интерактивный отчёт в Power BI и дашборд в Google Data Studio.

  • Курс Машинное обучение построите полносвязную нейросеть, создадите чатбота для поиска авиабилетов, построите классификатор изображений, создадите готовый к внедрению ML-проект.

  • Профессия Data Scientist: с нуля до middle выполните 90 домашних работ сфидбеком эксперта, а также лабораторные и тесты, получите рейтинг на Kaggle, создадите работающий проект на основе машинного обучения.

Подробнее..

Чтобы потолка не стало, а крышу не снесло о чем новый подкаст ВТБ

08.06.2021 22:04:34 | Автор: admin

Привет, Хабр! Команда ВТБ запустила серию подкастов о передовых решениях финтеха Деньги любят техно. Журналист, технологический обозреватель Марина Эфендиева будет обсуждать с экспертами банка, рынка, учеными и бизнесменами перспективы и сложности финтеха: внедрения технологий на основе Big Data, машинного обучения, искусственного интеллекта, вопросы кибербезопасности и защиты данных, перспективные технологические специальности, голосовых помощников и многое другое.

В первом выпускезаместитель президента-председателя правления ВТБ Вадим Кулик и директор Физтех-школы прикладной математики и информатики д.ф.-м.н. Андрей Райгородский обсуждают, почему банки вРоссии так любятData science, можно ли стать дата-сайнтистом за три месяцаигде учиться, чтобысоздатьуспешную карьеру. Под катом основные темы этой беседы и ссылка на сам подкаст.

Откуда взялся банковскийData Science

Тривиальный, но важный вопрос: почему именно банковский Data Science сегодня занимает передовые позиции?

По словам Вадима Кулика, сегодняшние тренды это новый этап в решении вопросов, которые стояли перед банковским сектором еще в 90-х. Тогда жесткая нехватка какой-либо информации о клиентах усложняла процесс выдачи потребительских кредитов и выход на B2C-рынок в целом.

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

Поэтому ВТБ уделяет такое внимание подходу Data Fusion, который предполагает объединение, обезличивание данных из разных источников и их обработку. По этому поводу недавно прошлабольшая конференция.

Хорошей иллюстрацией применения данного подхода может служить СП ВТБ и РостелекомаПлатформа больших данных, которое уже предоставляет рынку продукты на основе Big Data для увеличения эффективности и развития бизнеса.

Data Science за 3 месяца без SMS и регистрации

Андрей Райгородский ответил на ещё один очень важный вопрос: можно ли стать дата сайентистом за 3 месяца, как сейчас предлагают многие онлайн-платформы. Он также рассказал о том, какова сейчас потребность в этих специалистах.

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

По его словам, существуютхорошие онлайн-курсы по аналитике данных. Но стоит различать уровень квалификации, подходящий для решения некоторого ограниченного круга прикладных задач стандартными методами, и уровень, на котором строится повестка завтрашнего дня.

МФТИ (Московский физико-технический институт) лидер этого направления в России фокусируется на фундаментальном обучении и готовит кадры для будущего. При этом есть и специальные нишевые программы например,Школа глубокого обучения, которая заработала в онлайн-формате ещё до того, когда это стало ковидным мейнстримом.

Главной особенностью МФТИ можно считать взаимодействие прикладного и фундаментального. В наши дни это связка между коммерческой индустрией, которая формирует запрос, и академической наукой, которая даёт фундаментальные математические решения. Отличный пример такого симбиоза созданная в начале 2021 года лаборатория ВТБ при МФТИ.

Резюме

Современный мир устроен так, что во многих сферах а в финансовой в первую очередь умение собирать и анализировать данные становится главным фактором роста. Скорость этого роста такова, что не позволяет только сиюминутные задачи. Нужно уметь формировать повестку будущего. Как выразился Андрей Райгородский, нельзя упускать фундаментальное в гонке за количеством кадров: цель не в том, чтобы снесло крышу, а в том, чтобы потолка не стало. А что вы об этом думаете? Делитесь мнениями в комментариях.

А вот и сам подкаст:

Подробнее..

Switchback-эксперименты в Ситимобил Часть 1. Зачем это нужно

03.06.2021 20:19:56 | Автор: admin

Содержание

  1. Введение

  2. Про эксперименты

  3. Что такое сетевой эффект?

  4. Почему switchback помогает?

  5. Зачем так сложно, может, у вас нет сетевого эффекта?

  6. Убедили, как подобрать окно переключения по расстоянию и времени?

  7. Слабые стороны Switchback

  8. О следующей статье

Введение

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

Наша основная задача балансировка объёмов спроса и предложения в городе с помощью выставления определенной цены поездки. Если говорить проще, то нам необходимо подобрать такую цену, чтобы поддерживать хороший уровень сервиса, как для водителей, так и для пассажиров: водители могли не сталкиваться с большим холостым ходом и не простаивать в ожидании заказа, а пассажиры уезжать за короткое время и по приемлемым ценам. Подробнее об алгоритме и его необходимости мы уже писали, и если вы не читали, то приглашаем сюда.

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

Про эксперименты

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

До середины 2019 года чаще всего мы проводили рандомизированные A/B-тесты сосплитованием по hash (id), реже W2W (week-to-week, то есть когда производится сравнение выборок за одно время и один день недели, но в разные периоды), или diff-in-diff (подробнее см. здесь) эксперименты. Но все эти подходы для наших задач имеют ряд больших недостатков.

В W2W и diff-in-diff оценках может быть сложно обеспечить сопоставимые условия в тестовой и контрольной группах. Как-то мы хотели провести W2W-оценку, а в нашем тестовом городе на второй неделе была песчаная буря.

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

С рандомизированными A/B-тестами проблемы не такие очевидные. Когда вы запускаете рандомизированный А/В-тест в двух-трёх-n-стороннем маркетплейсе, то у вас может возникнуть сетевой эффект (не бойтесь, об этом термине поговорим в следующем разделе), который ставит под вопрос валидность теста в целом.

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

Что такое сетевой эффект?

Главное условие валидности А/В-теста stable unit treatment value assumption (SUTVA), которое говорит, что измененные условия воздействуют только на группу, к которой они были применены, и не воздействуют на пользователей из других групп.

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

Слишком сложная схема, давайте на примере:

Пусть Миша с Колей живут в соседних домах напротив друг друга и каждое утро примерно в одно время едут на такси до метро. Наша команда динамического ценообразования начала эксперимент, и так получилось, что Миша и Коля оказались в разных группах. Для Коли цена будет рассчитываться старым алгоритмом, а для Миши новым, который по каким-то причинам снизил утром на 5 % цену поездки до метро. Наступает очередное утро, и Миша с Колей заказывают такси примерно в одно время. Цена у Миши ниже обычного, и он принимает решение о заказе такси быстрее, тем самым отнимая водителя у Коли. Коля оказывается без машины, и мы вынуждены изменить для него цену, чтобы он отказался от поездки, так как свободных машин в округе больше нет. Получается, что конверсия Коли занижена из-за Миши, то есть измененные условия повлияли не только на решение Миши, но и на Колю, и SUTVA не выполняется.

Это и есть сетевой эффект. Если формулировать более научно, то:

Сетевой эффект это ситуация в экспериментах, когда поведение одного потребителя услуги или товара может влиять на характеристики или даже возможность предоставления услуги/товара для другого потребителя. Этот эффект особенно актуален для двустороннего маркетплейса, потому что предположение об отсутствии влияния (SUTVA) здесь не может быть принято.

Спасительный Switchback

SUTVA не выполняется, рандомизированный А/В-тест под угрозой. Как же нам теперь проводить честные эксперименты?

Здесь нам на помощь приходит тип эксперимента, который называется Switchback.

Switchback метод геохроносплитования контрольных и тестовых групп с гиперпараметрами в виде длительности применения группы на все наблюдения и площади применения группы.

Суть метода Switchback заключается в следующем:

  1. Имеющиеся районы разбивают на контрольные и экспериментальные группы. К экспериментальным применяется тестируемый алгоритм.

  2. Через короткий промежуток времени районы случайно изменяются (мы считаем районами группы гексагонов, используем гексагональную сетку от Uber; подробнее читайте здесь). Затем они снова меняются, и так далее. Процесс перестановки продолжается в течение всего эксперимента.

  3. Показатели за время, когда алгоритм действовал и бездействовал, считаются в разные корзины.

  4. Показатели из двух корзин сравниваются, что позволяет оценить влияние алгоритма на различные ситуации.

Теперь Миша и Коля с бОльшей вероятностью оказались бы в одной группе, так как они близко друг к другу по расстоянию и времени. Решение они принимали бы в одинаковых условиях, и SUTVA не нарушилось бы.

Почему Switchback помогает?

В какой ситуации сетевой эффект максимален? Когда пассажиры могут забирать друг у друга машины, то есть близки друг к другу по времени и расстоянию. А теперь попробуем визуализировать сетевой эффект и посмотрим, что делает Switchback. Обозначим взаимное влияние между пассажирами через линию. Она есть, если пассажиры относятся к разным группам то есть влияют своим измененным поведением на неизменных участников; и линии нет, если пассажиры относятся к одной группе. В первом случае пользователи разбились на группы случайно, и внутри одной геозоны есть пользователи из разных групп; во втором случае вся геозона полностью относится к одной группе. Как видите, во втором случае количество взаимодействия (сиреневых линий) резко сократилось, это и есть главный эффект Switchback.

Мы даже можем оценить сокращение взаимодействия численно!

Немного математики для бесстрашных

Взаимное влияние пассажиров друг на друга

Пусть пассажир определяется вектором:

r = \begin{bmatrix} t \\ latitude \\ longitude \end{bmatrix}, \\

где

  • t время, в которое клиент зашел в приложение;

  • latitude долгота точки заказа;

  • longtitude широта точки заказа.

Тогда взаимное влияние пассажиров друг на друга interaction введем следующим образом: как будто L_2 и мы считаем расстояние между точками, только одну из координат заменили на время:

interaction = \frac{1}{\beta}, \\ \beta = \sqrt{\alpha_1^2(t_1-t_2)^2 + \alpha_2^2(\Delta d)^2} \\ \Delta d = f(lat_1, lat_2, lon_1, lon_2)Почему interaction это дробь?

Interaction обратно пропорционален расстоянию между клиентами и временем между калькуляциями, то есть чем "дальше" друг от друга клиенты по расстоянию или времени, тем меньше они влияют друг на друга.

Поэтому подходящие виды зависимостей для определения interaction могут быть следующие:

y = \frac{1}{x^{\alpha}}, \alpha \geq 1 \\ y = e^{-x}

Для определения interaction в данном примере была выбрана зависимость \frac{1}{x} так как она убывает медленнее всего, значит позволит учитывать с бОльшим весом влияние между клиентами, которые находятся друг от друга далеко по времени или расстоянию, по сравнению с другими функциями. Интуитивно, кажется, что даже "далекие" к друг другу клиенты всё равно влияют на друг друга, поэтому мы и выбрали самую медленно убывающую функцию.

Зачем нужны веса?

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

В обычных метриках, например, L_2 , мы сравниваем между собой координаты x и y , эти величины имеют одинаковый масштаб. В нашем случае мы сравниваем метры и секунды. Поэтому чтобы они вносили одинаковый вклад их необходимо привести к одному масштабу. Здесь мы поступили очень просто и посмотрели на наших реальных данных отношение среднего времени между заходами клиентов в приложение, к среднему расстоянию между ними, и получили 1:16. Это соотношение и подставим в наши \alpha_1, \alpha_2 при расчетах.

Эта метрика не существует в нуле, но на наших данных и не было таких случаев, когда числитель был нулевым. Иначе можно было бы прибавить в знаменателе 1.

Сравним, как пассажиры влияют друг на друга в рандомизированном А/В и Switchback.

Теперь поступим так же, как в примере с кругами. Если пользователи относятся к разным группам, то взаимное влияние между ними есть, и мы его считаем по формуле для interaction выше. Если к разным, то считаем, что его нет. По сути, мы проставляем веса на черные линии из картинки выше и суммируем их для некоторого промежутка времени. Стоит отметить, что также для упрощения и ускорения подсчетов мы ограничили дельту между клиентами, когда учитываем их взаимное влияние, 6 минутами и 3 км, их также получили на реальных данных.

Если такое проделать на Москве в течение одного дня и сравнить уровень взаимодействия для рандомизированного эксперимента и Switchback, то Switchback снижает сетевой эффект более чем на 70%.

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

Зачем так сложно, может, у вас нет сетевого эффекта?

Может, действительно нет, потому что мы не проверяли этого честным экспериментом (но, скорее всего, есть). В ближайшее время мы хотим оценить наличие у нас сетевого эффекта способом, предложенным вот в этой статье.

Краткая идея статьи

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

Идея следующая:

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

  • измеряем разницу между группами по статистическому тесту, предложенному авторами. Если разница статистически значима, то сетевой эффект присутствует и оценивать результаты эксперимента можно только по второму сетапу. Если разницы нет, то эффект оценивается по совокупным данным.

Убедили, как подобрать окно переключения по расстоянию и времени?

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

Сформулируем, что есть Bias, а что Margin of Error.

Разница в средних между нашими группами при семплирования назовем Bias смещение. Например, когда мы делаем АА-тест нам бы очень хотелось, чтобы разница в средних между группами А1 и А2 не было, иначе мы не сможем запустить наш тест. Имеется в виду, конечно, что не будет статистически значимой разницы.

Margin of Error (предельная погрешность выборки) - насколько наше среднее в выборке будет отличаться от среднего в генеральной совокупности. Если уйти от точных определений и сказать простыми словами, то Margin of Error показывает, насколько широким мы получим доверительный интервал для оцениваемой величины. Здесь нам бы очень хотелось, чтобы коридор для среднего был узким, и мы как можно точнее оценили наше среднее.

Теперь опустимся на практику и поговорим про параметры сплитования, и как они связаны с Bias и Margin. Для более удобных формулировок введем понятие Unit. Unit кусочек времени и пространства, который отсекается определенным промежутком времени и геозоной.

Теперь обсудим связь размера Unit'a c Bias. Когда мы уменьшаем географическую зону и промежуток переключения групп, выборка уменьшается, и мы с большей вероятностью соберем нерепрезентативные смещенные данные. Представим ситуацию, где мы хотим протестировать два алгоритма, один из которых обрабатывает заказы по мере поступления, а другой - обрабатывает сначала короткие поездки, а уже потом все остальные. Тогда при слишком быстром переключении мы можем получить ситуацию, при которой один алгоритм будет обрабатывать только короткие поездки, а другой будет пытаться исправить ситуацию после выбора другого алгоритма. При этом сделать какие-то обобщающие выводы мы не сможем, так как в данных по поездкам будет заложено смещение, которое возникло из-за слишком частой смены групп. То есть при уменьшении размера Unit'a (уменьшаем окно сплитования, например, было 20 минут стало 10, и уменьшении геозоны стали работать с более маленькими гексагонами) растет Bias.

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

 Margin \sim \sqrt{\frac{D}{n}},

где D дисперсия выборки, а n сколько Unit'ов у нас есть. При уменьшении периода переключения или работе с более мелкими геозонами растет количество Unit'ов, с которых мы собираем наблюдения. Но при этом растет и дисперсия нашей выборки маленькие Unit'ы менее похожи друг на друга и содержат больше выбросов. При увеличении сплита и, как следствие, объема данных внутри него эти выбросы сглаживаются, дисперсия снижается.

Зависимость, конечно, не однозначная, но на практике всё-таки дисперсия растёт не так быстро, как количество зон, потому что города ведут себя относительно стабильно, за исключением, каких-то особых периодов, например, дождя или вечера 31-го декабря. Поэтому в целом можно сказать, что при уменьшении размера Unit'а Margin падает. Но важно иметь ввиду, что природа этой зависимости на ваших данных может оказаться другой.

Получается вот такая сложная зависимость, с которой нам нужно как-то жить, если хотим запустить Switchback):

Как же жить с такой сложной зависимостью на практике:

Можно провести АА-тест на исторических данных и посмотреть, за какое время он сходится и какой разброс в метриках мы получаем, чтобы сделать выводы о том, насколько вас это устраивает.

CookBook для запуска первого в вашей жизни Switchback-теста такой (такие вводные работают для нас):

  • держим тест около 2 недель в зависимости от объема рынка;

  • проводим сплитование по гексагонам размером 6 (то есть по районам площадью 36 кв. км.);

  • переключение происходит раз в 20 минут.

Выглядит это примерно так:

Теперь самое время пойти и запустить с первыми вводными AA-тест в Switchback на исторических данных для своего маркетплейса!

Слабые стороны Switchback

Конечно, Switchback не безгрешен и имеет несколько особенностей, с которыми стоит быть внимательными.

Сохранение сетевого эффекта

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

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

Осторожно, вы в эксперименте

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

Бороться с этим можно такой же очисткой данных, как и в предыдущем случае.

Мощность ниже

Чистка может негативно повлиять на мощность эксперимента. Кроме этого, на мощность switchback негативно влияет и единица рандомайза пара регион+время.

Сложность экспериментов с визуальными изменениями

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

Долгосрочный эффект

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

Сходимость групп

АА-тест стоит использовать не только для подбора окна или геозоны агрегации, но даже если вы уже проводили тест на городе и точно знаете, какие периоды переключения вас устраивают. Не стоит пренебрегать АА-тестом для проверки равномерности разбиения на группы.

Почему так? На практике города часто бывают неравномерны по объёмам спроса и предложения, есть разные особые точки или области, например, большие спальные районы или точки с многочисленными офисами, которые по стечению обстоятельств могли попасть в одну из групп больше раз и сместить выборки.

Завести А/А-тест в дизайн вашего эксперимента можно двумя путями. Если вы уверены, что ваш маркетплейс стабилен во времени, то можно подержать А/А-тест перед А/В-тестом и убедиться, что разбиение на группы равномерное. Если же такой уверенности нет, то можно сразу провести А/А/В-тест. Но здесь хорошо бы проверить, что вам хватит данных, чтобы честно сравнить группы А1 и А2 между собой.

Если всё-таки ваш выбор пал на А/А/В-тест, то распределение по группам лучше держать 25 %/25 %/50 %, так в теории мощность вашего теста будет выше (по сравнению с менее сбалансированными группами), подробнее об этом можно почитать вот тут.

О следующей статье

А теперь самое важное. В этой статье мы обсудили теорию о сетевом эффекте и Switchback и почти не касались математики и практического применения описанных идей. Например, какие есть способы оценки А/В-теста, запущенного в Switchback, или какой конвейер подготовки и проверки эксперимента стоит пройти. Ответы на эти вопросы мы дадим в нашей следующей статье, которая будет уже совсем скоро!

В подготовке статьи участвовали Артём Солоухин, Ксения Мензорова, Николай Ишмаметьев. Также выражаем благодарность за помощь в подготовке статьи ребятам из expf.ru, Искандеру Мирмахмадову и Виталию Черемисинову.

Подробнее..

Стоит ли смотреть в сторону Data science?

21.06.2021 16:11:25 | Автор: admin

Очень много людей с самым разным бэкграундом, и не всегда даже техническим, в последнее время пытаются перейти в data science. И такой ажиотажный интерес - проблема для всех, кто рассматривает переквалификацию в эту сферу. Потому что рынок труда может оказаться наводнён соискателям без опыта.

С точки зрения потенциального работодателя: вы скорее возьмёте выпускника технического вуза, или человека за 40, без профильного опыта, решившего изменить свою жизнь? Ведь вузы тоже ведут активную подготовку профильных специалистов (пусть и не всегда высокого уровня). На рынке явный недостаток специалистов с профильным опытом. Но среди людей с непрофильным опытом - вероятно, больше шансов найти работу у выпускников с профильным образованием.

Написать этот пост меня натолкнуло то, что полгода назад я начал писать цикл статей о самообучении и переквалификации в data sceince. В итоге, за 5 месяцев мне написало больше сотни людей с разными вопросами по такой переквалификации. И, вероятно, многие недооценивают объем знаний, который необходимо получить для этого. В этом, наверное, виноваты и заголовки моих постов "с нуля до senior data scientist за 2 года". Как мне подсказали в комментариях к тому посту - мой начальный уровень был отнюдь не нулевой (был топовым разработчиком 1С).

Почему в data science сложно попасть

Это очень много учебы и практики

Идеальный data scientist - специалист максимально высокой квалификации, знающий, одновременно:

  • всё что должны знать "простые аналитики" (SQL+визуализация данных)

  • хороший Python программист

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

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

  • хорошие коммуникативные навыки и понимание бизнеса (невозможно эффективно обрабатывать данные из предметной области, если вы её не понимаете)

По большому счету, это несколько лет профильного (само)образования + опыт работы.

Это дорого

Даже с большим опытом работы в ИТ я потратил 8 месяцев, не работая и проедая все свои накопления, только на учебу, оставаясь без работы. Мой уровень ЗП в первый год после того как я нашёл работу, был ниже, чем до этого. Только спустя 2 года я вышел на тот же уровень дохода. И это всё было достаточно страшновато, при том что у меня были своя квартира, большая финансовая подушка, и отсутствие финансово зависимых родственников. Большая часть людей, желающих поменять свою жизнь, не могут себе позволить такую траекторию переобучения, по её финансовым ограничениям.

Аналитика - сестра Data science

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

Отличие аналитика: нет нужды хорошо знать статистику, нет нужны заниматься машинным обучением.

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

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

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

Суть решаемых задач аналитка: разобраться в данных, понять их и найти интересные закономерности, представить результаты в удобном и понятном для коллег виде (обычно, графики и презентации).
Ключевой набор навыков для подобной работы: это прирожденные "аналитические способности" + знания базовых инструментов (SQL+Excel) + инструменты визуализации данных (Tableau, PowerBI).

Можно с этим набором знаний + знания специфичные для определенных областей, уже найти большое число вакансий, с хорошими зарплатами и интересными задачами.

Знаний SQL + инструмента визуализации достаточно чтобы работать на позиции специалиста по отчетности, создавающего необходимые отчеты и графики, для принятия каждодневных решений. Такая работа, обычно, требует большей усидчивости и чуть меньше креативности.

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

Рекомендуемый набор знаний для аналитика:

  • SQL + Excel

  • Tableau / PowerBI

  • Когортный анализ (принципы)

  • Понимать парадокс симпсона, чтобы не делать ошибок, к которым он приводит

  • Нужно знать основы теории вероятностей:

    • вероятности зависимых и независимых событий, условные вероятности

    • разные статистики: среднее, медиана, мода, стандартное отклонение.

  • знать что такое АВ-тесты: понимать принципы, калькуляторы есть онлайн

  • знать основы regexp. Например, веб-аналитике он используется в инструментах типа google analytics

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

Маркетинговая/веб аналитика

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

Знания специфические для веб-маркетинга (помимо обще-аналитических):

  • Понимание принципов работы контекстной рекламы (основные метрики и схемы оплаты).

  • Знание как работают UTM метки.

  • Понимание основных принципов юнит-экономики.

  • Желательно знание основ HTML

  • Популярные инструменты: Google Analytics, Яндекс.Метрика (эти инструменты можно учить уже выйдя на первую работу)

Продуктовая аналитика

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

Data engineer - брат для Data scientist

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

Но, потенциально, дата инженер, это не урезанный дата сайентист. К инженерам предъявляется больше требований по полной автоматизации процесса, по обеспечению высокого качества данных (без пропадания их кусков), высокой скорости их подготовки и доступности, настройке систем, способных обрабатывать данные о миллионах операций, товаров и клиентов за считанные секунды/минуты.
По сути, это позиция программиста, с акцентом на технологии и инструменты, позволяющие разрабывать системы работы с данными. И вместо создания интерфейса (как у фронтенд разработчиков, или разработчиков для андройд/ iOS), или какой-то бизнес-логики (бэкенд) - их продукт это система, автоматизировано готовящая данные для анализа. И поддержание это системы для работы коллег, занимающихся анализом данных.

Набор знаний в этой сфере очень сильно варьируется. Наверное, наиболее популярные навыки выглядят так:

  • SQL

  • Python (Java, Kotlin)

  • bash

  • Docker, Kubernets

Эта сфера отлично подходит для людей, которым интересно писать системы обработки больших данных (big data) и которым менее интересно придумывать как повысить эффективность бизнеса, стараясь убедить в этом каких-то коллег.

Ищете работу, которая вам подходит

Цель этого поста - показать что есть море вариантов интересной работы.

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

Идти в дата сайенс без опыта работы в ИТ, примерно как захотеть стать нейрохирургом, без опыта работы в медицине. Разумнее получить хотя бы часть более простых смежных навыков, начать работать в этой сфере, и далее расти в ней "естествнным путём", получая релевантный опыт не только из теории, но и из регулярной практики работы.

Подробнее..

RamblerMeetupampUsermodel

18.06.2021 18:20:53 | Автор: admin

Мы долго шли к этому и вот наконец! Наш внутренний RamblerMeetup&Usermodel выходит в свет! Уже 30 июня эксперты поделятся своими кейсами в области ML и Big Data.

Митап пройдет в онлайн-формате, начало в 19:00. Обязательна предварительная регистрация на Timepad.

Ведущий и модератор:

Артём Выборнов, руководитель направления машинного обучения и анализа данных Rambler&Co

В программе:

Павел Ашихмин, инженер-разработчик Python, Rambler&Co

Тема: Spark Structured Streaming и распределенный джойн в реальном времени

Spark Structured Streaming фреймворк для распределенной обработки данных в режиме, близком к реальному времени. Его внушительный функционал позволяет строить сложные realtime-pipeline поставки данных для аналитики и машинного обучения. Павел расскажет про свой опыт построения realtime-контура обработки данных с использованием Spark Structured Streaming. Обсудим, с какими подводными камнями можно столкнуться, если использовать его вместе с Kafka и Clickhouse, и как увеличить свои шансы на надежную шину для передачи данных в реальном времени.

Роман Ананьев, NoSQL Engineer, Avito

Тема: Kafka в Multi DC реалиях

Есть много способов сделать Apache Kafka работающей в нескольких DC от создания единого широкого кластера до разных версий репликаций между разрозненными инсталляциями. Также возможно совмещать все вместе. Рассмотрим на реализованных проектах, какой из вариантов в каком случае подходит и каким образом их можно воплотить. Погрузимся в работу таких репликаторов, как Mirror Maker 2 и Uber Replicator. Поговорим о концепте Kafka Federation, который объединяет в себе разные варианты Kafka в Multi DC.

Александр Ошурков, руководитель центра компетенций ML, МКБ

Тема: Как стартовать ML-практику в финтехе

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

Свои вопросы докладчикам уже можно задавать в чате в Telegram.

Подробнее..

Перевод Как Apache Spark 3.0 увеличивает производительность ваших SQL рабочих нагрузок

01.06.2021 12:20:22 | Автор: admin

Практически в каждом секторе, работающем со сложными данными, Spark "де-факто" быстро стал средой распределенных вычислений для команд на всех этапах жизненного цикла данных и аналитики. Одна из наиболее ожидаемых функций Spark 3.0 - это новая платформа Adaptive Query Execution (AQE), устраняющая проблемы, которые возникают при многих рабочих нагрузках Spark SQL. Они были задокументированы в начале 2018 года командой специалистов Intel и Baidu. Для более глубокого изучения фреймворка можно пройти наш обновленный курс по тюнингу производительности Apache Spark (Apache Spark Performance Tuning).

Наш опыт работы с Workload XM, безусловно, подтверждает реальность и серьезность этих проблем.

AQE был впервые представлен в Spark 2.4, но в Spark 3.0 и 3.1 он стал намного более развитым. Для начала, давайте посмотрим, какие проблемы решает AQE.

Недостаток первоначальной архитектуры Catalyst

На диаграмме ниже представлен вид распределенной обработки, которая происходит, когда вы выполняете простой group-by-count запрос с использованием DataFrames.

Spark определяет подходящее количество партиций для первого этапа, но для второго этапа использует по умолчанию "магическое число" - 200.

И это плохо по трем причинам:

1. 200 вряд ли будет идеальным количеством партиций, а именно их количество является одним из критических факторов, влияющих на производительность;

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

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

Что можно сделать? Вручную установить значение этого свойства перед выполнением запроса с помощью такого оператора:

spark.conf.set(spark.sql.shuffle.partitions,2)

Но это также создает некоторые проблемы:

  • Задавать данный параметр перед каждым запросом утомительно.

  • Эти значения станут устаревшими по мере эволюции ваших данных.

  • Этот параметр будет применяться ко всем шаффлингах в вашем запросе.

Перед первым этапом в предыдущем примере известно распределение и объем данных, и Spark может предложить разумное значение для количества партиций. Однако для второго этапа эта информация еще не известна, так как цена, которую нужно заплатить за ее получение, - это выполнение фактической обработки на первом этапе: отсюда и обращение к магическому числу.

Принцип работы Adaptive Query Execution

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

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

Поэтому AQE можно определить как слой поверх Spark Catalyst, который будет изменять план Spark "на лету".

Есть недостатки? Некоторые есть, но они второстепенные:

  • Выполнение останавливается на границе каждого этапа, чтобы Spark проверил свой план, но это компенсируется увеличением производительности.

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

Адаптивное количество перемешиваемых партиций

Эта функция AQE доступна, начиная с версии Spark 2.4.

Чтобы включить ее, вам нужно установить для spark.sql.adaptive.enabled значение true, значение по умолчанию - false. Когда AQE включено, количество партиций в случайном порядке регулируется автоматически и больше не равно 200 по умолчанию или заданному вручную значению.

Вот как выглядит выполнение первого запроса TPC-DS до и после включения AQE:

Динамическая конвертация Sort Merge Joins в Broadcast Joins

AQE преобразует соединения sort-merge в broadcast хэш-соединения, если статистика времени выполнения любой из сторон соединения меньше порога broadcast хэш-соединения.

Вот как выглядят последние этапы выполнения второго запроса TPC-DS до и после включения AQE:

Динамическое объединение shuffle партиций

Если количество разделов в случайном порядке больше, чем количество групп по ключам, то много циклов ЦП теряется из-за несбалансированного распределения ключей.

Когда оба:

spark.sql.adaptive.enabled и

spark.sql.adaptive.coalescePartitions.enabled

установлены на true, Spark объединит смежные перемешанные разделы в соответствии с целевым размером, указанным в spark.sql.adaptive.advisoryPartitionSizeInBytes. Это делается, чтобы избежать слишком большого количества мелких задач.

Динамическая оптимизация обьединений с перекосом

Skew (перекос) - это камень преткновения распределенной обработки. Это может задержать обработку буквально на несколько часов:

Без оптимизации время, необходимое для выполнения объединения, будет определяться самым большим разделом.

Оптимизация skew join, таким образом, разобъет раздел A0 на подразделы, используя значение, указанное park.sql.adaptive.advisoryPartitionSizeInBytes, и присоединит каждый из них к соответствующему разделу B0 таблицы B.

Следовательно, вам необходимо предоставить AQE свое определение перекоса.

Это включает в себя два параметра:

1. spark.sql.adaptive.skewJoin.skewedPartitionFactor является относительным: партиция считается с пересом, если ее размер больше, чем этот коэффициент, умноженный на средний размер партиции, а также, если он больше, чем

2. spark.sql.adaptive.skewedPartitionThresholdInBytes, который является абсолютным: это порог, ниже которого перекос будет игнорироваться.

Динамическое сокращение разделов

Идея динамического сокращения разделов (dynamic partition pruning, DPP) - один из наиболее эффективных методов оптимизации: считываются только те данные, которые вам нужны. Если в вашем запросе есть DPP, то AQE не запускается. DPP было перенесено в Spark 2.4 для CDP.

Эта оптимизация реализована как на логическом, так и на физическом уровне.

1. На логическом уровне фильтр размера идентифицируется и распространяется через обьединение на другую часть сканирования.

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

DPP в действительности может работать с другими типами обьединений (например, SortMergeJoin), если вы отключите spark.sql.optimizer.dynamicPartitionPruning.reuseBroadcastOnly.

В этом случае Spark оценит, действительно ли фильтр DPP улучшает производительность запроса.

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

Не все запросы получают такой впечатляющий прирост производительности, но 72 из 99 запросов TPC-DS положительно влияют на DPP.

Заключение

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

Анализ статического набора данных был пересмотрен из-за потоковой передачи: команда Spark сначала создала довольно неуклюжий дизайн на основе RDD, прежде чем придумать лучшее решение с использованием DataFrames.

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

Благодаря фреймворку AQE, DPP, усиленной поддержке графических процессоров и Kubernetes перспективы увеличения производительности теперь весьма многообещающие, поэтому мы и наблюдаем повсеместный переход на Spark 3.1

Подробнее..

Симпсоны лучшее TV-шоу для изучения английских слов. Доказано Big Data

08.06.2021 20:05:53 | Автор: admin

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

Симпсоны занимают особое место среди остальных сериалов и мультиков. Мы советуем его студентам из-за разнообразной лексики из разных сфер жизни. Но наше мнение основывалось на опыте преподавателей, а не на статистике и аналитике.

И вот мы нашли материал, который полностью подтверждает нашу точку зрения с помощью аналитики big data. Френк Андраде, Python-программист и data-аналитик, проанализировал 679 серий Симпсонов с точки зрения используемой лексики. Спешим поделиться тем, что мы в нем узнали.

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

Процесс изучения новых слов: как это происходит

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

Если пытаться зубрить, толку будет мало новые слова будут стираться из памяти через несколько дней. Уже через день студент забудет половину изученных слов, а через неделю в памяти останется только 10%.

Но есть способ это использовать каждое последующее повторение информации снижает скорость забывания. И уже после шестого повторения на забывание будут тратиться недели и месяцы.

Метод интервальных повторения один из лучших способов изучать новые слова на иностранных языках. Мы используем его в приложении для изучения английской лексики EDWords.

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

Что делает Симпсонов особенными

В Симпсонах огромное количество лексики: начиная из 1000 базовых слов и до редких, которые даже примерно не входят в базовый или средний словарный запас.

В статье исследователь разделил лексику на уровни в зависимости от распространенности слов в языке.

1 уровень 1000 базовых слов.

2 уровень вторая тысяча.

3 уровень третья.

То есть, когда аналитик ссылается на 4 уровень лексики, то это слова, которые в списке самых распространенных в английском языке занимают 3001-4000 места.

Оказалось, что Симпсоны отлично подходят как для пополнения базового словарного запаса, так и для проработки слов 4 уровня. А чтобы вы понимали, насколько это крутой инструмент для продвинутого уровня 1000 наиболее распространенных лексем (уровень 1) в английском языке покрывают 81,54% словарного запаса в кино и 85,11% словарного запаса в телепрограммах.

Сравнение 86 популярных сериалов, мультсериалов и ситкомов с позиции проработки словарного запаса 4 уровня и выше. В оригинальной статье диаграмма кликабельна.

Да, в Симпсонах довольно много молодежного и американского сленга, но это общепопулярный разговорный сленг, без перегибов в профессиональные.

Если брать усредненную статистику по всем эпизодам, то 81% слов, которые встречаются в мультике, это 1 уровень. Что практически идеально совпадает с общей статистикой.

Но Симпсоны особенны тем, что многие слова уровней 3+ (и даже 5+) повторяются в эпизодах достаточно часто, чтобы гарантировать запоминание лексем в контексте. Таким не может похвастаться ни один другой сериал или шоу.

Все серии Симпсонов по сложности словарного запаса

Это главная причина, почему мы захотели поделиться найденной аналитикой. Фрэнк Андраде оценил каждую из 679 существовавших на тот момент серий Симпсонов по сложности лексики.

В оригинальной статье диаграмма также кликабельна.

Вы можете посмотреть, какие серии будут достаточно простыми для студентов с уровнем Pre-Intermediate (уровень 1), а какие смогут в полной мере понять студенты с Upper-Intermediate (1+2+3).

Большинство серий мультика без проблем поймут люди с Intermediate английским. Процент понимания лексики в таком случае будет на уровне 88-96%. Это довольно много, если учитывать, что значение многих неизвестных лексем в большинстве случаев легко угадывается из контекста.

Простые серии основаны на бытовых ситуациях и диалогах. К примеру, в серии Секреты успешного брака (сезон 5, эпизод 22) самый высокий процент лексики 1 уровня. А это значит, что ее без проблем поймут даже студенты с уровнем Pre-Intermediate. Даже больше, она может быть учебным пособием для Elementary.

Or you can take an adult education course.

Oh, and how is education supposed to make me feel smarter?

Например, пойти на курсы.

Разве я стану чувствовать себя умнее в школе?

За перевод не бить, это адаптация от 2х2. Дословно это будет так:

Или ты можешь пойти на курсы для взрослых.

Оу, и как образование поможет мне чувствовать себя умнее?

А сюжет сложных в свою очередь часто основан на специфическую узкой тематике. К примеру, Деревенщины и мётлы (сезон 21, эпизод 7). Во-первых, этот эпизод своеобразная пародия на диснеевский фильм Набалдашник и метла (Bedknobs and Broomsticks) 1971 года, который также пародирует и его устаревшую лексику. А еще там много фраз по темам ведьм, сект и самогоноварения, которые не входят даже в первые 4000 популярных слов.

That is amazing! You have the eloquence and urgency of a census worker caught in a bear trap. We's gonna invite you to all our soirees, mixers and drink-'em-ups.

Это удивительно! У тебя красноречие и безапелляционность переписчика населения, попавшего в медвежий капкан. Отныне мы будем приглашать тебя на наши суаре, сабантуи и попойки.

Исходя из аналитики, вот 10 лучших эпизодов Симпсонов с самой простой английской лексикой:

  1. S5E22: Секреты успешного брака

  2. S9E7: Две миссис Нахасапимапетилон

  3. S1E6: Стонущая Лиза

  4. S15E20: Какими мы не были

  5. S22E5: Лиза Симпсон, это не твоя жизнь

  6. S8E19: Степень школьной конфиденциальности

  7. S5E12: Барт стал известным

  8. S9E16: Мошенничество со страховкой

  9. S1E9: Жизнь на быстрой дорожке

  10. S4E14: Брат с той же планеты

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

В оригинальной статье таблица интерактивная, можно фильтровать список по отдельному слову, эпизоду или сезону.

То есть, еще до просмотра отдельной серии можно оценить лексику и посмотреть значения слов, которые в ней попадутся. Плюсов такого подхода сразу несколько:

  • Не нужно останавливать эпизод и лезть в словарь. Мульт все еще остается развлечением, а не учебным пособием.

  • Сразу можно подсмотреть написание слова и отправить его на изучение в словарь или приложение.

  • Можно оценить количество повторений если их больше шести, а само слово встречается в нескольких сериях, то, скорее всего, его не нужно будет дополнительно тренировать хватит ресурсов и самого мульта.

Интересно, что у Гомера, Мардж, Барта и Лизы лексика по возможности простая. Оно и не странно они главные герои, у них максимум экранного времени, а сериал создается для широкой аудитории.

Но это в процентном соотношении. Если же брать количественное, то самый умный персонаж Гомер. За весь сериал он сказал больше 11 000 слов уровня 4+. Неплохо, правда?

У второстепенных персонажей также есть сложные диалоги. В основном, сложная лексика часто встречается в репликах бизнесмена Бернса и директора Скиннера.

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

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

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

Онлайн-школа EnglishDom.com вдохновляем выучить английский через технологии и человеческую заботу

Только для читателей Хабра первый урок с преподавателем в интерактивном цифровом учебнике бесплатно! А при покупке занятий получите до 3 уроков в подарок!

Получи целый месяц премиум-подписки на приложение ED Words в подарок. Введи промокод june_21 на этой странице или прямо в приложении ED Words. Промокод действителен до 01.07.2021.

Наши продукты:

Подробнее..

Открытые данные в России в 2021 году

10.06.2021 10:07:14 | Автор: admin

Открытые данные в России, официально существуют уже 8 лет, 10 июня 2013 года был мой пост на хабре о принятии соответствующего закона.

Что изменилось за эти годы? Стало ли лучше или хуже? Работают ли порталы открытых данных? Публикуются ли данные?

Для тех кто интересуется состоянием открытых данных в России, я решил актуализировать цифры и собрать в виде набора фактов:

  • за 2020 год на федеральном портале открытых данных (data.gov.ru) было опубликовано 223 набора данных, за 5 месяцев 2021 года - только 2 набора данных

  • всего с 2020 года объём этих 225 наборов данных - 405 мегабайт из которых более 390 мегабайт - это данные Минкультуры России и ФНС России (и то есть подозрение что цифры завышены потому что в реестре наборов данных есть дублирующиеся записи. Скорее всего реально данных значительно меньше)

  • лишь 9 178 наборов данных из 24 002 опубликованы федеральными органами власти, остальные региональными и муниципальными

  • 10 ФОИВов не опубликовали ни одного нового набора данных с 2013 года (за 8 лет)

  • 20 ФОИВов не опубликовали ни одного нового набора данных с 2015 года (за 6 лет)

  • 42 ФОИВа не опубликовали ни одного нового набора данных с 2017 года (за 4 лет)

  • 68 ФОИВов не опубликовали ни одного нового набора данных с 2019 года (за 2 года)

  • иначе говоря в 2020 и 2021 года лишь 6 ФОИВов разместили хотя бы один новый набор данных на портале открытых данных

  • некоторые ФОИВы, при этом, кое что опубликовали на своих сайтах, но куда меньше чем раньше и чем могли бы

  • общий объём опубликованных данных на портале data.gov.ru оценить сложно, сайт не даёт статистики, API сайта очень куцое, требуется очень много запросов сделать чтобы подсчитать хоть самые приблизительные цифры, но они будут невелики.

  • параллельно этому на сайтах и FTP серверах органов власти опубликовано открытых данных, оценочно, на 20 терабайт в форме архивов. Количественно - это сотни наборов данных, качественно - это данные большого объёма.

  • безусловные лидеры по масштабам раскрытия данных - Минкультуры, ФНС России, Федеральное казначейство, Минфин России. Даже при том что тенденции там не только к раскрытию, текущие объёмы доступных данных очень велики.

  • источники наиболее крупных наборов данных:

    • Сайт ФНС России (nalog.ru)

    • Портал открытых данных Минкультуры России (opendata.mkrf.ru)

    • Портал госзакупок (zakupki.gov.ru)

    • Единый портал бюджетной системы (budget.gov.ru)

    • ФИАС (fias.nalog.ru)

  • не удалось добиться раскрытия детальной статистики по учреждениям/территориям. Например, нет муниципальной статистики по преступности, качестве образования, качестве здравоохранения.

  • в ряде субъектов федерации закрывают порталы открытых данных. Например, его закрыли в Московской области

  • в других субъектах федерации перестали публиковать новые наборы данных, это касается и портала открытых данных Москвы и десятков других субъектов федерации (чуть ли не всех)

Выводы можно сделать самостоятельно. Нельзя сказать что открытость "схлопывается", но ситуация скорее тревожная. Открытость данных обеспечивают лишь ограниченное число органов власти которые и до легализации открытых данных публиковали немало данных. А вот при сборе сведений из разного рода реестров лицензий, сведений о юр лицах, по прежнему, в 75% случаях приходится писать скрейперы, а не выгружать машиночитаемые открытые данные.

Если видите что какие-то события не упомянуты, смело добавляйте новые факты.

Подробнее..

Что нам стоит загрузить JSON в Data Platform

16.06.2021 16:13:28 | Автор: admin

Всем привет!

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

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

Схема из прошлой нашей статьи.Схема из прошлой нашей статьи.

Напомним, что в нашей компании более 350 реляционных баз данных. Естественно, не все они уникальны и многие представляют собой по сути разные экземпляры одной и той же системы, установленной во всех магазинах торговой сети, но все же зоопарк разнообразия присутствует. Поэтому без какого-либо Frameworkа, упрощающего и ускоряющего интеграцию источников в Data Platform, не обойтись.

Общая схема доставки данных из источников в ODS-слой Greenplum посредством разработанного нами frameworkа приведена ниже:

Общая схема доставки данных в ODS-слой Greenplum Общая схема доставки данных в ODS-слой Greenplum
  1. Данные из систем-источников пишутся в Kafka в AVRO-формате, обрабатываются в режиме реального времени Apache NiFi, который сохраняет их в формате parquet на S3.

  2. Затем эти файлы с сырыми данными с помощью Sparkа обрабатываются в два этапа:

    1. Compaction на данном этапе выполняется объединение для снижения количества выходных файлов с целью оптимизации записи и последующего чтения (то есть несколько более мелких файлов объединяются в несколько файлов побольше), а также производится дедубликация данных: простой distinct() и затем coalesce(). Результат сохраняется на S3. Эти файлы используются затем для parsing'а , а также являются своеобразным архивом сырых необработанных данных в формате как есть;

    2. Parsing на этой фазе производится разбор входных данных и сохранение их в плоские структуры согласно маппингу, описанному в метаданных. В общем случае из одного входного файла можно получить на выходе несколько плоских структур, которые в виде сжатых (как правило gzip) CSV-файлов сохраняются на S3.

  3. Заключительный этап загрузка данных CSV-файлов в ODS-слой хранилища: создается временная external table над данными в S3 через PXF S3 connector, после чего данные уже простым pgsql переливаются в таблицы ODS-слоя Greenplum

  4. Все это оркестрируется с помощью Airflow.

DAGи для Airflow у нас генерируются динамически на основании метаданных. Parsing файлов и разложение их в плоские структуры также производится с использованием метаданных. Это приводит к упрощению интеграции нового источника, так как, для этого необходимо всего лишь:

  • создать в ODS-слое Хранилища таблицы-приемники данных;

  • в репозитории метаданных в Git согласно принятым стандартам прописать в виде отдельных YAML-файлов:

    • общие настройки источника (такие как: расписание загрузки, входной и выходной формат файлов с данными, S3-бакет, имя сервисного пользователя, имя и email владельца для нотификации в случае сбоя загрузки и т.п.);

    • маппинг данных объектов источника на таблицы слоя ODS (при этом поддерживаются как плоские, так и вложенные структуры и массивы, а также есть возможность данные из одного объекта раскладывать в ODS-слое по нескольким таблицам). То есть описать, как необходимо сложную вложенную структуру разложить в плоские таблицы;

До недавнего времени такой подход удовлетворял текущие наши потребности, но количество и разнообразие источников данных растет. У нас стали появляться источники, которые не являются реляционными базами данных, а генерируют данные в виде потока JSON-объектов. Кроме того на горизонте уже маячила интеграция источника, который под собой имел MongoDB и поэтому будет использовать MongoDB Kafka source connector для записи данных в Kafka. Поэтому остро встала необходимость доработки нашего frameworkа для поддержки такого сценария. Хотелось, чтобы данные источника сразу попадали на S3 в формате JSON - то есть в формате "как есть", без лишнего шага конвертации в parquet посредством Apache NiFi.

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

df = spark.read.format(in_format) \               .options(**in_options) \               .load(path) \               .distinct()    new_df = df.coalesce(div)new_df.write.mode("overwrite") \             .format(out_format) \            .options(**out_options) \            .save(path)

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

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

рассматривать файлы с JSON-объектами как DataFrame с одной колонкой, содержащей весь JSON-объект.

Попробуем сделать это. Допустим, мы имеем следующий файл данных:

file1:

{productId: 1, productName: ProductName 1, tags: [tag 1, tag 2], dimensions: {length: 10, width: 12, height: 12.5}}{productId: 2, price: 10.01, tags: [tag 1, tag 2], dimensions: {length: 10, width: 12, height: 12.5}}

Обратите внимание на формат этого файла. Это файл с JSON-объектами, где 1 строка = 1 объект. Оставаясь, по сути, JSON-ом, он при этом не пройдет синтаксическую JSON-валидацию. Именно в таком виде мы сохраняем JSON-данные на S3 (есть специальная "галочка в процессоре Apache NiFi).

Прочитаем файл предлагаемым способом:

# Читаем данныеdf = spark.read \          .format("csv") \          .option("sep", "\a") \          .load("file1.json")# Схема получившегося DataFramedf.printSchema()root |-- _c0: string (nullable = true)# Сами данныеdf.show()+--------------------+|                 _c0|+--------------------+|{"productId": 1, ...||{"productId": 2, ...|+--------------------+

То есть мы тут читаем JSON как обычный CSV, указывая разделитель, который никогда заведомо не встретится в наших данных. Например, Bell character. В итоге мы получим DataFrame из одного поля, к которому можно будет также применить dicstinct() и затем coalesce(), то есть менять существующий код не потребуется. Нам остается только определить опции в зависимости от формата:

# Для parquetin_format = "parquet"in_options = {}# Для JSONin_format = "csv"in_options = {"sep": "\a"}

Ну и при сохранении этого же DataFrame обратно на S3 в зависимости от формата данных опять применяем разные опции:

df.write.mode("overwrite") \           .format(out_format) \.options(**out_options) \  .save(path)  # для JSON     out_format = "text" out_options = {"compression": "gzip"}  # для parquet   out_format = input_format out_options = {"compression": "snappy"}

Следующей точкой доработки был шаг Parsing. В принципе, ничего сложного, если бы задача при этом упиралась в одну маленькую деталь: JSON -файл, в отличии от parquet, не содержит в себе схему данных. Для разовой загрузки это не является проблемой, так как при чтении JSON-файла Spark умеет сам определять схему, и даже в случае, если файл содержит несколько JSON-объектов с немного отличающимся набором полей, корректно выполнит mergeSchema. Но для регулярного процесса мы не могли уповать на это. Банально может случиться так, что во всех записях какого-то файла с данными может не оказаться некоего поля field_1, так как, например, в источнике оно заполняется не во всех случаях. Тогда в получившемся Spark DataFrame вообще не окажется этого поля, и наш Parsing, построенный на метаданных, просто-напросто упадет с ошибкой из-за того, что не найдет прописанное в маппинге поле.

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

file1 (тот же что и в примере выше):

{productId: 1, productName: ProductName 1, tags: [tag 1, tag 2], dimensions: {length: 10, width: 12, height: 12.5}}{productId: 2, price: 10.01, tags: [tag 1, tag 2], dimensions: {length: 10, width: 12, height: 12.5}}

file2:

{productId: 3, productName: ProductName 3, dimensions: {length: 10, width: 12, height: 12.5, package: [10, 20.5, 30]}}

Теперь прочитаем Sparkом их и посмотрим данные и схемы получившихся DataFrame:

df = spark.read \          .format("json") \          .option("multiline", "false") \          .load(path)df.printSchema()df.show()

Первый файл (схема и данные):

root |-- dimensions: struct (nullable = true) |    |-- height: double (nullable = true) |    |-- length: long (nullable = true) |    |-- width: long (nullable = true) |-- price: double (nullable = true) |-- productId: long (nullable = true) |-- productName: string (nullable = true) |-- tags: array (nullable = true) |    |-- element: string (containsNull = true)+--------------+-----+---------+-------------+--------------+|    dimensions|price|productId|  productName|          tags|+--------------+-----+---------+-------------+--------------+|[12.5, 10, 12]| null|        1|ProductName 1|[tag 1, tag 2]||[12.5, 10, 12]|10.01|        2|         null|[tag 1, tag 2]|+--------------+-----+---------+-------------+--------------+

Второй файл (схема и данные):

root |-- dimensions: struct (nullable = true) |    |-- height: double (nullable = true) |    |-- length: long (nullable = true) |    |-- package: array (nullable = true) |    |    |-- element: double (containsNull = true) |    |-- width: long (nullable = true) |-- productId: long (nullable = true) |-- productName: string (nullable = true)+--------------------+---------+-------------+|          dimensions|productId|  productName|+--------------------+---------+-------------+|[12.5, 10, [10.0,...|        3|ProductName 3|+--------------------+---------+-------------+

Как видно, Spark корректно выстроил схему отдельно для каждого файла. Если в какой-либо записи не было обнаружено поля, имеющегося в другой, то в DataFrame мы видим корректное проставление null (поля price и productName для первого файла).

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

root |-- price: double (nullable = true) |-- productId: long (nullable = true) |-- productName: string (nullable = true)

а во входных данных у нас присутствуют только файлы а-ля file2, где поля price нет ни у одной записи, то Spark упадет с ошибкой, так как не найдет поля price для формирования выходного DataFrame. С parquet-файлами такой проблемы как правило не возникает, так как сам parquet-файл генерируется из AVRO, который уже содержит полную схему данных и, соответственно, эта полная схема есть и в parquet-файле.

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

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

df = spark.read \          .format("json") \          .option("multiline","false") \          .schema(df_schema) \          .load(path)

Первая мысль была использовать для хранения схемы имеющийся сервис метаданных - то есть описать схему в YAML-формате и сохранить в имеющемся репозитории. Но с учетом того, что все данные источников у нас проходят через Kafka, решили, что логично для хранения схем использовать имеющийся Kafka Schema Registry, а схему хранить в стандартном для JSON формате (другой формат, кстати говоря, Kafka Schema Registry не позволил бы хранить).

В общем, вырисовывалась следующая реализация:

  • Читаем из Kafka Schema Registry схему

  • Импортируем ее в pyspark.sql.types.StructType что-то типа такого:

# 1. получаем через Kafka Schema Registry REST API схему данных # 2. записываем ее в переменную schema и далее:df_schema = StructType.fromJson(schema)
  • Ну и с помощью полученной схемы читаем JSON-файлы

Звучит хорошо, если бы Давайте посмотрим на формат JSON-схемы, понятной Sparkу. Пусть имеем простой JSON из file2 выше. Посмотреть его схему в формате JSON можно, выполнив:

df.schema.json()  
Получившаяся схема
{    "fields":    [        {            "metadata": {},            "name": "dimensions",            "nullable": true,            "type":            {                "fields":                [                    {"metadata":{},"name":"height","nullable":true,"type":"double"},                    {"metadata":{},"name":"length","nullable":true,"type":"long"},                    {"metadata":{},"name":"width","nullable":true,"type":"long"}                ],                "type": "struct"            }        },        {            "metadata": {},            "name": "price",            "nullable": true,            "type": "double"        },        {            "metadata": {},            "name": "productId",            "nullable": true,            "type": "long"        },        {            "metadata": {},            "name": "productName",            "nullable": true,            "type": "string"        },        {            "metadata": {},            "name": "tags",            "nullable": true,            "type":            {                "containsNull": true,                "elementType": "string",                "type": "array"            }        }    ],    "type": "struct"}

Как видно, это совсем не стандартный формат JSON-схемы.

Но мы же наверняка не первые, у кого встала задача конвертировать стандартную JSON-схему в формат, понятный Sparkу - подумали мы и В принципе, не ошиблись, но несколько часов поиска упорно выводили исключительно на примеры, из серии:

как сохранить схему уже прочитанного DataFrame в JSON, затем использовать повторно

либо на репозиторий https://github.com/zalando-incubator/spark-json-schema, который нам бы подошел, если мы использовали Scala, а не pySpark

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

К счастью, у нас уже был один источник, генерирующий данные в формате JSON. Как временное решение схема его интеграции в DataPlatform была незамысловата: NiFi читал данные из Kafka, преобразовывал их в parquet, использую прибитую гвоздями в NiFi схему в формате AVRO-schema, и складывал на S3. Схема данных была действительно непростой и с кучей вложенных структур и нескольких десятков полей - неплохой тест-кейс в общем-то:

Посмотреть длинную портянку, если кому интересно :)
root |-- taskId: string (nullable = true) |-- extOrderId: string (nullable = true) |-- taskStatus: string (nullable = true) |-- taskControlStatus: string (nullable = true) |-- documentVersion: long (nullable = true) |-- buId: long (nullable = true) |-- storeId: long (nullable = true) |-- priority: string (nullable = true) |-- created: struct (nullable = true) |    |-- createdBy: string (nullable = true) |    |-- created: string (nullable = true) |-- lastUpdateInformation: struct (nullable = true) |    |-- updatedBy: string (nullable = true) |    |-- updated: string (nullable = true) |-- customerId: string (nullable = true) |-- employeeId: string (nullable = true) |-- pointOfGiveAway: struct (nullable = true) |    |-- selected: string (nullable = true) |    |-- available: array (nullable = true) |    |    |-- element: string (containsNull = true) |-- dateOfGiveAway: string (nullable = true) |-- dateOfGiveAwayEnd: string (nullable = true) |-- pickingDeadline: string (nullable = true) |-- storageLocation: string (nullable = true) |-- currentStorageLocations: array (nullable = true) |    |-- element: string (containsNull = true) |-- customerType: string (nullable = true) |-- comment: string (nullable = true) |-- totalAmount: double (nullable = true) |-- currency: string (nullable = true) |-- stockDecrease: boolean (nullable = true) |-- offline: boolean (nullable = true) |-- trackId: string (nullable = true) |-- transportationType: string (nullable = true) |-- stockRebook: boolean (nullable = true) |-- notificationStatus: string (nullable = true) |-- lines: array (nullable = true) |    |-- element: struct (containsNull = true) |    |    |-- lineId: string (nullable = true) |    |    |-- extOrderLineId: string (nullable = true) |    |    |-- productId: string (nullable = true) |    |    |-- lineStatus: string (nullable = true) |    |    |-- lineControlStatus: string (nullable = true) |    |    |-- orderedQuantity: double (nullable = true) |    |    |-- confirmedQuantity: double (nullable = true) |    |    |-- assignedQuantity: double (nullable = true) |    |    |-- pickedQuantity: double (nullable = true) |    |    |-- controlledQuantity: double (nullable = true) |    |    |-- allowedForGiveAwayQuantity: double (nullable = true) |    |    |-- givenAwayQuantity: double (nullable = true) |    |    |-- returnedQuantity: double (nullable = true) |    |    |-- sellingScheme: string (nullable = true) |    |    |-- stockSource: string (nullable = true) |    |    |-- productPrice: double (nullable = true) |    |    |-- lineAmount: double (nullable = true) |    |    |-- currency: string (nullable = true) |    |    |-- markingFlag: string (nullable = true) |    |    |-- operations: array (nullable = true) |    |    |    |-- element: struct (containsNull = true) |    |    |    |    |-- operationId: string (nullable = true) |    |    |    |    |-- type: string (nullable = true) |    |    |    |    |-- reason: string (nullable = true) |    |    |    |    |-- quantity: double (nullable = true) |    |    |    |    |-- dmCodes: array (nullable = true) |    |    |    |    |    |-- element: string (containsNull = true) |    |    |    |    |-- timeStamp: string (nullable = true) |    |    |    |    |-- updatedBy: string (nullable = true) |    |    |-- source: array (nullable = true) |    |    |    |-- element: struct (containsNull = true) |    |    |    |    |-- type: string (nullable = true) |    |    |    |    |-- items: array (nullable = true) |    |    |    |    |    |-- element: struct (containsNull = true) |    |    |    |    |    |    |-- assignedQuantity: double (nullable = true) |-- linkedObjects: array (nullable = true) |    |-- element: struct (containsNull = true) |    |    |-- objectType: string (nullable = true) |    |    |-- objectId: string (nullable = true) |    |    |-- objectStatus: string (nullable = true) |    |    |-- objectLines: array (nullable = true) |    |    |    |-- element: struct (containsNull = true) |    |    |    |    |-- objectLineId: string (nullable = true) |    |    |    |    |-- taskLineId: string (nullable = true)

Естественно, я не захотел перебивать руками захардкоженную схему, а воспользовался одним из многочисленных онлайн-конвертеров, позволяющих из Avro-схемы сделать JSON-схему. И тут меня ждал неприятный сюрприз: все перепробованные мною конвертеры на выходе использовали гораздо больше синтаксических конструкций, чем понимала первая версия конвертера. Дополнительно пришло осознание, что также как и я, наши пользователи (а для нас пользователями в данном контексте являются владельцы источников данных) с большой вероятностью могут использовать подобные конвертеры для того, чтобы получить JSON-схему, которую надо зарегистрировать в Kafka Schema Registry, из того, что у них есть.

В результате наш SparkJsonSchemaConverter был доработан появилась поддержка более сложных конструкций, таких как definitions, refs (только внутренние) и oneOf. Сам же парсер был оформлен уже в отдельный класс, который сразу собирал на основании JSON-схемы объект pyspark.sql.types.StructType

У нас почти сразу же родилась мысль, что хорошо бы было поделиться им с сообществом, так как мы в Леруа Мерлен сами активно используем продукты Open Source, созданные и поддерживаемые энтузиастами со всего мира, и хотим не просто их использовать, но и контрибьютить обратно, участвуя в разработке Open Source продуктов и поддерживая сообщество. В настоящий момент мы решаем внутренние орг.вопросы по схеме выкладывания данного конвертера в Open Source и, уверен, что в ближайшее время поделимся с сообществом этой наработкой!

В итоге благодаря написанному SparkJsonSchemaConverterу доработка шага Parsing свелась только к небольшому тюнингу чтения данных с S3: в зависимости от формата входных данных источника (получаем из сервиса метаданных) читаем файлы с S3 немного по-разному:

# Для JSONdf = spark.read.format(in_format)\            .option("multiline", "false")\            .schema(json_schema) \            .load(path)# Для parquet:df = spark.read.format(in_format)\            .load(path)

А дальше отрабатывает уже существующий код, раскрывающий все вложенные структуры согласно маппингу и сохраняющий данные DataFrameа в несколько плоских CSV-файлов.

В итоге мы смогли при относительном минимуме внесенных изменений в код текущего frameworkа добавить в него поддержку интеграции в нашу Data Platform JSON-источников данных. И результат нашей работы уже заметен:

  • Всего через месяц после внедрения доработки у нас на ПРОДе проинтегрировано 4 новых JSON-источника!

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

Подробнее..

Категории

Последние комментарии

© 2006-2021, personeltest.ru