Category: Data Science

25
Июл
2021

📊 Как стать дата-инженером в 2021 году?

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

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

Типичные обязанности дата-инженера:

  • Исследовательский анализ данных.
  • Извлечение данных из массивов разнородной информации.
  • Оценка и очистка наборов данных.
  • Подготовка и написание логики ETL (процессов обработки/преобразования информации).
  • Построение конвейеров данных для распределения по нескольким серверам.
  • Сбор и запрос данных.
  • Объединение данных.
  • Создание хранилищ данных.
  • Оптимизация доставки данных.
  • Нормализация и моделирование данных.
  • Перепроектирование инфраструктуры данных для масштабируемости.
  • Использование инструментов для обслуживания данных.
  • Помощь специалистам по исследованию данных в оптимизации продуктов.

Главные технические компетенции дата-инженера:

  • Языки программирования Python, C++, Java и Scala.
  • Знание алгоритмов и структур данных.
  • Системы управления базами данных (SQL и NoSQL).
  • Инфраструктура – облачные вычисления.
  • Потоковая передача данных – Apache Beam.

Как стать успешным дата-инженером в 2021 году?


Изучите языки программирования

Требования индустрии вращаются вокруг Python и Scala. Чтобы создавать качественное ПО, вам потребуется подтянуть навыки владения этими языками и получить практический опыт работы с инструментами для инженерии данных. Также желательно владеть такими языками, как Java и C++.

Освойте SQL

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


Изучите облачные технологии

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

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

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

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

Обзор ресурсов для изучения

Алгоритмы и структуры данных

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

Python

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

SQL

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

  • Hadoop. Система для обработки больших объемов данных. Курс посвящен методам обработки больших объемов данных с помощью системы Hadoop. Завершив обучение, вы получите базовые знания об основных способах хранения и методов обработки больших объемов данных, а также поймете принципы работы распределенных систем в контексте фреймворка Hadoop.
Из более продвинутых курсов хочется отметить англоязычный GCP: Complete Google Data Engineer and Cloud Architect Guide на Udemy, где 28 часов контента дополняются 25 статьями и 48 ресурсами для скачивания. Программа обучения дает полное представление о дисциплине.

Итог

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

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

***

Если вы только начинаете путь в профессии, обратите внимание на курс Data Engineering образовательной онлайн-платформы GeekBrains. Занятия под руководством опытных наставников и поддержка опытных HR помогут вам продвинуться по карьерной лестнице. Вы научитесь собирать и обрабатывать данные, проектировать хранилища и работать с инфраструктурой. Специализированный опыт для этого не потребуется: программа предполагает освоение профессиональных навыков с нуля.

19
Июл
2021

🤖 Метод k-ближайших соседей (k-nearest neighbour)

Метод k-ближайших соседей (k Nearest Neighbors, или kNN) – популярный алгоритм классификации, который используется в разных типах задач машинного обучения. Наравне с деревом решений это один из самых понятных подходов к классификации.

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

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

Пример классификации k-ближайших соседей.


  • У нас есть тестовый образец в виде зеленого круга. Синие квадраты мы обозначим как класс 1, красные треугольники – класс 2.
  • Зеленый круг должен быть классифицирован как класс 1 или класс 2. Если рассматриваемая нами область является малым кругом, то объект классифицируется как 2-й класс, потому что внутри данного круга 2 треугольника и только 1 квадрат.
  • Если мы рассматриваем большой круг (с пунктиром), то круг будет классифицирован как 1-й класс, так как внутри круга 3 квадрата в противовес 2 треугольникам.

Теоретическая составляющая алгоритма k-NN

Помимо простого объяснения, необходимо понимание основных математических составляющих алгоритма k-ближайших соседей.

  • Евклидова метрика (евклидово расстояние, или же Euclidean distance) – метрика в евклидовом пространстве, расстояние между двумя точками евклидова пространства, вычисляемое по теореме Пифагора. Проще говоря, это наименьшее возможное расстояние между точками A и B. Хотя евклидово расстояние полезно для малых измерений, оно не работает для больших измерений и для категориальных переменных. Недостатком евклидова расстояния является то, что оно игнорирует сходство между атрибутами. Каждый из них рассматривается как полностью отличный от всех остальных.

Формула вычисления Евклидова расстояния:

        d(p, q) = d(q, p) = \sqrt{(q_1 - p_1)^2 + (q_2 - p_2)^2 + ...+ (q_n - p_n)^2} =\sqrt{\sum_{i=1}^n(q_i - p_i)^2}
    
  • Другой важной составляющей метода является нормализация. Разные атрибуты обычно обладают разным диапазоном представленных значений в выборке. К примеру, атрибут А представлен в диапазоне от 0.01 до 0.05, а атрибут Б представлен в диапазоне от 500 до 1000). В таком случае значения дистанции могут сильно зависеть от атрибутов с бо́льшими диапазонами. Поэтому данные в большинстве случаев проходят через нормализацию. При кластерном анализе есть два основных способа нормализации данных: MinMax-нормализация и Z-нормализация.

MinMax-нормализация осуществляется следующим образом:

        x' = (x - min[X])/(max[X] - min[X])
    

в данном случае все значения будут находиться в диапазоне от 0 до 1; дискретные бинарные значения определяются как 0 и 1.

Z-нормализация:

        x' = (x - M[X])/σ[X]
    

где σ – среднеквадратичное отклонение. В данном случае большинство значений попадает в диапазон.

Каков порядок действий?

  • Загрузите ваши данные.
  • Инициализируйте k путем выбора оптимального числа соседей.
  • Для каждого образца в данных:
  1. Вычислите расстояние между примером запроса и текущим примером из данных.
  2. Добавьте индекс образца в упорядоченную коллекцию, как и его расстояние.
  • Отсортируйте упорядоченную коллекцию расстояний и индексов от наименьшего до наибольшего, в порядке возрастания.
  • Выберите первые k записей из отсортированной коллекции.
  • Возьмите метки выбранных k записей.
  • Если у вас задача регрессии, верните среднее значение выбранных ранее k меток.
  • Если у вас задача классификации, верните наиболее часто встречающееся значение выбранных ранее меток k.

Реализация на языке Python

Для демонстрации мы будем использовать самое распространенное соревнованию-песочницу на Kaggle: Titanic. Данные вы можете найти здесь. Мы стремимся использовать python-библиотеку для машинного обучения scikit-learn. Мы используем набор данных «Титаник» для логистической регрессии.

Набор данных состоит из 15 столбцов, таких как sex (пол), fare (плата за проезд), p_class (класс каюты), family_size (размер семьи), и т. д. Главным признаком, который мы и должны предсказать в соревновании, является survived (выжил пассажир или нет).

Дополнительный анализ показал, что находящиеся в браке люди имеют больший шанс на то, чтобы быть спасенными с корабля. Поэтому были добавлены еще 4 столбца, переименованные из Name (Имя), которые обозначают мужчин и женщин в зависимости от того, были они женаты или нет (Mr, Mrs, Mister, Miss).

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

Чтобы наглядно продемонстрировать функциональность k-NN для предсказания выживания пассажира, мы рассматриваем только два признака: age (возраст), fare (плата за проезд).

        # Загружаем данные
train_df = pd.read_csv('/kaggle/input/titanic/train_data.csv') 
# Избавляемся от двух столбцов без нужной информации
train_df = train_df.drop(columns=['Unnamed: 0', 'PassengerId']) 
from sklearn.neighbors import KNeighborsClassifier 
predictors = ['Age', 'Fare'] 
outcome = 'Survived' 

new_record = train_df.loc[0:0, predictors] 
X = train_df.loc[1:, predictors] 
y = train_df.loc[1:, outcome] 

kNN = KNeighborsClassifier(n_neighbors=20) 
kNN.fit(X, y) 
kNN.predict(new_record)
print(kNN.predict_proba(new_record)) 

#[результат/вывод]: [[0.7 0.3]]
    

Здесь вероятность выживания составляет 0.3 – 30%.

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

        nbrs = knn.kneighbors(new_record)
maxDistance = np.max(nbrs[0][0])

fig, ax = plt.subplots(figsize=(10, 8))
sns.scatterplot(x = 'Age', y = 'Fare', style = 'Survived', 
                hue='Survived', data=train_df, alpha=0.3, ax=ax)
sns.scatterplot(x = 'Age', y = 'Fare', style = 'Survived', 
                hue = 'Survived', 
                data = pd.concat([train_df.loc[0:0, :], train_df.loc[nbrs[1][0] + 1,:]]), 
                ax = ax, legend=False)
ellipse = Ellipse(xy = new_record.values[0], 
                  width = 2 * maxDistance, height = 2 * maxDistance,
                  edgecolor = 'black', fc = 'None', lw = 1)
ax.add_patch(ellipse)
ax.set_xlim(.25, .29)
ax.set_ylim(0, .03)

plt.tight_layout()
plt.show()
    

Результат работы кода:


Как видите, на графике показаны 20 ближайших соседей, 14 из которых связаны с теми, кто не выжил (вероятность 0,7 – 70%), а 6 связаны с выжившими (вероятность 0,3 – 30%).

Мы можем просмотреть первые 20 ближайших соседей для заданных параметров при помощью следующего кода:

        nbrs = knn.kneighbors(new_record)
nbr_df = pd.DataFrame({'Age': X.iloc[nbrs[1][0], 0], 
                         'Fare': X.iloc[nbrs[1][0], 1],
                         'Survived': y.iloc[nbrs[1][0]]})
nbr_df
    

Результатом будет таким:


Выбор Оптимального значения для k-NN

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

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

Преимущества и Недостатки

Преимущества:

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

Недостатки:

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

В заключение

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

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

16
Июл
2021

🤖 Генеративная состязательная сеть (GAN) для чайников – пошаговое руководство

Лучшее руководство для новичков по пониманию, созданию и обучению GAN с надежным кодом на Python.

Текст публикуется в переводе, автор статьи – Мишель Кана.

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

Генеративная Состязательная Сеть – самая интересная идея в машинном обучении за последние десять лет.
Янн ЛеКун, вице-президент и Глава исследований по ИИ в Facebook, отец-основатель ИИ.

Хотя генеративная состязательная сеть – это старая идея, происходящая из теории игр, они были введены в коммьюнити машинного обучения в 2014-м Йэном Гудфеллоу и соавторами в статье “Генеративные состязательные сети“. Как же работают GAN и для чего они хороши?

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

Фейковые фотореалистичные лица, созданные GANом (<a href="https://research.nvidia.com/sites/default/files/pubs/2017-10_Progressive-Growing-of/karras2018iclr-paper.pdf" target="_blank" rel="noopener noreferrer nofollow">источник</a>)
Фейковые фотореалистичные лица, созданные GANом (источник)

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

Пример изображения и его восстановления с помощью нашего кода VAE
Пример изображения и его восстановления с помощью нашего кода VAE

VAE обычно генерируют размытые и не фотореалистичные изображения. Это и является стимулом к созданию генеративных состязательных сетей (GANов).

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

Игра вероятностей

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

Это можно считать вероятностным экспериментом с неизвестным результатом X, также называемого случайной переменной.

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

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

Тайриз Гибсон
Тайриз Гибсон

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


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

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

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

Распределение вероятностей лиц знаменитостей

Генерацию новых лиц можно определить как задачу генерации случайной переменной. Лицо описывается случайными переменными, при этом значения RGB его пикселей “сплющиваются” в вектор из N чисел.

Наши лица знаменитостей имеют ширину 218 пикселей, высоту 178 пикселей и 3 цветовых канала. Таким образом, каждый вектор будет иметь 116412 измерений.

Если мы построим пространство со 116412 (N) измерениями, каждое лицо будет точкой в этом пространстве. Функция распределения вероятности лиц знаменитостей P(X) поставит каждому лицу в соответствие неотрицательное целое число, чтобы сумма этих чисел была равна 1.

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

Функция распределения вероятности лиц знаменитостей
Функция распределения вероятности лиц знаменитостей

GAN генерирует новое лицо знаменитости, генерируя новый вектор, следуя распределению вероятности лиц знаменитостей в векторном пространстве размерности N.

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

Как генерировать случайные переменные со сложными распределениями?

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

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

Почему “генеративные состязательные сети”?

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

Теоретически, мы могли бы использовать эти выборки для сравнения истинного распределения со сгенерированным распределением, используя подход максимального среднего расхождения (Maximum Mean Discrepancy, MMD). Он предоставил бы нам ошибку несоответствия распределения, которую можно было бы использовать для обновления весов методом обратного распространения ошибки (backpropagation). На практике этот прямой метод очень трудно реализовать.

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

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

Генеративная часть отвечает за ввод N-мерных равномерно распределенных случайных чисел (шума) и генерацию ложных лиц. Генератор усваивает вероятность P(X), где X – это входные данные.

Дискриминационная часть – это простой классификатор, оценивающий и отделяющий сгенерированные лица от истинных лиц знаменитостей. Дискриминатор усваивает условную вероятность P(Y | X), где X – это входные данные, а Y – метка.

Генеративная состязательная сеть для лиц знаменитостей
Генеративная состязательная сеть для лиц знаменитостей

Обучение генеративных состязательных сетей

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

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

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

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

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

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

Приложение, синтезирующее изображения на основе GAN от Streamlit (<a href="https://towardsdatascience.com/build-an-app-to-synthesize-photorealistic-faces-using-tensorflow-and-streamlit-dd2545828021" target="_blank" rel="noopener noreferrer nofollow">источник</a>)
Приложение, синтезирующее изображения на основе GAN от Streamlit (источник)

Построение и обучение модели DCGAN

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

Дискриминатор

Дискриминатором может быть любой классификатор изображений, даже дерево решений. Мы используем вместо него сверточную нейронную сеть с четырьмя блоками слоев. Каждый блок включает сверточный слой, слой нормализации пакета, еще один сверточный слой с шагом, чтобы уменьшить изображение в 2 раза, и еще один слой нормализации пакета. Результат проходит через группировку усреднения (average pooling), за которой следует полносвязный сигмоидный слой, возвращающий единственную выходную вероятность.

gan_discriminator.py
        from keras.layers import Conv2D, BatchNormalization, Input, GlobalAveragePooling2D, Dense
from keras.models import Model
from keras.layers.advanced_activations import LeakyReLU

# функция для создания слоев дискриминатора 
def build_discriminator(start_filters, spatial_dim, filter_size):
    
    # функция создания блока CNN block для уменьшения размера изображения
    def add_discriminator_block(x, filters, filter_size):
      x = Conv2D(filters, filter_size, padding='same')(x)
      x = BatchNormalization()(x)
      x = Conv2D(filters, filter_size, padding='same', strides=2)(x)
      x = BatchNormalization()(x)
      x = LeakyReLU(0.3)(x)
      return x
    
    # ввод - это изображение с размерами spatial_dim x spatial_dim и 3 каналами
    inp = Input(shape=(spatial_dim, spatial_dim, 3))

    # строим дискриминатор для уменьшения изображения в 4 раза
    x = add_discriminator_block(inp, start_filters, filter_size)
    x = add_discriminator_block(x, start_filters * 2, filter_size)
    x = add_discriminator_block(x, start_filters * 4, filter_size)
    x = add_discriminator_block(x, start_filters * 8, filter_size)
    
    # усреднение и возврат бинарного вывода
    x = GlobalAveragePooling2D()(x)
    x = Dense(1, activation='sigmoid')(x)
    
    return Model(inputs=inp, outputs=x)
    

Генератор

Генератор принимает вектор шума с размерностью скрытого пространства и генерирует изображение. Размеры этого изображения должны совпадать с размерами входа дискриминатора (spatial_dim * spatial_dim).

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

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

gan_generator.py
        from keras.layers import Deconvolution2D, Reshape

def build_generator(start_filters, filter_size, latent_dim):
  
  # функция для создания блока CNN, увеличивающего размеры изображения
  def add_generator_block(x, filters, filter_size):
      x = Deconvolution2D(filters, filter_size, strides=2, padding='same')(x)
      x = BatchNormalization()(x)
      x = LeakyReLU(0.3)(x)
      return x

  # вход - это вектор шума 
  inp = Input(shape=(latent_dim,))

  # проекция вектора шума в тензор с такой же размерностью, 
  # как последний сверточный слой дискриминатора
  x = Dense(4 * 4 * (start_filters * 8), input_dim=latent_dim)(inp)
  x = BatchNormalization()(x)
  x = Reshape(target_shape=(4, 4, start_filters * 8))(x)

  # строим генератор для увеличения изображения в 4 раза
  x = add_generator_block(x, start_filters * 4, filter_size)
  x = add_generator_block(x, start_filters * 2, filter_size)
  x = add_generator_block(x, start_filters, filter_size)
  x = add_generator_block(x, start_filters, filter_size)    

  # превращаем вывод в трехмерный тензор, изображение с 3 каналами  
  x = Conv2D(3, kernel_size=5, padding='same', activation='tanh')(x)
  
  return Model(inputs=inp, outputs=x)
    

Собственно GAN

Объединенная DCGAN создается добавлением дискриминатора над генератором.

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

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

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

gan_full_model.py
        import pandas as pd
import os
from keras.optimizers import Adam

# загружаем атрибуты изображений знаменитостей 
df_celeb = pd.read_csv('list_attr_celeba.csv')
TOTAL_SAMPLES = df_celeb.shape[0]

# мы будем уменьшать изображения
SPATIAL_DIM = 64 
# размер вектора шума 
LATENT_DIM_GAN = 100 
# размер фильтра в сверточных слоях 
FILTER_SIZE = 5
# количество фильтров в сверточном слое 
NET_CAPACITY = 16
# размер пакета 
BATCH_SIZE_GAN = 32
# интервал для отображения сгенерированных изображений 
PROGRESS_INTERVAL = 80 
# директория для хранения сгенерированных изображений 
ROOT_DIR = 'visualization'
if not os.path.isdir(ROOT_DIR):
    os.mkdir(ROOT_DIR)
    
def construct_models(verbose=False):
    ### дискриминатор
    discriminator = build_discriminator(NET_CAPACITY, SPATIAL_DIM, FILTER_SIZE)
    # компилируем дискриминатор
    discriminator.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.0002), metrics=['mae'])

    ### генератор
    # не компилируем генератор
    generator = build_generator(NET_CAPACITY, FILTER_SIZE, LATENT_DIM_GAN)

    ### DCGAN 
    gan = Sequential()
    gan.add(generator)
    gan.add(discriminator)
    discriminator.trainable = False 
    gan.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.0002), metrics=['mae'])

    if verbose: 
        generator.summary()
        discriminator.summary()
        gan.summary()
        
    return generator, discriminator, gan
  
generator_celeb, discriminator_celeb, gan_celeb = construct_models(verbose=True)
    
Архитектура генератора
Архитектура генератора
Архитектура DCGAN
Архитектура DCGAN

Обучение GAN

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


Следующие шаги выполняются в прямом и обратном направлении, позволяя GAN справиться с проблемами генерации, которые иначе оказались бы неразрешимыми:

Шаг 1. Выбираем несколько реальных изображений из тренировочного набора

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

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

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

Шаг 4. Создаем еще несколько фейковых изображений.

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

Схема обучения генератора. Веса дискриминатора не обновляются, изменяются только веса генератора. Генератор учится обманывать дискриминатор.
Схема обучения генератора. Веса дискриминатора не обновляются, изменяются только веса генератора. Генератор учится обманывать дискриминатор.
gan_training.py
        import cv2
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
from IPython.display import clear_output
 
# количество обновлений дискриминатора на каждую итерацию смены порядка обучения 
DISC_UPDATES = 1  
# количество обновлений генератора на каждую итерацию смены порядка обучения
GEN_UPDATES = 1 

# функция для обучения GAN
def run_training(generator, discriminator, gan, df=df_celeb, start_it=0, num_epochs=1000, 
                 get_real_images=get_real_celebrity):

  # вспомогательная функция для выбора 'size' реальных изображений 
  # и их сжатия до меньшего размера SPATIAL_DIM
  def get_real_celebrity(df, size, total):
      cur_files = df.sample(frac=1).iloc[0:size]
      X = np.empty(shape=(size, SPATIAL_DIM, SPATIAL_DIM, 3))
      for i in range(0, size):
          file = cur_files.iloc[i]
          img_uri = 'img_align_celeba/' + file.image_id
          img = cv2.imread(img_uri)
          img = cv2.resize(img, (SPATIAL_DIM, SPATIAL_DIM))
          img = np.flip(img, axis=2)
          img = img.astype(np.float32) / 127.5 - 1.0
          X[i] = img
      return X
  
  # список для хранения потерь 
  avg_loss_discriminator = []
  avg_loss_generator = []
  total_it = start_it

  # основной цикл обучения
  for epoch in range(num_epochs):

      # поочередный цикл обучения 
      loss_discriminator = []
      loss_generator = []
      for it in range(200): 

          #### Цикл обучения дискриминатора ####
          for i in range(DISC_UPDATES): 
              # выбираем случайный набор реальных изображений
              imgs_real = get_real_images(df, BATCH_SIZE_GAN, TOTAL_SAMPLES)
              # генерируем набор случайных векторов шума 
              noise = np.random.randn(BATCH_SIZE_GAN, LATENT_DIM_GAN)
              # генерируем набор фейковых изображений с помощью нашего генератора 
              imgs_fake = generator.predict(noise)
              # обучаем дискриминатор на реальных изображениях с меткой 1
              d_loss_real = discriminator.train_on_batch(imgs_real, np.ones([BATCH_SIZE_GAN]))[1]
              # обучаем дискриминатор на фейковых изображениях с меткой 0 
              d_loss_fake = discriminator.train_on_batch(imgs_fake, np.zeros([BATCH_SIZE_GAN]))[1]

          # выводим несколько фейковых изображений для визуального контроля сходимости
          if total_it % PROGRESS_INTERVAL == 0:
              plt.figure(figsize=(5,2))
              num_vis = min(BATCH_SIZE_GAN, 5)
              imgs_real = get_real_images(df, num_vis, TOTAL_SAMPLES)
              noise = np.random.randn(num_vis, LATENT_DIM_GAN)
              imgs_fake = generator.predict(noise)
              for obj_plot in [imgs_fake, imgs_real]:
                  plt.figure(figsize=(num_vis * 3, 3))
                  for b in range(num_vis):
                      disc_score = float(discriminator.predict(np.expand_dims(obj_plot[b], axis=0))[0])
                      plt.subplot(1, num_vis, b + 1)
                      plt.title(str(round(disc_score, 3)))
                      plt.imshow(obj_plot[b] * 0.5 + 0.5) 
                  if obj_plot is imgs_fake:
                      plt.savefig(os.path.join(ROOT_DIR, str(total_it).zfill(10) + '.jpg'), format='jpg', bbox_inches='tight')
                  plt.show()  

          #### Цикл обучения генератора ####
          loss = 0
          y = np.ones([BATCH_SIZE_GAN, 1]) 
          for j in range(GEN_UPDATES):
              # создаем набор случайных векторов шума 
              noise = np.random.randn(BATCH_SIZE_GAN, LATENT_DIM_GAN)
              # обучаем генератор на фейковых изображениях с меткой 1 
              loss += gan.train_on_batch(noise, y)[1]

          # сохраняем потери
          loss_discriminator.append((d_loss_real + d_loss_fake) / 2.)        
          loss_generator.append(loss / GEN_UPDATES)
          total_it += 1

      # визуализируем потери
      clear_output(True)
      print('Epoch', epoch)
      avg_loss_discriminator.append(np.mean(loss_discriminator))
      avg_loss_generator.append(np.mean(loss_generator))
      plt.plot(range(len(avg_loss_discriminator)), avg_loss_discriminator)
      plt.plot(range(len(avg_loss_generator)), avg_loss_generator)
      plt.legend(['discriminator loss', 'generator loss'])
      plt.show()

  return generator, discriminator, gan

