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

Big data

Автоматическая виртуализация рендеринга произвольной вёрстки

14.01.2021 20:16:39 | Автор: admin

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

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

Тяжёлое прошлое: Огромные списки задач

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

Рекламная пауза: Богатый редактор

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

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

Альтернативная линия времени: $mol

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

mol.hyoo.ru

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

Типичный цикл разработки

Типичный цикл разработки выглядит так:

  • Написали код.

  • Проверили в тепличных условиях.

  • Пришли пользователи и всё заспамили.

  • Оптимизировали.

  • Пользователи всё не унимаются.

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

Наивный рендеринг: Скорость загрузки и Отзывчивость

Этот порочный круг приводит к таким вот последствиям:

Сейчас вы видите timeline загрузки и рендера двух с половиной тысяч комментариев. Скрипту требуется 50 секунд на формирование DOM, после чего ещё 5 секунд нужно браузеру чтобы рассчитать стили, лейаут и дерево слоёв.

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

Наивный рендеринг: Потребление памяти

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

На моем телефоне (потряхивает своим тапком) её меньше 3 гигов. И я думаю не надо объяснять откроется ли она у меня вообще. Тут мы плавно переходим к следующему риску..

Наивный рендеринг: Риск неработоспособности

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

  • Не влезли по памяти - приложение закрывается.

  • Обрыв соединения - страница обрывается.

  • Браузер может заглючить на больших объёмах.

Наивный рендеринг: Резюме

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

  • Медленная загрузка.

  • Плохая отзывчивость.

  • Высокое потребление памяти.

  • Риск неработоспособности.

Первый подопытный: Статья на Хабре

Недавно я опубликовал статью, где рассказывал как можно ускорить Хабр раз в десять, отказавшись от SSR.

Вырезаем SSR и ускоряем Хабр в 10 раз

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

https://nin-jin.github.io/habrcomment/#article=423889

Второй подопытный: Ченьжлог на GitLab

На сей раз мы разберём новый кейс - страница коммита на GitLab.

Я просто взял второй попавшийся коммит в первом попавшемся репозитории. Это всего порядка 5 тысяч строк в 100 файлах. Казалось бы - совсем не много. Однако, грузится всё довольно долго. Сначала 10 секунд ждём ответа сервера, потом ещё пол минуты любуемся мёртвыми кусками кода без подсветки синтаксиса. Короче, приходится ждать почти минуту, прежде чем приложением становится возможно пользоваться.

Перенос рендеринга HTML на сервер

Что ж, давайте откроем таймлайн и увидим там следующую картину.

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

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

Страдания Ильи Климова по GitLab-у

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

Год назад Илья Климов как раз рассказывал в своём выступлении страшные истории про работу как раз над этой страницей. Например, прикручивание спинера заняло 3 месяца работы не самого дешёвого разработчика. А сворачивание небольшого файла вешало вкладку на 10 секунд. Но это, правда, уже оптимизировали - теперь на это требуется всего лишь пара секунд!

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

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

Оптимизации вёрстки

Первое что приходит на ум - а давайте упростим вёрстку и DOM уменьшится. В качестве примера - кейс от Альфа-банка, который я разбирал в своей статье об истории $mol.

$mol: 4 года спустя

Там был компонент вывода денежных сумм, который рендерился в 8 DOM элементов вместо 3.

<div class="amount">    <h3 class="heading ...">        <span>            <span class="amount__major">1233</span>            <div class="amount__minor-container">                <span class="amount__separator">,</span>                <span class="amount__minor">43</span>            </div>            <span class="amount__currency"></span>        </span>    </h3></div>
<h3 class="amount">    <span class="amount__major">1233</span>    <span class="amount__minor">,43</span></h3>

Не смотря на высокую частоту использования он был не оптимизирован. После моей статьи над ним поработали и теперь он рендерится в 5 элементов.

Если так поработать и над остальными компонентами, думаю можно уменьшить размер DOM раза в 2. Однако

Достоинства оптимизации вёрстки

Важно понимать, что асимптотика таким образом не меняется. Допустим страница грузилась 30 секунд. Вы оптимизировали, и она сала грузиться 10 секунд. Но пользователи сгенерируют в 3 раза больше контента и страница снова грузится 30 секунд. А оптимизировать вёрстку уже не куда.

  • Кратное ускорение

  • Асимптотика не меняется

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

Прикладная оптимизация

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

  • Пагинация

  • Экспандеры

  • Бесконечный скролл

  • Виртуальный скролл

Прикладная оптимизация: Пагинация

Первое, что приходит на ум - это пагинация.

Не буду рассказывать что это такое - все и так с ней прекрасно знакомы. Поэтому сразу к достоинствам

Достоинства пагинации

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

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

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

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

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

  • Много кликать

  • Ожидание загрузки каждой страницы

  • Теряется контекст

  • Элементы скачут между страницами

  • Вероятность пропустить элемент

  • Применимо лишь для плоских списков

  • Большой элемент возвращает тормоза

  • Слепые вас ненавидят

  • Работает быстрее, чем всё скопом рендерить

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

Популярные анти паттерны: пагинация

Прикладная оптимизация: Экспандеры

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

https://nin-jin.github.io/my_gitlab/#collapse=true

Достоинства экспандеров

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

  • Очень много кликать

  • Ожидание загрузки каждой ветки

  • Если не закрывать, то снова тормоза

  • Слепые вас проклинают

  • Открывается быстро

  • Применимо не только для плоских списков

Прикладная оптимизация: Бесконечный скролл

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

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

Достоинства бесконечного скролла

  • Применимо лишь для плоских списков

  • Ожидание загрузки каждой ветки

  • Увеличение тормозов по мере прокрутки

  • Быстрое появление

Прикладная оптимизация: Виртуальный скролл

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

https://bvaughn.github.io/react-virtualized/#/components/WindowScroller

Достоинства виртуального скролла

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

  • Применимо лишь для плоских списков

  • Размеры элементов должны быть предсказуемы

  • Работает быстро

Прикладная оптимизация: Резюме

  • Ухудшение пользовательского опыта

  • Не решают проблему полностью

  • Ограниченная применимость

  • Полный контроль где какую применять

  • Нужно не забыть

  • Нужно продавить

  • Нужно реализовать

  • Нужно оттестировать

  • Нужно поддерживать

Оптимизация инструментов

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

  • Тайм слайсинг

  • Прогрессивный рендеринг

  • Ленивый рендеринг

  • Виртуальный рендеринг

Оптимизация инструментов: Тайм слайсинг

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

Квантовая механика вычислений в JS

Достоинства тайм слайсинга

Звучит вроде бы не плохо. Но тут есть такая проблема, как замедление общего времени работы всего вычисления. Например, если просто взять и выполнить вычисление без квантования занимает полсекунды, то если его постоянно прерывать каждые 16 мс, позволяя браузеру делать свои дела, то до завершения может пройти и пара секунд. Для пользователя это может выглядеть как замедление работы. Ну и другой аспект заключается в том что javascript не поддерживает файберы, то есть такие потоки исполнения, которые можно останавливать и возобновлять в любое время. Их приходится эмулировать тем или иным способом, а это всегда костыли, замедление работы и некоторые ограничения на то, как пишется код. В общем, с этим подходом всё не очень хорошо, поэтому в $mol мы и отказались от квантования.

  • Хорошая отзывчивость

  • Замедленность работы

  • Эмуляция файберов в JS

Оптимизация инструментов: Прогрессивный рендеринг

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

catberry.github.io

Достоинства прогрессивного рендеринга

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

  • Хорошая отзывчивость в процессе появления

  • Эмуляция файберов в JS

  • На больших объёмах всё встаёт колом

Оптимизация инструментов: Ленивый рендеринг

Вообще, изначально в $mol у нас был так называемый ленивый рендер. Суть его в том, что мы сначала рендерим первый экран и по мере прокрутки добавляем столько контента снизу, чтобы видимая область была гарантированно накрыта. А при прокрутке вверх, наоборот, удаляем снизу тот контент, что гарантированно на экран не попадает, чтобы минимизировать размер DOM для лучшей отзывчивости.

https://nin-jin.github.io/my_gitlab/#lazy=true

Достоинства ленивого рендеринга

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

  • Размеры элементов должны быть предсказуемы

  • Увеличение тормозов по мере прокрутки

  • Быстрое появление

Оптимизация инструментов: Виртуальный рендеринг

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

https://nin-jin.github.io/my_gitlab/

Достоинства виртуального рендеринга

  • Размеры элементов должны быть предсказуемы

  • Работает, наконец, быстро

Оптимизация инструментов: Резюме

На уровне инструментов поддержка сейчас есть лишь в полутора фреймворках: time slicing в React, прогрессивный рендер в catberry и виртуальный рендер в $mol. Зато, такую оптимизацию инструмента достатоxно реализовать один раз? и далее наслаждаться ею во всех своих приложениях не тратя дополнительное время на оптимизацию.

  • Поддерживает полтора фреймворка

  • Работает само по себе

Оптимизации: Резюме

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

Оптимизация

Стоит того?

Вёрстка

Прикладной код

Инструментарий

Виртуализация браузера

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

content-visibility: auto;contain-intrinsic-size: 1000px;

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

Логика рендеринга

Для каждого компонента нам нужно получить следующие данные.

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

Далее мы пройдёмся по этим шагам подробнее.

Оценка размеров

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

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

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

  • Последняя

  • Усреднённая

  • Минимальная

Типы компонент: Атомарный

Теперь о том как рассчитать размеры. Во первых мы можем просто напрямую задать эти размеры.

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

Типы компонент: Стек наложения

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

Соответственно мы просто берём максимальное значение минимального значения его элементов по соответствующим осям.

Типы компонент: Вертикальный список

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

Типы компонент: Горизонтальный список

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

Типы компонент: Горизонтальный список с переносами

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

Далее мы берём все компоненты все вложенные компоненты и рассчитываем их суммарную ширину. Поделив одно значение на другое, мы получаем количество строк, которые точно будут в нашем списке с переносами.

В данном примере у нас будет два переноса, а следовательно после рендеринга он расползётся не менее чем три строки.

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

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

Типы компонент: Грид и Буклет

Такие компоненты, как гриды и буклеты, - это просто композиция упомянутых ранее.

Грид - это вертикальный список из горизонтальных списков. А буклет - это горизонтальный список из вертикальных списков.

Типы компонент: Резюме

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

  • Атомарный

  • Стек наложения

  • Вертикальный список

  • Горизонтальный список

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

Отслеживание положения: onScroll

Теперь перейдем к вопросу о том, когда производить обновление DOM. Самое очевидное - это реагировать на событие scroll..

document.addEventListener( 'scroll', event => {    // few times per frame}, { capture: true } )

Достоинства отслеживания onScroll

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

  • Слишком часто

  • Изменения DOM

  • Изменения стилей

  • Изменения состояния элементов

  • Изменения состояния браузера

Отслеживание положения: IntersectionObserver

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

const observer = new IntersectionObserver(    event => {        // calls on change of visibility percentage        // doesn't call when visibility percentage doesn't changed    },    { root: document.body  })observer.observe( watched_element )

Достоинства отслеживания IntersectionObserver

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

  • Облом, если степень наложения не меняется

Отслеживание положения: requestAnimationFrame

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

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

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

function tick() {    requestAnimationFrame( tick )    for( const element of watched_elements ) {        element.getBoundingClientRect()    }    render()   }

Достоинства отслеживания requestAnimationFrame

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

  • Постоянная фоновая нагрузка

  • Просто и надёжно

Обновление: Резюме

  • onScroll

  • IntersectionObserver

  • requestAnimationFrame

Скачки при прокрутке

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

https://nin-jin.github.io/my_gitlab/#anchoring=false

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

Привязка скролла: Предотвращает скачки

Есть классический пример демонстрирующий проблему..

https://codepen.io/chriscoyier/embed/oWgENp?theme-id=dark&default-tab=result

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

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

Привязка скролла: Выбор точки привязки

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

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

Привязка скролла: Подавление привязки

Тут есть один нюанс - якорным элементом может быть только такой, для которого и для всех предков которого не запрещена привязка скролла. То есть элементы с запрещённой привязкой просто перескакиваются в поиске якорного элемента. А запрещена она может быть либо явно, через свойство overflow-anchor, либо неявно, при изменении css свойств влияющих на размеры и положение элемента.

  • overflow-anchor: none

  • top, left, right, bottom

  • margin, padding

  • Any width or height-related properties

  • transform

Виртуализация: Распорки

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

Виртуализация: Прокрутка вниз

Рассмотрим несколько сценариев работы виртуализации с привязкой скролла. Для примера, возьмём компонент вертикального списка. Изначально видны элементы 3, 4 и 5, а сверху и снизу - распорки.

Зелёная фаза - пользователь скроллит вниз. Как видно третий блок вышел из видимой области, а снизу образовалась дырка. Но пользователь это ещ1 не видит.

Синяя фаза - срабатывает обработчик requestAnimationFrame и мы обновляем DOM: удаляем третий узел и добавляем шестой. Как видно, контент уехал вверх относительно видимой области, но пользователь это ещё не видит.

Красная фаза - мы отдаём управление браузеру, а тот выбирает 4 элемент в качестве якоря и отскролливает чуть-назад. Так что пользователь видит лишь добавившийся снизу шестой элемент.

Виртуализация: Прокрутка вверх

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

Виртуализация: Расширение

Может так оказаться, что контент не достигает краёв видимой области с обоих концов.

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

Виртуализация: Превышение

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

Виртуализация: Скачок кенгуру

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

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

Привязка скролла в действии

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

https://nin-jin.github.io/my_gitlab/

Привязка скролла: Поддержка

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

Браузер

overflow-anchor

Chrome

Firefox

Safari

Привязка скролла: Запасный выход

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

const anchoring_support = CSS.supports( 'overflow-anchor:auto' )if( anchoring_support ) {    virtual render} else {    lazy render}

Проблема: Долгая раскладка

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

https://nin-jin.github.io/habrcomment/#article=423889

Минимизация расчётов лейаута

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

[mol_scroll] {    contain: content;}

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

Прокрутка в отдельном потоке

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

[mol_scroll] > * {    transform: translateZ(0);}

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

Плавная прокрутка (или нет)

Применив все оптимизации мы получаем плавную прокрутку..

https://nin-jin.github.io/habrcomment/#article=423889

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

Логика поиска

Скорость и отзывчивость - это, конечно, хорошо, но что насчёт поиска по странице? Он ведь ищет лишь по тому тексту, что есть в DOM, а мы тут рендерим лишь малую его часть. Делать нечего - надо перехватывать Ctrl+F, рисовать свой интерфейс поиска и искать самостоятельно. Для этого компоненты должны реализовывать метод, которому скармливаешь предикат, а он эмитит найденные пути от корня до компонент, соответствующих предикату.

*find_path(    check: ( view : View )=> boolean,    path = [] as View[],): Generator&lt; View[] > {    path = [ ... path, this ]    if( check( view ) ) return yield path    for( const item of this.kids ) {        yield* item.find_path( check, path )    }}
  • Рекурсивно спускаемся по компонентам.

  • Отбираем соответствующие запросу.

  • Рисуем интерфейс перехода между найденным.

Логика прокрутки к компоненту

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

scroll_to_view( view: View ) {    const path = this.find_path( v => v === view ).next().value    this.force_render( new Set( path ) )    view.dom_node.scrollIntoView()}

Логика форсирование рендеринга видимого

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

force_render( path : Set< View > ): number {    const items = this.rows    const index = items.findIndex( item => path.has( item ) )    if( index >= 0 ) {        this.visible_range = [ index, index + 1 ]        items[ index ].force_render( path )    }    return index}

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

Работающий поиск

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

https://nin-jin.github.io/habrcomment/#article=423889/search=vin

Подсветка найденного реализуется опять же на уровне компонент. Я для этого просто использую компонент $mol_dimmer, которому скармливаешь строку текста, а он сам уже заботится о поддержке поиска и подсветки найденного.

Доступность

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

https://nin-jin.github.io/my_gitlab/

Можете сами попробовать, просто включив NVDA и закрыв глаза.

Решаемые проблемы виртуализации

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

  • Оценка будущих размеров.

  • Скачки контента.

  • Тормоза при скроллинге.

  • Прокрутка к элементу.

  • Поиск по странице.

  • Доступность.

Фундаментальные особенности

Тем не менее у нас остался и ряд фундаментальных особенностей, с которыми придётся смириться..

  • Скачки скроллбара при неточной оценке размеров.

  • Scroll Anchoring может не работать в некоторых контекстах.

  • Копирование выделенного текста не работает.

Бенчмарки: Скорость открытия и Отзывчивость

Ладно, давайте погоняем бенчмарки. Понятное дело, что на огромных страницах виртуализация победит. Поэтому возьмём, что-то более типичное - небольшую мобильную страницу Хабра со 170 комментариями и откроем её на не самом слабом ноуте и жамкнем "показать 170". Таймлайн сверху показывает, что на формирование DOM через VueJS требуется три с половиной секунды, а потом ещё пол секунды требуется браузеру, чтобы всё это показать.

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

Итого: ускорение открытия не менее чем в 4 раза даже на сравнительно небольшом объёме данных.

Бенчмарки: Отзывчивость

Можем погонять и какие-нибудь синтетические бенчмарки. Например, dbmon.

https://mol.js.org/perf/dbmon/-/

Пока все реализации топчутся у меня вкруг 20 фпс, наивная реализация на $mol со встроенной виртуализацией показывает стабильные 60.

Бенчмарки: Потребление памяти

Нельзя забывать и про потребление оперативной памяти. Та реализация Хабра на VueJS на 170 комментариях отжирает 40 мегабайт хипа JS. Но если посмотреть понять вкладки, то это будет уже в 3 раза больше, так как самому браузеру нужно весь этот дом показывать. Если же открыть реализацию на $mol, где выводится статья, да ещё и две с половиной тысячи комментариев к ней, то мы получаем те же 40 мегабайт JS хипа. Но вкладка при этом кушает в два раза меньше, ибо браузеру показывать всего ничего - меньше тысячи DOM элементов.

Вариант

Память JS

Память вкладки

VueJS: 170 комментариев

40 MB

150 MB

$mol: статья + 2500 комментариев

40 MB

90 MB

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

Бенчмарки: Гулять так гулять!

Ну и, наконец, давайте сделаем немыслимое - загрузим разом 25 приложений..

https://showcase.hyoo.ru/

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

ООП против ФП

Короче, виртуализация - классная тема. И давайте посмотрим какие у нас есть перспективы, что она появится в ныне популярных инструментах. Но сперва определимся с вопросом чем объект отличается от функции..

  • Объект: одно состояние - много действий.

  • Функция: много состояний - одно действие.

Условный Angular использует концепцию объектов: каждый компонент - объект умеющий много разных действий. А вот в React популярна тема функциональных компонент - тут компонент имеет лишь одно действие - отрендерить своё содержимое в виртуальное дерево.

Ортогональные действия

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

  • Узнать минимальные размеры без полного рендера.

  • Частично отрендерить содержимое.

  • Проверить соответствие поисковому запросу.

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

Композиция против вёрстки

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

Column    Row        Search        Icon    Scroll        Column            Task            Task            Task

Второй подход - более популярный - это оживление готовой HTML вёрстки. Тут фактический лейаут зависит от стилей, что применены к html элементам. Как-то проанализировать это, наверно, можно, но это весьма сложно, крайне медленно и не очень надёжно. А в вебе и так хватает точек отказа.

<main class="panel">    <div class="header">        <input class="search">        <img src="..." class="icon">    </div>    <div class="scroll">        <div class="card">        <div class="card">        <div class="card">    </div></main>

Перспективы во фреймворках

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

Чуть ближе к виртуализации React Native, где нет никакого сырого HTML и всё строится из компонент. Но подражание html тут как собаке пятая нога.

К Angular, Vue, Svelte прикрутить виртуализацию скорее всего будет проще, ибо там каждый компонент - это некоторый объект. Правда ориентация на вёрстку, вместо компонент, существенно осложняет внедрение виртуализации на уровне фреймворка, а не прикладного кода.

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

Инструмент

ООП

КОП

React

React Native

Vue

Angular

Svelte

$mol

Выбери виртуализацию

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

Ну либо вы можете разработать свой какой-то инструмент, основанный на виртуализации. В любом случае, какой бы вариант вы ни выбрали, обращайтесь к нам, мы поможем чем сможем.

Ссылочки

Обратная связь

Превосходно: 34%

  • Вроде все знакомо, но нашёл для себя пару интересных нюансов.

  • Узнал кое что новое.

  • Все ок.

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

  • Изначально я слышал про $mol из комментариев на Хабре, многие из которых были неуместны / подавались в странной манере. В докладе я увидел, что автор - "видел некоторое дерьмо" (простите за мем) - понимает причины - предлагает здравые рассуждения по тому, как это чинить. Совершенно точно посмотрю на эту библиотеку, чтобы увидеть воплощение принципов из доклада на практике. Но даже если не буду использовать эту библиотеку в проде, разочарован не буду - настолько ценной и качественной я считаю информацию в этом докладе.

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

  • На удивление было мало $mol и много полезных вещей)

Хорошо: 42%

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

  • Карловский как всегда жжёт.

  • Очень круто и глубоко, но не очень понравилась подача. Хочется побольше "огонька".

Нормально: 18%

  • Слишком узкая специализация

  • Что смотрел помню, а про что нет.

  • Доклад на мой взгляд получился последовательным, но не очень сбалансированным с точки зрения теории и практики. Тема доклада очень общая, а по итогу практическую пользу можно получить судя по всему, если использовать конкретный фреймворк. Из плюсов - понравился разбор проблемы на примере GitLab.

Плохо: 6%

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

  • Оценка поставлена из-за несоответствия моих ожиданий и реальности =) Ожидания: я смогу применить полученные знания на своём проекте. Реальность: демонстрация своего фреймворка. Для проектов на любом другом фреймворке полученная информация неприменима. Если бы это было понятно из названия и описания, я бы не тратила время и пошла на другой доклад.

Подробнее..

От появления ЭВМ до периферийных вычислений в телекоме

18.01.2021 22:06:54 | Автор: admin

Edge Computing введение в тему

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

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

Рассмотрим, как произошёл переход от огромных машинных залов до периферийных вычислений на смартфонах.

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

Задачей самых первых операционных систем (ОС), появившихся в 50-х годах (например, GM-HAA), была координация запуска пакетов программ и вывод полученных результатов. Более развитые ОС (такие как Unix, RSX, VMS) появились в 70-х и получили много дополнительных функций, в том числе связанных с межкомпьютерным взаимодействием. Если первым пользователям приходилось для работы использовать системы ввода/вывода расположенные непосредственно в центрах обработки данных (ЦОД), то с развитием коммуникационных систем в 60-х годах появилась возможность подключать пользовательские терминалы по выделенным и коммутируемым медным телефонным линиям, а в конце 70-х по волоконно-оптическим. В середине 60-х для организации линий связи стали доступны первые коммерческие спутниковые каналы.

Параллельно с развитием линий связи совершенствовались и протоколы передачи данных. После появления пакетных систем передачи данных канального уровня (в 70-х годах протокола Ethernet и подобных, в 80-х годах протоколов SLIP, Token ring, HDSL и т.д.), а затем в 80-х протоколов для пакетной связи на региональном и на глобальном уровне (сеть Internet на основе стека протоколов TCP/IP), пользователям для обработки и хранения данных стали с рабочего места доступны удаленные компьютерные центры.

С выпуском в 70-х годах первых микропроцессоров начали активно развиваться специализированные вычислительные устройства и персональные компьютеры. Они подключались к мощным ЦОД через глобальную сеть в качестве клиентских периферических устройств для доступа к вычислительным мощностям и хранилищам данных. Как правило рабочее место использовалось в качестве тонкого клиента (например, как терминал подсоединенный по протоколам Telnet, rlogin и т.д.) для запуска вычислительных задач на удаленном сервере или для получения данных по таким протоколам как FTP.

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

Первоначально наиболее распространенный в операционных системах способ организации хранения данных в виде файловых систем оказался не оптимальным для работы со сложными структурами характерными для бизнес-приложений, что привело к созданию в 50-х и 60-х годах специализированных языков программирования для работы с большим количеством разнотипных записей сравнительно небольшого объема (таких как язык Cobol, на котором написаны многие приложения используемые до сих пор), и к возникновению в 70-х годах концепции реляционных баз данных и языка SQL.

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

Развитие сетевых технологий

В 90-х годах произошел кардинальный скачок в количестве пользователей сети Интернет, объеме трафика, производительности рабочих станций и серверов, в развитии сетевых технологий и вычислительных систем обработки данных обусловленный целым набором факторов:

  1. Широкое внедрение высокоскоростных соединений на основе семейства протоколов xDSL.

  2. Развитие волоконно-оптических линий связи (ВОЛС).

  3. Стали более доступны спутниковые системы связи VSAT и дешевый комбинированный доступ.

  4. Появление протоколов распределенного поиска и передачи документов (gopher, http и т.д.).

  5. Появление первых поисковых систем - Archie (90), Wandex (93), Yahoo! (94), Google (96).

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

  7. Степень интеграции, параметры микропроцессоров и технология SMP позволили использовать микропроцессоры при проектировании серверного оборудования, а центральные процессоры (ЦП) рабочих станции приблизились по производительности к ЦП серверов.

  8. Появление пользовательских операционных систем для персональных компьютеров с интегрированным программным обеспечением для подключения к интернет-провайдерам, простой настройкой сервисов Интернет и предустановленными Web-браузерами (Windows 95).

  9. Появление свободнораспространяемого и юридически чистого программного обеспечения на основе юниксоподобных систем (386BSD, FreeBSD, NetBSD, OpenBSD, ОС на основе ядра Linux и т.д.) портированных для широкой номенклатуры серверного и другого оборудования.

Для того что бы справляться с многократно возросшей вычислительной нагрузкой в ЦОДах интернет-провайдеров начали формироваться распределенные серверные кластеры объединенные высокоскоростными локальными вычислительными сетями (ЛВС) включающие десятки, сотни и тысячи серверов, обрабатывающих запросы клиентов и балансирующих нагрузку.

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

Облачные технологии

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

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

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

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

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

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

  1. IaaS аренда соединенных в сеть виртуальных серверов.

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

  3. SaaS доступ к данным через специализированный интерфейс.

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

Edge Computing периферийные вычисления

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

Напомним, Edge Computing концепция обработки критичных к скорости данных ближе к месту их возникновения без передачи в центральные ЦОДы.

Предпосылки для развития периферийных вычислений:

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

  2. Рост загруженности сетей мобильных операторов увеличение пропускной способности скорее не успевает за ростом объемов потребления трафика.

  3. Стремление разделить данные и сегменты сети для повышения безопасности.

  4. Желание повысить надежность и автономность отдельных частей IT-системы.

Децентрализация и перенос места обработки информации ближе к источнику данных производится для:

  1. Снижения нагрузки на сети передачи данных.

  2. Уменьшения времени задержки при обработке.

  3. Выполнения нормативных требований и законодательства.

Применимость концепции следует именно из этих трех основополагающих элементов. Фактически, любые системы, работающие в реальном времени, могут требовать использования периферийных вычислений. Развитию рынка периферийных вычислений способствуют IoT (концепция интернет вещей - Internet of Things) и массовый переход на сети 5G первые обеспечивают кратный рост устройств, подключенных к сети, а вторые дают возможность передачи довольно больших объемов данных при росте количества подключенных устройств.

Оборудование для периферических вычислений

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

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

  1. Локальные устройства отдельные шлюзы, промышленные компьютеры, минисерверы, контроллеры, банкоматы, онлайн кассы, терминалы для приема платежей, иногда сами пользовательские устройства типа смартфонов, беспилотные автомобили и т.д. Пользовательские устройства при этом иногда обозначают как endpoint-устройства. А промышленные компьютеры, минисерверы как Edge-устройства.

  2. Локальные ЦОДы или микроЦОДы 1-10 стоек, дают значительные возможности по обработке и хранению данных по сравнению с локальными устройствами.

  3. Региональные ЦОДы более 10 стоек.

2 и 3 пункт фактически может быть приравнен к CDN (Content Delivery Network) - Сеть доставки содержимого. Либо наоборот на базе чьего-то CDN можно строить инфраструктуру для периферийных вычислений.

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

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

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

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

Архитектура

Наиболее распространены двух- и трёхзвенные варианты построения Edge-систем.

Двухзвенная граничное устройство и ЦОД/облако.Двухзвенная граничное устройство и ЦОД/облако.Трёхзвенная граничное устройство, туман (микроЦОДы, микрооблака, отдельные сервера), ЦОД/облако.Трёхзвенная граничное устройство, туман (микроЦОДы, микрооблака, отдельные сервера), ЦОД/облако.

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

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

Достоинства

С точки зрения бизнеса следование концепции даёт:

  1. Повышение эксплуатационной эффективности работы.

  2. Создание новых технологически ёмких услуг и продуктов.

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

  4. Улучшение обслуживания клиентов.

Примеров использования множество и окружают они нас повсеместно.

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

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

Как всё это работает? Возьмем несколько упрощенных примеров.

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

Аналогично с камерами для фиксации потока автомобильного трафика - фиксируются количество и скорость автомобилей на трассе. На локальном оборудовании транспортные средства распознаются и классифицируются на мототранспорт, легковые авто, грузовые разного тоннажа и длины. Агрегированные данные отправляются в ЦОД. При нарушении скоростного режима, производится дополнительно фото/видеофиксация нарушителя номер ТС (Транспортного средства), фото авто и водителя (если возможно). Эти дополнительные данные также отправляются в ЦОД для формирования штрафа. Так же как с камерами в метро можно дополнительно отслеживать авто по госномерам по базе загруженной на локальное устройство.

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

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

Что еще можно назвать из наиболее востребованных периферийных вычислений?

  • Мониторинг сетевой активности, предотвращение атак и распространения вредоносного ПО, блокирование подозрительного трафика в момент и точке обнаружения.

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

  • Умные дома.

  • Безопасный город.

  • Онлайн-игры.

  • Любые сети доставки контента, инфраструктурные проекты интернет-гигантов.

  • Виртуальная и дополненная реальность.

Еще в 2018 году аналитики McKinsey говорили в своём отчете New demand, new markets: What edge computing means for hardware companies о 100 вариантах использования в 11 наиболее перспективных отраслях. А сейчас 2020 год и рынок динамично развивается несмотря на пандемию и экономический кризис.

Законы

Про это надо сказать отдельно. Законы и локальные нормативные акты диктуют свои правила игры. Из-за этого надо хранить данные граждан России на территории России, данные граждан Евросоюза на территории Евросоюза. Таких ограничений достаточно и это вынуждает технологические компании дробить базы и выносить их в CDN в конкретном регионе Земли.

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

Практика

Рассмотрим работу концепции переферических вычислений на примере компании Форвард-Телеком, одним из главных направлений работы которой является автоматизация деятельности операторов связи и интернет-провайдеров. Программное обеспечение Forward во многом является потребителем информации, полученной с edge- и endpoint-устройств. Система Forward BSS/OSS, как комплексная платформа, предназначена для поддержки бизнеса клиента практически при любой существующей модели сети оператора. Платформа Forward имеет логичную модульную структуру, легко масштабируется, поддерживает облачную и гибридную модель развертывания, при этом система позволяет настроить разнообразные внешние интерфейсы для взаимодействия с элементами сети оператора и клиентами.

Система OSS отвечает за правильную работу сетевой инфраструктуры и оборудования, а система BSS за учет оказанных услуг, взаиморасчеты с абонентами, управление ресурсами и проектами (элементы подсистемы ERP), за отношения с абонентами и хранение дополнительных данных (элементы системы CRM).

Для небольших операторов доступ к возможностям Forward BSS/OSS может предоставляться как стандартизованная услуга облачного сервиса по модели SaaS, при этом сеть оператора и его клиенты взаимодействуют с системой в рамках концепции Edge Computing.

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

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

Характерной особенностью многих крупных операторов является наличие исторически сложившегося зоопарка информационных систем. Плохо совместимое программное обеспечение различных вендоров, внедрённое на разных этапах развития компании в каких-то региональных подразделениях или полученное при покупке местных операторов. Быстрая замена такого зоопарка часто не возможна или слишком накладна. Интеграция исторических информационных систем может быть быстрее и дешевле произведена через Forward BSS/OSS через API или специально написанные шлюзы.

Поток обращений по интеграции OSS/BSS систем с мобильными приложениями становится больше. Все операторы связи, банки, ритейлеры, сервисные компании, госорганы постепенно обзаводятся приложениями B2B, B2C или B2B2C класса для коммуникации со своими заказчиками. Самостоятельное управление абонентскими услугами через мобильное приложение подразумевает глубокую интеграцию в бизнес-процессы компании и всё больше приближает нашу работу по автоматизации к endpoint-устройствам конечных пользователей.

Сложности при использования концепции

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

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

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

  3. Информационная безопасность edge- и endpoint-устройств заслуживает отдельного упоминания. Удаленность от основных объектов инфраструктуры, отсутствие охраны может дать злоумышленнику возможность физического доступа к устройству и его компрометации.

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

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

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

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

Для разработчиков систем автоматизации, 7 пункт является наиболее важным. Именно он входит в сферу ответственности Форвард-Телеком перед заказчиком и разработчики стараются выполнять свою работу хорошо. О том, как идёт у Форвард-Телеком разработка биллинговых систем уже писалось на Хабре в статье Как там биллинг делается: когда заказчик и разработчик говорят на разных языках.

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

Так что Prepare yourselves because cyberpunk is coming

Подробнее..

Перевод 12 платформ соревнований по Data Science и искусственному интеллекту для развития ваших навыков в 2021 году

12.01.2021 14:15:46 | Автор: admin
Data Science требует использования статистических методов и алгоритмов машинного обучения для работы с большим объёмом данных, и для того чтобы делать это эффективно, вам потребуется много практики. Отличная возможность попрактиковаться соревнования по Data Science. Они служат платформой для изучения лучших практик, получения отзывов и повышения квалификации. Это также отличный способ расширить возможности творить и границы в области науки о данных. Я делал подобный список и в прошлом году, поэтому подумал, что это будет хорошее время, чтобы обновить его на 2021 год.




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

1. Numer.ai


Что это такое?
Numer.ai, согласно их веб-сайту, самый сложный турнир по науке о данных на планете, его поддерживает Union Square Ventures, соучредитель Renaissance и Coinbase. Основная идея турнира создать мировой открытый хедж-фонд путём моделирования фондового рынка. На веб-сайте подробно описаны эти шаги:

  1. Начните с качественных данных о хедж-фондах.
  2. Примените машинное обучение для прогнозирования поведения фондового рынка.
  3. Предоставьте свои прогнозы, чтобы контролировать капитал хедж-фонда Numer.ai.

Специалисты по Data Science, которые примут во всём этом участие, получат выплаты (в криптовалюте), исходя из производительности моделей. На данный момент исследователям данных выплачено в общей сложности 37 160 659 долларов США.

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

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

2. IASC Data Analysis Competition 2021


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

Ваша презентация должна чётко описывать значимость ваших выводов как для отдельных людей, так и для общества. Первичный набор данных может поступать из одной или нескольких баз данных, но объединение информации из разных баз данных может помочь получить интересные и оригинальные выводы. Соревнование открыто для всех желающих представить свой плакат на выставке WSC 2021. Над вашим PDF можно работать лично или в небольшой группе (до 5 участников).

Когда окончательные материалы (в формате PDF) должны быть представлены 30 апреля 2021 года.

3. TopCoder Open 2021


Что это такое?
Ежегодный TopCoder Open (ТСО), организованный TopCoder, это запредельный турнир по программированию и дизайну.

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

  1. Алгоритмы.
  2. Разработка.
  3. Первый на финише.
  4. Марафон.
  5. Дизайн пользовательского интерфейса.
  6. Обеспечение качества.

Чтобы узнать больше, прочитайте обзор.

Когда старт дан 1 января 2021 года!

4. Challenge Data 2021


Что это такое?
Хозяева Challenge Data ENS и Collge de France. Организован сбор бизнес-задач Data Science с данными, предоставляемыми государственными службами, компаниями и лабораториями. Нужно решить следующие проблемы:

  • Данные.
  • Скоринг.
  • Тестовый набор.
  • Оценка.

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

Когда соревнование началось 4 января 2021 года.

5. Kaggle Competitions


Что это такое?
Kaggle не нуждается в представлении благодаря распространённости в сообществе Data Science. Это самая популярная платформа для проведения соревнований по Data Science с очень хорошими призами. Соревнования Kaggle созданы, чтобы бросать вызов конкурентам на всех этапах их карьеры в области машинного обучения. Существует обширный ряд типов соревнований (из документации):

  1. Оборочные соревнования.
  2. Соревнования исследований.
  3. Песочница.
  4. Рекрутинговые соревнования.
  5. Годовые соревнования.
  6. Соревнования с ограниченным участием.

Последние соревнования

6. CodaLab


Что это такое?
CodaLab это платформа с открытым исходным кодом, которая даёт экосистему для проведения вычислительных исследований более эффективным, воспроизводимым и командным образом. В CodaLab есть два аспекта: рабочие листы и соревнования.

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

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

Последние соревнования 2020 Seu Video Caption Competition.

7. Driven Data


Что это такое?
DrivenData привносит передовые методы в области Data Science и краудсорсинга в некоторые из самых больших социальных проблем, а также организации, берущие эти проблемы на себя. Существует множество онлайн-задач, обычно длящихся 2-3 месяца, где глобальное сообщество специалистов Data Science соревнуется за лучшую статистическую модель для решения сложных, значимых прогностических задач.
Согласно веб-сайту:

  1. Всё начинается с данных конкурентам даеётся набор данных как с зависимыми, так и с независимыми переменными.
  2. Второй набор данных данных только с независимыми переменными, а зависимые переменные, соответствующие этому набору, держатся в секрете.
  3. Вы строите модель.
  4. Представляете прогнозы для второго набора, сравниваете их с фактическими.
  5. Команда с лучшей производительностью объявляется победителем.

Последние соревнования MagNet: Model the Geomagnetic Field.

8. DataHack


Что это такое?
Последнее поле битвы Data Science, коллекция соревнований, чтобы сражаться, побеждать, практиковаться, учиться и создать своё портфолио Data Science! Хакатоны в области Data Science на DataHack позволяют конкурировать с ведущими исследователями данных и экспертами в области машинного обучения во всем мире. Это ваш шанс поработать над задачами науки на реальных данных, повысить мастерство, учиться у профессионалов в области информатики и машинного обучения, а также прорубить свой путь к вершине хакатона! У вас также есть шанс выиграть призы и устроиться на работу в компанию Data Science вашей мечты. Начните хакатон Data Science уже сегодня!

Последние соревнования Loan Prediction.

9. Machine Hack


Что это такое?
Онлайновая платформа для проведения соревнований по машинному обучению. Здесь найдутся самые сложные бизнес-проблемы, которые теперь можно решить с помощью Data Science и ML. Соревнуйтесь с сотнями специалистов на хакатоне, созданном индустрией.

Последние соревнования Buyers Time Prediction Challenge.

10. Zindi


Что это такое?
Zindi первая платформа для проведения соревнований в области Data Science в Африке. На Zindi расположена целая научная экосистема данных, в которую входят учёные, инженеры, академики, компании, НПО, правительства и институты, сосредоточенные на решении самых насущных проблем Африки.

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

Последние соревнования Uber Nairobi Ambulance Perambulation Challenge.

11. AIcrowd


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

Последние соревнования Motor insurance market simulation.

12. Iron Viz 2021


Что это такое?
IronViz крупнейший в мире конкурс по визуализации виртуальных данных зажигает и демонстрирует мощь сообщества Tableau, позволяя вам взаимодействовать с рок-звёздами данных по всему миру. Три финалиста (определяемые по результатам отборочного турнира IronViz в начале этого года) выйдут на Чемпионат IronViz в октябре 2021 года. Победитель зарабатывает не только право на хвастовство в течение года и место среди невероятного списка прошлых чемпионов, в 2020 году на кону было $ 10,000, но и пожертвование в размере $ 5,000 в пользу некоммерческой организации по выбору чемпионов.

Когда будет объявлено позже.

Для учащихся


Если вы студент или если вы преподаватель, поощряющий студентов изучать Data Science и AI, посмотрите на эти задачи.

  • Nittany AI Challenge предлагает командам студентов возможность побороться за награду в области Data Science, разрабатывая и представляя решения на основе искусственного интеллекта, чтобы сделать мир вокруг нас лучше с помощью четырёх столпов: образование, окружающая среда, здоровье и гуманизм.
  • Data Mining Cup вдохновляет отечественных и иностранных студентов на интеллектуальный анализ данных и предлагает им найти лучшее решение проблемы интеллектуального анализа данных, конкурируя с другими.
  • Imagine Cup Junior 2021 предоставляет учащимся в возрасте от 13 до 18 лет возможность узнать о технологиях и о том, как их можно использовать, чтобы изменить мир к лучшему. Глобальная задача сосредоточена на искусственном интеллекте (AI), знакомстве студентов с ИИ и инициативах [Microsoft AI for Good] (http://personeltest.ru/aways/www.microsoft.com/en-us/ai/ai-for-good), чтобы они могли придумать идеи для решения социальных, культурных и экологических проблем.

Идите в ногу с последними конкурсами с помощью этих ресурсов



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

image



Подробнее..

Kafka Streams непростая жизнь в production

14.01.2021 16:09:15 | Автор: admin

Привет, Хабр! Вокруг меня сформировался позитивный информационный фон на тему обработки событий через Kafka Streams. Этот инструмент привлекает множеством видео-докладов и статей на Хабре, подробной документацией, понятным API и красивой архитектурой. Некоторые мои знакомые и коллеги разрабатывают с его помощью свои системы. Но что происходит с в реальной жизни, когда эти системы уходят в production?

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

Коротко о проекте

Внутренней командой вместе с партнерами мы работаем над биржой Ad Exchange, которая помогает перепродавать рекламный трафик. Специфику подобных инструментов мы уже когда-то описывали в статье на Хабре. По мере роста числа партнеров среди SSP и DSP, нагрузка на сервера биржи растет. А для повышения ценности самой биржи мы должны собирать с этого трафика развернутую аналитику. Тут-то мы и попытались применить Kafka Streams.

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

Статья не претендует на объективность и описывает только лишь наш опыт и проблемы, с которыми мы столкнулись, работая с этой технологией. Надеюсь, кому-то она поможет избежать ошибок при использовании Kafka Streams. А может быть даст повод посмотреть по сторонам.

Агрегаты

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

Вроде бы стандартный кейс для Kafka Streams: используем функции groupBy и aggregate и получаем нужный результат. Всё работает именно так, причем с отличной скоростью за счёт внутреннего кэша: несколько последовательных изменений по одному и тому же ключу сначала выполняются в кэше и только в определённые моменты отправляются в changelog-топик. Далее Kafka в фоне удаляет устаревшие дублирующиеся ключи через механизм log compaction. Что здесь может пойти не так?

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

Если ваш ключ группировки отличается от ключа, под которым изначально пришло событие, то Kafka Streams создаёт специальный repartition-топик, отправляет в него событие уже под новым ключом, а потом считывает его оттуда и только после этого проводит агрегацию и отправку в changelog-топик. В нашем примере вполне может быть, что событие "Показ рекламы" пришло с ключом в виде UUID. Почему нет? Если вам надо сделать группировку, например по трём другим ключам, то это будет три разных repartition-топика. На каждый топик будет одно дополнительное чтение и одна дополнительная запись в Kafka. Чувствуете, к чему я веду?

Предположим, на входе у вас 100 тысяч показов рекламы в секунду. В нашем примере вы создадите дополнительную нагрузку на брокер сообщений в размере +600 тысяч сообщений в секунду (300 на запись и 300 на чтение). И ведь не только на брокер. Для таких объёмов надо добавлять дополнительные сервера с сервисами Kafka Streams. Можете посчитать, во сколько тысяч долларов обойдется такое решение с учётом цен на железо.

Для читателей, не очень хорошо знакомых с механизмом репартиционирования, я поясню один момент. Это не баг или недоработка Kafka Streams. С учётом её идеологии и архитектуры это единственное возможное поведение - его нельзя просто взять и отключить. Когда у сообщения меняется ключ, этот новый ключ надо равномерно "размазать" по кластеру так, чтобы каждый инстанс Kafka Streams имел собственный набор ключей. Для этого и служат дополнительные запись/чтение в repartition-топик. При этом если инстанс А записал в топик сообщение, то не факт, что он же его и прочитает. Это может сделать инстанс Б, В и т.д. в зависимости от того, кто какую партицию читает. В итоге каждый ключ группировки у вас будет более-менее равномерно распределён по серверам кластера (если вы его хэшируете, конечно).

Запросы к агрегатам

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

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

Ещё надо помнить, что на каждом отдельно взятом сервисе находится только часть ключей. Что если вам необходимо отдавать ваши агрегаты, скажем, по HTTP? Вот кто-то сделал запрос к одному из сервисов Kafka Streams: мол, дай мне такие-то данные. Сервис смотрит у себя локально - данных нет. Или есть, но какая-то часть. Другая часть может быть на другом сервере. Или на всех. Что делать? Документация Kafka Streams говорит, что это наши проблемы.

Стабильность Kafka Streams

У нас бывают проблемы с хостинг провайдером. Иногда выходит из строя оборудование, иногда человеческий фактор, иногда и то, и другое. Если по какой-то причине теряется связь с Kafka, то Kafka Streams переводит все свои потоки в состояние DEAD и ждёт, когда мы проснёмся и сделаем ей рестарт. При этом рядом стоят соседние сервисы, которые работают с той же Kafka через Spring и @KafkaListener. Они восстанавливаются сами, как ни в чём не бывало.

Kafka Streams может умереть и по другой причине: не пойманные исключения в вашем коде. Предположим, вы делаете какой-то внешний вызов внутри потоков Kafka Streams. Пусть это будет обращение к базе данных. Когда база данных падает, у вас два варианта. Первый - вы ловите эту ошибку и продолжаете работать дальше. Но если база будет лежать долго, а работа с ней - критична, вы будете считывать большое количество сообщений из топиков и некорректно их обрабатывать. Второй вариант кажется лучше - совсем не ловить исключение и дать Kafka Streams умереть. Дальше как обычно: ночной подъём, рестарт всех серверов с Kafka Streams. "Из коробки" у вас нет варианта подождать, пока база восстановится, и продолжить работу.

Нам пришлось дописать в каждый сервис Kafka Streams дополнительный модуль, который работает как watchdog: поднимает Kafka Streams, если видит, что она умерла.

Кстати, если вы работаете с Kafka Streams через Spring, то не забудьте переопределить стандартный StreamsBuilderFactoryBean, указав в нём свой CleanupConfig. Иначе будете неприятно удивлены тем, что при каждом рестарте будет удаляться вся локальная база RocksDB. Напомню, что это приведёт к тому, что при каждом рестарте все сервера начнут активно считывать данные из changelog-топика. Поверьте, вам это не нужно.

KStream-KStream Join

Здесь можно было бы обойтись одной фразой: никогда это не используйте. Джоин двух потоков создаёт десятки топиков в Kafka и огромную нагрузку на всю систему. Просто не делайте этого. Ну или хотя бы проверьте все под нагрузкой, прежде чем ставить в production.

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

Масштабируемость

Любой человек, знакомый с Kafka, скажет, что масштабируемость - одна из главных её преимуществ: "В чём проблема? Добавляем партиций и радуемся". Всё так. Но не для Kafka Streams.

Если вы используете джоины, то все ваши топики должны быть ко-партиционированы (co-partitioning), что, в числе прочего, означает, что у них должно быть одинаковое количество партиций. Так в чём же проблема?

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

На вопрос, что с этим делать, у меня сегодня ответа нет. Вероятно, можно потушить все рабочие инстансы Kafka Streams, потом поднять число партиций на всех причастных топиках, затем поднять Kafka Streams обратно и молиться. А может быть последовать совету отсюда: Matthias J. Sax пишет, что это нужно делать, создавая новый топик с новым количеством партиций и подключать к нему Kafka Streams с новым application.id. Там же есть совет, что если вы знаете заранее, что нагрузка будет большая, то лучше сделать партиций с запасом.

Заключение

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

Автор статьи: Андрей Буров, Максилект.

P.S. Мы публикуем наши статьи на нескольких площадках Рунета. Подписывайтесь на наши страницы в VK, FB, Instagram или Telegram-канал, чтобы узнавать обо всех наших публикациях и других новостях компании Maxilect.

Подробнее..

Перевод Строим надёжную конкурентность с FSP и моделированием процессов

15.01.2021 18:06:16 | Автор: admin

Делаем систему параллелизма надёжнее


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

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


Сгенерированная инструментом LTSA диаграмма состояний


Что это за язык FSP?


Finite state processes (FSP) это абстрактный язык, на котором разрабатывают системы конкурентных процессов.

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

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

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

Как с помощью алгебры процессов (FSP) описать конкурентные процессы


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

Вначале проанализируем принтер



  • В принтер помещается только три листа, студенты могут распечатать до трёх документов;
  • Если листов нет, принтер нужно заполнить ими.

const MIN_SHEET_COUNT=1const MAX_SHEET_COUNT=3range DOC_COUNT=MIN_SHEET_COUNT .. MAX_SHEET_COUNTrange SHEET_STACK=0 .. MAX_SHEET_COUNTPRINTER(SHEETS_AVAILABLE = MAX_SHEET_COUNT) =  ( start -> PRINTER_AVAILABLE[MAX_SHEET_COUNT]),  PRINTER_AVAILABLE[sheets_available: SHEET_STACK] = if   (sheets_available > 0)  then (acquire -> print[DOC_COUNT] -> release -> PRINTER_AVAILABLE[sheets_available - 1])  else (empty -> refill_printer -> release -> PRINTER_AVAILABLE[MAX_SHEET_COUNT]).

Процесс PRINTER

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

Как анимировать процесс


Чтобы анимировать процесс, сначала скомпилируйте (compile [1]) код, затем перейдите на вкладку draw. Нажмите кнопку animatе [2].


Анимация процесса PRINTER

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

Печатающий документы студент


Код на FSP можно написать при помощи условных процессов (if, then, else). DOCSTOPRINT = 3 это переданный процессу параметр 3. Процесс PRINT начинается с 0. Doc_count это метка индексированного действия, которая ведёт к этому действию: PRINT [doc_count].

STUDENT(DOCS_TO_PRINT = 3) =  PRINT[0],PRINT[doc_count: 0 .. DOCS_TO_PRINT] = if (doc_count < DOCS_TO_PRINT)then ( acquire -> print -> release -> PRINT[doc_count + 1]  )else ( terminate -> END ).

Процесс STUDENT с условным процессом

Тот же самый процесс можно написать и с помощью защищённых процессов.

STUDENT(DOCS_TO_PRINT = 3) =  PRINT[0],PRINT[doc_count: 0 .. DOCS_TO_PRINT] = (  when (doc_count < DOCS_TO_PRINT)  acquire -> print -> release -> PRINT[doc_count + 1] |  when (document_count == DOCUMENTS_TO_PRINT) terminate -> END ).

Процесс STUDENT с защищённым процессом


Анимация процесса STUDENT

Теперь проанализируем техника, который устанавливает бумагу в принтер


TECHNICIAN = (empty -> refill_printer -> release -> TECHNICIAN | terminate -> END) .

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


Анимация процесса техника

Наконец, давайте посмотрим на составной процесс


  • Составной процесс должен быть синхронизирован со всеми подпроцессами, для этого можно определить набор действий с именем PRINT_Actions.
  • terminate/s1.terminate это перемаркированное действие. С помощью мы переназначаем действие s1.terminate, чтобы просто завершить процесс. В противном случае аниматор покажет s1.terminate, s2.terminateиtcn.terminate.
  • Чтобы синхронизировать пользователей с PRINTER, можно использовать взаимоисключающий общий ресурс.

|| SHARED_PRINTER = (s1: STUDENT(2) || s2: STUDENT(3) || tcn : TECHNICIAN || All_Users :: PRINTER)

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

const MIN_SHEET_COUNT=1const MAX_SHEET_COUNT=3range DOC_COUNT=MIN_SHEET_COUNT .. MAX_SHEET_COUNTrange SHEET_STACK=0 .. MAX_SHEET_COUNTset All_Users = {s1, s2, tcn}set PRINT_Actions = {acquire, print, release, empty}PRINTER(SHEETS_AVAILABLE = MAX_SHEET_COUNT) = PRINTER_AVAILABLE[MAX_SHEET_COUNT],PRINTER_AVAILABLE[sheets_available: SHEET_STACK] = if   (sheets_available > 0)then ( acquire -> print -> release -> PRINTER_AVAILABLE[sheets_available - 1]  )else ( empty -> release -> PRINTER_AVAILABLE[MAX_SHEET_COUNT] ).STUDENT(DOCS_TO_PRINT = 1) =  PRINT[0],PRINT[doc_count: 0 .. DOCS_TO_PRINT] = if   (doc_count < DOCS_TO_PRINT)then ( acquire -> print -> release -> PRINT[doc_count + 1]  )else ( terminate -> END )+ PRINT_Actions.TECHNICIAN = (empty -> refill_printer -> release -> TECHNICIAN | terminate -> END) + PRINT_Actions.|| SHARED_PRINTER = (s1: STUDENT(2) || s2: STUDENT(3) || tcn : TECHNICIAN || All_Users :: PRINTER) / {terminate/s1.terminate,terminate/s2.terminate,terminate/tcn.terminate}.

Составной процесс системы принтера

Я надеюсь, что этот материал поможет вам в изучении параллелизма на FSP.




Подробнее..

Перевод Человек, который связывает большие информационные системы и Data Science

15.01.2021 16:07:39 | Автор: admin
image Уэс МакКинни, о котором писали в Quartz как о человеке, создавшем наиболее важный инструмент в области Data Science (речь о пакете для анализе данных Pandas), отправляется в новое плавание он запускает стартап под названием Ursa Computing.

По словам МакКинни, стартап будет заниматься разработкой продуктов и предоставлением услуг для ускорения работы с данными, машинным обучением и искусственным интеллектом для предприятий. МакКинни и его компании получили 4,9 миллиона долларов в рамках первого этапа финансирования, проведенного GV (бывшего Google Ventures). Также среди инвесторов числятся Walden International, Nepenthe, Amplify Partners, RStudio и несколько бизнес-ангелов.

Ursa Computing сосредоточится на корпоративном рынке и будет стремиться к широкому распространению Apache Arrow независимой от языка программной платформы для разработки приложений для анализа данных. Компания будет продолжать разработку проектов в области Data Science с открытым исходным кодом, изначально созданных Ursa Labs (некоммерческая независимая лаборатория разработки, также созданная МакКинни).

Если компания добьется успеха, Ursa Computing сделает МакКинни человеком, который преодолеет разрыв между Data Science и большими информационными системами.

Пропасть между Data Science и большими данными


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

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

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

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

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

image

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

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



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

Развитие Apache Arrow


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

1. Вычислительная мощность

Во-первых, сами инструменты для анализа данных, написанные на языках вроде R и Python, значительно отстали от достижений в области железа, заметил МакКинни. Большинство таких инструментов не поддерживают использование многоядерных процессоров, графических ускорителей или систем с большим объемом оперативной памяти, поскольку когда они разрабатывались, у нас не было процессоров с 16 ядрами.

Кроме того, все эти инструменты были разработаны задолго до появления Cuda, платформы параллельных вычислений и интерфейса программирования от Nvidia.

2. Ускорение работы с памятью

Также произошел скачок в работе с памятью. МакКинни отметил, что скорость работы накопителей непрерывно растет. Также появились SSD-накопители. Дело не только в скорости работы памяти, но и в расширении доступа к данным. А у инструментов скачка нет, они опять оказываются узким местом.

3. Необходимость эффективного массового перемещения больших массивов данных

Также по мнению МакКинни фактором развития в этой области стала потребность в эффективном перемещении больших массивов данных.

Обычно, данные просто выгружаются в базу данных Oracle (или любую другую, которую вы используете). Затем к этой базе делаются SQL-запросы. И данные просто хранятся в базе.

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

image

4. Независимость от языка программирования

Далее, у нас есть проблема с несовместимостью языков программирования. В Google, Facebook и других отраслевых компаниях стандартом является Python. Однако никуда не делись и другие языки R, JVM, Julia. Разные люди используют разные языки программирования, потому что считают, что могут добиваться с ними максимальной продуктивности, сказал МакКинни.

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

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

Следовательно, новая программная среда должна быть разработана для экосистем, в которых используются разные языки программирования. Впрочем, МакКинни отметил, что хочет работать с данными так, чтобы они не загрязнялись побочными эффектами программ на разных языках. Цель [Apache Arrow] обеспечить бесшовное взаимодействие языков программирования на уровне данных.

Большие усилия


Разработка Apache Arrow велась 5 лет. МакКинни признал, что формирование команды разработчиков проекта с открытым исходным кодом, стремящихся к созданию единого формата данных было чрезвычайно непростой задачей. Сообщество предоставило ядро платформы, с помощью которого Arrow может встраиваться в существующие системы (либо могут создаваться новые системы на основе Arrow).

Признавая, что сам процесс разработки был скучным, МакКинни сказал, что пока все идет хорошо.

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

Тем не менее, переход от некоммерческой деятельности к коммерческой это большой шаг.

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

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

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


МакКинни прославился как человек, создавший самый важный инструмент в Data Science, поскольку он разработал Pandas библиотеку для обработки и анализа данных для Python.

МакКинни начинал работу над Pandas как над проектом с закрытым исходным кодом в AQR Capital, инвестиционной фирме из Коннектикута. Фирма наняла его после того, как он получил степень математика в MIT. Через год МакКинни закончил работу над Pandas, сделал библиотеку бесплатной и открыл ее исходный код.

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

Он подчеркнул: Я действительно очень забочусь о расширении возможностей разработчиков и о том, чтобы специалисты могли быть более эффективными и продуктивными. С Ursa Computing он стремится построить всю экосистему вокруг Apache Arrow.




image

Вакансии
НПП ИТЭЛМА всегда рада молодым специалистам, выпускникам автомобильных, технических вузов, а также физико-математических факультетов любых других высших учебных заведений.

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

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

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



О компании ИТЭЛМА
Мы большая компания-разработчик automotive компонентов. В компании трудится около 2500 сотрудников, в том числе 650 инженеров.

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

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

Подробнее..

Как мы в СберМаркете боремся с товарами-призраками

14.01.2021 12:05:51 | Автор: admin
Так могла бы выглядеть наша команда, но мы на удаленкеТак могла бы выглядеть наша команда, но мы на удаленке

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

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

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

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

Как работает СберМаркет

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

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

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

Идея алгоритма

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

Исторически 70% таких артикулов имеют очень высокий показатель ненайденных товаров за последние дни продаж более 50%. Значит, нужно срочно заблокировать позицию в каталоге, чтобы клиенты не смогли купить то, что мы не можем привезти.

Выше представлена динамика неуспешных сборок по товару из категории фрукты в одном магазине. С 21 июня по 1 июля показатель ненайденных товаров был 100%. Хотя ретейлер передавал нам другие данные.

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

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

И начали писать его на Python.

Как работает алгоритм

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

  2. Из базы данных наших заказов вытаскиваем историю последних сборок. Для каждого ненайденного товара берём историю THRESHOLD_ORDERS.

  3. Если в последних THRESHOLD_ORDERS заказах процент ненайденных товаров более THRESHOLD_CANCELLATION процентов, то эту позицию нужно заблокировать.

  4. Если товар ещё ни разу не блокировался или с момента последней блокировки уже прошло DAYS_NO_CANC дней, то товар блокируется на HIDE_1 дней.

  5. Если с момента последней блокировки товара прошло менее DAYSNOCANC дней, то:

    ~ товар блокируется на HIDE_2 дней, если текущая блокировка ставится второй раз подряд;
    ~ товар блокируется на HIDE_3 дней, если уже блокировался более двух раз подряд.

Пример параметров алгоритма для магазина:

'params': {  'DAYS_NO_CANC': 4,  'HIDE_1': 2,  'HIDE_2': 11,  'HIDE_3': 9,  'THRESHOLD_CANCELLATION': 0.4,  'THRESHOLD_ORDERS': 3  }

Параметры алгоритма подбирались отдельно для каждого магазина на исторических данных с использованием библиотеки hyperopt на Python. В процессе оптимизации максимизировалась метрика F-мера с beta 0.7.

Зачем так усложнять

Почему нельзя просто всегда блокировать товары на N дней? Зачем нам параметры DAYS_NO_CANC, HIDE_1, HIDE_2 и HIDE_3?

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

Кейс 1: товары нужно блокировать на маленький срок

У ретейлера A в магазине закончились бананы. Новую поставку смогут выложить в торговый зал через 1-2 дня. Бананы необходимо заблокировать на максимально маленький срок после этого они точно будут доступны для клиентов и сборщиков.

Кейс 2: товары нужно блокировать на большой срок

У ретейлера B случился сбой в поставке яблочного сока. Возможно, новая партия доедет до магазина через 2-3 недели. Нет смысла блокировать товар на маленький срок, так как после такой блокировки клиенты все равно смогут заказать товар, но сборщик не сможет его собрать.

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

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

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

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

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

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

Чего вам не хватает в сервисах доставки продуктов или у нас? Делитесь в комментариях подумаем над решением.

Подробнее..

Перевод Как экономить память и удваивать размеры моделей PyTorch с новым методом Sharded

07.01.2021 18:21:18 | Автор: admin
Модели глубокого обучения улучшаются с увеличением количества данных и параметров. Даже с последней моделью GPT-3 от Open AI, которая использует 175 миллиардов параметров, нам ещё предстоит увидеть плато роста количества параметров.

Для некоторых областей, таких как NLP, рабочей лошадкой был Transformer, который требует огромных объёмов памяти графического процессора. Реалистичные модели просто не помещаются в памяти. Последний метод под названием Sharded [букв. сегментированный] был представлен в Zero paper Microsoft, в котором они разработали метод, приближающий человечество к 1 триллиону параметров.

Специально к старту нового потока курса по Machine Learning, делюсь с вами статьей о Sharded в которой показывается, как использовать его с PyTorch сегодня для обучения моделей со вдвое большей памятью и всего за несколько минут. Эта возможность в PyTorch теперь доступна благодаря сотрудничеству между командами FairScale Facebook AI Research и PyTorch Lightning.





Для кого эта статья?


Эта статья предназначена для всех, кто использует PyTorch для обучения моделей. Sharded работает на любой модели, независимо от того, какую модель обучать: NLP (трансформатор), зрительную (SIMCL, swav, Resnet) или даже речевые модели. Вот моментальный снимок прироста производительности, который вы можете увидеть с помощью Sharded во всех типах моделей.



SwAV это современный метод контролируемого данными обучения в области компьютерного зрения.
DeepSpeech2 это современный метод для речевых моделей.
Image GPT передовой метод для визуальных моделей.
Трансформер передовой метод обработки естественного языка.

Как использовать Sharded вместе с PyTorch


Для тех, у кого не так много времени, чтобы прочитать интуитивно понятное объяснение о том, как работает Sharded, я сразу объясню, как использовать Sharded с вашим кодом PyTorch. Но призываю прочитать конец статьи, чтобы понять, как работает Sharded.

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

Самый простой способ зарядить ваш код с помощью Sharded это преобразовать вашу модель в PyTorch Lightning (это всего лишь рефакторинг). Вот 4-минутное видео, которое показывает, как преобразовать ваш код PyTorch в Lightning.



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



Если ваша модель взята из другой библиотеки глубокого обучения, она всё равно будет работать с Lightning (NVIDIA Nemo, fast.ai, Hugging Face). Всё, что вам нужно сделать, это импортировать модель в LightningModule и начать обучение.

from argparse import ArgumentParserimport torchimport torch.nn as nnimport pytorch_lightning as plfrom pytorch_lightning.metrics.functional import accuracyfrom transformers import BertModelclass LitBertClassifier(pl.LightningModule):    def __init__(self, n_classes, pretrained_model_name='bert-base-uncased'):        super().__init__()        self.save_hyperparameters()        self.bert = BertModel.from_pretrained(pretrained_model_name)        self.drop = nn.Dropout(p=0.3)        self.out = nn.Linear(self.bert.config.hidden_size, n_classes)        self.loss_fn = nn.CrossEntropyLoss()    def forward(self, input_ids, attention_mask):        outputs = self.bert(            input_ids=input_ids,            attention_mask=attention_mask,            return_dict=False        )        pooled_output = outputs[1]        output = self.drop(pooled_output)        return self.out(output)    def training_step(self, batch, batch_idx):        loss, acc = self._shared_step(batch, batch_idx)        self.log("acc", acc)        return loss    def validation_step(self, batch, batch_idx):        _, acc = self._shared_step(batch, batch_idx)        self.log("val_acc", acc)    def _shared_step(self, batch, batch_idx):        input_ids = batch["input_ids"]        attention_mask = batch["attention_mask"]        targets = batch["targets"]        outputs = self.forward(            input_ids=input_ids,            attention_mask=attention_mask        )        _, preds = torch.max(outputs, dim=1)        loss = self.loss_fn(outputs, targets)        acc = accuracy(preds, targets)        return loss, acc    def configure_optimizers(self):        return torch.optim.AdamW(self.parameters(), lr=2e-5)if __name__ == '__main__':    # TODO: add your own dataset    train_dataloader = ...    val_dataloader = ...    bert = LitBertClassifier()    trainer = pl.Trainer(gpus=8, plugins='ddp_sharded')    trainer.fit(bert, train_dataloader)

Интуитивно понятное объяснение работы Sharded


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


Обучение DP

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

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


Параллельное распределение данных

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

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

Использование какого-либо распределённого режима




В PyTorch Lightning переключение режимов распределения тривиально.

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

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

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

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

image



Подробнее..

Самообучение в Data science, с нуля до Senior за два года

08.01.2021 18:05:33 | Автор: admin

Хочу поделиться методами освоения Data science с нуля человеком из другой ИТ специальности. Цель: дать понять, подходит ли Вам эта специальность в принципе, и рассказать про эффективные подходы к самообучению, которые мне помогли (отдельно планирую потом детальные статьи по отдельным темам).

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

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

Мой опыт:

  • Когда я понял, что скоро мне стукнет 30 лет, решил уйти в другую сферу и переехать из РФ. В своей сфере (1С) я был карьерно успешен, но стало ясно, что дальнейший рост очень затруднителен и требует выполнять работу, которая мне неинтересна и почти противна.

  • Через полгода перебора вариантов решил, что Data science мне интереснее всего.

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

  • Ещё через год стал Senior Data scientist в Vodafone (мой LinkedIn).

Цель - учиться эффективнее и бесплатно

Мне помогло то, что до этого я сформировал привычки к самообразованию, а экономность не позволила мне пойти по самому простому пути: найти онлайн курс с именитыми преподами, заплатить им много денег и довериться, что они всему научат лучше всего. В итоге я перебирал много бесплатно доступных книг и курсов (книги часто были найдены на b-ok.org). Из всех курсов и книг отбирал самые лучшие, забрасывая то, что казалось слишком теоретизированными или плохо структурированным.

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

Сначала надо понять, что такое Data science/машинное обучение и подойдет ли оно вам

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

Какие альтернативы:

Возможно, вы технарь-интроверт, желающий делать что-то своими руками и не желающий много общаться с другими людьми или вникать в бизнес (потому что DS очень прикладная штука, требующая погруженная в предметную область). Тогда есть варианты: или "просто программирование" вам будет интереснее (Не хочется разрабатывать сайты? - Нужны разработчики бэкенд приложений и дата-инженеры, в больших количествах), или если всё-таки хочется заниматься машинным обучением, то изучать все методы data science и знать их лучше всех, чтобы пойти сразу в более крупную компанию, где достаточно чисто-технических задач.

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

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

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

Как понять, будет ли вам интересно заниматься именно data science?

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

Мне кажется, что идеально эту роль выполняет книга Datasmart (выше писал сайт, на котором я нашёл её бесплатно). На русский она тоже переведена: "Много цифр. Анализ больших данных при помощи Excel, Джон Форман". Хотя, если вы хотите работать в data science, знание английского необходимо (технический английский выучить намного легче разговорного, и это будет очень полезно для любой работы в ИТ).

Эта книга показывет многие из технических методов Data science на уровне интуиции и даёт сразу достаточно детальное представление о решаемых задачах и где в бизнесе можно применить данные модели.

Если эта книга не вызовет интерес разобраться во всех указанных алгоритмах детальнее, вероятно, работа в data science не для вас.

Если книга интересн вызовет, но вам также хочется больше программировать, скорее всего, вам интересно будет стать machine learning engineer. Разница между data scientist и machine learning engineer в том, что первый должен общаться с людьми и понимать, какую задачу имеет смысл решать, а второй должен уметь состыковать программы с "искусственным интеллектом" с другими ИТ системами, мобильными телефонами или требованиями обрабатывать огромные объемы данных.

Кстати, подобная книга для тех, кто хочет понять стоит ли ему заниматься визуализацией данных (PowerBI, Tableau и т.п.) - "Storytelling with data". Если эта книга тоже вдохновила, вместе с предыдущей, вероятно вы data scientist, способный выполнять и роль аналитика. Если же заниматься объяснением данных вам неинтересно, вам стоит нацелеваться на позицию machine learning engineer или подумать, не легче ли быть "обычным" программистом.

Что учить

Если вы решили, что готовы "грызть гранит науки", то в образовании специалиста data science есть два кита:

  • Непосредственные методы Data science, которые стоят на трёх математических черепахах: теории вероятностей и статистике, линейной алгебре и основах мат.анализа (только основах, там требуется минимум сверх школьного курса "алегбра и начало анализа"). Кстати, вся эта математика далеко не так сложна. Проблема в том, что её плохо и неинтересно объясняют во многих вузах. Позже поделюсь советами, как её можно легче освоить.

  • Программирование на Python (+SQL и подобные), которое позволит применить все изученные методы с помощью логичных и простых в своей сути библиотек готовых функций.

    Каждый data scientist немного программист. При этом именно python является стандартом де-факто для нашей сферы. Вероятно, этот язык занял своё положение благодаря тому, что он очень простой и логичный. Если вы программировали на чём угодно, и слова "цикл" или "if-then-else" вас не пугают, то вам не будет очень сложно освоить Пайтон. Если вы никогда не программировали, но считаете, что структурное и математическое мышление - ваш конёк, с программированием у вас не будет проблем. Даже если вы "конченный гуманитарий", освоить Python значительно легче, чем выучить многие иностранные языки (но, внимание! для людей без предыдущего опыта программирования обучаться ему эффективнее по-другому, не так, как для тех, кто уже имеет опыт программирования)

Даже примерный учебный пландля изучения методов Data science требует отдельного поста. Ниже напишу чуть подробнее про Python и SQL

Английский необходим!

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

Принципы эффективного обучения

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

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

  2. Следует концентрироваться на понимании главных принципов - это легче, чем запоминать отдельные детали (они часто оказываются не нужны). Особенно важно это становится, когда вы учите язык программирования, тем более свой первый: не стоит зубрить правильное написание команд ("синтаксис") или заучивать API библиотек.

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

Программирование: что и как учить?

Что такое SQL и зачем его учить?

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

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

Сам язык программирования - это ограниченный набор команд.

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

Как учить SQL:

Наберите в Гугле "sql tutorial" и начните учиться по первой же ссылке. Если она вдруг окажется платной, выберете другую. По SQL полно качественных бесплатных курсов.

На русском языке тоже полно курсов. Выбирайте бесплатные.

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

На изучение достаточно всего лишь от 10 часов (общее понимание), до 20 часов (уверенное владение большей частью всего необходимого).

Почему именно Python?

В первую очередь, зачем учить Python. Возможно, вы слышали что R (другой популярный язык программирования) тоже умеет очень многое, и это действительно так. Но Python намного универсальнее. Мало сфер и мест работы, где Python вам не сможет заменить R, но в большинстве компаний, где Data Science можно делать с помощью Python, у вас возникнут проблемы при попытке использования R. Поэтому - точно учите Python. Если вы где-то услышите другое мнение, скорее всего, оно устарело на несколько лет (в 2015г было совершенно неясно какой язык перспективнее, но сейчас это уже очевидно).

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

Как учить Python

Основы:

http://pythontutor.ru/

Прочитать основы и пройти все упражнения с этого сайта можно за 5-40 часов, в зависимости от вашего предыдущего опыта.

После этого варианты (все эти книги есть и на русском):

  1. Learning Python, by Mark Lutz (5 издание). Существует и на русском.

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

    Эта книга, наоборот, разбирает Python досконально. Поэтому по началу её чтение будет идти медленнее, чем аналоги. Но зато, прочтя её, вы будете способны разобраться во всём.

    Я прочёл её почти целиком в поездах в метро за месяц. А потом сразу был готов писать целые программы, потому что самые основы были заложены в pythontutor.ru, а эта книга детально разжевывает всё.

    В качестве практики берите, что угодно, когда дочитаете эту книгу до 32 главы, и решайте реальные примеры (кстати, главы 21-31 не надо стараться с первого раза запоминать детально. Просто пробежите глазами, чтобы вы понимали что вообще Python умеет).

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

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

  2. Python Crash Course, byEric Matthes

    Эта книга проще написана и отсеивает те вещи, которые всё-таки реже используются. Если вы не претендуете быстрее стать высоко-классным знатоком Python - её будет достаточно.

  3. Automate the Boring Stuff with Python

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

Какие трудозатраты?

Путь с нуля до уровня владения Python, на котором я что-то уже мог, занял порядка 100ч. Через 200ч я уже чувствовал себя уверенно и мог работать над проектом вместе с коллегами.

(есть бесплатные программы - трекеры времени, некоторым это помогает для самоконтроля)

Пожалуйста, дайте обратную связь

Если это было кому-то полезно (а не просто помогло убить время), поставьте лайк. Можете написать на адрес ниже пожелания и рекомендации. Буду стараться быть полезным большинству.

Для желающих могу выступить в роли ментора

Посчитав, что мой опыт самообучения эффективен и быстрый рост (с нуля до синьора за 2 года) это доказывает, год назад я вписался в программу менторства родного университета (Высшая школа экономики). За год помог нескольким студентам не-ИТ факультетов начать изучать DS и ИТ вообще или выбрать более эффективные пути самообучения.

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

Буду раду помочь, пишите на адрес почты ниже.

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

self.development.mentor в домене gmail.com, Олег

Подробнее..

Перевод Как быть билингвом в Data Science

09.01.2021 20:18:44 | Автор: admin
В этой статье я хочу продемонстрировать R Markdown удобную надстройку для программирования вашего проекта как на R, так и на Python, позволяющую программировать некоторые элементы вашего проекта на двух языках и управлять объектами, созданными на одном языке, с помощью другого языка. Это может быть полезно потому, что:

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





Что нам понадобится


Для работы понадобятся эти компоненты:

  1. Конечно, R и Python.
  2. IDE RStudio (можно сделать это в других IDE, но в RStudio проще).
  3. Ваш любимый менеджер среды для Python (здесь я использую conda).
  4. Пакеты rmarkdown и reticulate, установленные в R.

При написании документов R Markdown мы будем работать в среде RStudio, но при этом перемещаться между фрагментами кода, написанными на R и на Python. Покажу пару простых примеров.

Настройка среды Python


Если вы знакомы с программированием на Python, то вы знаете, что любая выполняемая на Python работа, должна ссылаться на конкретную, содержащую все необходимые для работы пакеты среду. Есть много способов управления пакетами в Python, два самых популярных virtualenv и conda. Здесь я предполагаю, что мы используем conda и что он установлен в качестве менеджера среды Python.
Вы можете использовать пакет reticulate в R для настройки окружений conda через командную строку R, если хотите (используя такие функции, как conda_create()), но как обычный программист Python я предпочитаю настраивать свои среды вручную.

Предположим, мы создаём среду conda с именем r_and_python и устанавливаем в неё pandas и statsmodels. Итак, команды в терминале:

conda create -name r_and_pythonconda activate r_and_pythonconda install pandasconda install statsmodels

После установки pandas, statsmodels (и любых других пакетов, которые могут вам понадобиться) настройка среды завершена. Теперь запустите conda info в терминале и выберите путь к вашей среде. Он понадобится вам на следующем шаге.

Настройка вашего проекта R для работы с R и Python


Мы запустим проект R в RStudio, но хотим иметь возможность запускать Python в этом же проекте. Чтобы убедиться, что код Python работает нужной нам среде, необходимо установить системную переменную среды RETICULATE_PYTHON для исполняемого файла Python в этой среде. Это будет путь, который вы выбрали в предыдущем разделе, за которым следует /bin/python3.

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

Sys.setenv(RETICULATE_PYTHON=path_to_environment/bin/python3")

Замените pathtoenvironment на путь, который вы выбрали в предыдущем разделе. Сохраните файл .Rprofile и перезапустите сеанс R. Каждый раз, когда вы перезапускаете сеанс или проект, запускается .Rprofile, настраивающий вашу среду Python. Если вы хотите проверить это, вы можете запустить строку Sys.getenv (RETICULATE_PYTHON).

Написание кода первый пример


Теперь вы можете настроить в своём проекте документ R Markdown .Rmd и писать код на двух разных языках. Сначала нужно загрузить библиотеку reticulate в ваш первый фрагмент кода.

```{r}library(reticulate)```

Теперь, когда вы захотите написать код на Python, можно обернуть его обычными обратными кавычками, но пометить как фрагмент кода Python с помощью {python}, а когда захотите писать на R воспользуйтесь {r}.

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

```{python}import pandas as pdimport statsmodels.api as smimport statsmodels.formula.api as smf# obtain ugtests dataurl = http://peopleanalytics-regression-book.org/data/ugtests.csv"ugtests = pd.read_csv(url)# define modelmodel = smf.ols(formula = Final ~ Yr3 + Yr2 + Yr1, data = ugtests)# fit modelfitted_model = model.fit()# see results summarymodel_summary = fitted_model.summary()print(model_summary)```



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

Не бойтесь. Можно получить доступ ко всем объектам python, которые вы создали в общем списке с названием py. Поэтому, если создается блок R внутри вашего документа R Markdown, коллеги получат доступ к параметрам вашей модели:

```{r}py$fitted_model$params```



или первые несколько остатков:

```{r}py$fitted_model$resid[1:5]```



Теперь можно легко выполнить некоторую диагностику модели, например построить график остатков вашей модели типа квантиль-квантиль:

```{r}qqnorm(py$fitted_model$resid)```



Написание кода второй пример


Вы анализировали некоторые данные о быстрых знакомствах на Python и создали фрейм данных pandas со всеми данными в нём. Для простоты загрузим данные и посмотрим на них:

```{python}import pandas as pdurl = http://peopleanalytics-regression-book.org/data/speed_dating.csv"speed_dating = pd.read_csv(url)print(speed_dating.head())```


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

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

И снова ничего не бойтесь, отправьте проект коллеге и он напишет решение на R.

```{r}library(lme4)speed_dating <- py$speed_datingiid_intercept_model <- lme4:::glmer(dec ~ agediff + samerace + attr + intel + prob + (1 | iid), data = speed_dating, family = binomial)coefficients <- coef(iid_intercept_model)$iid```

Теперь вы можете получить код и посмотреть на коэффициенты. Также можно получить доступ к объектам R в Python внутри общего объекта r.

```{python}coefs = r.coefficientsprint(coefs.head())```


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

Вы можете увидеть готовый документ R Markdown, созданный на основе интеграции языков с фрагментами R и Python и объектами, перемещающимися между ними, опубликованный здесь. Репозиторий Github с исходным кодом находится здесь.

Примеры данных в документе взяты из моего Справочника по моделированию регрессии в People Analytics.

image


Подробнее..

Нападения на полицейских в США статистический обзор

18.01.2021 02:05:59 | Автор: admin

Эта статья логическое продолжение серии статей, которые я написал в этом году на тему криминала и правопорядка в США и их связи с расовой принадлежностью (раз, два). В первой серии статей, напомню, мы подробно рассматривали данные по гибели граждан от рук полицейских. А сегодня мы взглянем на этот вопрос с другой стороны: будем разбирать статистику нападений на самих полицейских и постараемся так же проследить закономерности и сделать выводы. Оружием преступников может быть пистолет или нож, а нашим оружием, как и прежде, будет python + pandas. Поехали!


Вместо предыстории


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

Кто-то из моих читателей оставил комментарий вроде понятно, почему в США полицейские не снимают палец со спускового крючка их самих отстреливают ежедневно. И я, естественно, захотел копнуть эту тему немного глубже и рассмотреть ее по другую сторону бронежилета: то есть, данные о нападениях на полицейских и гибели полицейских при исполнении обязанностей. Конечно же, тоже в США. Конечно же, тоже на основе открытых источников. Конечно же, опять python + pandas :)

Исходные данные


Задумано сделано. Благо, данные у меня уже были, я их накачал при изучении материала для предыдущего исследования. Напомню (или, вернее, сообщу) тем, кто по каким-то причинам не читал предыдущих статей, что все данные по преступности, численности полицейских, а также по нападениям на сотрудников правоохранительных органов в США я брал с сайта Crime Data Explorer, обеспечивающего публичный доступ к статистическим базам ФБР. При желании вы сами можете зайти и скачать оттуда те же исходные данные, которые использую я в своей работе.

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

Итак, какие файлы данных используются:

  • LEOKA_ASSAULT_TIME_WEAPON_INJURY_1995_2018.csv набор данных по нападениям на полицейских в США с 1995 по 2018 г. с указанием места, штата, города, времени, нанесенных телесных повреждений, случая гибели и т.п. (естественно, без личных сведений о преступниках и потерпевших)
  • crimes_by_state.csv количество совершенных преступлений насильственного характера (убийства, изнасилования, грабежи и нападения с отягчающими обстоятельствами) по годам и штатам
  • police_employee_1960_2019.csv количество работающих штатных и внештатных полицейских по годам (с 1960 по 2019 г.) и штатам, с указанием также общей численности населения штатов и доли полицейских от населения
  • us_pop_2010-2019_state_race.csv население по всем штатам США с 2010 по 2019 г., разбитое по расовой принадлежности (белые, черные, азиаты, гавайцы, индейцы и остальные) эти данные взяты с сайта Бюро переписи населения США (из России сайт не работает, можете не пытаться нажимать без VPN или прочих разных Торов)
  • us_states.csv перечень штатов США с сокращенными и полными названиями
  • us-states-geo.json координаты границ штатов США (для отображения данных на карте) взят отсюда
  • leoka_felony_2010-2019.xlsx подробные данные по убитым полицейским с 2010 по 2019 г. (включая информацию о возрасте, расе и статусе преступников и жертв и прочие полезные сведения)

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

Analiyze This...


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

Основной массив данных


После загрузки и объединения данных из различных источников получается вот такая большая таблица (показаны первые 15 из 1171 строк):

DATA_YEAR STATE_ABBR STATE_NAME TIME_0001_0200_CNT TIME_0201_0400_CNT TIME_0401_0600_CNT TIME_0601_0800_CNT TIME_0801_1000_CNT TIME_1001_1200_CNT TIME_1201_1400_CNT ... BLACK_POP POP OFFICER_COUNT OFFICER_RATE_PER_1000 ASSAULTS_PERMLN LETHAL_PERMLN LETHAL_ASSAULTS_PERC ASSAULTS_PER_OFFICERSCNT LETHAL_PER_OFFICERSCNT CRIME
0 1995 AK Alaska 24 31 9 4 4 4 7 ... 0.0 604000 1134 1.88 226.821192 0.000000 0.000000 0.120811 0.000000 4656
1 1995 AL Alabama 16 17 6 3 6 6 16 ... 0.0 4319212 9191 2.13 40.516650 0.231524 0.571429 0.019040 0.000109 26894
2 1995 AR Arkansas 49 30 22 17 21 20 17 ... 0.0 2540304 4743 1.87 173.994923 0.787307 0.452489 0.093190 0.000422 13741
3 1995 AZ Arizona 255 143 75 47 69 80 100 ... 0.0 4236915 8706 2.05 459.768487 0.708062 0.154004 0.223754 0.000345 30095
4 1995 CA California 893 537 212 159 280 328 469 ... 0.0 31854695 63218 1.98 235.538278 0.219748 0.093296 0.118685 0.000111 305154
5 1995 CO Colorado 61 29 17 4 13 15 24 ... 0.0 4892816 10982 2.24 81.956894 0.000000 0.000000 0.036514 0.000000 16494
6 1995 CT Connecticut 105 62 12 20 20 39 37 ... 0.0 3356858 7423 2.21 215.677875 0.000000 0.000000 0.097535 0.000000 13293
7 1995 DC District of Columbia 0 0 0 0 0 0 0 ... 0.0 554000 3691 6.66 0.000000 0.000000 0.000000 0.000000 0.000000 14744
8 1995 DE Delaware 1 5 1 0 0 0 0 ... 0.0 736565 2107 2.86 24.437762 0.000000 0.000000 0.008543 0.000000 5198
9 1995 FL Florida 1389 1041 430 260 318 565 508 ... 0.0 14214968 36383 2.56 705.523924 0.000000 0.000000 0.275651 0.000000 151711
10 1995 GA Georgia 277 58 34 12 45 42 41 ... 0.0 7259408 31523 4.34 109.099805 0.275505 0.252525 0.025125 0.000063 47317
11 1995 HI Hawaii 67 51 19 21 14 25 24 ... 0.0 1241665 2805 2.26 369.664926 0.000000 0.000000 0.163636 0.000000 3509
12 1995 IA Iowa 9 7 1 2 1 1 0 ... 0.0 3041956 4955 1.63 17.751736 0.000000 0.000000 0.010898 0.000000 10071
13 1995 ID Idaho 68 38 12 12 10 7 19 ... 0.0 1215666 2225 1.83 328.215151 0.000000 0.000000 0.179326 0.000000 3745
14 1995 IL Illinois 0 0 0 0 0 0 0 ... 0.0 12093701 32931 2.72 0.000000 0.000000 0.000000 0.000000 0.000000 117836


В таблице этой аж 37 столбцов! Давайте сразу разберемся, что тут есть:

Столбец Тип Описание
DATA_YEAR uint16 Год
STATE_ABBR object Краткое название штата
STATE_NAME object Полное название штата
TIME_0001_0200_CNT uint16 Кол-во нападений с 00:01 до 02:00 часов
TIME_0201_0400_CNT uint16 Кол-во нападений с 02:01 до 04:00 часов
TIME_0401_0600_CNT uint16 Кол-во нападений с 04:01 до 06:00 часов
TIME_0601_0800_CNT uint16 Кол-во нападений с 06:01 до 08:00 часов
TIME_0801_1000_CNT uint16 Кол-во нападений с 08:01 до 10:00 часов
TIME_1001_1200_CNT uint16 Кол-во нападений с 10:01 до 12:00 часов
TIME_1201_1400_CNT uint16 Кол-во нападений с 12:01 до 14:00 часов
TIME_1401_1600_CNT uint16 Кол-во нападений с 14:01 до 16:00 часов
TIME_1601_1800_CNT uint16 Кол-во нападений с 16:01 до 18:00 часов
TIME_1801_2000_CNT uint16 Кол-во нападений с 18:01 до 20:00 часов
TIME_2001_2200_CNT uint16 Кол-во нападений с 20:01 до 22:00 часов
TIME_2201_0000_CNT uint16 Кол-во нападений с 22:01 до 00:00 часов
FIREARM_INJURY_CNT uint16 Кол-во нападений с применением огнестрельного оружия
FIREARM_NO_INJURY_CNT uint16 Кол-во нападений с применением огнестрельного оружия
KNIFE_INJURY_CNT uint16 Кол-во нападений с применением холодного оружия
KNIFE_NO_INJURY_CNT uint16 Кол-во нападений с применением холодного оружия
HANDS_FISTS_FEET_INJURY_CNT uint16 Кол-во нападений с ударами руками, ногами (с телесными повреждениями)
HANDS_FISTS_FEET_NO_INJURY_CNT uint16 Кол-во нападений с ударами руками, ногами (без повреждений)
OTHER_INJURY_CNT uint16 Кол-во нападений с применением иного орудия (с телесными повреждениями)
OTHER_NO_INJURY_CNT uint16 Кол-во нападений с применением иного орудия (без повреждений)
LEOKA_FELONY_KILLED uint16 Кол-во предумышленных убийств
LEOKA_ACCIDENT_KILLED uint16 Кол-во непредумышленных убийств
ASSAULTS uint32 Кол-во нападений (общее)
WHITE_POP float64 Кол-во белого населения (чел.)
BLACK_POP float64 Кол-во черного населения (чел.)
POP uint32 Общее кол-во населения (чел.)
OFFICER_COUNT uint32 Численность сотрудников полиции (чел.)
OFFICER_RATE_PER_1000 float64 Численность сотрудников полиции на 1000 чел.
ASSAULTS_PERMLN float64 Кол-во нападений на 1 млн. населения
LETHAL_PERMLN float64 Кол-во убийств полицейских на 1 млн. населения
LETHAL_ASSAULTS_PERC float64 % убийств от нападений
ASSAULTS_PER_OFFICERSCNT float64 Кол-во нападений на 1 работающего полицейского
LETHAL_PER_OFFICERSCNT float64 Кол-во убийств полицейских на 1 работающего полицейского
CRIME uint32 Кол-во тяжких совершенных преступлений


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

Среднегодовые показатели по штатам


После усреднения данных по всему периоду наблюдений (напомню: с 1995 по 2018 год включительно) можем посмотреть, скажем, на среднегодовое количество нападений на полицейских по всем штатам США. Для наглядности также отразим на том же графике среднегодовое количество совершенных преступлений (здесь и далее все картинки кликабельны):



Картинка здесь примерно та же, которую мы видели при анализе распределения уровня преступности по штатам: самые населенные штаты ожидаемо доминируют (Калифорния, Флорида, Техас), поскольку, естественно, чем больше народа, тем больше и полиции, и конфликтов с полицией. Это подтверждает и зеленая кривая тяжких преступлений, которая по большому счету повторяет очертания синих столбиков. Но здесь обращает на себя внимание Мэриленд далеко не самый населенный штат (на 19-м месте по населению) в непосредственной близи от столицы страны. К этому моменту мы еще вернемся, а пока давайте попробуем отфильтровать составляющую населения и посмотреть на удельные показатели (на 1 млн. человек):



Здесь на первом плане не самые населенные штаты Округ Колумбия (т.е. Вашингтон), тот же Мэриленд, Делавэр, Аляска и та же Флорида. Отсюда можно сделать вывод: в Мэриленде и Флориде нападения на полицейских происходят практически независимо от того, сколько людей проживает в этих штатах. Также здесь налицо отсутствие четкой корреляции с данными по преступлениям: в лидирующих штатах по нападениям на полицейских (кроме Округа Колумбия) удельный уровень преступности не самый высокий, как, например, в Нью-Мексико, Неваде или Южной Каролине.

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



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

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



Здесь сразу бросается в глаза тот факт, что самое большое количество нападений в расчете на одного полицейского происходит в штатах, где численность полиции не самая высокая (первые три лидера Аляска, Мэриленд и Аризона). Во Флориде укомплектованность полицией очень высокая (оно и понятно наркотрафик и все такое), но при этом и нападений много почти каждый шестой полицейский ежегодно подвергается нападению. Конечно, это не то, что в Аляске и нашем любимом Мэриленде, где почти каждый четвертый полицейский огребает от населения, но все же это довольно много (интересно было бы, кстати, сравнить с ситуацией в России). В среднем же, как мы видим, в Штатах нападению подвергается каждый 11-ый полицейский.

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



Ожидаемо, здесь на вершине два крупнейших штата Техас и Калифорния, а также интересно, что довольно высокие показатели по этой зловещей статистике демонстрируют три восточных / юго-восточных штата Миссури, Луизиана и Вирджиния. Лучше даже посмотреть, как это выглядит на карте:



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

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





Интересно: неожиданно выстреливает (простите за дурной каламбур) Южная Дакота и четыре хлопковых штата на юго-востоке: Миссисипи, Алабама, Джорджия и Южная Каролина. Южная Дакота занимает одно из последних мест по количеству и плотности населения, а также 3-е место по численности коренного населения (индейцев около 8,5%). В индейских резервациях довольно низкий доход на душу населения, и, возможно, поэтому Впрочем, мы договорились: никаких гипотез, не кормим хейтеров :)

Нападения по времени суток


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



Так и есть! Количество неадекватовграждан, склонных решать свои разногласия с правоохранительными органами физическим путем, возрастает с наступлением ночи, достигая своего пика с часу до двух утра, и постепенно спадает под утро, с минимумом в промежуток с 06:00 до 08:00. Как говорится, мафия засыпает.

Идем дальше!

Годовые изменения общих показателей по стране


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



Что мы здесь можем увидеть? До 2008 г. численность полиции активно наращивается, но количество нападений остается примерно на одном уровне (в районе 60 тыс. в год). С 2008 по 2016 г. полицейские подразделения особо не растут в численности, зато нападения становятся год от года все реже, хотя и спад едва заметен. В 2016 году происходит какой-то всплеск насилия (с возвратом на уровень 1998 г.), а также достигает своего пика численность полиции. А после 2016 г. штат полиции начинает резко сокращаться до уровня 2000 г. в 2018 г., при этом снижающийся тренд нападений удается сохранить.

Сокращение штата полиции началось при Дональде Трампе в 2017 г. и, вполне вероятно, будет продолжено при новом президенте на фоне публичных движений против полиции (BLM, Defund the Police и т.д.). При этом сохранение спада нападений на полицейских может, конечно, объясняться как раз сокращением самих полицейских, однако здесь важнее прогноз уровня преступности в стране, который, естественно, зависит от наличия и количества стражей порядка. Если эта тема интересна, в этой статье представлен неплохой обзор.

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



А что с убийствами полицейских? Давайте посмотрим:



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

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



Очевидно, здесь аналогичная картина.

Но черт возьми, давайте уже разберемся с 2016 годом! Что за всплеск насилия против полиции? Посмотрим на этот год в разрезе штатов, отобразив как убийства, так и нападения:



В половине штатов убийств вообще не было, в четверти штатов было по 1-2 случаям, а остальные случаи приходятся, в основном, на южные и восточные штаты. Про Техас и Калифорнию мы уже знаем Но в чем проблема в Вирджинии? Синяя точка показывает, что в этот год в Вирджинии было не так уж много нападений на полицейских (чуть больше 1500) не то, что в Техасе, Калифорнии и Флориде. И при этом 11 убитых полицейских! Анализ исходного файла (LEOKA_ASSAULT_TIME_WEAPON_INJURY_1995_2018.csv) показывает, что было зарегистрировано 9 случаев, из которых в 8 случаях убито по 1 полицейскому, а в 1 случае убито сразу 3.

Здесь необходимо отдельно указать, что, конечно же, нельзя считать исходную базу ФБР, откуда мы берем данные по нападениям и убийствам полицейских, на 100% полной. Эти данные собираются ФБР на основе добровольно направляемой информации различными агентствами (подразделениями полиции). То есть если какое-то подразделение не участвует в программе предоставления сводной информации, соответствующих случаев в базе попросту не будет! Простой пример: за тот же 2016 г. в штате Айова в базе не зарегистрировано ни одного намеренного убийства полицейских. При этом был довольно громкий случай стрельбы в г. Де-Мойн из засады с гибелью целых двух полицейских, который даже описан на отдельной странице в Википедии. Кстати, обратите внимание на этот список убитых полицейских пока он не полный, но начиная с 2018 г. уже есть контент и ссылки на источники. В частности, отдельно освещены стрельбы в Техасе и Луизиане в 2016 г. Дополнительно, если нужны более детальные описания случаев убийства полицейских, на том же сайте ФБР доступна ежегодно пополняемая публикация, подробно освещающая эти события по каждому штату на настоящий момент книжечка покрывает события с 2002 по 2019 г. и занимает 563 страницы без картинок :)


Виды телесных повреждений


Давайте теперь посмотрим на статистику нападений по видам наносимых телесных повреждений. Зачем? Потому что мы можем :)