generator_celeb, discriminator_celeb, gan_celeb = run_training(generator_celeb, 
                                                               discriminator_celeb, 
                                                               gan_celeb, 
                                                               num_epochs=500, 
                                                               df=df_celeb)
    
Фейковые лица, сгенерированные нашим генератором в процессе обучения GAN
Фейковые лица, сгенерированные нашим генератором в процессе обучения GAN

Как мы видим, наш генератор работает неплохо. Сгенерированные лица выглядят неплохо, хотя качество фото не такое хорошее, как в наборе данных CelebA. Это произошло потому, что мы обучили наш GAN на уменьшенных изображениях 64 * 64, которые гораздо более размыты, чем исходные изображения 218 * 178.

Разница между VAE и GAN

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

Фейковые лица, сгенерированные Вариационным АвтоЭнкодером в процессе обучения
Фейковые лица, сгенерированные Вариационным АвтоЭнкодером в процессе обучения

GAN’ы, как правило, намного лучшие глубокие генеративные модели, чем VAE. Хотя VAE работают только в скрытом пространстве, их легче создавать и проще обучать. Можно считать, что VAE обучаются с частичным привлечением учителя (semi-supervised learning), поскольку они обучаются минимизировать потери при воспроизведении конкретных изображений. С другой стороны, GAN’ы – это уже задача обучения без учителя.

Заключение

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

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

Вы можете больше узнать о GANах на Google Developers или из статьи Джозефа Рокка. Вариационные автоэнкодеры были рассмотрены в моей прошлой статье.

12
Июл
2021

🛠 Сложноструктурные аналитические отчеты с Python и LaTeX

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

Экосистема LaTeX. Быстрый старт

  • TeX (произносится как «тех») – система компьютерной верстки, предназначенная для подготовки научно-технических материалов высокого полиграфического качества.
  • LaTeX (произносится «латех») – это, строго говоря, набор макросов на языке разметки TeX, но в зависимости от контекста под LaTeX может пониматься макропакет, издательская система или язык, служащий для разметки документа. LaTeX 2e – наиболее полная, стабильная версия LaTeX.
  • MikTеX – свободно распространяемая реализация TeX под основные операционные системы – Windows, macOS, Linux (Ubuntu, Debian, CentOS и пр.) – включающая в себя практически все наиболее значимые расширения.

Установить реализацию MikTеX под нужную операционную систему можно по инструкциям на странице проекта. При желании с системой можно взаимодействовать и без установки дистрибутива, просто запустив Docker-образ:

miktex_install.sh
        $ docker pull miktex/miktex
$ docker volume create --name miktex
$ docker run -it \
  -v miktex:/miktex/.miktex \
  -v $(pwd):/miktex/work \
  miktex/miktex \
  pdflatex main.tex
    

Здесь с помощью команды docker pull в локальное хранилище образов скачивается Docker-образ miktex/miktex. Затем командой docker volume в файловой системе хоста создается директория miktex/. Последним шагом с помощью команды docker run остается запустить контейнер Docker на базе образа miktex/miktex. Флаг -it создает сеанс интерактивной работы на подключаемом терминальном устройстве, а флаг -v отображает директорию файловой системы хоста на директорию внутри контейнера.

Контейнер ожидает получить аргументы командной строки указывающие на выбранный компилятор (в данном случае PDFLaTeX) и собственно tex-файл (размеченный документ, на основании которого позже будет создан pdf-файл).

В качестве альтернативы MikTEX можно использовать TeX Live – это еще один свободно распространяемый и наиболее полный дистрибутив TeX. Для операционной системы MacOS X можно пользоваться специализированным решением MacTeX.

Опорный документ LaTeX (tex-файл) представляет собой обычный текстовый файл с разметкой. Для редактирования такого рода файлов можно пользоваться и обычным текстовым Unix-редактором Vim, но практичнее использовать специальные решения, например, открытую среду разработки TeXstudio (поддерживает все основные операционные системы). Однако TeXstudio не единственный вариант. Вот наиболее распространенные альтернативы: TeXmaker, Kile, TeXCenter.

LaTeX состоит из пакетов, получить доступ к которым можно на странице CTAN (The Comprehensive TeX Archive Network). CTAN – центральный репозиторий, в который стекаются все сколько-нибудь стоящие наработки, имеющие отношение к TeX.

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

Итак, для запуска примеров из настоящего руководства потребуется установить дистрибутив TeX (например, MikTеX) и LaTeX-редактор (например, TeXstudio).

Введение в язык разметки LaTeX

В текстовых процессорах, которые позволяют в момент набора текста видеть его на экране дисплея точно таким, как он будет выглядеть на бумаге, используется концепция визуального проектирования (WYSIWYG – What You See Is What You Get). В LaTeX же используется концепция логического проектирования, когда внешний вид документа становится понятен только после компиляции.

Внешний вид документа определяется инструкциями, описанными на языке разметки TeX или LaTeX. Между этими языками сложно провести четкую границу. Сам LaTeX написан в командах TeX и в LaTeX-документе можно использовать практические любые TeX-команды. Упрощенно можно считать, что язык разметки LaTeX это высокоуровневая «синтаксически-сахарная» обертка для низкоуровневого языка TeX. Таким образом, TeX в основном применяется при разработке классов и пакетов, в то время как LaTeX – для подготовки печатного документа.

Теперь рассмотрим общий синтаксис языка LaTeX и познакомимся с базовой структурой tex-документа.

  • LaTeX-файл должен начинаться с команды \documentclass, задающей стиль оформления документа, например, \documentclass{article}. Аргумент команды article означает, что документ будет оформлен в соответствии с наиболее общими правилами оформления статей. При желании можно изменить (с незначительными оговорками) любой элемент макета документа.
  • Команда \documentclass поддерживает и другие классы, доступные «из коробки»: book (для оформления книг), report (для оформления отчетов – нечто среднее между book и article), proc (для оформления трудов конференций) и letter (для деловых писем со сложной структурой).
  • После команды \documentclass могут следовать команды, относящиеся ко всему документу. Далее с помощью окружения\begin{document}\end{document} (условимся называть его документарным окружением) указывается тело документа. В общем случае окружением называют сложные конструкции вида \begin{}\end{}.
  • Часть tex-файла между командой \documentclass и \begin{document}\end{document} называют преамбулой. Команды указанные после закрывающей скобки окружения документа \end{document} LaTeX проигнорирует.

В итоге наипростейший шаблон документа будет выглядеть так:

base_example.tex
        \documentclass{article}
% область преамбулы
\begin{document} % тело документа: начало
% текст
\end{document} % тело документа: конец
% команды в этой части документа не будут учитываться при сборке документа
    

Инструкции, управляющие макетом страницы и прочие настройки tex-документа, могут быть размещены и в преамбуле, но когда инструкций становится много, будет удобнее вынести их в отдельный стилевой файл с расширением *.sty. Позже стилевой файл можно будет подключить командой \usepackage{}, принимающей в качестве аргумента путь до этого файла.

Сам стилевой файл содержит импорты пакетов \RequirePackage{}, пользовательские команды \newcommand{}, псевдонимы математических операторов \DeclareMathOperator и прочие элементы кастомизации:

style_template.sty
        % начало стилевого файла
\RequirePackage[english,russian]{babel}
\RequirePackage[utf8]{inputenc}
\RequirePackage{amsmath, amsfonts, amssymb, latexsym}
\RequirePackage[
	left=2cm,
	right=2cm,
	top=2cm,
	bottom=2cm
		]{geometry}