ОК, по годам доли остаются примерно теми же. Посмотрим в укрупненном виде, усреднив данные по всем наблюдениям:



Итак, подавляющее большинство всех телесных повреждений при нападениях наносится голыми руками и ногами. Огнестрельное и холодное оружие используется только в 3% нападений, и остальные 13% может быть чем угодно (хоть плюшевым мишкой). Впрочем, средняя доля смертельных случаев составляет всего 0,07%, поэтому эти 3% огнестрельного и холодного оружия (а также не забываем про все остальное) вполне объясняют смертельные случаи.

Расовый и возрастной состав преступников и их жертв


Далее рассмотрим более подробные данные по расовому и возрастному составу убийц и убитых полицейских. Эти данные доступны в файле leoka_felony_2010-2019.xlsx, который я собрал из отдельных таблиц, доступных на том же сайте LEOKA. Отличие от основного массива данных в том, что в этом случае наблюдения ограничены периодом с 2010 по 2019 г., однако при этом нам доступны более подробные сведения о расе, поле, возрасте преступников и жертв и их статусе с точки зрения закона (например, под домашним арестом, рецидивист и т.д.).

Начнем с расового состава преступников (т.е. убийц полицейских):



Ожидаемо белая раса выделяется просто потому, что белых в США больше. Но обратим мимоходом внимание: пропорция не всегда была одинаковой (например, в 2010 чернокожие преступники даже численно превосходили, а в 2015 г. примерно 50/50). Но давайте посмотрим на усредненные показатели:



56% белых, 37% черных и 6% всех остальных. При этом если брать все население США, расовый состав довольно сильно отличается. Так представители каких же рас статистически чаще убивают полицейских? Давайте посмотрим на удельные показатели:



Здесь однозначно доминируют черные и индейцы. Примерно на каждые 2 млн. чернокожих или индейцев один убийца. Для белых же этот показатель 1 убийца на каждые 8 млн. (т.е. в 4 раза меньше). Это наблюдение согласуется с результатами предыдущего исследования по преступности в США, где также была выявлена большая склонность чернокожих к совершению преступлений (под склонностью я имею в виду, конечно, не этническую или психологическую расположенность, а статистическую закономерность).

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



Картина здесь также довольно обычная: половина всех убийств приходится на молодых людей в возрасте от 18 до 30 лет. Целесообразно предположить, что именно этот промежуток жизни в целом наиболее связан с наиболее активными действиями (плохими или хорошими). По мере старения (после 35 лет) убивают все меньше, хотя и на возраст после 60 лет приходится 2% убийств старый не значит безобидный :) Несовершеннолетних убийц 3%.

А теперь посмотрим на статистику по убитым полицейским. Начнем с расового состава:



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



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

Последнее, на что осталось взглянуть, это возрастной состав убитых:



Здесь видим довольно ровное распределение возрастных групп от 25 до 50 лет (с небольшим превалированием группы с 31 до 35 лет), что говорит о таком же равномерном распределении оперативных работников полиции по возрасту. Убитых в возрасте до 25 лет всего 4%, из чего можем заключить, что новичков обычно не отправляют на опасные задания, связанные с риском для жизни. Впрочем, чтобы эти заключения были более достоверными, также необходимы данные по возрастному составу всех полицейских.

Корреляции


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

Для анализа же возьмем самые основные показатели: количество нападений на полицейских, количество совершаемых преступлений, численность полиции и численность населения:
Нападения Преступления Кол-во полицейских Население
Нападения 1.000000 0.827702 0.739385 0.779203
Преступления 0.827702 1.000000 0.904080 0.931361
Кол-во полицейских 0.739385 0.904080 1.000000 0.958782
Население 0.779203 0.931361 0.958782 1.000000

Здесь все наиболее значимые зависимости выделены жирным шрифтом. Таким образом, очевидны следующие взаимосвязи:

  • Между количеством нападений на полицейских и количеством тяжких преступлений: логично предположить, что конфликты, приводящие к физической агрессии против полицейских, в свою очередь связаны с уровнем преступности. Чем больше преступлений, тем больше стычек с полицией (спасибо, кэп!).
  • Между количеством нападений на полицейских и численностью полиции. Здесь также все однозначно: чем больше объектов нападения, тем больше и самих нападений. Так как нападение (в отличие, в какой-то мере, от убийства) трудно предотвратить (например, теоретически любой может подойти к человечку в форме и дать ему пинка это будет уже нападением), отсюда и корреляция. Кстати, мы уже говорили, что именно поэтому количество нападений на полицейских снижается с 2017 г. потому что снижается и численность самих полицейских. Что, конечно, не говорит о повышении безопасности в обществе.
  • Между количеством нападений на полицейских и населением. Тут тоже все ясно: больше людей больше преступников и полицейских больше конфликтов между ними.
  • Между количеством преступлений и численностью полиции: численность полиции наращивается в ответ на увеличение преступности или, говоря по-другому, в регионах, где совершается больше преступлений, нанимается больше полиции для сдерживания преступности.
  • Между количеством преступлений и населением: эту корреляцию мы уже рассматривали в предыдущих исследованиях, она самоочевидна.
  • Между численностью полиции и населением. Здесь логика та же: больше народа больше преступников больше полицейских.


На этом наш небольшой анализ подошел к концу. Спасибо за ваши отзывы!
Подробнее..
Категории: Python , Open source , Big data , Data mining , Pandas , Usa , Police , Statistics

Перевод Как сделать Data Science приложение для Windows (и не только) с графическим интерфейсом с помощью PySimpleGUI

23.01.2021 16:18:40 | Автор: admin
Работать с Data Science в Jupyter, конечно, очень приятно, но если вы хотите пойти дальше и развернуть свой проект или модель на облачном сервере, то здесь есть много отличных решений с помощью Flask, Django или Streamlit. Хотя облачные решения по-прежнему самые популярные, часто хочется создать быстрое приложение с графическим интерфейсом. Например:

  • Модель ML тестируется на различных наборах данных. Вы можете перетащить файлы CSV в модель и отрисовать кривую AUS/ROC. Здесь GUI проявит себя прекрасно, правда?
  • Построить случайную переменную или статистическое распределение в заданном диапазоне и динамически управлять параметрами с помощью графического интерфейса.
  • Быстро запустить некоторые задачи обработки или предварительной обработки данных в наборе с помощью GUI вместо того, чтобы писать кучу кода.

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




Что такое PySimpleGUI?


В экосистеме Python есть несколько очень популярных GUI-фреймворков, таких как Tkinter, PyQt и т. д. Но часто они несколько раздуты и трудны в изучении для специалистов по Data Science, которые могут захотеть написать простое приложение с минимумом кода, а не тратить время на разработку крупной программы с графическим интерфейсом на уровне энтерпрайза.

Обёртка, которую легко изучить


На сайте PySimpleGUI написано: Python GUI для людей трансформирует Tkinter, Qt, Remi, WxPython в портативные Pythonic-интерфейсы, дружественные людям. По сути, этот GUI-фреймворк берёт все эти популярные и хорошо зарекомендовавшие себя GUI-фреймворки и обёртывает их в единую библиотеку, которую просто изучить и затем собирать приложения. Вам даже не нужно писать определение класса, чтобы создать GUI-приложение! Часто специалисты по Data Science не имеют достаточно опыта в разработке. Они могут извлечь огромную пользу из изучения и применения инструмента, который даёт возможность создавать небольшие целевые приложения с графическим интерфейсом для изучения данных, их анализа, экспериментов с моделями ML и т. д. Поэтому я создал репозиторий, чтобы заполнять его короткими, целенаправленными скриптами, которые при запуске создают настольные приложения. Вот этот репозиторий. В сети уже есть несколько хороших туториалов о PySimpleGUI. В моём репозитории я уделяю особое внимание созданию простых демонстрационных программ, связанных с наукой о данных (простая аналитика, статистическое моделирование, визуализации и базовое машинное обучение), с использованием этого мощного инструмента построения графического интерфейса.

Преимущества обёртки


  • Не нужно никаких обратных вызовов.
  • Чтобы сократить объём кода, используются конструкции Python. Например, виджет настраивается прямо на месте, в котором он должен быть, а не на расстоянии нескольких строк кода от этого места.
  • Зависит от одного пакета: обёртывает Tkinter и не требует установки других пакетов.
  • Одна и та же программа с GUI может выполняться на нескольких платформах, включая веб-браузер, без изменения исходного кода, за исключением оператора импорта.
  • Можно разрабатывать интерфейс для нескольких платформ ОС Windows, Linux, Raspberry Pi и Android (PyDroid3) с очень незначительными изменениями.



В принципе, можно начать создавать работающие (и полезные) приложения с GUI, имея базовые знания Python, и вы справитесь за день.

Примеры приложений


Установите библиотеку вот так: pip install pysimplegui. Чтобы запустить примеры, вам также понадобятся эти библиотеки:

  • Numpy.
  • Pandas.
  • Matplotlib.
  • Scikit-learn.
  • Seaborn.

Data Science Hello World