... 
\newcommand{\str}[1]{cтр.~\pageref{#1}}
\newcommand{\strbook}[1]{стр.~{#1}}
...
\DeclareMathOperator*{\argmin}{arg\,min}
\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\sign}{sign}
\DeclareMathOperator*{\const}{const}
...
    

С подключенным стилевым файлом tex-документ будет выглядеть так:

base_example_with_usepackage.tex
        \documentclass{article}
\usepackage{style_template} % подключаем стилевой файл style_template.sty, расположенный в той же директории, что и tex-файл
\begin{document}
% текст
\end{document}
    

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

Далее предполагается, что все настройки макета документа описаны в стилевом файле style_template.sty, который расположен в той же директории, что и tex-файл.

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

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

Наберем в документарном окружении следующие строки:

simple_onepage_template.tex
        ...
\begin{document}

\title{Аналитический отчет по ...} % заголовок отчета
\author{\itshape Иванов И.И.} % автор работы
\date{} % просим LaTeX не указывать дату, так как будет
        % использован наш вариант оформления даты, описанный в стилевом файле
\maketitle % создает заголовок

\thispagestyle{fancy} % задает стиль страницы

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

\tableofcontents % создает оглавление

\section{Пример многострочной формулы}
    Для набора сложных многострочных формул используются различные окружения, например, окружение \texttt{multline}
	\begin{multline}
		F_{\zeta}(z)=P[\,\zeta\leqslant z\,] = \int\!\!\!\int_{x/y\leqslant z}f_X(x;n)f_Y(y;m)\,dxdy =\\ \dfrac{1}{2^{(n+m)/2}\Gamma(n/2)\Gamma(m/2)}\int\!\!\!\int_{x/y\leqslant z}x^{n/2-1}y^{m/2-1}\exp\left( -\frac{x}{2} \right) \exp\left( -\frac{y}{2} \right) \,\mathrm{d}x \, \mathrm{d}y.
	\end{multline}

\section{Пример группового размещения формул}

Несколько формул можно разместить в одной группе с помощью окружения \texttt{gather}
\begin{gather}
	\sum_{j \in \mathbf{N}} b_{ij} \hat{y}_{j} = \sum_{j \in \mathbf{N}} b_{ij}^\lambda \hat{y}_j + (b_{ii} - \lambda_i)\hat{y}_i \hat{y},\notag \\
	\det \mathbf{K}(t=1, t_1, \ldots, t_n) = \sum_{I \in \mathbf{n} } (-1)^{|I|} \prod_{i \in I} t_i \prod_{j \in I} (D_j + \lambda_j t_j) \det \mathbf{A}^{(\lambda)} (\, \overline{I} | \overline{I} \,) = 0,\tag{$a$} \\
	\mathbb{F} = \sum_{i=1}^{\left[ \frac{n}{2}\right] } \binom{ x_{i,i+1}^{i^2}}{ \left[ \frac{i+3}{3} \right]} {{\sqrt{\mu(i)^\frac{3}{2} (i^2-1)}} \over\displaystyle {\sqrt[3]{\rho(i)-2} + \sqrt[3]{\rho(i)-1}} }, \tag{$b$}
\end{gather}

\section{Простая однострочная формула}

Теорема Хинчина-Винера утверждает, что спектральная плотность мощности стационарного в широком смысле случайного процесса представляет собой преобразование Фурье от соответствующей автокорреляционной функции
\begin{equation*} % без нумерации
    S_{xx}(f) = \int\limits_{-\infty}^{\infty}  \, r_{xx} (\tau) e^{-j 2 \pi f \tau} \mathrm{d} \tau,\ \text{где}\ r_{xx}(\tau) = \mathbb{E}[\,x(t) \, x^{*}(t - \tau)\,].
\end{equation*}

\end{document}
    

Теперь можно вызвать компилятор PDFLaTeX через командную оболочку и передать ему имя tex-файла. Результат компиляции приведен на рисунке ниже.

Результат компиляции файла <code class="inline-code">analyt_report_template.tex</code>
Результат компиляции файла analyt_report_template.tex

Рассмотрим более подробно код файла analyt_report_template.tex.

  • В первых строках файла с помощью команд \title и \author мы объявляем заголовок отчета и имя автора работы соответственно, а с помощью команды \maketitleсоздаем заголовок.
  • Затем с помощью команды \date, вызванной без аргументов, подавляем вывод временной метки. Здесь для привязки ко времени будет использоваться специальная низкоуровневая командная вставка в стилевом файле style_template.sty (этот фрагмент кода приводится только для справки, так как конечному пользователю приложения нет необходимости вносить в стилевой файл изменения напрямую):
fragment_style_template.sty
        ... 
\def\@maketitle{
    \begin{flushright}
	\footnotesize\itshape
	Дата последней сборки документа:\\ \today\ в \currenttime
    \end{flushright}

    \begin{center}
	\let \footnote \thanks
	\begin{spacing}{1.5}
	    {\Large\bfseries\@title}
	\end{spacing}\vskip 1mm

	{\normalsize
	    \begin{tabular}[t]{l}
		\@author
	    \end{tabular}\par	
	}
    \end{center}
    \par
    \vskip 1.5em
}
...
    

Команда \thispagestyle задает стиль страницы, а команда \tableofcontents создает оглавление документа. С помощью команды \section создаются разделы документа высшего уровня (с учетом класса документа). Для того чтобы создать раздел более низкого уровня следующей ступени можно воспользоваться командой \subsection.

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

Как должно быть понятно из приведенного выше рисунка, equation используется для однострочных формул, multline – для многострочных, а gather – для группового размещения формул. Звездочка после имени окружения означает, что LaTeX не станет присваивать номера формулам, попавшим в это окружение.

При наборе формул используются специальные LaTeX-команды с названиями созвучными набираемому элементу, например, для того чтобы добавить в формулу знак суммы с нижним lowindex и верхним upindex индексом используется команда \sum_{lowindex}^{upindex}, чтобы вставить символ большой омеги – \Omega, а для вставки символа гамма потребуется \gamma и т.д.

Для быстрого поиска нужных математических LaTeX-команд, специальных символов, приемов оформления псевдокода и пр. удобно пользоваться компактным, но очень содержательным сборником Константина Воронцова «LaTeX 2e в примерах».

Прочие детали работы с издательской системой LaTeX можно выяснить из следующих работ:

Введение в Python-библиотеку Streamlit

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

Установить библиотеку проще всего с помощью менеджера пакетов pip: pip install streamlit.

Запускается приложение командой streamlit run:

streamlit_run.sh
        $ streamlit run streamlit_simple_example.py

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8502 # <-- 
  Network URL: http://192.168.1.247:8502
    

После запуска сценария в браузере (http://localhost:8502) откроется вкладка с приложением. Завершить работу приложения можно, закрыв вкладку браузера и набрав Ctrl+C в командной оболочке.

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

Начать работу со Streamlit можно с вводного руководства, которое подробно описывает все возможности библиотеки, включая Markdown-разметку, аудио и видео объекты, различные графические объекты (Bokeh, Altair, Plotly и др.), а также оптимизацию загрузки объемных наборов данных.

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

streamlit_simple_example.py
        import streamlit as st
import math
import pandas as pd
from pandas import Series
import plotly.graph_objects as go
import numpy as np
import numpy.random as rnd

title_app = "Простой пример использования библиотеки Streamlit"
# чтобы на вкладке браузера отображалось имя приложения, а не имя файла
st.set_page_config(
    layout="wide",
    page_title=title_app,
    initial_sidebar_state="expanded",
)


def gauss_with_exp_acf_gen(
    *,
    sigma: float = 2,
    w_star: float = 1.25,
    delta_t: float = 0.05,
    N: int = 1000,
) -> np.array:
    """
    Описание
    --------
    Генерирует дискретную реализацию
    стационарного гауссовского ПСП
    с КФ экспоненциального типа

    Параметры
    ---------
    sigma : стандартное отклонение ординат ПСП.
    w_star : параметр модели ПСП.
    delta_t : шаг по времени.
    N : число отсчетов ПСП.

    Возвращает
    ----------
    xi : массив элементов ПСП с заданной КФ
    """
    gamma_star = w_star * delta_t
    rho = math.exp(-gamma_star)
    b1 = rho
    a0 = sigma * math.sqrt(1 - rho ** 2)

    xi = np.zeros(N)
    xi[0] = rnd.rand()
    x = rnd.randn(N)

    for n in range(1, N):
        xi[n] = a0 * x[n] + b1 * xi[n - 1]

    return xi


def main(N: int = 100):
    timestmp = np.arange(N)
    # временной ряд №1
    time_series_1 = gauss_with_exp_acf_gen(sigma=5, w_star=1.25, N=N)
    # временной ряд №2
    time_series_2 = gauss_with_exp_acf_gen(sigma=6.5, w_star=1.75, N=N)

    fig = go.Figure()

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=time_series_1,
            name="Временной ряд (объект-1)",
            opacity=0.8,
            mode="lines",
            line=dict(
                color="#E84A5F",
            ),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=Series(time_series_1).rolling(window=7).mean(),
            name="Скользящее среднее (объект-1)",
            mode="lines",
            opacity=0.6,
            line=dict(
                color="#FF847C",
            ),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=time_series_2,
            name="Временной ряд (объект-2)",
            mode="lines",
            opacity=0.8,
            line=dict(
                color="#5E63B6",
            ),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=Series(time_series_2).rolling(window=7).mean(),
            name="Скользящее среднее (объект-2)",
            mode="lines",
            opacity=0.6,
            line=dict(
                color="#6EB6FF",
            ),
        )
    )

    fig.update_layout(
        title=dict(
            # text="<i>Временной ряд</i>",
            font=dict(
                family="Arial",
                size=18,
                color="#07689F",
            ),
        ),
        xaxis_title=dict(
            text="<i>Временная метка</i>",
            font=dict(
                family="Arial",
                size=13,
                color="#537791",
            ),
        ),
        yaxis_title=dict(
            text="<i>Продолжительность простоя, час</i>",
            font=dict(
                family="Arial",
                size=13,
                color="#537791",
            ),
        ),
        xaxis=dict(
            showline=True,
        ),
        yaxis=dict(
            showline=True,
        ),
        autosize=False,
        showlegend=True,
        margin=dict(
            autoexpand=False,
            l=70,
            r=10,
            t=50,
        ),
        legend=dict(
            orientation="v",
            yanchor="bottom",
            y=0.01,
            xanchor="right",
            x=0.99,
            font=dict(family="Arial", size=12, color="black"),
        ),
        plot_bgcolor="white",
    )

    st.plotly_chart(fig, use_container_width=True)


if __name__ == "__main__":
    main(N=350)
    

В этом примере к библиотеке Streamlit имеет отношение только:

  • функция st.set_page_config(), которая переопределяет имя вкладки браузера – отображается не имя файла, а имя приложения;
  • функция st.plotly_chart(), которая принимает сконфигурированный Plotly-объект и выводит его в окно браузера.
Результат работы сценария <code class="inline-code">streamlit_simple_example.py</code>
Результат работы сценария streamlit_simple_example.py

Прочие элементы сценария streamlit_simple_example.py играют лишь вспомогательную роль.

Пример-шаблон аналитического отчета

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

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

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

Часто возникает необходимость выгрузить подготовленный с помощью Streamlit файл результатов (например, табличных объект Pandas), но сам Streamlit не предлагает никаких решений. Тем не менее это ограничение можно обойти с помощью следующей функции:

downloader_for_streamlit.py
        def text_downloader(multiline: str) -> NoReturn:
    """
    Принимает LaTeX-шаблон документа в виде многострочной строки и
    создает на странице ссылку для скачивания шаблона
    """
    OUTPUT_TEX_FILENAME = "base_template_for_latex.tex"
    
    b64 = base64.b64encode(multiline.encode()).decode()
    # создает ссылку для скачивания файла
    href = (f'<a href="data:file/txt;base64,{b64}" '
            f'download="{OUTPUT_TEX_FILENAME}">Скачать ...</a>')
    st.markdown(href, unsafe_allow_html=True)
    

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

При наборе текстового шаблона для Python (latex_template_for_python.txt) – по сути файл представляет собой каркас документа с заглушками под строковую интерполяцию – важно помнить о синтаксических особенностях LaTeX. Дело в том, что в контексте строковой интерполяции фигурные скобки означают «место подстановки», а в контексте LaTeX – обязательный аргумент команды. То есть, чтобы Python корректно «прочитал» строку следует фигурные скобки, относящиеся к синтаксису LaTeX, удвоить.

В результате получится текстовый файл вида:

fragment_latex_template_for_python.txt
        \documentclass[
    11pt,
    a4paper,
    utf8,
]{{article}}

\usepackage{{style_template}}

\begin{{document}}
...
Усталостная долговечность по модели \eqref{{eq:miles}} составляет $ Y_{{NB}} = {Y_NB:.2f} $, сек.

\section{{Оценка усталостной долговечности по модели P.H. Wirsching и C.L.~Light}}
...
    

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

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

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

pdflatex_start.sh
        # для сборки каркаса
$ pdflatex base_template_for_latex.tex
# для вычисления конечных ссылок на страницы, формулы и пр.
$ pdflatex base_template_for_latex.tex

    

После сборки документа в рабочей директории проекта будет создан pdf-файл.

Выгрузка подготовленного LaTeX-шаблона
Выгрузка подготовленного LaTeX-шаблона
Результат работы <code class="inline-code">pdflatex base_template_for_latex.tex</code>. Фрагмент собранного аналитического отчета
Результат работы pdflatex base_template_for_latex.tex. Фрагмент собранного аналитического отчета

Чтобы развернуть приложение на свободной облачной платформе Streamlit, достаточно кликнуть на Deploy this app в правой верхней части панели запущенного приложения, как изображено на рисунке. Однако предварительно необходимо зарегистрироваться на Streamlit и отправить заявку на допуск к ресурсам (обычно обработка заявки занимает несколько дней).

Развертывание приложения на облачной платформе Streamlit
Развертывание приложения на облачной платформе Streamlit

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

Заключение

Из руководства вы узнали:

  • что собой представляет система компьютерной вёрстки LaTeX, где найти ее дистрибутивы и пакеты, как правильно читать документацию, как начать работать с системой;
  • как разрабатывать гибкие, масштабируемые шаблоны документов с помощью языка разметки TeX/LaTeX;
  • как использовать приемы разработки приложений с помощью Python-библиотеки Streamlit;
  • как может выглядеть пример связки «LaTeX + Streamlit»;
  • и, наконец, как развернуть приложение на облачной платформе Streamlit.

Полезные источники:

Связные материалы с платформы Proglib:

12
Июл
2021

🛠 Сложноструктурные аналитические отчеты с Python и LaTeX

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

Экосистема LaTeX. Быстрый старт

  • TeX (произносится как «тех») – система компьютерной верстки, предназначенная для подготовки научно-технических материалов высокого полиграфического качества.
  • LaTeX (произносится «латех») – это, строго говоря, набор макросов на языке разметки TeX, но в зависимости от контекста под LaTeX может пониматься макропакет, издательская система или язык, служащий для разметки документа. LaTeX 2e – наиболее полная, стабильная версия LaTeX.
  • MikTеX – свободно распространяемая реализация TeX под основные операционные системы – Windows, macOS, Linux (Ubuntu, Debian, CentOS и пр.) – включающая в себя практически все наиболее значимые расширения.

Установить реализацию MikTеX под нужную операционную систему можно по инструкциям на странице проекта. При желании с системой можно взаимодействовать и без установки дистрибутива, просто запустив Docker-образ:

miktex_install.sh
        $ docker pull miktex/miktex
$ docker volume create --name miktex
$ docker run -it \
  -v miktex:/miktex/.miktex \
  -v $(pwd):/miktex/work \
  miktex/miktex \
  pdflatex main.tex
    

Здесь с помощью команды docker pull в локальное хранилище образов скачивается Docker-образ miktex/miktex. Затем командой docker volume в файловой системе хоста создается директория miktex/. Последним шагом с помощью команды docker run остается запустить контейнер Docker на базе образа miktex/miktex. Флаг -it создает сеанс интерактивной работы на подключаемом терминальном устройстве, а флаг -v отображает директорию файловой системы хоста на директорию внутри контейнера.

Контейнер ожидает получить аргументы командной строки указывающие на выбранный компилятор (в данном случае PDFLaTeX) и собственно tex-файл (размеченный документ, на основании которого позже будет создан pdf-файл).

В качестве альтернативы MikTEX можно использовать TeX Live – это еще один свободно распространяемый и наиболее полный дистрибутив TeX. Для операционной системы MacOS X можно пользоваться специализированным решением MacTeX.

Опорный документ LaTeX (tex-файл) представляет собой обычный текстовый файл с разметкой. Для редактирования такого рода файлов можно пользоваться и обычным текстовым Unix-редактором Vim, но практичнее использовать специальные решения, например, открытую среду разработки TeXstudio (поддерживает все основные операционные системы). Однако TeXstudio не единственный вариант. Вот наиболее распространенные альтернативы: TeXmaker, Kile, TeXCenter.

LaTeX состоит из пакетов, получить доступ к которым можно на странице CTAN (The Comprehensive TeX Archive Network). CTAN – центральный репозиторий, в который стекаются все сколько-нибудь стоящие наработки, имеющие отношение к TeX.

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

Итак, для запуска примеров из настоящего руководства потребуется установить дистрибутив TeX (например, MikTеX) и LaTeX-редактор (например, TeXstudio).

Введение в язык разметки LaTeX

В текстовых процессорах, которые позволяют в момент набора текста видеть его на экране дисплея точно таким, как он будет выглядеть на бумаге, используется концепция визуального проектирования (WYSIWYG – What You See Is What You Get). В LaTeX же используется концепция логического проектирования, когда внешний вид документа становится понятен только после компиляции.

Внешний вид документа определяется инструкциями, описанными на языке разметки TeX или LaTeX. Между этими языками сложно провести четкую границу. Сам LaTeX написан в командах TeX и в LaTeX-документе можно использовать практические любые TeX-команды. Упрощенно можно считать, что язык разметки LaTeX это высокоуровневая «синтаксически-сахарная» обертка для низкоуровневого языка TeX. Таким образом, TeX в основном применяется при разработке классов и пакетов, в то время как LaTeX – для подготовки печатного документа.

Теперь рассмотрим общий синтаксис языка LaTeX и познакомимся с базовой структурой tex-документа.

  • LaTeX-файл должен начинаться с команды \documentclass, задающей стиль оформления документа, например, \documentclass{article}. Аргумент команды article означает, что документ будет оформлен в соответствии с наиболее общими правилами оформления статей. При желании можно изменить (с незначительными оговорками) любой элемент макета документа.
  • Команда \documentclass поддерживает и другие классы, доступные «из коробки»: book (для оформления книг), report (для оформления отчетов – нечто среднее между book и article), proc (для оформления трудов конференций) и letter (для деловых писем со сложной структурой).
  • После команды \documentclass могут следовать команды, относящиеся ко всему документу. Далее с помощью окружения\begin{document}\end{document} (условимся называть его документарным окружением) указывается тело документа. В общем случае окружением называют сложные конструкции вида \begin{}\end{}.
  • Часть tex-файла между командой \documentclass и \begin{document}\end{document} называют преамбулой. Команды указанные после закрывающей скобки окружения документа \end{document} LaTeX проигнорирует.

В итоге наипростейший шаблон документа будет выглядеть так:

base_example.tex
        \documentclass{article}
% область преамбулы
\begin{document} % тело документа: начало
% текст
\end{document} % тело документа: конец
% команды в этой части документа не будут учитываться при сборке документа
    

Инструкции, управляющие макетом страницы и прочие настройки tex-документа, могут быть размещены и в преамбуле, но когда инструкций становится много, будет удобнее вынести их в отдельный стилевой файл с расширением *.sty. Позже стилевой файл можно будет подключить командой \usepackage{}, принимающей в качестве аргумента путь до этого файла.

Сам стилевой файл содержит импорты пакетов \RequirePackage{}, пользовательские команды \newcommand{}, псевдонимы математических операторов \DeclareMathOperator и прочие элементы кастомизации:

style_template.sty
        % начало стилевого файла
\RequirePackage[english,russian]{babel}
\RequirePackage[utf8]{inputenc}
\RequirePackage{amsmath, amsfonts, amssymb, latexsym}
\RequirePackage[
	left=2cm,
	right=2cm,
	top=2cm,
	bottom=2cm
		]{geometry}
... 
\newcommand{\str}[1]{cтр.~\pageref{#1}}
\newcommand{\strbook}[1]{стр.~{#1}}
...
\DeclareMathOperator*{\argmin}{arg\,min}
\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\sign}{sign}
\DeclareMathOperator*{\const}{const}
...
    

С подключенным стилевым файлом tex-документ будет выглядеть так:

base_example_with_usepackage.tex
        \documentclass{article}
\usepackage{style_template} % подключаем стилевой файл style_template.sty, расположенный в той же директории, что и tex-файл
\begin{document}
% текст
\end{document}
    

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

Далее предполагается, что все настройки макета документа описаны в стилевом файле style_template.sty, который расположен в той же директории, что и tex-файл.

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

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

Наберем в документарном окружении следующие строки:

simple_onepage_template.tex
        ...
\begin{document}

\title{Аналитический отчет по ...} % заголовок отчета
\author{\itshape Иванов И.И.} % автор работы
\date{} % просим LaTeX не указывать дату, так как будет
        % использован наш вариант оформления даты, описанный в стилевом файле
\maketitle % создает заголовок

\thispagestyle{fancy} % задает стиль страницы

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

\tableofcontents % создает оглавление

\section{Пример многострочной формулы}
    Для набора сложных многострочных формул используются различные окружения, например, окружение \texttt{multline}
	\begin{multline}
		F_{\zeta}(z)=P[\,\zeta\leqslant z\,] = \int\!\!\!\int_{x/y\leqslant z}f_X(x;n)f_Y(y;m)\,dxdy =\\ \dfrac{1}{2^{(n+m)/2}\Gamma(n/2)\Gamma(m/2)}\int\!\!\!\int_{x/y\leqslant z}x^{n/2-1}y^{m/2-1}\exp\left( -\frac{x}{2} \right) \exp\left( -\frac{y}{2} \right) \,\mathrm{d}x \, \mathrm{d}y.
	\end{multline}

\section{Пример группового размещения формул}

Несколько формул можно разместить в одной группе с помощью окружения \texttt{gather}
\begin{gather}
	\sum_{j \in \mathbf{N}} b_{ij} \hat{y}_{j} = \sum_{j \in \mathbf{N}} b_{ij}^\lambda \hat{y}_j + (b_{ii} - \lambda_i)\hat{y}_i \hat{y},\notag \\
	\det \mathbf{K}(t=1, t_1, \ldots, t_n) = \sum_{I \in \mathbf{n} } (-1)^{|I|} \prod_{i \in I} t_i \prod_{j \in I} (D_j + \lambda_j t_j) \det \mathbf{A}^{(\lambda)} (\, \overline{I} | \overline{I} \,) = 0,\tag{$a$} \\
	\mathbb{F} = \sum_{i=1}^{\left[ \frac{n}{2}\right] } \binom{ x_{i,i+1}^{i^2}}{ \left[ \frac{i+3}{3} \right]} {{\sqrt{\mu(i)^\frac{3}{2} (i^2-1)}} \over\displaystyle {\sqrt[3]{\rho(i)-2} + \sqrt[3]{\rho(i)-1}} }, \tag{$b$}
\end{gather}

\section{Простая однострочная формула}

Теорема Хинчина-Винера утверждает, что спектральная плотность мощности стационарного в широком смысле случайного процесса представляет собой преобразование Фурье от соответствующей автокорреляционной функции
\begin{equation*} % без нумерации
    S_{xx}(f) = \int\limits_{-\infty}^{\infty}  \, r_{xx} (\tau) e^{-j 2 \pi f \tau} \mathrm{d} \tau,\ \text{где}\ r_{xx}(\tau) = \mathbb{E}[\,x(t) \, x^{*}(t - \tau)\,].
\end{equation*}

\end{document}
    

Теперь можно вызвать компилятор PDFLaTeX через командную оболочку и передать ему имя tex-файла. Результат компиляции приведен на рисунке ниже.

Результат компиляции файла <code class="inline-code">analyt_report_template.tex</code>
Результат компиляции файла analyt_report_template.tex

Рассмотрим более подробно код файла analyt_report_template.tex.

  • В первых строках файла с помощью команд \title и \author мы объявляем заголовок отчета и имя автора работы соответственно, а с помощью команды \maketitleсоздаем заголовок.
  • Затем с помощью команды \date, вызванной без аргументов, подавляем вывод временной метки. Здесь для привязки ко времени будет использоваться специальная низкоуровневая командная вставка в стилевом файле style_template.sty (этот фрагмент кода приводится только для справки, так как конечному пользователю приложения нет необходимости вносить в стилевой файл изменения напрямую):
fragment_style_template.sty
        ... 
\def\@maketitle{
    \begin{flushright}
	\footnotesize\itshape
	Дата последней сборки документа:\\ \today\ в \currenttime
    \end{flushright}

    \begin{center}
	\let \footnote \thanks
	\begin{spacing}{1.5}
	    {\Large\bfseries\@title}
	\end{spacing}\vskip 1mm

	{\normalsize
	    \begin{tabular}[t]{l}
		\@author
	    \end{tabular}\par	
	}
    \end{center}
    \par
    \vskip 1.5em
}
...
    

Команда \thispagestyle задает стиль страницы, а команда \tableofcontents создает оглавление документа. С помощью команды \section создаются разделы документа высшего уровня (с учетом класса документа). Для того чтобы создать раздел более низкого уровня следующей ступени можно воспользоваться командой \subsection.

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

Как должно быть понятно из приведенного выше рисунка, equation используется для однострочных формул, multline – для многострочных, а gather – для группового размещения формул. Звездочка после имени окружения означает, что LaTeX не станет присваивать номера формулам, попавшим в это окружение.

При наборе формул используются специальные LaTeX-команды с названиями созвучными набираемому элементу, например, для того чтобы добавить в формулу знак суммы с нижним lowindex и верхним upindex индексом используется команда \sum_{lowindex}^{upindex}, чтобы вставить символ большой омеги – \Omega, а для вставки символа гамма потребуется \gamma и т.д.

Для быстрого поиска нужных математических LaTeX-команд, специальных символов, приемов оформления псевдокода и пр. удобно пользоваться компактным, но очень содержательным сборником Константина Воронцова «LaTeX 2e в примерах».

Прочие детали работы с издательской системой LaTeX можно выяснить из следующих работ:

Введение в Python-библиотеку Streamlit

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

Установить библиотеку проще всего с помощью менеджера пакетов pip: pip install streamlit.

Запускается приложение командой streamlit run:

streamlit_run.sh
        $ streamlit run streamlit_simple_example.py

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8502 # <-- 
  Network URL: http://192.168.1.247:8502
    

После запуска сценария в браузере (http://localhost:8502) откроется вкладка с приложением. Завершить работу приложения можно, закрыв вкладку браузера и набрав Ctrl+C в командной оболочке.

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

Начать работу со Streamlit можно с вводного руководства, которое подробно описывает все возможности библиотеки, включая Markdown-разметку, аудио и видео объекты, различные графические объекты (Bokeh, Altair, Plotly и др.), а также оптимизацию загрузки объемных наборов данных.

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

streamlit_simple_example.py
        import streamlit as st
import math
import pandas as pd
from pandas import Series
import plotly.graph_objects as go
import numpy as np
import numpy.random as rnd

title_app = "Простой пример использования библиотеки Streamlit"
# чтобы на вкладке браузера отображалось имя приложения, а не имя файла
st.set_page_config(
    layout="wide",
    page_title=title_app,
    initial_sidebar_state="expanded",
)


def gauss_with_exp_acf_gen(
    *,
    sigma: float = 2,
    w_star: float = 1.25,
    delta_t: float = 0.05,
    N: int = 1000,
) -> np.array:
    """
    Описание
    --------
    Генерирует дискретную реализацию
    стационарного гауссовского ПСП
    с КФ экспоненциального типа

    Параметры
    ---------
    sigma : стандартное отклонение ординат ПСП.
    w_star : параметр модели ПСП.
    delta_t : шаг по времени.
    N : число отсчетов ПСП.

    Возвращает
    ----------
    xi : массив элементов ПСП с заданной КФ
    """
    gamma_star = w_star * delta_t
    rho = math.exp(-gamma_star)
    b1 = rho
    a0 = sigma * math.sqrt(1 - rho ** 2)

    xi = np.zeros(N)
    xi[0] = rnd.rand()
    x = rnd.randn(N)

    for n in range(1, N):
        xi[n] = a0 * x[n] + b1 * xi[n - 1]

    return xi


def main(N: int = 100):
    timestmp = np.arange(N)
    # временной ряд №1
    time_series_1 = gauss_with_exp_acf_gen(sigma=5, w_star=1.25, N=N)
    # временной ряд №2
    time_series_2 = gauss_with_exp_acf_gen(sigma=6.5, w_star=1.75, N=N)

    fig = go.Figure()

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=time_series_1,
            name="Временной ряд (объект-1)",
            opacity=0.8,
            mode="lines",
            line=dict(
                color="#E84A5F",
            ),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=Series(time_series_1).rolling(window=7).mean(),
            name="Скользящее среднее (объект-1)",
            mode="lines",
            opacity=0.6,
            line=dict(
                color="#FF847C",
            ),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=time_series_2,
            name="Временной ряд (объект-2)",
            mode="lines",
            opacity=0.8,
            line=dict(
                color="#5E63B6",
            ),
        )
    )

    fig.add_trace(
        go.Scatter(
            x=timestmp,
            y=Series(time_series_2).rolling(window=7).mean(),
            name="Скользящее среднее (объект-2)",
            mode="lines",
            opacity=0.6,
            line=dict(
                color="#6EB6FF",
            ),
        )
    )

    fig.update_layout(
        title=dict(
            # text="<i>Временной ряд</i>",
            font=dict(
                family="Arial",
                size=18,
                color="#07689F",
            ),
        ),
        xaxis_title=dict(
            text="<i>Временная метка</i>",
            font=dict(
                family="Arial",
                size=13,
                color="#537791",
            ),
        ),
        yaxis_title=dict(
            text="<i>Продолжительность простоя, час</i>",
            font=dict(
                family="Arial",
                size=13,
                color="#537791",
            ),
        ),
        xaxis=dict(
            showline=True,
        ),
        yaxis=dict(
            showline=True,
        ),
        autosize=False,
        showlegend=True,
        margin=dict(
            autoexpand=False,
            l=70,
            r=10,
            t=50,
        ),
        legend=dict(
            orientation="v",
            yanchor="bottom",
            y=0.01,
            xanchor="right",
            x=0.99,
            font=dict(family="Arial", size=12, color="black"),
        ),
        plot_bgcolor="white",
    )

    st.plotly_chart(fig, use_container_width=True)


if __name__ == "__main__":
    main(N=350)
    

В этом примере к библиотеке Streamlit имеет отношение только:

  • функция st.set_page_config(), которая переопределяет имя вкладки браузера – отображается не имя файла, а имя приложения;
  • функция st.plotly_chart(), которая принимает сконфигурированный Plotly-объект и выводит его в окно браузера.
Результат работы сценария <code class="inline-code">streamlit_simple_example.py</code>
Результат работы сценария streamlit_simple_example.py

Прочие элементы сценария streamlit_simple_example.py играют лишь вспомогательную роль.

Пример-шаблон аналитического отчета

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

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

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

Часто возникает необходимость выгрузить подготовленный с помощью Streamlit файл результатов (например, табличных объект Pandas), но сам Streamlit не предлагает никаких решений. Тем не менее это ограничение можно обойти с помощью следующей функции:

downloader_for_streamlit.py
        def text_downloader(multiline: str) -> NoReturn:
    """
    Принимает LaTeX-шаблон документа в виде многострочной строки и
    создает на странице ссылку для скачивания шаблона
    """
    OUTPUT_TEX_FILENAME = "base_template_for_latex.tex"
    
    b64 = base64.b64encode(multiline.encode()).decode()
    # создает ссылку для скачивания файла
    href = (f'<a href="data:file/txt;base64,{b64}" '
            f'download="{OUTPUT_TEX_FILENAME}">Скачать ...</a>')
    st.markdown(href, unsafe_allow_html=True)
    

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

При наборе текстового шаблона для Python (latex_template_for_python.txt) – по сути файл представляет собой каркас документа с заглушками под строковую интерполяцию – важно помнить о синтаксических особенностях LaTeX. Дело в том, что в контексте строковой интерполяции фигурные скобки означают «место подстановки», а в контексте LaTeX – обязательный аргумент команды. То есть, чтобы Python корректно «прочитал» строку следует фигурные скобки, относящиеся к синтаксису LaTeX, удвоить.

В результате получится текстовый файл вида:

fragment_latex_template_for_python.txt
        \documentclass[
    11pt,
    a4paper,
    utf8,
]{{article}}

\usepackage{{style_template}}

\begin{{document}}
...
Усталостная долговечность по модели \eqref{{eq:miles}} составляет $ Y_{{NB}} = {Y_NB:.2f} $, сек.

\section{{Оценка усталостной долговечности по модели P.H. Wirsching и C.L.~Light}}
...
    

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

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

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

pdflatex_start.sh
        # для сборки каркаса
$ pdflatex base_template_for_latex.tex
# для вычисления конечных ссылок на страницы, формулы и пр.
$ pdflatex base_template_for_latex.tex

    

После сборки документа в рабочей директории проекта будет создан pdf-файл.

Выгрузка подготовленного LaTeX-шаблона
Выгрузка подготовленного LaTeX-шаблона
Результат работы <code class="inline-code">pdflatex base_template_for_latex.tex</code>. Фрагмент собранного аналитического отчета
Результат работы pdflatex base_template_for_latex.tex. Фрагмент собранного аналитического отчета

Чтобы развернуть приложение на свободной облачной платформе Streamlit, достаточно кликнуть на Deploy this app в правой верхней части панели запущенного приложения, как изображено на рисунке. Однако предварительно необходимо зарегистрироваться на Streamlit и отправить заявку на допуск к ресурсам (обычно обработка заявки занимает несколько дней).

Развертывание приложения на облачной платформе Streamlit
Развертывание приложения на облачной платформе Streamlit

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

Заключение

Из руководства вы узнали:

  • что собой представляет система компьютерной вёрстки LaTeX, где найти ее дистрибутивы и пакеты, как правильно читать документацию, как начать работать с системой;
  • как разрабатывать гибкие, масштабируемые шаблоны документов с помощью языка разметки TeX/LaTeX;
  • как использовать приемы разработки приложений с помощью Python-библиотеки Streamlit;
  • как может выглядеть пример связки «LaTeX + Streamlit»;
  • и, наконец, как развернуть приложение на облачной платформе Streamlit.

Полезные источники:

Связные материалы с платформы Proglib:

05
Июл
2021

🤖 Вариационные автоэнкодеры (VAE) для чайников – пошаговое руководство

Практическое руководство в стиле “сделай сам” с работающим кодом создания и обучения VAE для лиц знаменитостей на Keras.

Текст публикуется в переводе, автор статьи – Мишель Кана.

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

Мотивация

Зачем нужно генерировать новые данные, если в мире и так огромное количество данных? Согласно IDC, в мире более 18 зеттабайтов данных.

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

Как сгенерировать изображения, которых никто не видел?

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

Пример изображения и его реконструкции с помощью нашего кода VAE
Пример изображения и его реконструкции с помощью нашего кода VAE

Данные

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

  • 10.177 личностей;
  • 202.599 изображений;
  • 5 важнейших локаций;
  • 40 бинарных атрибутов для каждого изображения.
        import pandas as pd

df_celeb = pd.read_csv('list_attr_celeba.csv')
df_celeb.head()
    

Ниже мы выбираем случайные лица и выводим их метаданные (атрибуты). Изображения имеют высоту 218 пикселей, ширину 178 пикселей и 3 цветовых канала.

        import matplotlib.pyplot as plt
import random
from skimage.io import imread

def show_sample_image(nb=3, df=df_celeb, verbose=True):
    f, ax = plt.subplots(1, nb, figsize=(10,5))
    for i in range(nb):
        idx = random.randint(0, df.shape[0]-1)
        img_id = df.loc[idx].image_id
        img_uri = 'img_align_celeba/' + img_id
        img = skimage.io.imread(img_uri)  
        if verbose:
            label = img_id
            for col in df.columns:
                if df.loc[idx][col]==1:
                    label = label + '\n' + col  
            if nb > 1:
                ax[i].imshow(img)
                ax[i].set_title(label)
            else:
                ax.imshow(img) 
                ax.set_title(label)
        
    return img, list(df.loc[idx][1:df.shape[1]])
  
sample_img, sample_img_meta = show_sample_image()
    

Что такое автоэнкодер (AE)?

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

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

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

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

Как работают компоненты автоэнкодера
Как работают компоненты автоэнкодера
  • Модель энкодера переводит входное значение X в маленькое плотное представление Z, примерно так же, как работает сверточная нейронная сеть, используя фильтры для усвоения представлений.
  • Модель декодера можно считать генеративной моделью, способной генерировать специфические признаки X’.
  • Энкодер и декодер обычно обучаются вместе. Функция потерь штрафует объединенную сеть за создание выходных лиц, отличающихся от входных лиц.

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

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

Что такое вариационный автоэнкодер (VAE)?

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

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

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

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

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

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

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

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

Генератор данных изображений

Давайте создадим (условный) VAE, который сможет обучаться на лицах знаменитостей. Мы используем пользовательский эффективный по памяти генератор Keras, чтобы справиться с нашим большим набором данных (202599 изображений, примерно по 10Кб каждое). Его цель – получать пакеты изображений на лету в процессе обучения.

        import numpy as np

class CustomCelebrityFaceGenerator(Sequence):
    # инициализируем пользовательский генератор
    def __init__(self, df, batch_size, target_height, target_width, conditioning_dim=0):
        self.df = df
        self.batch_size = batch_size
        self.target_height = target_height
        self.target_width = target_width
        self.conditioning_dim = conditioning_dim
        
    # перетасуем данные после каждой эпохи 
    def on_epoch_end(self):
        self.df = self.df.sample(frac=1)
    
    # выберем пакет в виде тензора
    def __getitem__(self, index):
        cur_files = self.df.iloc[index*self.batch_size:(index+1)*self.batch_size]
        X, y = self.__data_generation(cur_files)
        return X, y
    
    # 
    def __data_generation(self, cur_files):
        # инициализируем пустые тензоры для хранения изображений  
        X = np.empty(shape=(self.batch_size, self.target_height, self.target_width, 3))
        Y = np.empty(shape=(self.batch_size, self.target_height, self.target_width, 3))
        # инициализируем пустой тензор для хранения условных переменных
        if self.conditioning_dim > 0:
            C = np.empty(shape=(self.batch_size, self.conditioning_dim))
        
        # проходим циклом по текущему пакету и создаем тензоры 
        for i in range(0, self.batch_size):
            # читаем изображение
            file = cur_files.iloc[i]
            img_uri = 'img_align_celeba/' + file.image_id
            img = skimage.io.imread(img_uri)
            # изменяем размеры изображения
            if img.shape[0] != self.target_height or img.shape[1] != self.target_width:
                img = skimage.transform.resize(img, (self.target_height, self.target_width)) 
            # сохраняем изображение в тензорах 
            img = img.astype(np.float32) / 255.
            X[i] = img
            Y[i] = img
            # сохраняем условные параметры в тензорах
            if self.conditioning_dim > 0:
                C[i] = list(file[1:file.shape[0]])
            
        if self.conditioning_dim > 0:
            return [X, C], Y
        else:
            return X, Y
    
    # получить количество пакетов
    def __len__(self):
        return int(np.floor(self.df.shape[0] / self.batch_size))
    

Нейронная сеть VAE

Мы хотим, чтобы наш энкодер был сверточной нейронной сетью, принимающей изображение и выдающей параметры распределения Q(z | [x,c]), где x – входное изображение лица, c – условная переменная (атрибуты лица), а z – скрытая переменная. В этой статье мы используем простую архитектуру, состоящую из двух сверточных слоев и слоя группировки (pooling).

Декодер – это сверточная нейронная сеть, построенная по-другому. Это генеративная нейронная сеть, выдающая параметры распределения похожести P([x,z] | c).

        from keras.layers import Conv2D, MaxPooling2D, UpSampling2D

def get_encoder_network(x, num_filters):  
    x = Conv2D(num_filters, 3, activation='relu', padding='same', kernel_initializer='he_normal')(x)
    x = Conv2D(num_filters, 3, activation='relu', padding='same', kernel_initializer='he_normal')(x)
    x = MaxPooling2D()(x)
    return x

def get_decoder_network(x, num_filters):
    x = UpSampling2D()(x)
    x = Conv2D(num_filters, 3, activation='relu', padding = 'same', kernel_initializer = 'he_normal')(x)
    x = Conv2D(num_filters, 3, activation='relu', padding = 'same', kernel_initializer = 'he_normal')(x)
    return x
    

Вот так выглядит архитектура всей сети VAE:

        from keras.layers import Input, Dense, Reshape, Concatenate, Flatten, Lambda, Reshape
from keras.models import Model
from keras import backend as K
from keras.optimizers import Adam

# функция для создания нейронной сети автоэнкодера 
def get_vae(height, width, batch_size, latent_dim, 
            is_variational=True, conditioning_dim=0,
            start_filters=8, nb_capacity=3, 
            optimizer=Adam(lr=0.001)):
    
    # ВХОД ##
    
    # создаем слой для входного изображения 
    # объединяем метаданные изображений 
    inputs = Input((height, width, 3))
    if conditioning_dim > 0:
        condition = Input([conditioning_dim])
        condition_up = Dense(height * width)(condition)
        condition_up = Reshape([height, width, 1])(condition_up)
        inputs_new = Concatenate(axis=3)([inputs, condition_up])
    else:
        inputs_new = inputs
    
    
    # ЭНКОДЕР ##
    
    # создаем кодирующие слои 
    # дублируем кодирующие слои, увеличивая фильтры 
    eblock = get_encoder_network(inputs_new, start_filters)
    for i in range(1, nb_capacity+1):
        eblock = get_encoder_network(eblock, start_filters*(2**i))
        
    # создаем слой скрытого пространства
    _, *shape_spatial = eblock.get_shape().as_list()
    eblock_flat = Flatten()(eblock)    
    if not is_variational:
        z = Dense(latent_dim)(eblock_flat)
    else:
        # выборка скрытых значений из нормального распределения
        def sampling(args):
            z_mean, z_log_sigma = args
            epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0., stddev=1.)
            return z_mean + K.exp(z_log_sigma) * epsilon
        
        z_mean = Dense(latent_dim)(eblock_flat)
        z_log_sigma = Dense(latent_dim)(eblock_flat)
        z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_sigma])
    
    if conditioning_dim > 0:
        z_ext = Concatenate()([z, condition])

        
    ## ДЕКОДЕР ##
    
    # создаем декодирующие статьи
    inputs_embedding = Input([latent_dim + conditioning_dim])
    embedding = Dense(np.prod(shape_spatial), activation='relu')(inputs_embedding)
    embedding = Reshape(eblock.shape.as_list()[1:])(embedding)
    
    # дублируем кодирующие слои, увеличивая фильтры 
    dblock = get_decoder_network(embedding, start_filters*(2**nb_capacity))
    for i in range(nb_capacity-1, -1, -1):
        dblock = get_decoder_network(dblock, start_filters*(2**i))
        
    output = Conv2D(3, 1, activation = 'tanh')(dblock)
    
    ## VAE ##
    
    # объединяем энкодер с декодером 
    decoder = Model(input = inputs_embedding, output = output)
    if conditioning_dim > 0:
        encoder_with_sampling = Model(input = [inputs, condition], output = z)
        encoder_with_sampling_ext = Model(input = [inputs, condition], output = z_ext)
        vae_out = decoder(encoder_with_sampling_ext([inputs, condition]))
        vae = Model(input = [inputs, condition], output = vae_out)
    else:
        encoder_with_sampling = Model(input = inputs, output = z)
        vae_out = decoder(encoder_with_sampling(inputs))
        vae = Model(input = inputs, output = vae_out)
    
    # определяем потери VAE как сумму MSE and потерь расстояния Кульбака-Лейблера
    def vae_loss(x, x_decoded_mean):
        mse_loss = K.mean(mse(x, x_decoded_mean), axis=(1,2)) * height * width
        kl_loss = - 0.5 * K.mean(1 + z_log_sigma - K.square(z_mean) - K.exp(z_log_sigma), axis=-1)
        return mse_loss + kl_loss
        
    if is_variational:
        vae.compile(loss=vae_loss, optimizer=optimizer)
    else:
        vae.compile(loss='mse', optimizer=optimizer)    
        
    return vae, encoder_with_sampling, decoder

# гиперпараметры
VARIATIONAL = True
HEIGHT = 128 
WIDTH = 128 
BATCH_SIZE = 16 
LATENT_DIM = 16
START_FILTERS = 32 
CAPACITY = 3 
CONDITIONING = True 
OPTIMIZER = Adam(lr=0.01)

vae, encoder, decoder = get_vae(is_variational=VARIATIONAL,
                                   height=HEIGHT, 
                                   width=WIDTH, 
                                   batch_size=BATCH_SIZE, 
                                   latent_dim=LATENT_DIM,
                                   conditioning_dim=df_celeb.shape[1]-1, 
                                   start_filters=START_FILTERS,
                                   nb_capacity=CAPACITY,
                                   optimizer=OPTIMIZER)
    

Обучение

Ниже представлен процесс обучения моделей VAE на наборе данных celebA. Этот код выполнялся около 8 часов на инстансе AWS с использованием 1 GPU.

        # делим изображения на тренировочный набор и набор валидации
msk = np.random.rand(len(df_celeb)) < 0.5
df_celeb_train = df_celeb[msk]
df_celeb_val = df_celeb[~msk]

# создаем генераторы изображений для обучения
gen = CustomCelebrityFaceGenerator(df_celeb_train, 
                          batch_size=BATCH_SIZE, 
                          target_height=HEIGHT, 
                          target_width=WIDTH, 
                          conditioning_dim=df_celeb.shape[1]-1)

# создаем генераторы изображений для валидации
gen_val = CustomCelebrityFaceGenerator(df_celeb_val, 
                          batch_size=BATCH_SIZE, 
                          target_height=HEIGHT, 
                          target_width=WIDTH, 
                          conditioning_dim=df_celeb.shape[1]-1)

# обучаем вариационный автоэнкодер
vae.fit_generator(gen, verbose=1, epochs=20, validation_data=gen_val)
    

Визуализируем скрытые представления

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

        # выбираем случайное изображение
sample_img, sample_img_meta = show_sample_image(nb=1)

# функция для кодирования одного изображения, возвращающая его скрытое представление
def encode_image(img, conditioning, encoder, height, width, batch_size):
    # изменяем размеры изображения
    if img.shape[0] != height or img.shape[1] != width:
        img = skimage.transform.resize(img, (height, width))
    # заполняем изображение, чтобы оно соответствовало размеру пакета
    img_single = np.expand_dims(img, axis=0)
    img_single = img_single.astype(np.float32)
    img_single = np.repeat(img_single, batch_size, axis=0)
    # используем энкодер для вычисления представления в скрытом пространстве
    if conditioning is None:
        z = encoder.predict(img_single)
    else:
        z = encoder.predict([img_single, np.repeat(np.expand_dims(conditioning, axis=0), batch_size, axis=0)])
    return z

# выводим представление в скрытом пространстве, созданное энкодером
z = encode_image(sample_img.astype(np.float32) / 255., 
                 np.array(sample_img_meta), 
                 encoder, HEIGHT, WIDTH, BATCH_SIZE)
print('latent sample:\n', z[0])
    


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

        def decode_embedding(z, conditioning, decoder):
    if z.ndim < 2:
        z = np.expand_dims(z, axis=0)
    if conditioning is not None:
        z = np.concatenate((z, np.repeat(np.expand_dims(conditioning, axis=0), z.shape[0], axis=0)), axis=1)
    return decoder.predict(z)

# восстановим исходное изображение, используя представление скрытого пространства 
ret = decode_embedding(z, sample_img_meta, decoder)
plt.imshow(ret[0])
plt.show()
    

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

Генерируем новые лица

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

        def generate_new_images_vae(nb=16, smiling=None, male=None, no_beard=None, attractive=None, 
                        bald=None, chubby=None, eyeglasses=None, young = None):
    sample_training_img, sample_training_img_meta = show_sample_image(nb=1, verbose=False)
    plt.clf();
    f, ax = plt.subplots(2, nb//2, figsize=(20,7));
    for i in range(nb):
        meta=2*np.random.rand(meta_cols.shape[0])-1
        meta[2] = attractive if attractive else meta[2]
        meta[4] = bald if bald else meta[4]
        meta[13] = chubby if chubby else meta[13]
        meta[15] = eyeglasses if eyeglasses else meta[15]
        meta[20] = male if male else meta[20]
        meta[24] = no_beard if no_beard else meta[24]
        meta[31] = smiling if smiling else meta[31]
        meta[39] = young if young else meta[39]
        z1 = np.random.rand(LATENT_DIM, LATENT_DIM)
        ret = decode_embedding(z1, meta, decoder)
        ax[i%2][i//2].imshow(ret[0])
        ax[i%2][i//2].set_title('generated img {}'.format(i))
    ax[0][0].imshow(sample_training_img)
    ax[0][0].set_title('training img')
    
 generate_new_images_vae()
    

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

От улыбки станет мир светлей

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

        # интерполяция скрытого пространства, чтобы изменить исходное изображение
def display_manifold(decoder, height, width, base_vec, 
                     bound_x=15, bound_y=15, 
                     axis_x=0, axis_y=1, n=15,
                     desc_x = 'x', desc_y = 'y', 
                     file_out=None):
 
    figure = np.zeros((height * (n if bound_y > 0 else 1), width * (n if bound_x > 0 else 1), 3))
    grid_x = np.linspace(-bound_x, bound_x, n) if bound_x > 0 else [0]
    grid_y = np.linspace(-bound_y, bound_y, n) if bound_y > 0 else [0]
    individual_outputs = []

    for i, yi in enumerate(grid_y):
        for j, xi in enumerate(grid_x):
            z_sample = base_vec.copy()
            z_sample[axis_x] = xi 
            z_sample[axis_y] = yi 

            x_decoded = decoder.predict(np.expand_dims(z_sample, axis=0))
            sample = np.clip(x_decoded[0], 0, 1)
            figure[i * height: (i + 1) * height, j * width: (j + 1) * width] = sample
            individual_outputs.append(sample)

    plt.figure(figsize=(10, 10))
    plt.imshow(figure)
    plt.xlabel(desc_x)
    plt.ylabel(desc_y)
    if file_out is not None:
        plt.savefig(file_out, dpi=200, bbox_inches='tight')
    return figure, individual_outputs

# доступные атрибуты
meta_cols = df_celeb.columns[1:].values

# изменяемые атрибуты
dim1 = 'Male'
dim2 = 'Smiling'

# используемое скрытое пространство 
base_vec = np.array(list(z[0]) + sample_img_meta)

# создаем изменения
rendering, _ = display_manifold(
                                decoder, 
                                HEIGHT, 
                                WIDTH, 
                                base_vec, 
                                bound_x=15, 
                                bound_y=15, 
                                axis_x=LATENT_DIM + np.where(meta_cols==dim1)[0][0], 
                                axis_y=LATENT_DIM + np.where(meta_cols==dim2)[0][0], 
                                n=10,
                                desc_x = dim1,
                                desc_y = dim2,
                                file_out = 'rendering_celeba_' + dim1.lower() + '_' + dim2.lower() + '.png'
                                )
    

Заключение

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

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

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

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

Если вы хотите узнать больше об автоэнкодерах, читайте статью Джозефа Рокка «Разбираемся с вариационными автоэнкодерами (VAE)».

30
Июн
2021

👨‍🎓️ Школа анализа данных – плюсы и минусы

Школа анализа данных – двухгодичная программа обучения от Яндекса. Основной упор в ней делается на данные и методы работы с ними. В небольшом обзоре мы разберём плюсы и минусы учёбы в ШАД.

Как поступить?

Итак, ШАД – полноценное обучение на протяжении двух лет, с нагрузкой по 30 часов в неделю. Обучение бесплатное, но сначала требуется пройти онлайн-тестирование, затем экзамен и собеседование в филиалах ШАД.

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

Онлайн-тестирование – обычное заполнение анкеты с тестовыми вариантами задач. После него есть два варианта: для москвичей следует прибыть в отделение ШАД и сдать экзамен по математике, алгоритмам, а затем по программированию и основам анализа данных. Заочники или учащиеся в региональных отделениях сдают онлайн-экзамен.

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

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

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

Кому это нужно?

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

В целом, целевую аудиторию можно описать так: хочется попасть в сферу Data Science, сделать это максимально эффективно и интересно. К тому же, обучение проходит по вечерам.

ШАД: Плюсы обучения

  • Знания. Преподаватели в ШАДе частенько в “первую смену” работают в различных вузах Москвы, а затем читают лекции на свою любимую тему в школе Яндекса. Квалификация у них точно на высоте.
  • Вечерняя программа. Учёба по вечерам отлично стимулирует освоение тайм-менеджмента: нужно и задания успеть выполнить, и подготовиться к следующему дню, и время на сон оставить.
  • Математика, данные и программирование. Здесь всё сосредоточено на этих предметах. Нужно знать математику, чтобы с помощью математической же культуры уметь работать с данными. Нужно знать и понимать данные, выявляя среди них закономерности и прочее. И программирование потребуется, чтобы это всё автоматизировать.
  • Интенсивная нагрузка. Слоган ШАДа: «Будет сложно, но интересно». Стимул к обучению студенты получают за счёт интересных задач. Им также предоставляют все необходимые инструменты для подготовки. Можно даже постоянно мучить преподавателей вопросами.

ШАД: Минусы обучения

  • Вечерняя программа. Если ваша жизнь уже загружена, то добавлять к ней вечерние курсы – стрелять себе в ногу. При этом, обучение действительно интенсивное и требует внимательности.
  • Серьёзная нагрузка. Так как здесь учат анализировать, то мозги будут работать на полную катушку. А то потребуется их перегружать их. Следует заранее прокачать выносливость и… умение отдыхать.
***

Зачем стремиться в ШАД? Первое – возможность целиком погрузиться в пучину данных, математических идей и алгоритмов целиком. Второе – полноценная программа обучения в сфере Data Science, диплом и рекомендации, которые помогут получить желанную работу (или сразу отправиться в Яндекс). Третье – высокий уровень самоорганизованности (в основном, для молодых людей), который обязательно разовьётся в ШАДе и при любом исходе будет очень ценным навыком во всей жизни.

«Библиотека программиста» желает вам удачного поступления! Для подготовки к экзаменам записывайтесь на наши курсы по математике в Data Science.

28
Июн
2021

🥇 Не любите Kaggle? Вы просто не умеете его готовить

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

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

Kaggle это платформа, на которой собраны соревнования, курсы, базы данных, туториалы с кодом и обсуждения для решения реальных проблем с помощью Data Science. Существует несколько типов соревнований:

  • Проекты для обучения, предназначенные для новичков, например одни из самых известных Titanic-Machine Learning from Disaster и House Prices- Advanced Regression Techniques.
  • Проекты, в которых представлены данные для обучения и в которых ожидаемый результат известен как компании, так и участникам.
  • Соревнования с денежными призами, с помощью которых компании ищут лучшие решения своих проблем или новых сотрудников (в данном случае результат обычно известен только компании). По мере того, как участники загружают свои материалы, Kaggle делится в режиме реального времени распределением результатов каждой из команд в списке лидеров.

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


С чего начать?

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

Изучите данные

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

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

Присоединитесь к сообществу

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

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

Построение моделей

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

Отправьте результаты

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

Как продолжить

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

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

Обзор последних соревнований


SIIM-FISABIO-RSNA COVID-19 Detection

Дедлайн для регистрации команд: 2 августа 2021 г.

Дата окончания: 9 августа 2021 г.

Призы: 1 место – $30,000, 2 место – $20,000, 3 место – $10,000, специальный приз для студенческой команды.

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

Подробнее: https://www.kaggle.com/c/siim-covid19-detection

CommonLit Readability Prize

Дедлайн для регистрации команд: 26 июля 2021 г.

Дата окончания: 2 августа 2021 г.

Призы: 1 место – $20,000, 2 место – $15,000, 3 место – $10,000.

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

Подробнее: https://www.kaggle.com/c/commonlitreadabilityprize/overview/description

Google Smartphone Decimeter Challenge

Дедлайн для регистрации команд: 28 июля 2021 г.

Дата окончания: 4 августа 2021 г.

Призы: 1 место – $5,000, 2 место – $3,000, 3 место – $2,000.

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

Подробнее: https://www.kaggle.com/c/google-smartphone-decimeter-challenge

SETI Breakthrough Listen – E.T. Signal Search

Дедлайн для регистрации команд: 21 июля 2021 г.

Дата окончания: 28 июля 2021 г.

Призы: 1 место – $6,000, 2 место – $5,000, 3 место – $4,000.

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

Подробнее: https://www.kaggle.com/c/seti-breakthrough-listen

Hungry Geese

Дедлайн для регистрации команд: 26 июля 2021 г.

Дата окончания: 26 июля 2021 г.

Призы: мерч Kaggle (футболки, кружки и т. д.) достанется лучшей команде в ежемесячной таблице лидеров.

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

Подробнее: https://www.kaggle.com/c/hungry-geese/overview/prizes

***

Если вы только начинаете путь в профессии или хотите научиться решать реальные задачи из смежных областей науки о данных, соревнования – хороший способ это сделать. Обратите внимание на курс по спортивному Data Science образовательной онлайн-платформы GeekBrains. Он включает обучение с элементами соревнования в Kaggle и работу с преподавателем, который разбирает на примерах каждый урок.

21
Июн
2021

🐍 Создание интерактивных панелей с Streamlit и Python

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

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

Создать интерактивные панели можно с использованием библиотек вроде Plotly и Bokeh. Мы расскажем о Streamlit – еще одной простой библиотеке Python с открытым исходным кодом, которая стремительно набирает популярность в области машинного обучения и Data Science. Она позволяет публиковать веб-приложения в открытом доступе, а также включает встроенный веб-сервер с возможностью развертывания в контейнере docker. В этом обзоре вы найдете подробную инструкцию о том, как самостоятельно разработать и опубликовать интерактивную панель для визуализации данных.

Подготовка

Подготовка среды

Начнем с установки Streamlit и запуска команды hello. Откройте терминал и запустите приведенные ниже команды:

        $ pip install streamlit
$ streamlit hello
    

Если приложение работает, вы увидите следующий результат:


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


Tip💡
Чтобы выйти из запущенного приложения, используйте Ctrl+с.

Установка библиотек

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

        import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
from urllib.request import urlopen
import json
    

Streamlit позволяет отображать текст по-разному:

  • st.title() – для установки заголовка;
  • st.text() – для записи описания для конкретного графика;
  • st.markdown() – для отображения текста в виде markdown;
  • st.latex() – для отображения математических выражений на панели мониторинга;
  • st.write() – помогает отображать все возможные детали, например, график, фрейм данных, функции, модель и т. д.;
  • st.sidebar() – для отображения данных на боковой панели;
  • st.dataframe() – для отображения фрейма данных;
  • st.map() – для отображения карты в одной строке кода и т. д.

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

Подготовим данные

Чтобы приложение работало более эффективно, уменьшим размер данных, оставив только необходимые переменные:

        # Оставляем только необходимые переменные
df = df[['iso_code','location','total_cases_per_million','total_deaths_per_million','people_vaccinated_per_hundred','date']]
df = df[df.location != 'World']
df["date"] = pd.to_datetime(df["date"])
# Сохраним данные в формате csv для создания приложения
df.to_csv('data.csv', index = False)
    

Настройка заголовка и боковой панели для мониторинга

        # Настройка заголовка и текста 
st.title("COVID 19 IN THE WORLD DASHBOARD")
st.write("""This dashboard will present the spread of COVID-19 in the world by visualizing the timeline of the total cases and deaths. As well as the total number of vaccinated people.""")

# Настройка боковой панели
st.sidebar.title("About")
st.sidebar.info(
    """
    This app is Open Source dashboard.
    """
)
st.sidebar.info("Feel free to collaborate and comment on the work. The github link can be found "
                "[here](https://github.com/yuliianikolaenko/COVID_dashboard_proglib).")


    
Tip💡
Добавьте изображение с помощью st.image().

Загружаем данные

На примере данных о COVID-19 Центра системных наук и инженерии (CSSE) Университета Джона Хопкинса, мы создадим визуализацию для интерактивной панели Streamlit.

        # Загружаем новые оптимизированные данные
DATA = ('data.csv')
DATE_COLUMN = 'date'
@st.cache # для оптимизации работы приложения

# Создадим функцию для загрузки данных
def load_data():
    df = pd.read_csv(DATA, parse_dates=[DATE_COLUMN])
    return df   

# Применим функцию 
df = load_data() 

# Загружаем координаты стран для карты
with urlopen('https://storage.googleapis.com/kagglesdsdata/datasets/4456/6834/world-countries.json?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=gcp-kaggle-com%40kaggle-161607.iam.gserviceaccount.com%2F20210609%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210609T153957Z&X-Goog-Expires=259199&X-Goog-SignedHeaders=host&X-Goog-Signature=13594c9ddedccd436258d48a33dcd74195dcd598a8330ffc5f86b669ca8c744260e0db0ef9e00771989fadab546b45fe5bcf8ab0f882ec554d50488544eafcae313c57548815b3af7fcaaeafab309a95ac263680e6b5ad50a77422414cabf2b14a7e3a37486db7ec29f77428ee48a3d568d3375ec7f3a5f460001d41bde1c62514bfa195e3853fd6a5f9b046ae47f14ddd5bc35f9a33607d4eb080a1554522ba3a443f72c06a1896b8f617da4cc4b5762bff0c3c64ed739fe89669eae0011220895406f43ba81fd6ad8000eb5b53b328c2f170caee41dfeb8448c9982ea6ab3e2878200d195c2cf15e4d9e40574a8fe411f075e47b44f923524ea86e022f850f') as response:
    json_locations = json.load(response)

    

Визуализация

        # Создадим функции для визуализации количества случаев заражения, смертей и вакцинированных людей.
def draw_map_cases():
    fig = px.choropleth_mapbox(df, geojson=json_locations, locations='iso_code', color='total_cases_per_million',
                               color_continuous_scale="Reds",
                               mapbox_style="carto-positron",
                               title = "COVID 19 cases per million",
                               zoom=1,
                               opacity=0.5,
                               )
    fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
    return fig

def draw_map_deaths():
    fig = px.choropleth_mapbox(df, geojson=json_locations, locations='iso_code', color='total_deaths_per_million',
                               color_continuous_scale="Greys",
                               mapbox_style="carto-positron",
                               title = "Deaths from COVID 19 per million",
                               zoom=1,
                               opacity=0.5,
                               )
    fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
    return fig

def draw_map_vaccine():
    fig = px.choropleth_mapbox(df, geojson=json_locations, locations='iso_code', color='people_vaccinated_per_hundred',
                               color_continuous_scale="BuGn",
                               mapbox_style="carto-positron",
                               title = "Vaccinations from COVID 19 per hundred",
                               zoom=1,
                               opacity=0.5,
                               )
    fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
    return fig
    
Tip💡
Измените цветовую палитру карты с помощью аругумента color_continuous_scale. Подробнее: https://plotly.com/python/builtin-colorscales/.

Добавьте интерактивность с помощью виджетов:

  • st.sidebar.checkbox() – для отображения/скрытия данных;
  • st.sidebar.selectbox() – для выбора для отображения параметров.
Tip💡
Используйте флажки, чтобы выбрать данные для визуализации в разных категориях. В поле выбора отобразите raw data, а также кнопку выбора между количеством зараженных, смертельных или восстановленных случаев.

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

        show_data = st.sidebar.checkbox('Show raw data')
if show_data == True:
    st.subheader('Raw data')
    st.markdown(
        "#### Data on COVID-19 (coronavirus) by Our World in Data could be found [here](https://github.com/owid/covid-19-data/tree/master/public/data).")
    st.write(df)

    

        # Создадим поле выбора для даты
show_timerange = st.sidebar.checkbox("Show date range")
if show_timerange == True:
    # Вычислим даты для создания временного слайдера
    min_ts = min(df[DATE_COLUMN]).to_pydatetime()
    max_ts = max(df[DATE_COLUMN]).to_pydatetime()
    day_date = pd.to_datetime(st.sidebar.slider("Date to chose", min_value=min_ts, max_value=max_ts, value=max_ts))
    st.write(f"Data for {day_date.date()}")
    df = df[(df['date'] == day_date)]

# Создадим поле выбора для визуализации общего количества случаев, смертей или вакцинаций
select_event = st.sidebar.selectbox('Show map', ('cases per million', 'deaths per million', 'vaccinated per hundred'))
if select_event == 'cases per million':
    st.plotly_chart(draw_map_cases(), use_container_width=True)

if select_event == 'deaths per million':
    st.plotly_chart(draw_map_deaths(), use_container_width=True)

if select_event == 'vaccinated per hundred':
    st.plotly_chart(draw_map_vaccine(), use_container_width=True)

    

Для построения графика мы используем метод библиотеки plotly.express, в формате который поддерживает Streamlit – st.plotly_chart().


Tip💡
Чтобы просмотреть фрейм данных в табличном представлении, воспользуйтесь st.dataframe() и st.table().

Соединяем все вместе

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

        # Настройка заголовка и текста 
st.title("COVID 19 IN THE WORLD DASHBOARD")
st.write("""This dashboard will present the spread of COVID-19 in the world by visualizing the timeline of the total cases and deaths. As well as the total number of vaccinated people.""")

# Настройка боковой панели
st.sidebar.title("About")
st.sidebar.info(
    """
    This app is Open Source dashboard.
    """
)
st.sidebar.info("Feel free to collaborate and comment on the work. The github link can be found "
                "[here](https://github.com/yuliianikolaenko/COVID_dashboard_proglib).")
# Загружаем новые оптимизированные данные
DATA = ('data.csv')
DATE_COLUMN = 'date'
@st.cache # для оптимизации работы приложения

# Создадим функцию для загрузки данных
def load_data():
    df = pd.read_csv(DATA, parse_dates=[DATE_COLUMN])
    return df   

# Применим функцию 
df = load_data()  


# Создадим функции для визуализации количества случаев заражения, смертей и вакцинированных людей.
def draw_map_cases():
    fig = px.choropleth(df, locations="iso_code",
                         color="total_cases",
                         hover_name="location",
                         title="Total COVID 19 cases in the world",
                         color_continuous_scale=px.colors.sequential.Redor)
    return fig

def draw_map_deaths():
    fig = px.choropleth(df, locations="iso_code",
                         color="total_deaths",
                         hover_name="location",
                         title="Total deaths from COVID 19 in the world",
                         color_continuous_scale=px.colors.sequential.Greys)
    return fig

def draw_map_vaccine():
    fig = px.choropleth(df, locations="iso_code",
                         color="total_vaccinations",
                         hover_name="location",
                         title="Total vaccinated from COVID 19 in the world",
                         color_continuous_scale=px.colors.sequential.Greens)
    return fig

show_data = st.sidebar.checkbox('Show raw data')
if show_data == True:
    st.subheader('Raw data')
    st.markdown(
        "#### Data on COVID-19 (coronavirus) by Our World in Data could be found [here](https://github.com/owid/covid-19-data/tree/master/public/data).")
    st.write(df)

# Вычислим даты для создания временного слайдера
min_ts = min(df[DATE_COLUMN]).to_pydatetime()
max_ts = max(df[DATE_COLUMN]).to_pydatetime()

# Создадим поле выбора для даты
show_timerange = st.sidebar.checkbox("Show date range")
if show_timerange:
    min_selection, max_selection = st.sidebar.slider("Timeline", min_value=min_ts, max_value=max_ts, value=[min_ts, max_ts])
    df = df[(df[DATE_COLUMN] >= min_selection) & (df[DATE_COLUMN] <= max_selection)]

# Создадим поле выбора для визуализации общего количества случаев, смертей или вакцинаций
select_event = st.sidebar.selectbox('Show map', ('total_cases', 'total_deaths', 'total_vaccinations'))
if select_event == 'total_cases':
    st.plotly_chart(draw_map_cases(), use_container_width=True)

if select_event == 'total_deaths':
    st.plotly_chart(draw_map_deaths(), use_container_width=True)

if select_event == 'total_vaccinations':
    st.plotly_chart(draw_map_vaccine(), use_container_width=True)
    

Публикация приложения

Создайте запрос

Теперь, когда вы создали свое приложение, вы можете поделиться им. Используйте Streamlit sharing, чтобы приложение с открытым кодом совершенно бесплатно. Оно будет развертываться непосредственно из вашего репозитория GitHub.

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

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

Чтобы начать работу, сначала запросите приглашение по адресу streamlit.io/sharing. Как только вы получите электронное письмо, можно будет приступить к развертыванию. Для этого придется выполнить несколько шагов.


Поместите свое приложение на GitHub

Поместите ваше приложение Streamlit в публичное репозиторий GitHub. Добавьте файл requirements.txt для управления любыми внешними зависимостями. Streamlit просматривает имя файла ваших требований, чтобы определить, какой менеджер зависимостей Python использовать:


Войдите в систему

Зайдите на share.streamlit.io, нажмите на кнопку кнопка для входа в систему с помощью GitHub (используйте адрес электронной почты, связанный с вашей учетной записью).

Разверните приложение

Нажмите кнопку «Новое приложение»‎, затем введите имя вашего репозитория, ветвь и путь к файлу и нажмите кнопку «Развернуть»‎.

Разработанное в данном туториале приложение живет по адресу:

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

Ваше приложение теперь живет по фиксированному URL в открытом доступе для имеющих ссылку. Достаточно нажать кнопку меню в правом верхнем углу и выбрать «Поделиться этим приложением».

Tip💡
Ознакомьтесь с документацией Streamlit подробнее: https://docs.streamlit.io/en/stable/deploy_streamlit_app.html#python-dependencies.

Заключение

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

19
Июн
2021

🗣 Собеседование на вашу первую работу Data Scientist’ом: чего ожидать и к чему готовиться

Виды собеседований на должность Data Scientist’а, их течение и советы для успеха.

Текст публикуется в переводе. Автор оригинальной статьи – Emma Ding.

Если вы ошеломлены подготовкой к собеседованию на должность Data Scientist’а, вы не одиноки. Поиск “собеседование в Data Science” вернет вам бесконечное количество ссылок, включая статьи о Python, R, статистике, A/B тестированию, машинному обучению, Big Data. Вам посоветуют прочитать бесконечное количество книг. К сожалению, мы и сами давали такие же обширные рекомендации другим.

В реальности вам не нужно готовиться ко всему, чтобы получить свою первую работу Data Scientist’ом.

В этой статье мы расскажем вам о четырех ключевым вещах:

  • Виды должностей Data Scientist’ов.
  • Виды собеседований, к которым вы должны приготовиться.
  • Чего ожидать в процессе собеседования.
  • Что оценивают собеседующие.

Давайте погрузимся в эти темы.

Разбираемся в видах должностей Data Scientist’ов

Мы часто слышим жалобы на запутанные названия должностей. Этих названий очень много, например: Product Data Scientist, Machine Learning Data Scientist, Data Science Engineer, Data Analyst, и этот список постоянно растет. Если вы не знакомы с отраслью, будет очень трудно понять, на какую должность подавать заявление.

В общем, есть четыре вида должностей: Аналитика, Статистика, Инженерия данных и Алгоритмы. Это разделение построено на примере крупных компаний с большими командами Data Science (например, Facebook, Lyft, Airbnb, Netflix).

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

Опишем каждый вид должностей подробнее.

  • Аналитика. Сотрудники на этих должностях оказывают влияние на бизнес, делая рекомендации на основе изучения данных. Их обязанности включают в себя помощь заинтересованным лицам в принятии информированных решений на основе данных, проведение исследовательских анализов, определение бизнес-метрик и визуализация данных (напр., создание информационных панелей).
  • Статистика. Эти должности определяют возможности масштабировать эксперименты и применять статистические подходы (напр., казуальные модели) для решения проблем бизнеса.
  • Инженерия данных. Эти специалисты создают масштабируемые конвейеры данных, которые делают возможными принятие решений на основе этих данных, обычно для потребителей, разбирающихся в данных (аналитиков и Data Scientist’ов). Такие специалисты похожи на типичных инженеров данных, но обычно работают в команде data science, а не обслуживают широкий круг заинтересованных лиц (таких, как инженеры и product manager’ы).
  • Алгоритмы. Эти специалисты создают бизнес-ценности, разрабатывая статистические, оптимизационные модели и модели машинного обучения. Они часто проводят исследовательский анализ данных, чтобы получить глубокое понимание бизнес-задачи и выпустить модели в продакшн.

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

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


Очевидно, что доминирующим видом должностей является Аналитика, а Статистика востребована меньше прочих. То есть, если вы только начинаете свою карьеру Data Scientist’а, Аналитика будет отличным стартовым вариантом.

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

Процесс собеседования: 5 стадий

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

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


1. Онлайн-отсев. Обычная продолжительность: от 30 минут до 1 часа. Вид собеседования: кодирование. Вероятность: 1 случай из 3.

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

2. Беседа с рекрутером по телефону. Обычная продолжительность: 30 минут. Вид собеседования: Поведение и Многофункциональный. Вероятность: 3 случая из 3.

Цель компании: рекрутер хочет убедиться, что ваши интересы, жизненные планы и требования (напр., виза) подходят для этой вакансии. Этот этап – возможность определить, что кандидат не подходит для данной вакансии или наоборот.

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

3. Тестовое задание на обработку данных. Обычная продолжительность: 1 день – 2 недели. Вид собеседования: кодирование. Вероятность: 2 случая из 3.

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

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

4. Телефонный разговор с техническим специалистом. Обычная продолжительность: 30 минут – 1 час. Вид собеседования: кодирование. Вероятность: 2.5 случая из 3.

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

Как правило, у вас будет собеседование с Data Scientist’ом или нанимающим менеджером. Для начала они могут представиться и попросить вас рассказать о своем предыдущем опыте работы.

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

5. Тесты на сайте (обычно 4-6 раундов). Обычная продолжительность: 4-6 часов. Вид собеседования: все. Вероятность: 3 случая из 3.

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

Тестирование на сайте – это последний и самый сложный этап перед получением предложения о работе (offer). Это тестирование обычно более полное, чем предыдущие собеседования, поскольку оно состоит из нескольких собеседований (обычно 4-6). До COVID-19 большинство тестирований проводилось в кампусах компаний, но теперь они стали виртуальными. Комбинация собеседований зависит от вида должности, на которую вы претендуете. Например, тесты на роль Аналитика могут включать несколько собеседований по разным задачам бизнеса, но не включать машинного обучения. Мы обсудим это подробнее в следующем разделе.

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

Семь видов собеседований


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

Собеседования можно разделить на технические и не-технические. Технические собеседования сосредоточены на проверке “hard-навыков”, необходимых для работы, а не-технические – на “soft-навыках” (например, умение общаться и руководить командой), а также пригодность для будущей команды.

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

1. Собеседование кодирования

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

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

Примеры вопросов:

  • Найдите среднюю стоимость покупок для каждого пользователя (SQL).
  • Найдите медианный доход, сгруппированный по странам, не используя функции медианы и процентные функции.
  • Найдите медиану несортированного массива (Python).
  • Закодируйте классический алгоритм машинного обучения – напр., метод k-средних или k ближайших соседей (Python).

Основные советы:

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

Ресурсы:

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

2. Тест обработки данных


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

Примеры вопросов:

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

Основные советы:

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

Ресурсы:

  • Онлайн-сообщество по решению разных задач с данными (Kaggle).
  • Блестящее решение домашних заданий по Data Science (блог).

3. Собеседование метрик/кейсов

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

Примеры вопросов:

  • Как бы вы исследовали негативный сдвиг метрики дохода?
  • Каковы “за” и “против” использования Ежедневных Активных Пользователей (Daily Active Users, DAU) в качестве метрики успеха?
  • Как бы вы устроили эксперимент для признака X?
  • Если A/B тест показывает, что желаемая метрика (напр., показатель кликабельности) растет при понижении другой метрики (напр., количества кликов), как бы вы подошли к решению вопроса о запуске?

Основные советы:

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

Ресурсы:

  • Полное руководство по прохождению собеседований по бизнес-кейсам для Data Scientist’ов (часть 1, часть 2).
  • Чаще всего задаваемые вопросы о метриках и фреймворках (видео).
  • Реальные вопросы и ответы о метриках (видео плейлист).
  • Семь часто задаваемых вопросов и ответов по A/B тестированию с собеседований (блог).

4. Собеседование по статистике и теории вероятностей


Это собеседование тестирует ваше понимание прикладной статистики (напр., проведения экспериментов) и теории вероятностей (напр., теоремы Байеса).

Примеры вопросов:

  • Как бы вы объяснили 10-летнему ребенку, что такое p-value и доверительные интервалы?
  • Какова вероятность заражения пациента, если его тест позитивен, а вероятность заболевания в его популяции составляет 0.1%?
  • Чему равны среднее значение и дисперсия биномиального распределения?
  • Как смоделировать бросок жульнической монеты с помощью обычной монеты?

Основные советы:

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

Ресурсы:

5. Собеседование по машинному обучению

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

Примеры вопросов:

  • Что такое переобучение? Как с ним бороться?
  • Что бы вы делали с несбалансированным набором данных?
  • Расскажите, что такое сдвиг против разброса (bias vs variance).
  • Расскажите, что такое классификатор Случайного Леса (Random Forest).
  • В каких случаях вы бы использовали регуляризацию L1 и L2?

Основные советы:

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

Ресурсы:

  • Полное руководство, как блистать на собеседованиях по машинному обучению (блог).
  • 4 вида задач машинного обучения на собеседованиях по Data Science (видео).
  • Реализация алгоритмов машинного обучения с нуля (плейлист).

6. Собеседование по опыту

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

Примеры вопросов:

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

Основные советы:

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

Ресурсы:

7. Многофункциональные собеседования и собеседования о ценностях компании

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

Примеры вопросов:

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

Основные советы:

  • Просмотрите “ценности компании” (обычно на веб-сайте компании). Подготовьте ситуации, в которых вы действовали в соответствии с этими ценностями.
  • Заранее узнайте, кто будет проводить собеседование, если это возможно. Визуализируйте их проблемы (например, product manager’ы склонны интересоваться тем, как предоставлять данные заинтересованным лицам) и найдите в своем прошлом ситуации, имеющие отношение к этим проблемам.

Ресурсы:

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

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

Вот несколько общих советов:

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

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


Вы можете заметить, что кодирование и не-технические собеседования требуются для всех видов должностей, но некоторым видам Data Scientist’ов не приходится полностью готовиться к собеседованиям всех типов. Например, Аналитики могут меньше внимания уделять Машинному обучению, но больше – собеседованиям метрик/кейсов.

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

Имейте в виду: оцениваемые качества

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

  • Коммуникация – способность эффективно общаться в устном и письменном виде с технической и не-технической аудиторией. Это можно продемонстрировать, отвечая на вопросы последовательным и логическим образом, и объясняя технические концепции с помощью примеров и аналогий.
  • Проницательность в бизнесе / Чувство продукта – способность думать стратегически и практически о “большой картине”, чтобы разрабатывать решения задач, принимая в расчет основные соображения насчет продукта и бизнеса, такие, как экономика, организационные ограничения и точка зрения заинтересованных лиц. Это можно продемонстрировать, вплетая соображения бизнеса и организации в ваши ответы на вопросы.
  • Решение задач – способность разбивать задачу на составные части и разрабатывать подходящие решения, исходя из заданных ограничений. Это можно продемонстрировать на основании полноты и глубины ваших ответов.
  • Сотрудничество и влияние – способность исследовать разные точки зрения и достигать консенсуса с партнерами. Это можно продемонстрировать вашим умением реагировать на обратную связь в процессе собеседования и внедрением нескольких точек зрения в ваши ответы.

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

  • Говорите, не забывая о контексте и аудитории. Различные виды собеседников имеют разные интересы. Например, менеджеры более заинтересованы в идеях высокого уровня и влиянии на бизнес, а индивидуальные участники проекта могут быть более заинтересованы в технических деталях. Большинство собеседников потребуют серьезного погружения в ситуацию и детали.
  • Не торопитесь. Потратьте минуту на то, чтобы записать свои мысли сгруппировать их в “корзины”, которые вы будете использовать при беседе. Это спасет вас от бессвязной болтовни и поможет собеседующему следовать за вашими мыслями. Не бойтесь общаться с собеседующим! Часто задавайте вопросы и сделайте ваше собеседование диалогом.
  • Продемонстрируйте свой интерес к компании, поделившись своими догадками. Докажите, что вы провели исследования, прочитав сведения о компании и ее маркетинговые материалы, а также протестировали продукт. Говорите на языке собеседующего.

Заключение и мысли под занавес

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

Если вы находитесь в самом начале этого пути, вот какие шаги вы должны сделать:

  1. Выберите одну должность, к которой вы стремитесь, и уделяйте особое внимание собеседованиям, наиболее важным для этой должности. Если вы новичок в этой отрасли, мы рекомендуем должности Аналитиков, концентрируясь на подготовке к собеседованиям Кодирования (SQL) и собеседованиям Метрик/кейсов.
  2. Планируйте наперед. Процесс собеседования обычно занимает не менее 3 недель, от подачи заявления до получения предложения работы. Зачастую он занимает месяцы. Вы должны стараться получить предложения сразу от нескольких компаний одновременно, чтобы максимизировать диапазон ваших возможностей и поднять себе цену.
  3. Приготовьтесь потратить немало времени на собеседования. Да, поиск новой работы – это почти вторая работа на полный рабочий день!
  4. Практикуйтесь, практикуйтесь и практикуйтесь! Попросите своих друзей, уже работающих в отрасли, устроить вам тестовые собеседования. Обязательно просите у них обратную связь, чтобы совершенствоваться.
15
Июн
2021

⚕ Какие специалисты по Data Science требуются в медицинских проектах и что им нужно знать?

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

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

  1. Врачи работают по стандартам. С одной стороны, это хорошо, так как в основе стандарта лежит доказательная медицина и врач использует проверенную методологию. С другой стороны, тело и взаимосвязь тела и психики все еще плохо изучены, поэтому при чистых анализах и нестандартных симптомах пациенту вряд ли помогут. В таких случаях намекают на психосоматику и выписывают успокоительные средства. Таким образом врач сообщает: «не знаю, что делать».
  2. Ограниченное время на одного пациента. В РФ терапевту выделяется около 15 минут на пациента, за которые толком ничего не узнаешь.
  3. Врач может ошибиться, ведь он тоже человек. Врачебные ошибки приводят к осложнениям и в некоторых случаях к смерти в среднем у 70 тыс. россиян в год.
  4. Узкая специализация. Врачи узких специализаций рассматривают только свою область компетенций, изолированную от других направлений, в то время как в теле человека все связано и причина болезни может находиться не там, где прописано в стандарте или вообще в другой медицинской области.

Как исправить ситуацию: анализ данных

Часто одни заболевания по симптоматике похожи на другие и поставить верный диагноз невозможно, особенно на ранних стадиях развития болезни. У врача нет времени днями и ночами читать научные статьи на иностранных языках, чтобы сказать пациенту с редким заболеванием или со смазанными симптомами: «В Японии был похожий случай в 2011 г. Лечили вот так и так». Врач не может за несколько минут просмотреть историю болезней пациента за всю его жизнь и найти корреляцию с его текущим состоянием. А машина может с некоторой долей вероятности.

Работа по стандарту подразумевает наличие алгоритма:

  • Узнать симптоматику.
  • Провести диагностику и сделать анализы.
  • Определить диагноз.
  • Назначить лечение.

Эти четыре шага может выполнить машина на основе массива данных.

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

Что нужно знать


  • Питон или язык R;
  • библиотеки Pandas, PyTorch, TensorFlow, Numpy, Matplotlib, Scikit-learn;
  • основы реляционных баз данных. MySQL;
  • обработку естественного языка;
  • прикладную статистику в медицине;
  • уметь визуализировать данные.

Бесплатные курсы:

Чем еще может помочь наука о данных?

1. Фармакология


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

Одной из основных парадигм механизма действия лекарств является теория «замка и ключа». Белок – это «замок», а поиск лекарства заключается в поиске правильного «ключа» для отпирания замка. Лекарство избирательно связывается с определенным местом в белке-мишени, ответственной за заболевание и модулирует – увеличивает или уменьшает – активность мишени.

Что нужно знать

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

Популярные библиотеки:

Бесплатные курсы:

2. Послеоперационный период


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

Что нужно знать

  • Питон или C/C++ на среднем уровне;
  • основы схемотехники;
  • разбираться в датчиках;
  • уметь паять и собирать контроллеры самому;
  • программировать контроллеры: Arduino, ESP, STM или Raspberry Pi.

Бесплатные курсы:

3. Геномика


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

Что нужно знать

  • Питон на среднем+ уровне;
  • библиотеки Pandas, NumPy, SciPy, Scikit-learn, PyTorch или TensorFlow;
  • догмы молекулярной биологии;
  • алгоритмы для секвенирования ДНК;
  • математическую биологию на начальном уровне.

Популярные библиотеки:

Бесплатные курсы:

4. Распознавание изображений


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

Что нужно знать

  • Питон на среднем уровне и выше;
  • принципы ООП, библиотеки NumPy, SciPy и Scikit-learn;
  • алгоритмы и структуры данных на Python;
  • основы высшей математики;
  • уметь работать с библиотекой PyTorch или TensorFlow;
  • строить нейронные сети и проводить сегментацию изображений.

Популярные библиотеки:

Бесплатные курсы:

***

Если есть желание использовать науку о данных не только как двигатель капиталистической машины, но и делать что-то полезное для людей, то, медицина – правильный выбор. Образовательная онлайн-платформа GeekBrains проводит набор на факультет Data Science в медицине, на котором студенты научатся с нуля решать задачи в области медицины. Обучение длится 18 месяцев, плюс 6 месяцев занимает практика по медицинской специализации. По итогам получите 15 проектов в портфолио и гарантию трудоустройства.

10
Июн
2021

📊 NLP и визуализация текста на примере твитов о президентских выборах в США

В написанном совместно с Elbrus Coding Bootcamp туториале мы подробно разберем процесс подготовки данных для визуализации и тематического моделирования на примере твитов о выборах президента США.

Загружаем необходимые библиотеки

        # Обработка/манипулирование данными
import pandas as pd
import numpy as np
pd.options.mode.chained_assignment = None
import re
from unidecode import unidecode 
import warnings
warnings.filterwarnings("ignore",category=DeprecationWarning)

# Визуализация данных
import matplotlib.pyplot as plt
%matplotlib inline
from PIL import Image
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import seaborn as sns

# Визуализация результата тематического моделирования
import pyLDAvis.sklearn 

# Стоп-слова, токенизатор, стеммер
import nltk  
from nltk.corpus import wordnet
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer 

# Sklearn
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import CountVectorizer

# Gensim
import gensim
from gensim.parsing.preprocessing import remove_stopwords

# Spacy 
import spacy
    

Данные

Kaggle dataset US Election 2020 Tweets представляют собой коллекцию твитов, собранных с помощью Twitter API и ключевых слов #donaldtrump и #joebiden в период с 15.10.2020 г. по 08.11.2020 г.

        # Загружаем данные
trump_df = pd.read_csv('hashtag_donaldtrump.csv', lineterminator='\n')
biden_df = pd.read_csv('hashtag_joebiden.csv', lineterminator='\n')

print('Общее количество записей в наборе данных Trump: ', trump_df.shape)
print('Общее количество записей в наборе данных Biden: ', biden_df.shape)

Общее количество записей в наборе данных Trump:  (970919, 21)
Общее количество записей в наборе данных Biden:  (776886, 21)
    

Предварительная обработка данных

Цель: создать финальный датасет для двух кандидатов, который содержит твиты, опубликованные в США и не содержит дубликаты.

        # Удаляем ненужные столбцы
irrelevant_columns = ['user_name','user_screen_name','user_description','user_join_date','collected_at']
trump_df = trump_df.drop(columns=irrelevant_columns)
biden_df = biden_df.drop(columns=irrelevant_columns)
 
# Меняем имена некоторых столбцов для удобства анализа
trump_df = trump_df.rename(columns={"likes": "Likes", "retweet_count": "Retweets",
                                   "state": "State", "user_followers_count": "Followers"})
biden_df = biden_df.rename(columns={"likes": "Likes", "retweet_count": "Retweets",
                                   "state": "State", "user_followers_count": "Followers"})
 
# Переименуем United States of America в United States 
d = {"United States of America":"United States"}
trump_df['country'].replace(d, inplace=True)
biden_df['country'].replace(d, inplace=True)
 
# Создаем новый датасет с твитами, опубликованными только в США
trump_usa_df = trump_df.loc[trump_df['country'] == "United States"]
biden_usa_df = biden_df.loc[biden_df['country'] == "United States"]
 
# Удаляем пустые строки
trump_usa_df = trump_usa_df.dropna()
biden_usa_df = biden_usa_df.dropna()

# Проверяем размер данных
print('Общее количество записей в наборе данных Trump USA: ', trump_usa_df.shape)
print('Общее количество записей в наборе данных Trump Biden USA: ', biden_usa_df.shape)

Общее количество записей в наборе данных Trump USA: (101953, 16) 
Общее количество записей в наборе данных Trump Biden USA: (90639, 16)
    
        trump_usa_df['initial_dataset'] = 'trump'
biden_usa_df['initial_dataset'] = 'biden'

# Объединение данные в единый финальных датасет
twitter_usa_df = pd.concat([trump_usa_df,biden_usa_df],ignore_index=True)
 
# Найдем дубликаты
twitter_usa_df_duplicates = twitter_usa_df[twitter_usa_df.duplicated(['tweet_id'], keep=False)]
 
#Удаляем дубликаты 
trump_usa_df = trump_usa_df[~trump_usa_df.tweet_id.isin(twitter_usa_df_duplicates.tweet_id)]
biden_usa_df = biden_usa_df[~biden_usa_df.tweet_id.isin(twitter_usa_df_duplicates.tweet_id)]
twitter_usa_df.drop_duplicates(subset ="tweet_id", keep = False, inplace = True) 
 
# Проверяем размер данных в финальном датасете
print('Общее количество записей в наборе данных Trump и Biden USA: ', twitter_usa_df.shape)

Общее количество записей в наборе данных Trump и Biden USA: (152376, 17)
    

Подготовка текста

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

Очистка текста

        # Создаем функцию для очистки текста
def clean_text(text):
    text=unidecode(text)
    text=text.lower() # Приведение к строчной форме
    text=re.sub(r'&',' ',text) # Удаляем ampersand (заменяет and)
    text=re.sub(r'[^\[email protected]\[\]]',' ',text)# Удаляем специальные знаки
    text=re.sub(r'@[A-Za-z0-9]+','',text) # Удаляем упоминания других пользователей Twitter 
    text=re.sub(r'#','',text)    
    text=re.sub(r'RT[\s]+','',text)
    text=remove_stopwords(text) # Удаляем стоп-слова
    text=re.sub(r'http\S+'', '', text) # Удаляем все ссылки 
    text=re.sub(r'https?:\/\/\S+','',text)
    text=re.sub(r'donal\S+'', ' ', text) # Удаляем упоминания имен кандидатов
    text=re.sub(r'trum\S+'', ' ', text)
    text=re.sub(r'donaldtrum\S+'', ' ', text)
    text=re.sub(r'joe\S+'', ' ', text)   
    text=re.sub(r'biden\S+'', ' ', text)
    text=re.sub(r'joebide\S+'', ' ', text)
    text=re.sub(r'vot\S+'', ' ', text) # Удаляем частотные слова vote и election
    text=re.sub(r'electio\S+'', ' ', text)
    text=re.sub(r'/s\s', '', text) # Удаляем единичные буквы s и t 
    text=re.sub(r'/t\s', '', text)
    return text
    
        # Применяем функцию для очистки текста
trump_usa_df['cleaned_tweet'] = trump_usa_df.tweet.apply(lambda x: clean_text(x))
biden_usa_df['cleaned_tweet'] = biden_usa_df.tweet.apply(lambda x: clean_text(x))
twitter_usa_df['cleaned_tweet'] = twitter_usa_df['tweet'].apply(lambda x: clean_text(x))
    

Лемматизация

Лемматизация – процесс приведения словоформы к лемме – её нормальной (словарной) форме.

Пример в английском языке:
Walk, walked, walks, walking → to walk

В русском:
Кошками, кошки, кошкам → кошка

        # Создаем функцию для преобразование тега nltk в тег wordnet
lemmatizer = WordNetLemmatizer()
def nltk_tag_to_wordnet_tag(nltk_tag):
    if nltk_tag.startswith('J'):
        return wordnet.ADJ
    elif nltk_tag.startswith('V'):
        return wordnet.VERB
    elif nltk_tag.startswith('N'):
        return wordnet.NOUN
    elif nltk_tag.startswith('R'):
        return wordnet.ADV
    else:         
        return None
      
# Создаем функцию для лемматизации текста
def lemmatize_sentence(sentence):
    nltk_tagged = nltk.pos_tag(nltk.word_tokenize(sentence)) 
    wordnet_tagged = map(lambda x: (x[0], nltk_tag_to_wordnet_tag(x[1])), nltk_tagged)
    lemmatized_sentence = []
    for word, tag in wordnet_tagged:
        if tag is None:
            lemmatized_sentence.append(word)
        else:  
                lemmatized_sentence.append(lemmatizer.lemmatize(word, tag))
    return " ".join(lemmatized_sentence)
    
        # Применяем функцию для лемматизации текста
trump_usa_df['lemmat_tweet'] = trump_usa_df.cleaned_tweet.apply(lambda x: lemmatize_sentence(x))
biden_usa_df['lemmat_tweet'] = biden_usa_df.cleaned_tweet.apply(lambda x: lemmatize_sentence(x))
twitter_usa_df['lemmat_tweet'] = twitter_usa_df.cleaned_tweet.apply(lambda x: lemmatize_sentence(x))
    
        # Сравним результаты очистки и подготовки твитов с оригинальным текстов
pd.options.display.max_colwidth = 50
print(twitter_usa_df[['tweet', 'cleaned_tweet', 'lemmat_tweet']].head(3))

                                               tweet  \
0  #Trump: As a student I used to hear for years,...   
1  You get a tie! And you get a tie! #Trump ‘s ra...   
3  #Trump #PresidentTrump #Trump2020LandslideVict...   

                                       cleaned_tweet  \
0    student hear years years heard china 2019 1 ...   
1               tie tie   s rally iowa  t jjaluumh5d   
3    president      maga kag 4moreyears america a...   

                                        lemmat_tweet  
0  student hear year year heard china 2019 1 5 t ...  
1                  tie tie s rally iowa t jjaluumh5d  
3  president maga kag 4moreyears america americaf...  
    

Токенизация

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

        # Подготовка текста для анализа частотности для всех твитов
list_text = []
for string in twitter_usa_df['lemmat_tweet']:
    list_text.append(string)
list_text

str_text = str(list_text)
tokens = word_tokenize(str_text)
txt_tokens = [word.lower() for word in tokens if word.isalpha()]
    

Исследовательский анализ данных

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

Количество твитов по датам

        # Преобразуем дату в pandas datetime формат
twitter_usa_df['created_at'] =  pd.to_datetime(twitter_usa_df['created_at'])
# Проверяем период во время которого были собраны данные 
print(f" Данные собраны с {twitter_usa_df.created_at.min()}")
print(f" Данные собраны по {twitter_usa_df.created_at.max()}")

Данные собраны с 2020-10-15 00:00:02
Данные собраны по 2020-11-08 23:58:44
    
        # Создаем датасет с частотностью твитов согласно дате
cnt_srs = twitter_usa_df['created_at'].dt.date.value_counts()
cnt_srs = cnt_srs.sort_index()
    
        # Визуализация количества твитов согласно дате
plt.figure(figsize=(14,6))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color='lightblue')
plt.xticks(rotation='vertical')
plt.xlabel('Date', fontsize=12)
plt.ylabel('Number of tweets', fontsize=12)
plt.title("Number of tweets according to dates")
plt.show()
    

Анализ частности слов

Word Clouds

        # Создаем текст для облака частотных слова
text_wordcloud= ' '.join(map(str, txt_tokens)) 
wordcloud = WordCloud(width=1600, height=800, max_font_size=200, max_words=100, colormap='vlag',background_color="white", collocations=True).generate(text_wordcloud)

# Визуализация 
plt.figure(figsize=(20,10))
plt.imshow(wordcloud)
plt.title('Wordcloud of TOP 100 frequent words for all tweets')
plt.axis("off")
plt.show()
    

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

Для Трампа:


Для Байдена:


        list_text = []
for string in biden_usa_df['lemmat_tweet']:
    list_text.append(string)
list_text

text_biden = str(list_text)
tkns_biden = word_tokenize(text_biden)
tokens_biden = [word.lower() for word in tkns_biden if word.isalpha()]
tokens_biden= ' '.join(map(str, tokens_biden)) 

# Загружаем портрет Байдена и используем np.array для преобразования файла в массив
biden_mask=np.array(Image.open('biden.png'))
biden_mask=np.where(biden_mask > 3, 255, biden_mask)

# Создаем облако частотных слова
wordcloud = WordCloud(background_color='white',
                      contour_color='blue',
                      mask=biden_mask, colormap='Blues',
                      contour_width=4).generate(tokens_biden)

# Визуализация
plt.figure(figsize=(20,10))
plt.imshow(wordcloud, interpolation='bilinear')
plt.title('Wordcloud of TOP frequent words for Biden tweets', fontsize = 20)
plt.axis('off')
plt.show()
    

        # Повторяем для Трампа
list_text = []
for string in trump_usa_df['lemmat_tweet']:
    list_text.append(string)
list_text

text_trump = str(list_text)
tokens_trump = word_tokenize(text_trump)
tokens_trump = [word.lower() for word in tokens_trump if word.isalpha()]
tokens_trump = ' '.join(map(str, tokens_trump)) 
trump_mask=np.array(Image.open('trump.png'))
trump_mask=np.where(trump_mask > 3, 255, trump_mask)

wordcloud = WordCloud(background_color='white',
                      contour_color='red',
                      mask=trump_mask, colormap='Reds',
                      contour_width=1).generate(tokens_trump)


# Визуализация 
plt.figure(figsize=(20,10))
plt.imshow(wordcloud, interpolation='bilinear')
plt.title('Wordcloud of TOP frequent words for Trump tweets')
plt.axis('off')
plt.show()
    

Идея💡
Для создания персонализированной цветовой гаммы воспользуйтесь Colormaps in Matplotlib.

Анализ частотности би-граммов

Цель: создать список наиболее часто встречающихся биграмм (пара последовательных слов) в твитах для более глубокого изучения текста.

        # Создаем датасет самых частотных биграммов
bigrams_series = (pd.Series(nltk.ngrams(txt_tokens, 2)).value_counts())[:10]
bigrams_top = pd.DataFrame(bigrams_series.sort_values(ascending=False))
bigrams_top = bigrams_top.reset_index().rename(columns={'index': 'bigrams', 0:'counts'})

# Визуализация биграммов
plt.figure(figsize=(20,10))
sns.catplot(x = 'counts' , y='bigrams', kind="bar", palette="vlag", data=bigrams_top, height=8.27, aspect=11.7/8.27)
plt.title('TOP 10 pair of words which occurred the texts')
    

Анализ популярности твитов

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

        # Самый популярный твит в датасете согласно количеству ретвитов пользователей
tweet_retweet_max = twitter_usa_df.loc[twitter_usa_df['Retweets'].idxmax()]
tweet_retweet_max

created_at                                       2020-11-06 16:31:06
tweet              America Assembled!🇺🇸🎉\n\[email protected] @KamalaHarr...
Likes                                                          74528
Retweets                                                       20615
source                                            Twitter for iPhone
Followers                                                       8080
user_location                                           Brooklyn, NY
lat                                                          40.6501
long                                                        -73.9496
city                                                        New York
country                                                United States
continent                                              North America
State                                                       New York
state_code                                                        NY
initial_dataset                                                biden
clean_tweets       america assembled            brothers election...
tokenize_tweets    [america, assembled, brothers, election2020, e...
Name: 170447, dtype: object
    
        # Полный текст твита
print(f" The tweet '{tweet_retweet_max.tweet}' was retweeted the most with {tweet_retweet_max.Retweets} number of retweets.")
    
Самый популярный твит в датасете:
America Assembled!🇺🇸🎉@JoeBiden @KamalaHarris @BarackObama @ChrisEvans @MarkRuffalo @RobertDowneyJr @brielarson @AOC @staceyabrams @michaelb4jordan @Russo_Brothers #Election2020 #ElectionResults2020 #joebiden #DonaldTrump #BidenHarris2020 #avengers #endgame

Тематическое моделирование

Цель: автоматически определить темы в наборе текстов и предсказать топик для новых твитов.

Создание модели

        vectorizer = CountVectorizer(analyzer='word',       
min_df=3, # минимально необходимые вхождения слова
stop_words='english',# удаляем стоп-слова
lowercase=True,# преобразование всех слов в нижний регистр
token_pattern='[a-zA-Z0-9]{3,}',# удаляем специальные знаки
max_features=5000,# максимальное количество уникальных слов
)

data_matrix = vectorizer.fit_transform(twitter_usa_df.lemmat_tweet)

lda_model = LatentDirichletAllocation(
n_components=12, # Выбираем количество тем
learning_method='online',
random_state=62,       
n_jobs = -1  
)

lda_output = lda_model.fit_transform(data_matrix)
    

Визуализация модели с pyLDAvis

        pyLDAvis.enable_notebook()
p = pyLDAvis.sklearn.prepare(lda_model, data_matrix, vectorizer, mds='tsne')
pyLDAvis.save_html(p, 'lda.html')
    
Идея💡
Сохраните интерактивную визуализацию в формате html.


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

        for i,topic in enumerate(lda_model.components_):
    print(f'Top 10 words for topic #{i + 1}:')
    print([vectorizer.get_feature_names()[i] for i in topic.argsort()[-10:]])
    print('\n')

Top 10 words for topic #1:
['leader', 'corruption', 'nevada', 'gop', 'politics', 'video', 'real', 'georgia', 'ballot', 'hunter']


Top 10 words for topic #2:
['united', 'medium', 'michigan', 'believe', 'look', 'people', 'country', 'news', 'need', 'state']


Top 10 words for topic #3:
['people', 'mail', 'today', 'man', 'work', 'obama', 'american', 'count', 'pennsylvania', 'let']


Top 10 words for topic #4:
['time', 'gon', 'matter', 'turn', 'thing', 'hear', 'kamala', 'win', 'life', 'good']


Top 10 words for topic #5:
['like', 'lose', 'poll', 'time', 'talk', 'debate', 'try', 'maga', 'know', 'win']


Top 10 words for topic #6:
['tax', 'cnn', 'que', 'china', 'hope', 'usa', 'day', 'elect', '2020', 'president']


Top 10 words for topic #7:
['arizona', 'party', 'florida', 'stop', 'covid', '000', 'covid19', 'win', 'republican', 'democrat']


Top 10 words for topic #8:
['racist', 'fraud', 'guy', 'say', 'speech', 'presidential', 'house', 'white', 'lie', 'presidentelect']


Top 10 words for topic #9:
['case', 'claim', 'anti', 'feel', 'fuck', 'lead', 'blm', 'dump', 'new', 'come']


Top 10 words for topic #10:
['red', 'lol', 'political', 'truth', 'child', 'person', 'demvoice1', 'bluewave', 'care', 'end']


Top 10 words for topic #11:
['msnbc', 'black', 'thank', 'support', 'wtpsenate', 'year', 'love', 'harris', 'america', 'kamalaharris']


Top 10 words for topic #12:
['campaign', 'democracy', 'watch', 'debates2020', 'family', 'supporter', 'great', 'wtpblue', 'like', 'think']
    

Соединяем найденные темы с твитами

        topic_values = lda_model.transform(data_matrix)
twitter_usa_df['Topic'] = topic_values.argmax(axis=1)

twitter_usa_df[['tweet', 'Topic']].head(4)

	tweet	Topic
0	#Trump: As a student I used to hear for years,...	0
1	You get a tie! And you get a tie! #Trump ‘s ra...	11
3	#Trump #PresidentTrump #Trump2020LandslideVict...	8
4	#Trump: Nobody likes to tell you this, but som...	7
    

Прогнозная модель для новых твитов

        # Определяем топ ключевых слов в каждой теме 
def show_topics(vectorizer=vectorizer, lda_model=lda_model, n_words=100):
    keywords = np.array(vectorizer.get_feature_names())
    topic_keywords = []
    for topic_weights in lda_model.components_:
        top_keyword_locs = (-topic_weights).argsort()[:n_words]
        topic_keywords.append(keywords.take(top_keyword_locs))
    return topic_keywords
topic_keywords = show_topics(vectorizer=vectorizer, lda_model=lda_model, n_words=100)        

# Создаем датасет тема - ключевое слово 
df_topic_keywords = pd.DataFrame(topic_keywords)
df_topic_keywords.columns = ['Word '+str(i) for i in range(df_topic_keywords.shape[1])]
df_topic_keywords.index = ['Topic '+str(i) for i in range(df_topic_keywords.shape[0])]
    
        # Создаем функции для подготовки текста
def sent_to_words(sentences):
    for sentence in sentences:
        yield(gensim.utils.simple_preprocess(str(sentence), deacc=True)) 

def lemmatization(texts, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
    texts_out = []
    for sent in texts:
        doc = nlp(" ".join(sent)) 
        texts_out.append(" ".join([token.lemma_ if token.lemma_ not in ['-PRON-'] else '' for token in doc if token.pos_ in allowed_postags]))
    return texts_out

# Загружаем модель 
nlp = spacy.load("en_core_web_sm")

# Создаем функцию для прогнозирования темы для новых твитов
def predict_topic(text, nlp=nlp):
    global sent_to_words
    global lemmatization
    # Подготовим текст
    mytext_2 = list(sent_to_words(text))
    # Лемматизация
    mytext_3 = lemmatization(mytext_2, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV'])
    # Векторизация
    mytext_4 = vectorizer.transform(mytext_3)
    # Трансформация модели
    topic_probability_scores = lda_model.transform(mytext_4)
    topic = df_topic_keywords.iloc[np.argmax(topic_probability_scores), :].values.tolist()
    return topic, topic_probability_scores
    
        # Прогноз для нового твита "Biden is the best president for this country vote for him"
mytext =  ["Biden is the best president for this country vote for him"]
topic, prob_scores = predict_topic(text = mytext)

# Визуализация ключевых слов для нового твита
fig, ax = plt.subplots(figsize=(20,10))
plt.bar(topic[:12], prob_scores[0])
axes = plt.gca()
axes.set_ylim(0, 0.5)
axes.set_xlabel('Related keywords', fontsize = 20)
axes.set_ylabel('Probability score', fontsize = 20)

fig.tight_layout()
plt.show()
    

Новый твит был определен как Тема 6 с ключевыми словами DAY и HOPE.

        # Прогноз для нового твита "CNN lies to people"
mytext = ["CNN lies to people"]
topic, prob_scores = predict_topic(text = mytext)
# Визуализация ключевых слов для нового твита

fig, ax = plt.subplots(figsize=(20,10))
plt.bar(topic[:12], prob_scores[0])
axes = plt.gca()
axes.set_ylim(0, .4)
axes.set_xlabel('Related keywords', fontsize = 20)
axes.set_ylabel('Probability score', fontsize = 20)

fig.tight_layout()
plt.show()
    

Новый твит был определен как Тема 8 с ключевыми словами LIE и GUY.

Идея💡
Узнайте подробнее о том как создать grid search лучших тематических моделей.

Заключение

Подготовить текст к анализу данных и визуализировать дискурс вокруг выборов оказалось несложно, а еще мы смогли построить простую модель для определения темы нового твита. За этой кажущейся простотой кроется довольно серьезная математика, притом помимо теоретических знаний настоящий Data Scientist должен освоить и практические умения. Сделать это сидя за книгами будет затруднительно – лучше сразу ввязаться в драку. Разработанная в США методика Bootcamp предполагает интенсивное очное обучение с полным погружением в процесс. В России этот формат практикует образовательный проект Elbrus: студенты практически живут в московском кампусе, посвящая науке о данных все будние дни с 9 до 18 часов.

***

Заниматься в онлайне без отрыва от производства не получится, но формат буткампа обеспечивает высочайшую вовлеченность всех участников в учебный процесс. В течение 12 недель под руководством практикующего Data Scientist студенты осваивают сбор и анализ данных, нейронные сети, машинное обучение и другие hard и soft skills: количество практических занятий при этом сравнимо со стажировкой в крупной ИТ-компании. Успешно завершив курс, вы получите не только ценные знания, но и возможность их применить, а также добавите несколько проектов в свое портфолио. Удачи!

08
Июн
2021

🎨 Используем CycleGAN для применения стиля к видео, полученному с веб-камеры

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

Текст публикуется в переводе, автор оригинальной статьи Бен Сантос.

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

Чем больше я изучал CycleGAN, тем больше меня привлекала одна из областей его применения: передача стиля (style transfer). Цель передачи стиля – это изучение того, как поставить в соответствие изображениям из пространства A изображения из другого пространства B. Классический пример – одно из пространств является коллекцией фотографий, а второе – картины знаменитого художника, например, Клода Моне. Применение передачи стиля заставляет обычные фотографии выглядеть так, как если бы их рисовал Моне.

Взято из <a href="https://arxiv.org/abs/1703.10593" target="_blank" rel="noopener noreferrer nofollow">"Беспарного перевода изображений с помощью цикло-устойчивых соревновательных сетей"</a>
Взято из “Беспарного перевода изображений с помощью цикло-устойчивых соревновательных сетей”

Этот процесс известен как перевод изображений, и традиционно он требует большого набора данных с парными изображениями – то есть, для обучения переводу вам нужны рисунки и фотографии одних и тех же мест, сделанные под одним и тем же углом, в одно и то же время дня и так далее. По очевидным причинам, получение таких парных данных нереалистично, а зачастую даже невозможно. Разве не было бы замечательно, если бы можно было переводить изображения в картины без парных примеров? Эта задача была исследована, и в результате появился эффективный беспарный метод перевода изображений в виде “циклически-согласованных соревновательных сетей” (CycleGAN), использующих архитектуры GAN для изучения необходимых соответствий и выполнения высококачественного перевода изображений. Меня заинтересовало, насколько эффективен CycleGAN при обработке видео, поэтому в этой краткой статье я приведу краткое описание принципов работы CycleGAN, а потом расскажу, как использовать официальную реализацию CycleGAN для применения художественных стилей Моне, Ван Гога и прочих к вашей собственной веб-камере.

Идеи, лежащие в основе CycleGAN

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

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

Для достижения первой цели мы используем два генератора с двумя соответствующими дискриминаторами и применяем соревновательную функцию потерь, приведенную ниже (формула взята из “Беспарного перевода изображений с помощью цикло-устойчивых соревновательных сетей”):

LGAN(G,DY,X,Y)=Ey∼pdata(y)[logDY(y)]+Ex∼pdata(x)[log(1−DY(G(x)))]

Здесь генератор G принимает изображение X и генерирует изображение G(X), выглядящее так, как могло бы выглядеть изображение из пространства Y. Дискриминатор DY пытается корректно отличить сгенерированные изображения от случайно выбранных изображений из пространства Y. G пытается минимизировать эту цель (генерируя реалистичные изображения), а DY пытается его максимизировать (верно различая сгенерированные и реальные изображения). Эта же цель может использоваться при установке соответствия и переводе из пространства Y в пространство X.

Одного этого недостаточно для достижения желаемой передачи стиля. Обучение с одними соревновательными потерями приведет к успешной генерации из пространства X в пространство Y, но не даст гарантий того, что сгенерированное изображение будет похожим на оригинал. Мы хотим, чтобы преобразование было “цикло-устойчивым”, то есть изображение, переведенное в целевое пространство, а затем переведенное обратно, должно быть как можно ближе к исходному изображению: X -> G(X) -> F(G(X)) примерно эквивалентно X, где F – это генератор, переводящий изображения из пространства Y в пространство X.


Взято из <a href="https://arxiv.org/abs/1703.10593" target="_blank" rel="noopener noreferrer nofollow">"Беспарного перевода изображений с помощью цикло-устойчивых соревновательных сетей"</a>
Взято из “Беспарного перевода изображений с помощью цикло-устойчивых соревновательных сетей”

Чтобы обеспечить этот принцип и достичь нашей второй цели, определим функцию потерь цикло-устойчивости, показанную ниже. Эта функция потерь стимулирует, чтобы X -> G(X) -> F(G(X)) было примерно эквивалентно X, а Y -> F(Y) -> G(F(Y)) было примерно эквивалентно Y.

Lcyc(G,F)=Ex∼pdata(x)[‖F(G(x)−x)‖1]+Ey∼pdata(y)[‖G(F(y))−y‖1]

Итак, у нас есть три функции потерь, которые мы используем для обновления весов CycleGAN в процессе обучения:

  • Соревновательные потери G против DY (X -> Y)
  • Соревновательные потери F против DX (Y -> X)
  • Потери цикло-устойчивости.

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

Автор CycleGAN рекомендует присваивать этим функциям потерь разные веса с помощью переменной lambda. Если вас интересует, что это такое, или какие-либо другие аспекты архитектуры CycleGAN, (например, архитектура слоев), я советую вам обратиться к исходной статье. А теперь, имея некоторое представление о CycleGAN, давайте заставим ее работать с веб-камерами!

Применяем передачу стиля к вашей веб-камере

Чтобы применить стиль Моне, Ван Гога или какой-нибудь другой к вашей веб-камере, мы будем использовать предобученные модели CycleGAN, созданные авторами статьи. Начнем с клонирования репозитория и перейдем на корень в терминале или командной строке. Оттуда нужено запустить несколько bash-команд, предоставленных в папке ./scripts, чтобы загрузить необходимые модели.

        bash ./scripts/download_cyclegan_model.sh style_monet_pretrained
bash ./scripts/download_cyclegan_model.sh style_ukiyoe_pretrained
bash ./scripts/download_cyclegan_model.sh style_cezanne_pretrained
bash ./scripts/download_cyclegan_model.sh style_vangogh_pretrained
    

Эти команды сохранят предобученные CycleGAN’ы в папке ./checkpoints.

Теперь мы создадим в корневой папке файл Python по имени webcam.py – измененную версию test.py, который вместо прогона набора данных через CycleGAN пропустит через нее поток данных с веб-камеры.

Когда вы создадите файл webcam.py, начните с импорта необходимых пакетов:

webcam.py
        import os
from options.test_options import TestOptions
from data import create_dataset
from models import create_model
import cv2
import torch
import numpy as np
    

Затем скопируйте из test.py строки кода для разбора параметров из командной строки:

webcam.py
        if __name__ == '__main__':
    opt = TestOptions().parse()  # получаем опции теста
    # прописываем значения по умолчанию для теста
    opt.num_threads = 0   # тестовый код поддерживает только num_threads = 0
    opt.batch_size = 1    # тестовый код поддерживает только batch_size = 1
    opt.serial_batches = True  # запретить перетасовку данных; закомментируйте эту строку, если нужны результаты для случайно выбранных изображений 
    opt.no_flip = True    # нет поворотов; закомментируйте эту строку, если нужно поворачивать изображения
    opt.display_id = -1   # тестовый код сохраняет результаты в файл HTML
    model = create_model(opt)      # создать модель по заданному opt.model и другим параметрам
    model.setup(opt)               # обычные настройки: конвейеры загрузки и печати; создание scheduler'ов
    if opt.eval:
        model.eval()
    

Мы собираемся изменить параметры webcam.py, отредактировав ./options/base_options.py и установив требуемое логическое значение –dataroot в False, поскольку при использовании веб-камеры нам не нужно указывать папку с данными. Теперь мы используем cv2 для настройки нашей веб-камеры и выдачи ошибки в случае неудачи:

webcam.py
        # начинаем получение видео / настройка веб-камеры
    webcam = cv2.VideoCapture(0)
    # Проверим, удачно ли открылась камера
    if not webcam.isOpened():
        raise IOError("Cannot open webcam")
    

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

webcam.py
         # CycleGan принимает данные в виде словаря
    # проще выполнить это требование, чем переделывать
    # начинаем бесконечный цикл - читаем фреймы с веб-камеры, пока пользователь не прервет цикл с клавиатуры
    data = {"A": None, "A_paths": None}
    while True:

        #ret - это bool, который вернула cap.read() -> независимо от того, удалось ли считать фрейм
        #если считали удачно, сохраняем его в frame
        ret, frame = webcam.read()

        #изменяем размеры frame
        frame = cv2.resize(frame, (256,256), interpolation=cv2.INTER_AREA)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        #модель рассчитывает получить batchsize * channels * h * w
        #добавляем измерение для размера пакета 
        frame = np.array([frame])
        #теперь форма - batchsize * channels * h * w
        frame = frame.transpose([0,3,1,2])

        #переводим массив numpy в тензор
        #данные должны быть тензором для совместимости с запущенной моделью, ожидающей floatTensor'ы
        data['A'] = torch.FloatTensor(frame)
        
        model.set_input(data)  # распаковать данные из загрузчика 
        model.test()

        #получаем только сгенерированное изображение - ищем в словаре ключ "fake"
        result_image = model.get_current_visuals()['fake']
        #используем tensor2im, предоставленный в файле util
        result_image = util.tensor2im(result_image)
        result_image = cv2.cvtColor(np.array(result_image), cv2.COLOR_BGR2RGB)  
        result_image = cv2.resize(result_image, (512, 512))  
    

В конце концов, мы показываем стилизованные фреймы в новом окне. Если пользователь в любой момент нажмет клавишу “Esc”, это окно закроется.

webcam.py
            cv2.imshow('style', result_image)

    #код ASCII клавиши Esc - 27.
    c = cv2.waitKey(1)
    if c == 27:
        break
  cap.release()
  cv2.destroyAllWindows()
    

В данный момент вы уже можете запустить webcam.py с выбранной вами моделью CycleGAN, используя следующую команду из корневой папки:

        python webcam.py  --name MODEL_NAME --model test --preprocess none --no_dropout
    

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

Переход от одного стиля к другому

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

webcam.py
        #настройка циклического переключения стилей
style_models = ['style_monet_pretrained', 'style_vangogh_pretrained', 'style_ukiyoe_pretrained', 'style_cezanne_pretrained']
style_model_index = 0
    

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

Вставьте этот код перед циклом while, кроме предыдущего кода
        #настройка текста
# шрифт
font = cv2.FONT_HERSHEY_SIMPLEX 
# расположение
org = (0, 25) 
# масштаб шрифта
fontScale = 1
# Синий цвет фона 
color = (255, 255, 255) 
# Толщина линий 2 пикселя
thickness = 2
    

Чтобы поместить текст в левом верхнем углу, мы используем функцию cv2.putText(), а для изменения стилей добавим условие, что при нажатии клавиши ‘c’ программа должна загрузить следующую модель из списка style_models. Полная итоговая реализация webcam.py приведена ниже:

webcam.py
        """Тестовый скрипт общего назначения для перевода изображений.

После обучения вашей модели с помощью train.py, вы можете использовать этот скрипт для ее тестирования.
Он загрузит сохраненную модель из '--checkpoints_dir' и сохранит результаты в '--results_dir'.

Сначала он создает модель и набор данных в соответствии с опциями. Некоторые параметры жестко прописаны в коде.
Затем он запускает перевод для '--num_test' изображений и сохраняет результаты в файл HTML.

Пример (Сначала надо обучить модели или загрузить предобученные с нашего сайта):
    Тестировать модель CycleGAN (в обе стороны):
        python test.py --dataroot ./datasets/maps --name maps_cyclegan --model cycle_gan

    Тестировать модель CycleGAN (только в одну сторону):
        python test.py --dataroot datasets/horse2zebra/testA --name horse2zebra_pretrained --model test --no_dropout

    Опция '--model test' используется для генерации результатов CycleGAN только в одну сторону.
    Эта опция автоматически устанавливает '--dataset_mode single', при которой изображения загружаются только из одного набора.
    Напротив, использование '--model cycle_gan' требует загрузки и генерации результатов в обе стороны,
    что иногда не нужно. Результаты будут сохранены в ./results/.
    Use '--results_dir <directory_path_to_save_result>' to specify the results directory.

    Test a pix2pix model:
        python test.py --dataroot ./datasets/facades --name facades_pix2pix --model pix2pix --direction BtoA

См. больше опций в options/base_options.py и options/test_options.py.
См. подсказки для обучения и тестов на: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/docs/tips.md
Часто задаваемые вопросы см: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/docs/qa.md
"""
import os
from options.test_options import TestOptions
from data import create_dataset
from models import create_model
import cv2
import torch
import numpy as np


if __name__ == '__main__':
    opt = TestOptions().parse()  # загружаем тестовые опции
    # жестко пропишем некоторые параметры для теста
    opt.num_threads = 0   # тестовый код поддерживает только num_threads = 0
    opt.batch_size = 1    # тестовые код поддерживает только batch_size = 1
    opt.serial_batches = True  # запретить перетасовку данных; закомментируйте эту строку, если нужен перевод случайно выбранных изображений.
    opt.no_flip = True    # нет поворотов; закомментируйте эту строку, если нужен результат на повернутых изображениях.
    opt.display_id = -1   # тестовый код сохраняет результаты в файл HTML.
    model = create_model(opt)      # создать модель по заданному opt.model и другим параметрам
    model.setup(opt)               # обычные настройки: конвейеры загрузки и печати; создание scheduler'ов
    if opt.eval:
        model.eval()
    
    #начать съемку видео/настроить камеру
    webcam = cv2.VideoCapture(0)
    # Проверить, корректно ли открылась камера
    if not webcam.isOpened():
        raise IOError("Cannot open webcam")
    
    #циклический проход по стилям
    style_models = ['style_monet_pretrained', 'style_vangogh_pretrained', 'style_ukiyoe_pretrained', 'style_cezanne_pretrained']
    style_model_index = 0

    #настройка текста
    # шрифт
    font = cv2.FONT_HERSHEY_SIMPLEX 
    # начальная точка
    org = (0, 25) 
    # масштаб шрифта
    fontScale = 1
    # Синий цвет фона
    color = (255, 255, 255) 
    # Толщина линий 2 пикселя
    thickness = 2


    #CycleGan принимает данные в виде словаря
    # проще выполнить это требование, чем переделывать
    # начинаем бесконечный цикл - читаем фреймы с веб-камеры, пока пользователь не прервет цикл с клавиатуры
    data = {"A": None, "A_paths": None}
    while True:

        #ret - это bool, который вернула cap.read() -> независимо от того, удалось ли считать фрейм
        #если считали удачно, сохраняем его в frame
        ret, frame = webcam.read()

        #изменяем размеры frame
        frame = cv2.resize(frame, (256,256), interpolation=cv2.INTER_AREA)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        #модель рассчитывает получить batchsize * channels * h * w
        #добавляем измерение для размера пакета
        frame = np.array([frame])
        #теперь форма - batchsize * channels * h * w
        frame = frame.transpose([0,3,1,2])

        #переводим массив numpy в тензор
        #данные должны быть тензором для совместимости с запущенной моделью, ожидающей floatTensor'ы
        data['A'] = torch.FloatTensor(frame)
        
        model.set_input(data)  # распаковать данные из загрузчика
        model.test()

        #получаем только сгенерированное изображение - ищем в словаре ключ "fake"
        result_image = model.get_current_visuals()['fake']
        #используем tensor2im, предоставленный в файле util
        result_image = util.tensor2im(result_image)
        result_image = cv2.cvtColor(np.array(result_image), cv2.COLOR_BGR2RGB)  
        result_image = cv2.resize(result_image, (512, 512))      
        result_image = cv2.putText(result_image, str(opt.name)[6:-11], org, font,  
                   fontScale, color, thickness, cv2.LINE_AA)   
        cv2.imshow('style', result_image)

        #ASCII value of Esc is 27.
        c = cv2.waitKey(1)
        if c == 27:
            break
        if c == 99:
            if style_model_index == len(style_models):
                style_model_index = 0
            opt.name = style_models[style_model_index]
            style_model_index += 1
            model = create_model(opt)      # создаем модель с заданными опциями create a model given opt.model and other options
            model.setup(opt) 
      
        
    cap.release()
    cv2.destroyAllWindows()
        
    

Этот скрипт можно запустить той же командой bash:

        python webcam.py  --name MODEL_NAME --model test --preprocess none --no_dropout
    

Заключение

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

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

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

<a href="https://unsplash.com/photos/T7K4aEPoGGk" target="_blank" rel="noopener noreferrer nofollow">Исходное изображение</a> от Пьетро Ди Гранди
Исходное изображение от Пьетро Ди Гранди
"Ван-Гогнутое" изображение!
“Ван-Гогнутое” изображение!
Это было всего лишь одно из применений CycleGAN, и я рекомендую прочитать в Сети или в литературе о других замечательных возможностях, которыми она обладает.

Файл webcam.py и файлы репозитория можно найти в моей ветке на GitHub.

08
Июн
2021

🤖 Планирование маршрута роботом при помощи RRT

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

06
Июн
2021

📊 Кто такой дата-инженер, чем он занимается и что должен знать?

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

*Слово “дата” используется нами в значении английского термина data – информация (данные).

Причём здесь дата и почему ею должен заниматься целый инженер?

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

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

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

Накопленная информация сама по себе ничего не даёт: для получения выгоды её нужно обработать. Тут в дело вступает дата-инженер.

Чем дата-инженер отличается от аналитика?


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

Термин дата-сайентист (от англ. data scientist) у всех на слуху и обозначает коллегу дата-инженера. С учётом современных трендов на объединение или работу в команде, штатные единицы сайентиста (ученого, аналитика) и инженера представлены либо в одном лице, либо эти специалисты тесно сотрудничают друг с другом.

Итак, инженер выстраивает все каналы связи – от процесса сбора информации до её преобразования в нужный формат. Как в каком-нибудь промышленном симуляторе Factorio или Satisfactory: он находит источник данных, выстраивает конвейер для их передачи, а также создаёт инфраструктуру для обрабоки и преобразования информации.

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

Что нужно знать дата-инженеру?

Так как наша задача – собрать данные, сохранить их, преобразовать и отдать дальше, то основными языками для инженера являются Python и SQL. С учётом популярности облачных технологий – ещё и Java (вкупе с её универсальностью). Нужно также разбираться в облачных платформах.

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

Базовые требования


Дата-инженер работает с данными, а значит ему нужно знать о данных всё:

  • Алгоритмы и структуры данных. Здесь важна не теоретическая подготовка с вызубренными определениями, а понимание всех рабочих процессов. К примеру, на Udemy есть курс, полностью посвящённый данным, их типам и структурам.
  • SQL – язык структурированных запросов. Почти каждая реляционная СУБД поддерживает этот язык организации запросов для получения или обработки данных. Он не слишком сложен, к тому же есть хороший учебник, водящий “за руку” по всем понятиями и возможностям SQL.
  • Python, Java/Scala. Python считается одним из лучших языков для работы с данными (и, определенно, самым популярным), а Java/Scala следует знать, поскольку на них написаны почти все инструменты для работы с информацией.
  • Инструменты для работы с большими данными (Hadoop, Spark, Kafka).
  • Облачные платформы (MS Azure или Amazon Web Services).
  • Распределённые системы. Большие объёмы данных предполагают, что работать с ними придётся в кластерах. Новичкам стоит прочесть книгу Эндрю Таненбаума “Распределённые системы”. Для начала она может показаться сложной, но потом это пройдет.
  • Конвейеры данных. Выстраивание путей сбора, обработки и хранения информации занимают большую часть рабочего времени дата-инженера.

Заключение

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

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

***

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

04
Июн
2021

Курс «Профессия Data Scientist» с трудоустройством

За 2 года освоите профессию Data Science: научитесь программировать на Python и R, применять алгоритмы машинного обучения и визуализировать данные.
— Читать дальше «Курс «Профессия Data Scientist» с трудоустройством»

04
Июн
2021

Интенсив «3 дня машинного обучения: Python, нейросети и биткоин»

Вы создадите свою первую модель машинного обучения и поймёте, как нейросети решают задачи бизнеса.
— Читать дальше «Интенсив «3 дня машинного обучения: Python, нейросети и биткоин»»

31
Май
2021

Скрапинг сайта с помощью Python: гайд для новичков

Пишем простой скрапер на Python для сайта с объявлениями о недвижимости. Получаем готовый очищенный готовый к экспорту датасет.
— Читать дальше «Скрапинг сайта с помощью Python: гайд для новичков»

31
Май
2021

🎥 Делаем DeepFake на коленке: пошаговое практическое руководство

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

07
Май
2021

Интенсив «Профессия Data Scientist: учимся обработке и анализу данных за 3 дня»

Попробуете себя в роли Data Scientist: с нуля подготовите данные, построите модель и научитесь анализу и визуализации с помощью Python.
— Читать дальше «Интенсив «Профессия Data Scientist: учимся обработке и анализу данных за 3 дня»»

30
Апр
2021

📊 Соревнования по Data Science и Machine Learning: сравнительно простой путь в профессию

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

Профессия Data Scientist подразумевает коллективную работу над проектами. Для этого необходимы навыки коммуникации и решения реальных задач. Один из лучших способов их развить участие в соревнованиях. Оно позволяет не только обновить портфолио и попробовать себя в различных областях науки о данных, но и научиться эффективно взаимодействовать с другими специалистами. Предлагаем вниманию читателей подборку актуальных соревнований по Data Science и Machine Learning, на которые стоит обратить внимание.

Data Science


HuBMAP – Hacking the Kidney

Research Code Competition

  • Дедлайн для регистрации команд: 3 мая 2021 года.
  • Дата окончания: 10 мая 2021 года.
  • Призы за точность: первое место – $18000, второе место – $10000, третье место – $4000.
  • Специальные премии судей: научная премия – $15000, премия за инновации – $10000, премия за разнообразие: $3000.

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

Подробнее: https://www.kaggle.com/c/hubmap-kidney-segmentation/overview


Hungry Geese

Playground Simulation Competition

  • Дедлайн для регистрации команд: 26 июля 2021 года.
  • Дата окончания: 26 июля 2021 года.
  • Призы: мерч Kaggle (футболки, кружки и т. д.) достанется лучшей команде в ежемесячной таблице лидеров.

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

Подробнее: https://www.kaggle.com/c/hungry-geese/overview/prizes


Hash Code 2021 – Traffic Signaling

Playground Simulation Competition

  • Дедлайн для регистрации команд: 25 мая 2021 года.
  • Дата окончания: 25 мая 2021 года.

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

Подробнее: https://www.kaggle.com/c/hashcode-2021-oqr-extension/overview/description

Coleridge Initiative – Show US the Data

Featured Code Competition

  • Дедлайн для регистрации команд: 15 июня 2021 года.
  • Дата окончания: 22 июня 2021 года.
  • Призы: первое место – $30000, второе место – $20000, третье место – $15000, четвертое место – $10000, с пятого по седьмое место – $5000.

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

Подробнее: https://www.kaggle.com/c/coleridgeinitiative-show-us-the-data

Differential Privacy Temporal Map Challenge: Sprint 3 (Prescreened Arena)

  • Дедлайн для регистрации команд: 10 мая 2021 года.
  • Дата окончания: 17 мая 2021 года.
  • Призовой фонд: 79 000 $.

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

Подробнее: https://www.drivendata.org/competitions/77/deid2-sprint-3-prescreened/page/332/

HackerEarth DevOps Challenge

  • Дедлайн для регистрации команд: 09 мая 2021 года.
  • Дата окончания: 09 мая 2021 года.
  • Призы: первое место – $125, второе место – $100, третье место – $75.

Соревнование для участников с опытом от одного года, работающих с Python, Django, Linux, Jenkins, Docker, Git и Web Server. Вашей задачей будет разработка модульных тестовых примеров для исходного кода приложения. Практическое соревнования для тех, кто хочет улучшить свои навыки работы с Github, Django и Jenkins.

Подробнее: https://www.hackerearth.com/en-us/challenges/competitive/hackerearth-devops-challenge/


ADoBo — Automatic Detection of Borrowings

  • Дедлайн для регистрации команд: 01 июня 2021 года.
  • Дата окончания: 01 июня 2021 года.

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

Подробнее: https://competitions.codalab.org/competitions/28771#learn_the_details

Machine Learning


Indoor Location & Navigation

Research Prediction Competition

  • Дедлайн для регистрации команд: 10 мая 2021 года.
  • Дата окончания: 17 мая 2021 года.
  • Призы: первое место – $5000, второе место – $3000, третье место – $2000.

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

Подробнее: https://www.kaggle.com/c/indoor-location-navigation

Predict The Price Of Books

  • Дедлайн для регистрации команд: 10 октября 2030 года.
  • Дата окончания: 10 октября 2030 года.

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

Подробнее: https://www.machinehack.com/hackathons/predict_the_price_of_books/overview

Predict The News Category Hackathon

  • Дедлайн для регистрации команд: 05 сентября 2030 года.
  • Дата окончания: 05 сентября 2030 года.

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

Подробнее: https://www.machinehack.com/hackathons/predict_the_news_category_hackathon/overview


ELECTRICAL SUBSTATIONS EXTRACTION FROm IMAGES

  • Следующий дедлайн для фидбека: 16 июня 2021 года.
  • Дата окончания: неизвестно.

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

Подробнее: https://competitions.codalab.org/competitions/30861

Shopee – Price Match Guarantee

Featured Code Competition

  • Дедлайн для регистрации команд: 03 мая 2021 года.
  • Дата окончания: 10 мая 2021 года.
  • Призы: первое место – $15000, второе место – $10000, третье место – $5000.

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

Подробнее: https://www.kaggle.com/c/shopee-product-matching/overview/prizes

Airborne Object Tracking Challenge

От Amazon Prime Air

  • Дедлайн для регистрации команд: 08 июля 2021 года.
  • Дата окончания: 08 июля 2021 года.
  • Призы: первое место – $15000, второе место – $7500, третье место – $1250, специальный приз за креативность – $2500.

Задача конкурса связана с обнаружением и отслеживанием воздушных объектов для предотвращения их столкновений.

Подробнее: https://www.aicrowd.com/challenges/airborne-object-tracking-challenge


The Music Demixing Challenge

От Sony Group Corporation

  • Дедлайн для регистрации команд: июль 2021 года.
  • Дата окончания: июль 2021 года.
  • Призы: первое место – 3500 CHF, второе место – 1000 CHF, третье место – 500 CHF.

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

Подробнее: https://www.aicrowd.com/challenges/music-demixing-challenge-ismir-2021#competition-timeline

***

Если вы только начинаете путь в профессии или хотите научиться решать реальные задачи из смежных областей науки о данных, соревнования – хороший способ это сделать. Обратите внимание на курс по спортивному Data Science образовательной онлайн-платформы GeekBrains. Он включает обучение с элементами соревнования в Kaggle и работу с преподавателем, который разбирает на примерах каждый урок.

29
Апр
2021

📊 Как начинающий Data Scientist может заработать на фрилансе?

Хотите начать карьерный путь в Data Science в качестве фрилансера? Мы подготовили для вас 8 простых шагов: от регистрации на платформе до обустройства рабочего места.

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

С чего начать?


Выберите платформу

При поиске фриланс-офферов и проектов обратите внимание на самые крупные и авторитетные российские и международные онлайн-платформы, такие как Upwork, AngelList, Freelancer, Kaggle, Indeed, Peopleperhour, Freelance.ru, Freelancehunt, Weblancer, Workzilla.

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

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


Исследуйте рынок труда

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

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

О необходимых специалисту по анализу данных ресурсах мы подробнее писали в статьях «Data Science с нуля: обзор книг и видеокурсов для начинающих» и «10 навыков, необходимых в профессии Data Scientist».

Чем больше у вас опыта и чем лучше ваше образование (включая самообучение с помощью онлайн-ресурсов), тем выше ставка, которую вы можете установить. Не хватает практики? Ознакомьтесь с материалом «Обучение на Data Scientist: как получить работу, если без опыта никуда не берут?».


Продайте себя

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

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

Оцените свои навыки

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

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

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


Определите свою ставку

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

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

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

Как продолжить?


Подготовьте рабочее место

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

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

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

Планирование времени

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


Присоединись к сообществу и начните строить сеть контактов

Необходимо регулярно посещать мероприятия, где вы можете встретить потенциальных клиентов. Сделайте нетворкинг частью ежедневной рутины. Окружите себя новостями, ресурсами и людьми, которые работают и заинтересованы в сфере Data Science. Подпишитесь на рассылки, ежедневно читайте посты, статьи и книги, слушайте подкасты и смотрите видео на YouTube. Общайтесь с людьми в LinkedIn, просите их о помощи, будьте любопытным и полезным в решении их проблем. Участвуйте в онлайн-дискуссиях и обсуждениях проектов, высказываете свое мнение и задавайте правильные вопросы.

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

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

Заключение

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

***

Если вы только начинаете свой путь в Data Science, стоит обратить внимание на курс Факультета Искусственного интеллекта образовательной онлайн-платформы GeekBrains. Рассчитанная на 2 года обучения программа – одна из самых объемных и содержательных на рынке. Она включает основательную математическую подготовку, изучение программирования и статистического анализа, а также работу с базами данных, нейронные сети и машинное обучение. Курс построен на основе практической работы с ведущими специалистами технологических компаний и личным помощником-куратором. Успешно завершившие обучение студенты получат диплом о профессиональной подготовке и помощь в трудоустройстве, а также смогут добавить в портфолио реализованные проекты.

26
Апр
2021

Исследование: размер коммьюнити у 14 самых популярных языков программирования

Тут информация и о JS, и о Python, и о многих других языках, что на слуху.
— Читать дальше «Исследование: размер коммьюнити у 14 самых популярных языков программирования»

26
Апр
2021

📊 Где изучать Data Science в 2021 году?

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

Data Science – стремительно развивающаяся область, которая требует от специалистов постоянного следования за новыми трендами. В статье «Data Science с нуля: обзор книг и видеокурсов для начинающих» можно найти необходимые специалисту по анализу данных ресурсы. В очередном обзоре мы предлагаем читателям подборку книг, курсов и блогов 2021 года, актуальных в 2021 году. Здесь вы найдете новости, а также информацию о последних разработках в сфере машинного обучения, больших данных и искусственного интеллекта.

Новы


Practical Weak Supervision: Doing More with Less Data 1st Edition by Wee Hyong Tok, Amit Bahree, Senja Filipi

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


TensorFlow 2 Pocket Reference 1st Edition by KC Tung

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


Fundamentals of Deep Learning: Designing Next-Generation Machine Intelligence Algorithms 2nd Edition by Nithin Buduma, Nikhil Buduma

Второе издание книги, авторы которой простыми словами рассказывают о технологиях и инновациях в сфере Deep Learning. Новые главы посвящены последним достижениям генеративного моделирования. Примеры кода обновлены до TensorFlow 2 и PyTorch 1.4. Книга подойдет владеющим Python программистам и специалистам по Data Science.


Essential Math for Data Science. Take Control of Your Data with Fundamental Calculus, Linear Algebra, Probability, and Statistics by Hadrien Jean

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


97 Things About Ethics Everyone in Data Science Should Know by Bill Franks

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


Machine Learning with Python. Learn the art of Programming with a complete crash course for beginners. Strategies to Master Data Science, Numpy, Keras, Pandas and Arduino like a Pro in 7 days by Jason Test

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

Курсы

Data Science Course 2021: Complete Machine Learning Training

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

Data Analysis Bootcamp – Python, Seaborn and Pandas

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

Confetti AI

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

Elements of AI

The Elements of AI серия бесплатных онлайн-курсов от Reaktor и Университета Хельсинки. Курс предназначен для широкой публики и людей, которые хотят узнать, что такое искусственный интеллект простыми словами. Программа сочетает теорию с практическими упражнениями и включает множество примеров с иллюстрациями.

Collaborative Working in a Remote Team

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

Видеолекции

Intro to Deep Learning (ML Tech Talks)

Структурированный обзор глубокого обучения от разработчика Google ML. Эксперт проводит разбор обучения признакам, рассказывает о семействе нейронных сетей и их приложениях, а также приводит множество примеров кода и концепций из TensorFlow.

Data Professor

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

Data Science vs Machine Learning vs Artificial Intelligence vs Big Data

Канал Александра Кондуфорова, руководителя направления Data Science Competence в компании AltexSoft. Здесь обсуждаются различия между Data science, машинным обучением, искусственным интеллектом и большими данными.

Deepfake Tutorial | How to Create Deepfake using AI

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

DeepMind x UCL | Deep Learning Lectures | 7/12 | Deep Learning for Natural Language Processing

В лекции ученого-исследователя DeepMind Феликса Хилла обсуждается мотивация моделирования языка с помощью нейронных сетей. Рассматриваются такие концепции, как Elman’s Finding Structure во времени и в простых рекуррентных сетях, важность контекста и трансформаторов, а также неконтролируемое и репрезентативное обучение языку от Word2Vec до BERT.

Блоги


Inside Big Data

Блог посвящен аспектам машинного обучения в области науки о данных и больших данных в ИТ и бизнесе. Особо интересны в нем интервью с выдающимися специалистами, которые делятся опытом работы в индустрии. В этом блоге есть специальные разделы, охватывающие Hadoop, Spark, Developers, Data Science 101, а также публикуются вакансии.

Dataconomy

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

Simply Statistics

Этот блог ведут три профессора биостатистики: здесь есть статьи по основам статистики для новичков, а также раздел интервью с опытными младшими специалистами по обработке данных и старшими преподавателями. Основатели блога также являются авторами курсов Data analysis for life sciences и Data Science Specialization on Coursera.

Data Science Report

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

Datafloq

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

Information is beautiful

Дэвид Маккэндлесс из Information is Beautiful использует свой блог, чтобы представить проекты в области анализа данных и показать варианты эффективной визуализации. Это отличный пример симбиотической связи между данными и дизайном: цвета, формы и размеры передают массу информации, не занимая много места и увлекая читателя.

Storytelling with data

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

Flowing Data

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

The Pudding

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

Заключение

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

***

Если вы только начинаете свой путь в Data Science, стоит обратить внимание на курс Факультета Искусственного интеллекта образовательной онлайн-платформы GeekBrains. Рассчитанная на 2 года обучения программа – одна из самых объемных и содержательных на рынке. Она включает основательную математическую подготовку, изучение программирования и статистического анализа, а также работу с базами данных, нейронные сети и машинное обучение. Курс построен на основе практической работы с ведущими специалистами технологических компаний и личным помощником-куратором. Успешно завершившие обучение студенты получат диплом о профессиональной подготовке и помощь в трудоустройстве, а также смогут добавить в портфолио реализованные проекты.

21
Апр
2021

Интенсив «Профессия Data Scientist: учимся обработке и анализу данных за 3 дня»

На интенсиве вы сможете примерить на себя роль Data Scientist: поработаете с основными инструментами профессии, визуализируете данные, построите формулы и выявите зависимости на Python.
— Читать дальше «Интенсив «Профессия Data Scientist: учимся обрабо…

24
Мар
2021

📕 ТОП-10 книг по обработке естественного языка: от новичка до профессионала

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

24
Мар
2021

Интенсив «Профессия Data Scientist: учимся обработке и анализу данных за 3 дня»

На интенсиве по анализу данных поработаете с основными инструментами профессии, визуализируете данные, построите формулы и выявите зависимости на Python.
— Читать дальше «Интенсив «Профессия Data Scientist: учимся обработке и анализу данных за 3 дня»»