Простейшая программа в PySimpleGUI отобразит строку Hello World в маленьком окне. Но, в духе DS, давайте сделаем нашу вводную программу интереснее и полезнее! Вот скрипт. Назовём его GenRandom.py.



Перейдите в каталог с этим скриптом, выполните команду python GenRandom.py. Вы увидите простое всплывающее окно, в котором можно нажать кнопку, чтобы вызвать функцию обновления (см. код выше), чтобы сгенерировать случайное число от 1 до 99.



Хотя это очень простой сценарий, в нём есть:

  • макет (с аргументами стиля, например size и font) и окно;
  • элемент кнопки, который вызывает внешнюю функцию (событие);
  • функция обновления текстового элемента в объекте окна.

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

Другие виджеты


Вот еще один сценарий, иллюстрирующий другие виджеты. Просто запустите команду:

python FontUpdate.py

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



Решатель уравнений


Запустите команду python QuadraticEquation.py и вы увидите всплывающее окно, в котором можно ввести коэффициенты квадратного уравнения, чтобы решить его (даже если корни окажутся комплексными числами!).



Анализатор Pandas DataFrame


В этом примере мы показываем, как легко создать GUI, который взаимодействует с широко используемым объектом, например с Pandas DataFrame. Как обычно, вы запускаете скрипт командой python SimpleDataFrame.py. Вначале он запросит у вас файл набора данных (CSV).



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



После выбора cars.csv появятся другие запросы:







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



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



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



Генератор случайных диаграмм рассеяния


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



Приложение для подгонки кривой


Специалисты по DS и аналитики всегда подгоняют кривые или аналитические функции под некоторые данные. Легко создать простое приложение, где вы сможете продемонстрировать это с помощью PySimpleGUI.

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



Пример обучения модели Scikit-learn


Наконец-то мы снисходим до примера настоящего ML. Мы покажем, как построить простое приложение, позволяющее загрузить набор данных Pima Indians diabetes и обучить модель Случайного леса на этих данных с помощью Scikit-learn в фоновом режиме. Скрипт лежит здесь. На рисунке ниже показывается работа этой программы с графическим интерфейсом. Обратите внимание, что она охватывает стандартные процессы, как ожидается от программы машинного обучения:

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



Резюме


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

Cookbook PySimpleGUI не так давно вернула в название слово Cookbook, поэтому использовалась устаревшая документация pysimplegui.readthedocs.io.

В этой статье мы показали примеры из списка ниже:

  • различные виды виджетов для управления;
  • ввод и вывод данных чтение файлов и генерация графиков;
  • традиционные библиотеки DS: Numpy, Pandas, Matplotlib, и Scikit-learn.

Очевидно, что на этих примерах можно построить гораздо больше интуитивно понятных GUI-приложений для работы с данными. Я планирую продолжать добавлять такие примеры в свой репозиторий на Github, их вы можете форкнуть или отметить звёздочкой, если захотите. Посмотрите мои репозитории, там есть не только код, но идеи и ресурсы по ML и Data Science.

А если хотите учиться ML и Data Science приходите к нам, будет сложно но интересно. А промокод HABR, добавляющий 10% к скидке на баннере, вам поможет.



image



Подробнее..

Перевод Как использовать функцию UNNEST в Google BigQuery для анализа параметров событий Google Analytics

21.01.2021 10:23:56 | Автор: admin

В этой статье я расскажу о том, как использовать функцию UNNEST в Google BigQuery для анализа параметров событий и свойств пользователей, которые вы получаете вместе с данными Google Analytics.

От автора перевода:

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

Если вы интересуетесь анализом данных возможно вам будут интересены мои telegram и youtube канал. Большая часть контента посвящена языку программирования R.

Cложность работы с данными Firebase в BigQuery - и это относится не только к данным Analytics, но и к данным Crashlytics - заключается в том, что ваши данные не организованы в виде простых строк и столбцов, как на примере ниже:

Как вы, вероятно, представляете свои данные BigQueryКак вы, вероятно, представляете свои данные BigQuery

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

Как выглядят ваши данные в BigQuery на самом делеКак выглядят ваши данные в BigQuery на самом деле

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

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

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

SELECT *FROM `firebase-public-project.analytics_153293282.events_20180915`WHERE event_name = "level_complete_quickplay"LIMIT 10

Выполнив приведённый выше запрос, вы получите записи событий прохождения уровня, а также несколько других параметров событий, которые могут показаться интересными. У нас есть параметр value, который регистрирует количество ходов, которые потребовались игроку, чтобы пройти уровень, и параметр board, который записывает размер игрового поля (S, M или L).

Вы также можете заметить, что каждый из этих параметров содержит не один столбец значений, а несколько: int_value, string_value, double_value и float_value.

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

Такая запись аналогичка JSON объектуТакая запись аналогичка JSON объекту

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

SELECT *FROM `firebase-public-project.analytics_153293282.events_20180915`WHERE event_name = "level_complete_quickplay"AND event_params.key = "value"LIMIT 10

В результате мы получим не особо информативное сообщение об ошибке.

Проблема здесь в том, что поле event_params по сути является массивом (на самом деле, говоря языком BigQuery, это повторяющаяся запись (repeated record), но вы можете представлять её как массив). Таким образом, хотя event_params может содержать несколько строк, которые сами по себе имеют поле key, само поле event_params его не содержит.

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

Для начала рассмотрим более простой пример. Представим, что у нас есть таблица, заполненная информацией о космических кораблях. А экипаж (поле crew) - это массив, очень похожий на event_params в наших таблицах из Analytics.

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

SELECT * FROM `spaceships` WHERE crew = "Zoe"

Но я получу нужный результат используя следующий запрос:

SELECT * FROM `spaceships` CROSS JOIN UNNEST(crew) as crew_member

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

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

SELECT * FROM `spaceships` CROSS JOIN UNNEST(crew) as crew_member WHERE crew_member = "Zoe"

На практике большинство пользователей BigQuery заменяют CROSS JOIN запятой, например:

SELECT * FROM `spaceships`,UNNEST(crew) as crew_member WHERE crew_member = "Zoe"

Этот запрос делает то же самое что и предыдущий, но выглядит компактнее и аккуратнее.

Итак, возвращаясь к нашему основному примеру, мы, по сути, имеем массив (или повторяющуюся запись) event_params Если я напишу:

SELECT * FROM `my_analtyics_table`,UNNEST(event_params) as param

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

Обратите внимание, сам параметр param по-прежнему является вложенным объектом. Но это единичная запись, а не повторяющаяся. (Опять же, вроде как структура.) Таким образом, мы можем обращаться к таким полям как param.key или param.value.int_value. В частности, теперь мы можем искать только те строки, в которых param.key равен value.

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

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

SELECT event_name, paramFROM `firebase-public-project.analytics_153293282.events_20180915`,UNNEST(event_params) AS paramWHERE event_name = "level_complete_quickplay"AND param.key = "value"

Теперь мне не составит труда получить фактическое значение параметра value, посмотрев на param.value.int_value.

SELECT event_name, param.value.int_value AS scoreFROM `firebase-public-project.analytics_153293282.events_20180915`,UNNEST(event_params) AS paramWHERE event_name = "level_complete_quickplay"AND param.key = "value"

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

SELECT AVG(param.value.int_value) AS average,   APPROX_QUANTILES(param.value.int_value, 2) AS quantiles,   STDDEV(param.value.int_value) AS stddevFROM `firebase-public-project.analytics_153293282.events_20180915`,UNNEST(event_params) AS paramWHERE event_name = "level_complete_quickplay"AND param.key = "value"

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

SELECT param.value.int_value AS score, COUNT(1) AS countFROM `firebase-public-project.analytics_153293282.events_20180915`,UNNEST(event_params) AS paramWHERE event_name = "level_complete_quickplay"AND param.key = "value"GROUP BY 1ORDER BY 1

Итак это интересно. Есть довольно большой пик в районе 21 или 22 ходов но если вы продолжите поиск, то найдёте еще несколько более мелких пиков в районе 29 ходов и в диапазоне 3436 ходов.

Причина тому - другой параметр, о котором я говорил - board. Большая часть игр ведется на маленькой доске (S), есть и другие игры, которые проводятся на средних (M) и больших (L) досках, и они, вероятно, составляют меньшие пики.

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

SELECT paramFROM `firebase-public-project.analytics_153293282.events_20180915`,UNNEST(event_params) AS paramWHERE event_name = "level_complete_quickplay"AND (param.key = "value" OR param.key = "board")

Всё верно, параметр value , т.е. количество сделанных пользователем ходов, выше, когда игра проходит на поле размером M или L.

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

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

SELECT MAX(if(param.key = "value", param.value.int_value, NULL)) AS score,  MAX(if(param.key = "board", param.value.string_value, NULL)) AS board_typeFROM (  SELECT user_pseudo_id, event_timestamp, param  FROM `firebase-public-project.analytics_153293282.events_20180915`,  UNNEST(event_params) AS param  WHERE event_name = "level_complete_quickplay"  AND (param.key = "value" OR param.key = "board"))GROUP BY user_pseudo_id, event_timestamp

Затем мы можем проанализировать результат в разрезе размера игрового поля.

SELECT ANY_VALUE(board_type) as board, AVG(score) as average_scoreFROM  (  SELECT MAX(if(param.key = "value", param.value.int_value, NULL)) AS score,    MAX(if(param.key = "board", param.value.string_value, NULL)) AS board_type  FROM (    SELECT user_pseudo_id, event_timestamp, param    FROM `firebase-public-project.analytics_153293282.events_20180915`,    UNNEST(event_params) AS param    WHERE event_name = "level_complete_quickplay"    AND (param.key = "value" OR param.key = "board")  )  GROUP BY user_pseudo_id, event_timestamp) GROUP BY board_type

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

Подробнее..

Кластеризация и классификация больших Текстовых данных с помощью М.О. на Java. Статья 3 АрхитектураРезультаты

24.01.2021 14:08:22 | Автор: admin

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

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

Архитектуры системы можно разделить на две основные части: веб приложение и программное обеспечение кластеризации и классификации данных

Алгоритм программного обеспечение для машинного обучение состоит из 3 основных частей:

  1. обработка естественного языка;

    1. токенизация;

    2. лемматизация;

    3. стоп-листинг;

    4. частота слов;

  2. методы кластеризации ;

    1. TF-IDF ;

    2. SVD;

    3. нахождение кластерных групп;

  3. методы классификации Aylien API.

Обработка естественного языка

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

Ниже приводим сравнение при запуске алгоритмов Лемматизации и Стеммитизации:

Общее количество слов: 4173415Количество слов после приминение Лемматизации: 88547Количество слов после приминение Стеммитизации: 82294

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

characterize, design, space, render, robot, face, alisa, kalegina, university, washington, seattle, washington, grace, schroeder, university, washington, seattle, washington, aidan, allchin, lakeside, also, il, school, seattle, washington, keara, berlin, macalester, college, saint, paul, minnesota, kearaberlingmailcom, maya, cakmak, university, washington, seattle, washington, abstract, face, critical, establish, agency, social, robot, building, expressive, mechanical, face, costly, difficult, robot, build, year, face, ren, der, screen, great, flexibility, robot, face, open, design, space, tablish, robot, character, perceive, property, despite, prevalence, robot, render, face, systematic, exploration, design, space, work, aim, fill, gap, conduct, survey, identify, robot, render, face, code, term, property, statistics

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

character, design, space, render, robot, face, alisa, kalegina, univers, washington, seattl, washington, grace, schroeder, univers, washington, seattl, washington, grsuwedu, aidan, allchin, lakesid, also, il, school, seattl, washington, keara, berlin, macalest, colleg, saint, paul, minnesota, kearaberlingmailcom, maya, cakmak, univers, washington, seattl, washington, abstract, face, critic, establish, agenc, social, robot, build, express, mechan, face, cost, difficult, mani, robot, built, year, face, ren, dere, screen, great, flexibl, robot, face, open, design, space, tablish, robot, charact, perceiv, properti, despit, preval, robot, render, face, systemat, explor, design, space, work, aim, fill, gap, conduct, survey, identifi, robot, render, face, code, term, properti, statist, common, pattern, observ, data, set, face, conduct, survey, understand, peopl, percep, tion, render, robot, face, identifi, impact, differ, face, featur, survey, result, indic, prefer, vari, level, realism, detail, robot, facecharacter, design, space, render, robot, face, alisa, kalegina, univers, washington, seattl, washington, grace, schroeder, univers, washington, seattl, washington, grsuwedu, aidan, allchin, lakesid, also, il, school, seattl, washington, keara, berlin, macalest, colleg, saint, paul, minnesota, kearaberlingmailcom, maya, cakmak, univers, washington, seattl, washington, abstract, face, critic, establish, agenc, social, robot, build, express, mechan, face, cost, difficult, mani, robot, built, year, face, ren, dere, screen, great, flexibl, robot, face, open, design, space, tablish, robot, charact, perceiv, properti, despit, preval, robot, render, face, systemat, explor, design, space, work, aim, fill, gap, conduct, survey, identifi, robot, render, face, code, term, properti, statist, common, pattern, observ, data, set, face, conduct, survey, understand, peopl, percep, tion, render, robot, face, identifi, impact, differ, face, featur, survey, result, indic, prefer, vari, level, realism, detail, robot, face

Методы кластеризации

Для применения алгоритма tf-idf нужно подсчитать сколько раз слово встречается в каждом документе. Можно использовать HashMap, где ключ - слово, значение - кол-во.

После этого нужно построит матрицу документы-слова:

Далее по формуле вычисляем tf-idf:

Следующий этап, использование метода сингулярного разложение, где на вход приходит результат tf-idf. Пример выходных данных алгоритма сингулярного разложение:

-0.0031139399383999997 0.023330604746 -1.3650204652799997E-4-0.038380206566 0.00104373247064 0.056140327901-0.006980774822399999 0.073057418689 -0.0035209342337999996-0.0047152503238 0.0017397257449 0.024816828582999998-0.005195951771999999 0.03189764447 -5.9991080912E-4-0.008568593700999999 0.114337675179 -0.0088221197958-0.00337365927 0.022604474721999997 -1.1457816390099999E-4-0.03938283525 -0.0012682796482399999 0.0023486548592-0.034341362795999995 -0.00111758118864 0.0036010404917-0.0039026609385999994 0.0016699372352999998 0.021206653766000002-0.0079418490394 0.003116062838 0.072380311755-0.007021828444599999 0.0036496566028 0.07869801528199999-0.0030219410092 0.018637386319 0.00102082843809-0.0042041069026 0.023621439238999998 0.0022947637053-0.0061050946438 0.00114796066823 0.018477825284-0.0065708646563999995 0.0022944737838999996 0.035902813761-0.037790461814 -0.0015372596281999999 0.008878823611899999-0.13264545848599998 -0.0144908102251 -0.033606397957999995-0.016229093174 1.41831464625E-4 0.005181988760999999-0.024075296507999996 -8.708131965899999E-4 0.0034344653516999997

Матрицу SVD можно использовать как координаты в трехмерном пространстве.

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

Теперь нужно применить данную операцию и для терминов, то есть слов.

Последний этап метода кластеризации найти кластерные группы. Так как у нас уже есть трехмерная пространство, где хранятся точки документов и терминов в виде вершин, то нужно соединить эти документы и слова использовав схожий метод кластеризации DBSCAN. Для определения расстояние между документом и словом используется Евклидовое расстояние. А радиус можно определить по формуле ниже. В данном примере и при тестировании используется r=0.007. Так как в пространстве находится 562 документов и более 80.000 тысяч слов, то они расположены близко. При большом радиусе алгоритм будет связывать термин и документ в один кластер, которые не должны быть в одной группе.

r=max(D)/n

где max(D) это дистанция между документом и самой дальней точкой термина, то есть максимальная дистанция документа в пространстве. n - это количество документов в пространстве

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

После этого нужно всего лишь соединить вершины документов, которые имеют общие вершины терминов. Для соединения документов нужно чтобы общее число терминов было больше 4-х. Формула определение общего сила слов (в данном случае > nt)

nt=N/S

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

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

Методы классификации Aylien API

Для классификации в инструменте Aylien API всего лишь нужно передать любой текст. API вернет ответ в виде json объекта, где внутри есть категории классификации. Можно было бы отправлять весь текст каждого документа в одной группе кластеров через API и получить категории классификации. Для примера рассмотрим 9 групп кластеров, которые состоят из статьи про ИТ технологии. Все тексты документов каждой группы записываются в массив и отправляют запрос POST через API:

String queryText = "select  DocText from documents where clusters = '" + cluster + "'";   OResultSet resultSet = database.query(queryText);   while (resultSet.hasNext()) {   OResult result = resultSet.next();   String textDoc = result.toString().replaceAll("[\\<||\\>||\\{||\\}]", "").replaceAll("doctext:", "")   .toLowerCase();   keywords.add(textDoc.replaceAll("\\n", ""));   }   ClassifyByTaxonomyParams.Builder classifyByTaxonomybuilder    = ClassifyByTaxonomyParams.newBuilder();   classifyByTaxonomybuilder.setText(keywords.toString());   classifyByTaxonomybuilder.setTaxonomy(ClassifyByTaxonomyParams.StandardTaxonomy.IAB_QAG);   TaxonomyClassifications response = client.classifyByTaxonomy(classifyByTaxonomybuilder.build());   for (TaxonomyCategory c : response.getCategories()) {   clusterUpdate.add(c.getLabel());   }

После успешного получение ответа от сервиса методам GET, данные группы обновляются:

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

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

Разработка веб-интерфейса

Цель разработки веб-интерфейса наглядный вид результата использование алгоритма кластеризации и классификации. Это дает пользователю удобный интерфейс не только увидеть сам результат, но и в дальнейшем использовать эти данные для нужд. Так же разработка веб-интерфейса показывает, что данный метод можно успешно использовать для онлайн библиотек. Веб приложение было написано с использованием Фреймворка Vaadin Flow:

В данном приложении есть следующие функции:

  • Документы, разделенные по предметам методом кластеризации и классификации.

  • Поиск по ключевым словам.

  • Поиск по хэш-тегам.

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

  • Возможность скачивание файла.

Список документов классификации по предмету Technology & Computing:

Список документов найденные по ключевым словам:

Табличный список всех документов:

Заключение

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

Разработка алгоритма кластеризации, который включают в себе последовательное применение алгоритмов лемматизации, токенизации, стоп-листниг, tf-idf, сингулярного разложение. Первые три метода относится к методу обработки естественного языка, данные методы можно изменить под язык обрабатываемого текста. Для нахождение кластерных групп используется алгоритм на основе метода DBSCAN и использование Евклидового расстояние для определения расстояние между объектами. При исследовании было доказано что точность кластеризации зависит от отношения количества кластеров к количеству объектов в одном кластере. Количество кластеров определяется радиусом каждого документа, а количество объектов в одном кластере определяется средним количеством общих объектов, в данном случае слов или терминов. Алгоритм кластеризации описанный в работе можно использовать не только для классификации групп, а и для других целей, таких как нахождение ассоциативных правил, нахождение групп документов, которые схожи по смысловому тексту и т.д.

В результате исследование, было предложено использование NoSQL базы данных, о именно OrinetDB, который поддерживает все 4 модели NoSQL. Данный тип базы данных очень хорошо подходит для хранения результатов алгоритма кластеризации, так как данный результат является не реляционным. Стоит отметить что OrientDB очень удобен для хранения, обработки и визуализации хранимых данных.

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

Подробнее..

Перевод Как обучать огромные модели машинного обучения на случайных GPU

11.01.2021 14:11:20 | Автор: admin
Вы можете спросить: почему эти полумагические модели машинного обучения работают так хорошо? Короткий ответ: эти модели чрезвычайно сложны и обучаются на огромном количестве данных. На самом деле, Lambda Labs недавно подсчитала, что для обучения GPT-3 на одном GPU потребовалось бы 4,6 миллиона долларов если бы такое было возможно.

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

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





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

Эксперименты показывают, что систему на базе BERT можно за день обучить с помощью более чем 8 GPU, большинство из которых нам пришлось позаимствовать в неработающих лабораториях. Прежде чем мы представим HetSeq, нужна небольшая предыстория.

Типовое обучение нейронной сети


def train(args):    # main components    dataset = Dataset()    dataloader = DataLoader(dataset)    model = Model()    loss_ = Loss()    optimizer = Optimizer(model.parameters())    # specify the GPU and transfer model to the GPU     device = Device()     model.to(device)    model.train()        # actual training loops    for epoch in range(1, Max_Epoch):        for (data, target) in dataloader:            data, target = data.to(device), target.to(device)   # **load input data and target to GPU**            optimizer.zero_grad()            output = model(data)    # **forward compute the output of model given input data**            loss = loss_(output, target)   # **forward process to compute the real loss function**            loss.backward()    # **backward process to obtain the**            optimizer.step()    # **update parameters** 

Обучение на одном GPU

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

Фактически процесс обучения состоит из четырёх отдельных этапов: (1) загрузка данных, (2) прямой проход, (3) обратный проход, (4) обновление.

1. Загрузка данных


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


Прямой проход с одним GPU

2. Прямой проход


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

3. Обратный проход


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


Параметры обновления с единственным GPU

4. Обновление


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

Краткое описание этапов обучения


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

Что делать, если у нас несколько GPU?


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

def torch.nn.parallel.DistributedDataParallel(    module,  # pre-defined model    device_ids=None, # input device_ids    output_device=None,  # output device_ids, in our case, input device = output device = single GPU    dim=0,     broadcast_buffers=True, # set to False in our implementation    process_group=None, # Core part    bucket_cap_mb=25,     find_unused_parameters=False,     check_reduction=False)view raw

Класс параллельного распределения данных

Это не новая идея. В PyTorch мы используем для модели модуль torch.nn.parallel.DistributedDataParallel (DDP) вместо модуля torch.nn.Module. Каждый GPU это отдельный процесс, и связь между ними осуществляется с помощью стандартного IPC. Но это ещё не всё. Четыре шага требуют некоторой настройки.

1. Загрузка данных с помощью DDP


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

Это основная идея параллельного распределения данных (DDP): каждый GPU имеет идентичные параметры модели, но одновременно обрабатывает разные пакеты данных.


Прямой проход с несколькими GPU

2. Прямой проход с DDP


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

3. Обратный проход с DDP


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


Синхронизация градиента

4. Обновление с DDP


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

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

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

def train_multiple_GPUs(args, device_id):    # main components    dataset = Dataset()    dataloader = DataLoader(dataset)    model = DDP(Model())    loss_ = Loss()    optimizer = Optimizer(model.parameters())    device = Device(device_id)     model.to(device)    model.train()        # actual training loops    for epoch in range(1, Max_Epoch):        for (data, target) in dataloader:            data, target = data.to(device), target.to(device)              optimizer.zero_grad()            model.synchronization()    #  parameter synchronization            output = model(data)                loss = loss_(output, target)            loss_average = average(loss)            loss.backward()            model.parameter.grad.average()            optimizer.step()

Обучение на нескольких GPU

Масштабирование несколько узлов с несколькими GPU


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

def torch.distributed.init_process_group(            backend=args.distributed_backend,    # 'nccl' is the best available backend for GPU            init_method=args.distributed_init_method,    # 'tcp' or shared file system            world_size=args.distributed_world_size,  # number of nodes in total            rank=args.distributed_rank, # index of current node        )

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

Коммуникация вот где возникают сложности



Внутриузловая и межузловая коммуникация

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

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

Когда родители заставляют вас делиться игрушками


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

  1. Некоторые игрушки имеют сложные инструкции. Распределённая параллельная обработка данных пакета (DDP) это боль, трудно понять её и заставить работать. Особенно верно это для большинства исследователей машинного обучения, которые не очень хорошо разбираются в особенностях распределённых вычислений. В дополнение к базовой настройке DDP мирный тренировочный запуск различных архитектур GPU на многих узлах требует тщательного разделения данных и изнурительного налаживания связи между GPU и узлами.
  2. С какими-то игрушками лучше играть лучше, чем с другими. В гетерогенной системе некоторые GPU работают быстрее других, а некоторые имеют больше памяти, чем у других. Это означает, что какие-то процессоры получают больше данных для обработки, чем другие, что прекрасно; но это также означает, что средние значения градиентов и обновления параметров должны тщательно взвешиваться.
  3. Родители не разрешают нам играть с какими-то игрушками. Большинство существующих распределённых обучающих платформ GPU требуют дополнительных пакетов, таких как Docker, OpenMPI и т. д. К сожалению, большинство компетентных администраторов кластеров не позволяют пользователям иметь административные привилегии, необходимые для настройки каждого узла, чтобы обучить модель.
  4. Какие-то игрушки плохо работают с другими. Пакеты глубокого обучения, такие как BERT и GPT2/3, разработанные крупными компаниями, как правило, имеют определённые форматы дизайна модели с несколькими логическими слоями, что затрудняет их использование и адаптацию к приложению.

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

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

BERT в университете с HetSeq


Начнём с Anaconda. Создадим виртуальную среду и установим Python.

$ conda create --name hetseq$ conda activate hetseq$ conda install python=3.7.4


Затем мы установим пакеты и привязки HetSeq: загрузим HetSeq с GitHub, установим пакеты из requirements.txt, а также HetSeq и биндинги из setup.py.
$ git clone https://github.com/yifding/hetseq.git $ cd /path/to/hetseq $ pip install -r requirements.txt $ pip install --editable .

Последний шаг перед обучением это загрузка файлов данных BERT, включая корпус обучения, конфигурацию модели и словарь BPE отсюда. Загрузите DATA.zip, распакуйте его и поместите в каталог preprocessing/.

Обучение BERT с помощью HetSeq


Крутая вещь в HetSeq: она абстрагирует все детали о распределённой обработке. Таким образом, код обучения для 100 GPU почти такой же, как для одного! Давайте попробуем!

$DIST=/path/to/hetseq $python3 ${DIST}/train.py  \ $       --task bert   --data ${DIST}/preprocessing/test_128/ \ $       --dict ${DIST}/preprocessing/uncased_L-12_H-768_A-12/vocab.txt  \ $       --config_file ${DIST}/preprocessing/uncased_L-12_H-768_A-12/bert_config.json  \ $       --max-sentences 32  --fast-stat-sync --max-update 900000 --update-freq 4  \ $       --valid-subset test --num-workers 4 \ $       --warmup-updates 10000  --total-num-update 1000000 --lr 0.0001  \ $       --weight-decay 0.01 --distributed-world-size 1  \ $       --device-id 0 --save-dir bert_single_gpu

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

На первом узле:

$DIST=/path/to/hetseq $python3 ${DIST}/train.py  \ $       --task bert   --data ${DIST}/preprocessing/test_128/ \ $       --dict ${DIST}/preprocessing/uncased_L-12_H-768_A-12/vocab.txt  \ $       --config_file ${DIST}/preprocessing/uncased_L-12_H-768_A-12/bert_config.json  \ $       --max-sentences 32  --fast-stat-sync --max-update 900000 --update-freq 4  \ $       --valid-subset test --num-workers 4 \ $       --warmup-updates 10000  --total-num-update 1000000 --lr 0.0001  \ $       --weight-decay 0.01 --save-dir bert_node2gpu4  \ $       --distributed-init-method tcp://10.00.123.456:11111 \ $       --distributed-world-size 8 --distributed-gpus 4 --distributed-rank 0

На втором узле:

$DIST=/path/to/hetseq $python3 ${DIST}/train.py  \ $       --task bert   --data ${DIST}/preprocessing/test_128/ \ $       --dict ${DIST}/preprocessing/uncased_L-12_H-768_A-12/vocab.txt  \ $       --config_file ${DIST}/preprocessing/uncased_L-12_H-768_A-12/bert_config.json  \ $       --max-sentences 32  --fast-stat-sync --max-update 900000 --update-freq 4  \ $       --valid-subset test --num-workers 4 \ $       --warmup-updates 10000  --total-num-update 1000000 --lr 0.0001  \ $       --weight-decay 0.01 --save-dir bert_node2gpu4  \ $       --distributed-init-method tcp://10.00.123.456:11111 \ $       --distributed-world-size 8 --distributed-gpus 4 --distributed-rank 4

Два блока кода работают на двух разных узлах. Адрес TCP/IP должен быть установлен как один из IP-адресов узла. Как только они будут запущены, вы сможете наблюдать за выполнением кода на 8 процессорах и 2 разных узлах!

Так насколько хорошо это работает? Мы провели несколько экспериментов (подробности тут) над различными однородными (гомогенными, hom) и неоднородными (гетерогенными, het) установками.

nodes GPUs training_time speed_up
1 4 7.19day 1.00
2(het) 8 4.19day 1.72
2(hom) 8 4.26day 1.69
4(het) 16 2.23day 3.22
4(hom) 16 2.19day 3.28
8(het) 32 1.21day 5.94

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

Под капотом HetSeq



Структура пакета HetSeq

Пакет HetSeq содержит три основных модуля, показанных на рисунке слева: train.py, task.py и controller.py для координации основных компонентов, показанных справа. Модуль train.py инициализирует распределённую систему и её различные компоненты.

Модуль task.py определяет функции модели, набора данных, загрузчика данных и оптимизатора; он также выполняет функции прямого и обратного распространения. Модуль controller.py действует как главный контроллер обучения. Он работает как модель, оптимизатор и планировщик скорости обучения; загружает и сохраняет чекпоинты, сообщает о потере и обновляет параметры.
Но я хочу обучить не BERT!

Но я хочу обучить не BERT!


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

image



Подробнее..

Business Intelligence на больших данных наш опыт интеграции

20.01.2021 14:20:49 | Автор: admin

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

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

Зачем потребовалась интеграция Arenadata и Visiology?

Подходов к работе BI-систем на сегодняшний день несколько. Но когда речь идет о больших данных для самых разных задач, обычно используется ROLAP. Работает он достаточно просто: когда пользователь нажимает что-то на дашборде, например, выбирает какой-то фильтр, внутри платформы формируется SQL-запрос, который уходит на тот или иной бэкэнд. В принципе, под системой BI может лежать любая СУБД, которая поддерживает запросы от Postgres до Teradata. Подробнее о схемах работы OLAP я рассказывал здесь.

Преимущество интеграции BI с СУБД заключается в том, что для работы системы, по сути, нет ограничения по объему данных. Но при этом падает скорость выполнения запросов - конечно, если не использовать специализированную колоночную СУБД, например, ClickHouse или Vertica. И, хотя у ClickHouse спектр возможностей пока еще уже, чем у той же Vertica, система развивается и выглядит очень многообещающей.

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

Второй момент это ограничение аналитической функциональности: все, что не укладывается в SQL-запрос, поддерживаемый распределенной СУБД, отсекается автоматически (например, в случае ClickHouse - это оконные функции). И это проблема, потому что в BI есть много вещей, которые с трудом транслируются в SQL-запросы или выполняются неоптимально.

Второй вариант это In-memory OLAP. Он подразумевает перенос всех обрабатываемых данных в специальный движок, который молниеносно прорабатывает базу в 200-300 Гб это порядок единицы миллиардов записей. Кстати, подробнее про ограничения In-Memory OLAP я уже рассказывал здесь. На практике встречаются инсталляции In-Memory OLAP, укомплектованные 1-2-3 терабайтами оперативной памяти, но это скорее экзотика, причем дорогостоящая.

Практика показывает, что далеко не всегда можно обойтись тем или иным подходом. Когда требуются одновременно гибкость, возможность работы с большим объемом данных и поддержка значительного количества пользователей, возникает потребность в гибридной системе, которая с одной стороны загружает данные в движок In-Memory OLAP, а с другой постоянно подтягивает нужные записи из СУБД. В этом случае движок OLAP используется для доступа ко всему массиву данных, без всяких задержек. И в отличие от чистого In-Memory OLAP, который нужно периодически перезагружать, в гибридной модели мы всегда получаем актуальные данные.

Такое разделение данных на горячие и холодные объединяет плюсы обоих подходов ROLAP и In-Memory, но усложняет проект внедрения BI. Например, разделение данных происходит вручную, на уровне ETL процедур. Поэтому для эффективной работы всего комплекса очень важна совместимость между бэкэндом и самой BI-системой. При том, что SQL-запросы остаются стандартными, в реальности всегда есть аспекты их выполнения, нюансы производительности.

Arenadata и Arenadata QuickMarts

Платформа данных Arenadata состоит из нескольких компонентов, построенных на базе открытых технологий, и используется многими российскими и зарубежными компаниями. В состав решения входит собственное MPP решение на базе Greenplum, дистрибутив Hadoop для хранения и обработки неструктурированных и слабоструктурированных данных, система централизованного управления ADCM (Сluster Management) на базе Ansible и другие полезные компоненты, в том числе Arenadata QuickMarts (ADQM).

СУБД ADQM это колоночная СУБД от Arenadata, построенная на базе ClickHouse, аналитической СУБД, которую развивает Яндекс. Изначально ClickHouse создавалась для внутреннего проекта Яндекс.Метрика, но эта СУБД очень понравилась сообществу. В результате исходный код ClickHouse был переведен в OpenSource (лицензия Apache-2) и стал популярен по всему миру. На сегодняшний день насчитывается порядка 1000 инсталляций ClickHouse по всему миру, и только 1/3 из них в России. И хотя Яндекс остается основным контрибьютором развития СУБД, лицензия Apache-2 позволяет абсолютно свободно использовать продукт и вносить изменения в проект.

Современная колоночная СУБД использует аппаратную оптимизацию CPU (SSE). ClickHouse может очень быстро выполнять запросы за счет векторных оптимизаций и утилизации всего ресурса многоядерных CPU. На базе ClickHouse работают огромные кластера сам Яндекс растягивает эту СУБД на несколько сотен серверов. Это гарантирует, что вместе с этим решением вы можете масштабироваться в достаточно больших объемах.

Но главная фича ClickHouse в нашем контексте это эффективная работа с достаточно специфическими аналитическими запросами. Если витрины уже отстроены и вам нужно предоставить доступ пользователей к BI с минимальной латентностью, эта история как раз для ClickHouse. Эта СУБД прекрасно справляется с запросами без джойнов и соединений.

Во многих сравнениях ClickHouse дает серьезную фору даже классическим СУБД, например, той же Oracle Exadata. Результаты этих тестов можно найти на ресурсах Яндекса.

Производительность QuickMarts

  • Типичные запросы быстрей чем за секунду

  • > 100 раз быстрей чем Hadoop и обычные СУБД

  • 100 млн - 1 миллиард строк в секунду на одной ноде

  • До 2 терабайт в секунду для кластера на 400 нод

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

При этом установка и настройка ADQM происходит из Arenadata Cluster Manager. Кастомизированная СУБД обладает расширенными механизмами авторизации пользователей, a также средствами мониторинга на базе Graphite и Grafana. Но самое главное, что QuickMarts изначально располагает готовыми коннекторами и прозрачно взаимодействует с другими компонентами платформы, в т.ч. с ADB (Greenplum), что позволяет по мере необходимости подгружать данные из ADB в ADQM.

В нашем случае QuickMarts используется для работы с витринами, к которым через BI обращаются сотни или тысячи пользователей. Архитектура системы позволяет выдать им данные здесь и сейчас, а не ждать 20-30 секунд, когда обработается их запрос по витринам в более медленной СУБД.

Как работает интеграция Arenadata и Visiology

Когда Visiology используется вместе с Arenadata, схема работы системы выглядит следующим образом. Основное хранилище данных может быть реализовано на базе ADB (GreenPlum), из которой создаются витрины данных, хранящиеся уже в ADQM. За счет интеграции между компонентами решения система работает как единое целое, а необходимые для запросов данные поднимаются на нужный уровень автоматически.

Фактически в аналитической системе создается только один дашборд, а графику обрабатывает движок In-Memory ViQube ядро платформы Visiology. Пользователь лишь выбирает те или иные фильтры, а задача по выгрузке самих транзакций выполняется уже на бэкенде ресурсами QuickMarts.

Раньше подобная интеграция была только с Vertica, но сейчас мы совместно с коллегами сделали интеграцию для Arenadata QuickMarts. Это радостная новость для сторонников ClickHouse, потому что BI работает с популярной СУБД по гибридной схеме. При этом Arenadata DB, выполняющая функцию корпоративного хранилища данных, обеспечивает необходимую трансформацию данных для дальнейшей работы QuickMarts и Visiology.

Все запросы BI обрабатываются движком ViQube. Если пользователь обращается к тем данным, которых нет в памяти, система автоматически генерирует SQL-запрос, который выполняется на Arenadata QuickMarts.

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

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

Развиваемся дальше

Сейчас интеграция находится на стадии версии v1.0, и мы планируем дальнейшие доработки. В частности, уже сейчас речь идет о том, чтобы расширить набор доступных аналитических возможностей, а также об интеграции в единую консоль управления (например, у Arenadata есть решение Cluster Manager (ADCM), которое позволяет управлять всеми компонентами ландшафта из единой консоли, рассматриваем это как один из вариантов).

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

В целом, мы остались очень довольны и сотрудничеством с Arenadata, и той интеграцией с ClickHouse и ADQM, которая получилась. Теперь в аналитической платформе Visiology можно одновременно работать с источниками данных любого масштаба - от Small Data (ручной ввод, Excel) до Big Data (миллиардов или даже сотни миллиардов транзакций из распределенных хранилищ данных). А гибридный режим работы, который мы реализовали вместе с Arenadata, еще и позволяет сделать это с разумными затратами на оборудование.

Будем признательны, если вы напишете в комментариях, с какими сценариями запуска BI на больших данных вы сталкивались. Ну а мы всегда готовы поделиться своим опытом в деталях!

Подробнее..

Изучение data science c нуля этапы и вехи

22.01.2021 02:23:24 | Автор: admin

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

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

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

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

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

Этап 1. Базовые инструменты анализа данных: SQL, Excel

  • SQL, основы (20ч). Самостоятельное знание SQL может пригодится для выполнения кучи других задачи. И оно, в любом случае, необходимо для большой (большей?) части вакансий на позицию аналитика, дата сайентиста и, тем более, machine learning engineer.

  • Основы Excel (10ч): фильтры и сортировка данных, формулы, vlookup, pivot tables, базовая работа с графиками. Коллеги, партнеры или руководство будут присылать входящие данные в excel, и вам нужно будет уметь их быстро понять и изучить. Нередко и результаты анализа сделанного на Питоне удобнее подготовить и предоставить в Excel.

  • Базовый английский (20-200ч, зависит от предыдущего уровня), на уровне самостоятельного чтения технической документации и спец.литературы. Например, вам совершенно необходимо уметь читать официальную документацию pandas/scikit, и также многие хорошие материалы по Python доступны только на английском.

В некоторые компании с таким набором знаний берут на позиции: аналитика/ младшего аналитика/ веб-аналитика. В Москве хорошие знания этих вещей могут, иногда, давать ЗП до 100тыс, но вероятнее ЗП порядка 50-70 тыс и начальная позиция .

Этап 2. Основы Python и Pandas

  • Основы Python (80ч). Без знания Питона невозможно использовать львиную часть инструментов машинного обучения. Другие языки менее эффективны в этой сфере и непопулярны.

  • pandas (20 ч) - основа основ в работе с данными в Питоне. На первых порах достаточно хотя бы самых базовых знаний: индексирование, выбор данных по условиям, группировка данных, и соединение разных датафреймов

  • Также научиться основам работы с разными API и парсингом данных (requests, beatiful soup)

На этом этапе дополнительные знания Python позволяют вытаскивать данные из разных API, или путем веб-парсинга.

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

Этап 3. Базовые понятия и классические алгоритмы машинного обучения

(Этот этап может занять 200-400 ч в зависимости от того, насколько хорошо изначально вы владеете математикой)

Базовые понятия машинного обучения:

  • Кросс-валидация

  • Overfitting

  • Регуляризация

  • Data leakage

  • Экстраполяции (понимание возможности в контексте разных алгоритмов)

Базовые алгоритмы, которые достаточно знать на уровне главных принципов:

  • Прогнозирование и классификация:

    • Линейная регрессия

    • Дерево решений

    • Логистическая регрессия

    • Random forest

    • Градиентный бустинг

    • kNN

  • Кластерзиация: k-means

  • Работа с временными рядами: экспоненциальное сглаживание

  • Понижение размерности: PCA

Базовые приёмы подготовки данных: dummy переменные, one-hot encoding, tf-idf

Математика:

  • умение считать вероятности: основы комбинаторики, вероятности независимых событий и условные вероятности (формула Байеса).

  • Понимать смысл фразы: "correlation does not imply causation", чтобы верно трактовать результаты моделей.

  • Мат.методы, необходимые для полного понимания, как работают ключевые модели машинного обучения: Градиентный спуск. Максимальное правдоподобие (max likelihood), понимание зачем на практике используются логарифмы (log-likelihood). Понимание как строиться целевая функция логистической регрессии (зачем log в log-odds), понимание сути логистической функции (часто называемой "сигмоид"). С одной стороны, нет жесткой необходимости всё это понять на данном этапе, т.к все алгоритмы можно использовать как черные ящики, зная только основные принципы. Но понимание математики поможет глубже понять разные модели и придать уверенности в их использовании. Позднее, для уровня senior, эти знания являются уже обязательным:

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

Этап 4. Набор базовых навыков решения задач

Цель данного этапа - получение навыков применения всех ранее изученных методов машинного обучения с помощью scikit-learn, pandas (numpy).

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

Тут же следует инвестировать время в изучение разных приёмов и трюков feature engineering

По завершению данного этапа есть шанс устроиться на позицию junior data scientist. ЗП будет низкая. Но главное будет продолжать учиться. До достижения уровня senior возможность учиться у коллег ценнее, чем текущая зарплата.

Знакомство с основами нейронных сетей

На данном этапе может быть полезно знание основ нейронных сетей, CNN, RNN/LSTM слоев, vector embeddings. Но не обязательно уметь тренировать их самому, на данном этапе. Пока это важно для "общего развития" и чтобы вы не хотели применять нейронные сети там, где без можно обойтись, и, наоборот, понимали где они могут быть полезны и когда имеет смысл или обращаться к коллеге уже их знающему, или браться за глубокое изучение и практику.

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

Рекомендую ограничить это объемом в 20-40ч, необходимым только для общего понимания концепций.

Этап 5. Дополнительные технические навыки, необходимые в работе

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

  • Conda, понимание проблем зависимостей версий библиотек, и как conda это может решить

  • основы bash

  • Python standard library, если не освоили ранее (необходимый минимум itertools, collections, contextlib), умение эффективно разбивать код на функции и модули, классы; умение применять context managers.

  • Основы git, также очень полезно умение работать с IDE: pycharm/vs code. Их использование облегчит работу с git, заменив графическим интерфейсом работу с командной строкой

  • Библиотеки визуализации (matplotlib+seaborn, plotnine, plotly), если не освоили их раньше.

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

В принципе, на этом уровне знаний можно работать годами, практикуясь в применении разных из уже изученных моделей, библиотек и инструментов, осваивая вспомогательные методы (feature engineering), нюансы, и способы решения похожих же задач, с помощью разных библиотек (xgboost, cat-boost). Постепенно будет уровень рост ЗП. Но это не уровень Senior специалиста.

Изучаем по необходимости, этапы 2-5

Визуализация данных

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

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

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

  • plotnine - позволяет создавать очень креативные графики. Супер-мощный инструмент, позволяющий в несколько строчек кода создать самые нетривиальные графики. В сравнении - seaborn не имеет подобной гибкости, а в matplotlib замучаешься разбираться чтобы сделать такой же график, если он не совсем примитивный. Однако, поначалу, plotnine требует определенного времени на освоение. Если бы не существовал plotly - это был бы самый мощный инструмент.

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

До начала применения в реальной практике, на обучение можно себя ограничить в 10-20ч на одну библиотеку.

Если вам нет нужды сначала применять питон для подготовки данных, или вы хотите создать визуальные дэшборды которыми смогут пользоваться другие люди - посмотрите в сторону PowerBI и Tableau, это крайне мощные и популярные инструменты визуализации данных. Изучить каждый из этих инструментов на минимальном рабочем уровне можно, примерно, за 60ч. Знание связки SQL+Excel+PowerBI/Tableau откроет вам позиции аналитиков и "BI-специалистов" c окладами в Москве от 100 тыс., коммуникабельные специалисты с хорошими знаниями этих инструментов находят позиции с ЗП от 150 тыс. Подобные вакансии в основном встречаются в корпорациях и системных интеграторах.

Средства работы с данными

Можно учить на разных этапах, в зависимости от задач, с которыми столкнётесь

  • Основы regular expressions, aka RegExp (10ч). Знания regexp необходимо для продвинутой фильтрации данных в разных инструментах для работы с данными.

  • PySpark (40ч на изучение основ, 100-200ч на достижение хорошего рабочего навыка) . Он необходим когда у вас данных очень много, и приходиться обрабатывать их сразу на целой группе серверов (кластере). Это уже Big data. Не имеет смысл разбираться с ним заранее, т.к. знания являются не фундаментальными и легко забываются. Эффективнее осваивать когда планируете начать использовать (или перед тем как подать резюме на позицию, требующую данных знаний).

    Внутри Spark устроен сильно не так, как обычные базы данных, но с точки зрения использования он оказывается сильно похожим, т.к. поддерживает почти стандартный SQL синтаксис или, как альтернативу, API отдалённо похожий на pandas. Определенные концептуальные отличия присутствуют, но больших сложностей в освоении это не вызывает. В последнее время продвигают библиотеку Koalas, которая будет использовать команды совсем как у pandas для работы с spark-кластером, но пока не советую делать это основным подходом по работе с Spark.

  • Основы html - необходимы, как минимум, для общения с коллегами и понимания их языка, если вы хоть немного сталкиваетесь с сайтами и необходимостюь их парсить или анализировать данные с них.

Этап 6

Углубление и развитие технических навыков

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

  • Python на хорошем уровне: декораторы, уверенное знание классов и наследования, изучение базовых классов, dunderscore __методы__ .

  • Уверенное пользование bash, понимание основ linux

  • Полезно изучить основы docker

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

Другие области машинного обучения

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

Нейронные сети

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

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

Другие статьи о самообразовании

Вводная статья о том, как понять, стоит ли вам вообще идти в data science и как сделать первые шаги

Принципы эффективного самообучения

Как минимум, планируется статья с рекомендациями книг и курсов, в соответствии с приведенными этапами

Готов стать ментором

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

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

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

self.development.mentor в домене gmail.com, Олег

Подробнее..

А вы все еще генерируете данные руками? Тогда GenRocket идет к вам

06.01.2021 20:05:30 | Автор: admin

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

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

Проблема генерации тестовых данных

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

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

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

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

Функциональность идеального сервиса генерации данных

Идеальный сервис по генерации тестовых данных должен иметь возможность:

  • генерировать данные в разных форматах (JSON, XML, CSV и т.д.)

  • генерировать данные с зависимостями (parent, child)

  • генерировать сложные зависиммые данные (if a then 1 or 2 else 3 or 5)

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

Хотелось бы иметь возможность:

  • загрузки данные в прямо в БД

  • интерграции в CI/CD

  • создавать модель данных автоматом из схем

GenRocket университет

Сервис GenRocket предоставяет тренинг-университет, пройдя который вы ознакомитесь с основным базовым функционалом, установкой и настройкой.

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

GenRocket сервис

GenRocket - это сервис для генерации данных, созданный в 2011 году Hycel Taylor и Garth Rose для решения проблемы создания реалистичных тестовых данных для любой модели данных. Сервис обладает функциональностью генерировать данные для автоматического тестирования, для тестирования нагрузки, тестирования безопасности и др.

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

Что бы начать работу с GenRocket пользователь должен быть авторизирован, затем что бы начать работу с GenRocket необходимо скачать архив для Runtime* для cli части, распаковать его и прописать в системных переменных путь к папке с GenRocket в переменную GEN_ROCKET_HOME и в переменно PATH прописать %GEN_ROCKET_HOME%\bin значение.

Затем открываем командную строку, набираем genrocket и видим картинку ниже.

GenRocket cli часть работает в двух режимах on-line и off-line, но для работы с off-line надо скачать сертификат, который будет валиден только 24 часа.

GenRocket домен и его атрибуты

Первые два из основных компонентов - это Домен и Атрибуты домена. Домен - это существительное, например, пользователь: адрес, кредитная карта и т.д. Каждый домен описывается атрибутами, например: имя, фамилия, e-mail, пароль и день рождения. На картинке ниже вы видите домент User (1), описанный атрибутами (2) и пример сгенерированных данных (3).

Атрибуты к домену могут добавляться вручную по одному (2), с помощью блокнота или импортируя DDL, CSV, JSON или другие форматы. Если мы говорим о табличных данных, то можно сказать, что домен - это таблица, а атрибуты - это клонки этой таблицы.

GenRocket генераторы

Следующий компонент - генератор (generator) - это функциональность, которая непосредственно отвечает за генерацию данных в различных форматах. Генераторов в GenRocket 150+ для различных типов данных. Например:

Каждому атрибуту домена GenRocket назначает свой генератор, опираясь на имя атрибута, автоматом. Например, для атрибута, который содержит слово Name, будет подобран генератор NameGen, а для атрибута с SSN будет подобран генератор SSNGen.

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

GenRocket получатель (receiver)

Следующий компонент - получатель (receiver) - это функциональность, которая отвечает за выгрузку данных в необходимом формате: XML, JSON, SQL, CSV, JDBC, REST, SOAP. В GenRocket 35+ подобных получателелей.

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

GenRocket сценарий (scenarios)

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

Сценарий выгружается в виде grs файла (3) и должен быть исполнен на машине, где был установлен GenRocket. Открываем командную строку и выполняем сценарий при помощи команды genrocket -r UserInsertScenario.grs.

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

Применение GenRocket на реальном проекте

Возьмем небольшую схему данных, в которой есть таблицы user, grantHistory и notificationSetting.

Используя импорт DDL создадим домен для user.

create table `user` ( id int(10) not null auto_increment,  external_id varchar(50) not null unique,  first_name varchar(25) not null,  last_name varchar(25) not null,  middle_initial char(1),  username varchar(100) not null,  ssn varchar(15) not null,  password varchar(255) not null,  activation_date date,  primary key (id));

После создания доменов GenRocket подбирает подходящие генераторы для каждого атрибута. При необходимости настраиваем специфичные генераторы или модифицируем существующие. Например, изменяем generationType на random и сохраняем изменения.

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

driver=org.h2.Driveruser=sapassword=saurl=jdbc:h2:file:~/lms_course/lms_alpha;AUTO_SERVER=TRUE;batchCount=1000

И так же для этой базы настраивается специфичные получатели H2InsertV2Receiver для вставки и SQLUpdateV2Receiver для модификации.

После всех манипуляций с настройками получаем файлы сценарии InsertScenarioChain.grs для вставки и UpdateScenarioChain.grs для модификации, после выполнения которых получаем картинку ниже.

И вуаля, данные в таблицах:

Заключение

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

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

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

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

Ниже расценка на доступ для GenRocket

Для сравнения я приготовила несколько ссылок бесплатных сервисов:

https://www.datprof.com/solutions/test-data-generation/ - только 14 дней бесплатного использования, похоже что цена договорная

http://generatedata.com/ - бесплатно, но возможна генерация только 100 записей

https://www.mockaroo.com/ - бесплатна возможна генерация только 1000 записей, остальное платно - для самого дорогого доступа $5000/year

Подробнее..

Перевод Kafka как хранилище данных реальный пример от Twitter

07.01.2021 14:19:53 | Автор: admin
Привет, Хабр!

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


Введение



Когда разработчики потребляют общедоступные данные Twitter через API Twitter, они рассчитывают на надежность, скорость и стабильность. Поэтому некоторое время назад в Twitter запустили Account Activity Replay API для Account Activity API, чтобы разработчикам было проще обеспечить стабильность своих систем. Account Activity Replay API это инструмент восстановления данных, позволяющий разработчикам извлекать события со сроком давности до пяти дней. Этот API восстанавливает события, которые не были доставлены по разным причинам, в том числе, из-за аварийных отказов сервера, происходивших при попытках доставки в режиме реального времени.

Инженеры Twitter стремились не только создать API, которые будут положительно восприняты разработчиками, но и:

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


По этой причине при работе над созданием системы воспроизведения, на которую полагается при работе API, было решено взять за основу имеющуюся систему для работы в режиме реального времени, на которой основан Account Activity API. Так удалось повторно воспользоваться имеющимися разработками и минимизировать переключение контекста и объем обучения, которые были бы гораздо значительнее, если бы для описанной работы создавалась совершенно новая система.

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

Контекст


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

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



Рис. 1: Конвейер генерации данных

Хранение и сегментирование



Как правило, при создании системы воспроизведения, требующей подобного хранилища данных, выбирается архитектура на основе Hadoop и HDFS. В данном случае, напротив, был выбран Apache Kafka, по двум причинам:

  • Система для работы в режиме реального времени была по принципу публикация-подписка, органичному для устройства Kafka
  • Объем событий, который требуется хранить в системе воспроизведения, исчисляется не петабайтами. Мы храним данные не более чем за несколько дней. Кроме того, обращаться с заданиями MapReduce для Hadoop затратнее и медленнее, чем потреблять данные в Kafka, и первый вариант не отвечает ожиданиям разработчиков.


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

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

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

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

Запросы и обработка



В системе, сконструированной таким образом, API отправляет запросы на воспроизведение. В составе полезной нагрузки каждого валидируемого запроса приходит webhookId и диапазон данных, для которых должны быть воспроизведены события. Эти запросы долговременно хранятся в MySQL и ставятся в очередь до тех пор, пока их не подхватит сервис воспроизведения. Диапазон данных, указанный в запросе, используется, чтобы определить смещение, с которым нужно начать считывание с диска. Функция offsetForTimes объекта Consumer используется для получения смещений.



Рис. 2: Система воспроизведения. Она получает запрос и отправляет его сервису конфигурации (уровень доступа к данным) для дальнейшего долговременного хранения в базе данных.

Инстансы сервиса воспроизведения обрабатывают каждый запрос на воспроизведение. Инстансы координируются друг с другом при помощи MySQL, чтобы обработать следующую запись на воспроизведение, хранимую в базе данных. Каждый рабочий процесс, обеспечивающий воспроизведение, периодически опрашивает MySQL, чтобы узнать, нет ли там задания, которое следует обработать. Запрос переходит от состояния к состоянию. Запрос, который не был подхвачен для обработки, находится в состоянии OPEN. Запрос, который только что был выведен из очереди, находится в состоянии STARTED. Запрос, обрабатываемый в данный момент, находится в состоянии ONGOING. Запрос, претерпевший все переходы, оказывается в состоянии COMPLETED. Рабочий процесс, отвечающий за воспроизведение, подбирает только такие запросы, обработка которых еще не началась (то есть, находящиеся в состоянии OPEN).

Периодически, после того, как рабочий процесс выведет запрос из очереди на обработку, он отстукивается в таблице MySQL, оставляя метки времени и демонстрируя тем самым, что задание на воспроизведение до сих пор обрабатывается. В случаях, когда инстанс воспроизводящего рабочего процесса отмирает, не успев закончить обработку запроса, такие задания перезапускаются. Следовательно, воспроизводящие процессы выводят из очереди не только запросы, находящиеся в состоянии OPEN, но и подбирают те запросы, что были переведены в состояние STARTED или ONGOING, но не получили отстука в базе данных, спустя заданное количество минут.



Рис. 3: Уровень доставки данных: сервис воспроизведения опрашивает MySQL по поводу нового задания на обработку запроса, потребляет запрос из топика Kafka и доставляет события через сервис Webhook.

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

Реально ли big data настолько круты?

20.01.2021 10:13:24 | Автор: admin


Как собрать в прямом эфире 17 000 зрителей? Значит, рецепт такой. Берем 15 актуальных IT-направлений, зовем зарубежных спикеров, дарим подарки за активность в чате, и вуа-ля крупнейший в Украине и восточной Европе онлайн-ивент готов. Именно так прошла ежегодная мультитул конференция NIXMultiConf.

Под слоганом айтишникам от айтишников эксперты из Украины, Беларуси, России, Великобритании и Германии поделились опытом и рассказали о новинках индустрии. Полезно было всем дизайнерам, девелоперам, тестировщикам и менеджерам. И теперь делимся инсайтами с вами.

По мотивам докладов экспертов NIX запускаем серию статей на самые актуальные темы. Начнем с хайповой Data Engineering. Поклонник Python и Data Engineer в NIX Илья Кальченко выяснил, реально ли big data настолько круты?

Хотите узнать больше смотрите конференцию на YouTube-канале.

Эпоха big data, или Почему в 2021-м не обойтись без обработки данных


Только ленивый не говорит, что работа с big data профессия будущего. А я даже больше скажу: это потребность здесь и сейчас. До 2003 года мы создали столько петабайт данных, сколько сегодня производим каждые два дня. Аналитики Gartner среди технотрендов 2021 года назвали облачные сервисы и кибербезопасность. Тенденция легко объясняется. Огромные массивы big data нужно хранить в безопасности и обрабатывать, получая полезную информацию. На удаленке эти потребности компаний стали более ощутимы. E-commerce, Healthcare, Edtech хотят знать все о своих онлайн-потребителях. Пока данные лежат на серверах, толку от них нет.

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

Что такое big data и зачем они нужны


Чистить, структурировать, конвертировать основные операции data инженерии. Специалист должен знать, как объединить данные разного формата, собранные из нескольких источников. Три года я программирую на Python, из них два года погружен в big data. На личном опыте понял: для ежедневной работы нужно уметь больше.

Data Engineer это сборная солянка четырех профессий:

  • Software Engineer. Пишет код, тестирует и оптимизирует его. По моему мнению, Software Engineer наипростейший путь в data инженерию. Специалист знает, как устроены компьютер/программы, базово знаком с разработкой качественного ПО и работой с базами данных.
  • Big Data Developer. Понимает принципы обработки данных, использует различные инструменты для их трансформации. Он готовит описание моделей данных в зависимости от задачи или бизнес-процессов клиента.
  • Database Administrator. На его плечах построение архитектуры хранилищ. Знает, как оптимальнее хранить данные и проводить над ними базовые операции.
  • Cloud Engineer. Объемы данных сегодня настолько большие, что хранить их на серверах слишком дорого или невозможно они там просто не помещаются. В помощь облачные решения. Инженер разбирается, какие есть cloud решения, какова их структура, специфика и взаимодействие между собой, как настроить облачные сервисы.

Из каждого направления можно перейти в Data Engineering.

Data Engineer VS Data Scientist VS Data Analyst


Представим условную соцсеть для изучения иностранных языков. Люди находят друзей по переписке и практикуют английский, немецкий, китайский. Миллионы ежедневных пользователей оставляют цифровые следы: авторизуются через личную почту, покупают премиум-аккаунты, скачивают приложение, созваниваются по видеосвязи. Каждый клик регистрируется и отправляется на сервер. Бизнес хочет отслеживать эффективность и прибыльность платформы. Как в этом поможет data инженер? Лично никак. Но с коллегами Data Scientist и Data Analyst найденные им данные превращаются в полезную информацию статистику, инфографики, прогнозы.

Нельзя сказать, что кто-то из них полезнее, выполняет больше работы или лучше справляется с обязанностями. Объем задач у них и правда может отличаться и зависит от поставленных клиентом задач. Единственное data инженер будто работает в тени. Если вы коммуникабельны и умеете общаться с заказчиками, стоит присмотреться к профессии аналитика или Data Scientist. Но решать, конечно, вам.

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

Работа с данными разбираем пошагово


Есть определенные источники данных. Задача инженера получить оттуда информацию, подружить данные из разных источников, обработать и по запросу упростить и разнообразить их. Отправляем в базу данных запрос, написанный на Structured Query Language. SQL самый распространенный язык для манипуляций с данными. Поэтому многие инструменты используют уже всем знакомый синтаксис. Например, Apache Hive или Impala.

Чтобы изменить данные, нужны специальные фреймворки. Такие как Apache Spark, Apache Flink и Hadoop MapReduce позволяют выполнять такие виды трансформаций:

  • data cleaning;
  • удаление дубликатов;
  • конвертация типов данных (строку в число или в дату);
  • фильтрация;
  • data joins;
  • data derivation.

Одни фреймворки подходят только для обработки стриминговых данных, другие исключительно для данных, которые давно хранятся на сервисе. Некоторые могут делать и то, и другое. Допустим, нам нужно удалить ненужные записи и заполнить пропущенные значения. Делается это заготовленными скриптами. Не для всех фреймворков есть возможность писать скрипты на том языке, на котором хочется инженеру. Чаще всего для преобразования данных берут инструменты Python, Java и Scala. На Java созданы Hadoop, HDFS, Apache Cassandra, HBase и Apache Hive; на Scala Apache Kafka и Apache Spark; на Python Pandas/Numpy, Dask + обертки для фреймворков, написанных на других языках (PyFlink, PySpark, Python Hadoop API).


Чтобы все структурировать, есть два подхода ETL и ELT. Если мы работаем с небольшим объемом или с базами готовых данных от разных клиентов, удобнее использовать ЕTL. Если много смешанной информации, подойдет ELT. В этом случае сначала загружаем данные в хранилище, трансформируем на отдельном сервере и по необходимости вытаскиваем.


Готовые данные попадают в data warehouse или data lakes. Доставку настраиваем через SQL-запрос или кастомный скрипт, включенный в API внешнего сервиса. Далее за дело берутся Data Analyst и Data Scientist. На основе данных они формируют полезную информацию. Первый создает отчеты, графики и находит закономерности в данных, второй с помощью подходов machine learning делает прогнозы.

Бизнесу Data Engineering полезен в трех аспектах:

  • находим, чистим и приводим данные в порядок
    Информация о профилях пользователей, покупках, количество кликов в приложении на разных девайсах все это собирает инженер и группирует данные по содержанию. Если компания строит планы на следующий год и хочет узнать предполагаемый рост бизнеса, к инженеру подключается Data Scientist и Analyst. На основе собранной инженером информации они выясняют, в какой нише и почему падают продажи, какие продукты или фичи самые популярные.
  • увеличиваем скорость доставки данных в целевую систему или к целевому пользователю
    Скорость зависит от выбора фреймворка, подхода и сервиса. Например, Hadoop MapReduce более кост-эффективен по сравнению со Spark, но и скорость обработки данных ниже. Если у нас стриминговые данные, их удобнее и быстрее обрабатывать на лету, вместо того, чтобы сохранять на диск, а обработкой заниматься когда-нибудь потом.
  • уменьшаем стоимость хранения данных
    В 80-х годах 1 ГБ пространства на HDD стоил $500 тыс, а сейчас $0,025. С тех пор объемы данных выросли в сотни раз, и жесткие диски с ними не справляются. Удобнее и безопаснее хранить информацию на облаке. Терабайты на сервисе обойдутся от нескольких десятков до сотен долларов в месяц. Специалисты могут подобрать клиенту наиболее выгодный сервис и тарифный план.

От промышленной революции к технологической


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

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

Полный доклад Ильи Кальченко и других спикеров NIX смотри на YouTube-канале.
Подробнее..
Категории: Big data , Блог компании nix

Категории

Последние комментарии

© 2006-2021, personeltest.ru