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

Анализ данных

Новые возможности анализа табличных данных с алгоритмами машинного обучения в Elastic

11.03.2021 12:11:09 | Автор: admin


Elastic stack, также известный как ELK Stack (аббревиатура из программных компонентов: Elasticsearch, Kibana и Logstash), это платформа построения озера данных с возможностью аналитики по ним в реальном масштабе времени. В настоящее время широко применяется для обеспечения информационной безопасности, мониторинга бесперебойности и производительности работы ИТ-среды и оборудования, анализа рабочих процессов, бизнес-аналитики.


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


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


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


  1. Обнаружение аномалий на потоке данных (Anomaly detection)
  2. Аналитика табличных данных (Data frame analytics)

Примечание: Попрактиковаться в использовании перечисленных выше наборов инструментов анализа данных можно будет 24 марта. Совместно с коллегами Elastic мы продемонстрируем, как применять Anomaly detection и Data frame analytics для выявления инцидентов информационной безопасности. Ссылка на регистрацию.

Об инструментах обнаружения аномалий Elastic ранее уже писали на Хабре. С того времени (Elastic версии 7.1) они продолжали активно развиваться, было улучшено качество алгоритмов и удобство их применения для прикладных задач. Но в этой статье мы решили осветить совершенно новый набор функций анализа табличных данных, появившийся в версиях с 7.2 до 7.11.


Data frame analytics это набор функций Elasticsearch и визуализаций Kibana, позволяющих проводить анализ данных без их привязки к временным меткам. В отличии от Anomaly detection, где предполагается временная последовательность анализируемых данных.


Работа с Data frame analytics осуществляется через графический интерфейс с пошаговым мастером настройки. При этом, за счёт автоматической оптимизации параметров обучения (hyperparameters) пользователю не требуются глубокие знания стоящих за ними математических алгоритмов.


Возможности Data frame analytics Elastic версии 7.11 включают в себя:


  1. Выявление отклонений в значениях параметров (outlier detection) с использованием алгоритмов машинного обучения без учителя (unsupervised)
  2. Построение моделей машинного обучения с учителем (supervised) для решения задач:


    a) Регрессии (regression), как определение зависимости одного значения от одного или нескольких других значений


    b) Классификации (classification), как определение принадлежности произвольного объекта к одному из заданных классов



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


Выявление отклонений с использованием алгоритмов машинного обучения без учителя (Outlier detection)


Функция Outlier detection, как и ранее существовавшая в Elastic anomaly detection, предназначена для выявления аномальных значений (выбросов) каких-либо параметров и не предполагает обучение с учителем модель строится каждый раз при запуске. Но в отличие от anomaly detection, значения признаков (фич, особенностей, характерных черт анализируемых объектов) в ней анализируются без учета временной последовательности.


Исходными данными для функции выступает массив записей (JSON документов), в котором данные представлены в виде полей и их значений (поддерживаются числовые и логические типы значений). Каждая запись характеризует поведение какого-либо объекта. Поля в записи включают в себя поле, идентифицирующее объект, и поля со значениями, указывающими на аномальное поведение объекта, их называют признаками (feature).


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


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


  • Метод ближайшего соседа (distance of Kth nearest neighbor)
  • Метод K ближайших соседей (distance of K-nearest neighbors)
  • Локальный уровень выброса (local outlier factor)
  • Локальный уровень выброса на основе расстояния (local distance-based outlier factor)

Подробнее про алгоритмы можно почитать здесь и здесь.


Для оценки и интерпретации результатов выявления отклонений Elastic рассчитывает степень влияния признаков на искомое значение.


В качестве иллюстрации приведём несколько примеров применения Outlier detection:


  • анализ метрик производительности для выявления отклонений в нагрузке на сервера со стороны сразу нескольких приложений (здесь);
  • анализ отпечатков бинарных гистограмм исполняемых файлов для обнаружения обфусцированных и вредоносных файлов (здесь);
  • анализ публичных объявлений airnbnb.com (insideairbnb.com) для поиска необычных предложений (здесь).

Ниже рассмотрим функцию анализа выбросов на примере из документации Elastic.



Цель анализа в этом примере выявить необычное поведение пользователей интернет-магазина. Из магазина в систему поступают события оформления заказа продукции, каждое из которых содержит полное имя заказчика (customer_full_name.keyword), количество покупок в заказе (products.quantity), стоимость заказа (products.taxful_price), id заказа (order_id).


Документы в исходном индексе выглядят так
{  "_index": "kibana_sample_data_ecommerce",  "_type": "_doc",  "_id": "_mXypHcB6S7rlhJIFCvB",  "_version": 1,  "_score": null,  "_source": {    "category": [      "Women's Clothing",      "Women's Accessories"    ],    "currency": "EUR",    "customer_first_name": "Sonya",    "customer_full_name": "Sonya Smith",    "customer_gender": "FEMALE",    "customer_id": 28,    "customer_last_name": "Smith",    "customer_phone": "",    "day_of_week": "Saturday",    "day_of_week_i": 5,    "email": "sonya@smith-family.zzz",    "manufacturer": [      "Oceanavigations",      "Pyramidustries"    ],    "order_date": "2021-03-06T23:31:12+00:00",    "order_id": 592097,    "products": [      {        "base_price": 28.99,        "discount_percentage": 0,        "quantity": 1,        "manufacturer": "Oceanavigations",        "tax_amount": 0,        "product_id": 19238,        "category": "Women's Clothing",        "sku": "ZO0265502655",        "taxless_price": 28.99,        "unit_discount_amount": 0,        "min_price": 13.05,        "_id": "sold_product_592097_19238",        "discount_amount": 0,        "created_on": "2016-12-31T23:31:12+00:00",        "product_name": "Vest - red/white",        "price": 28.99,        "taxful_price": 28.99,        "base_unit_price": 28.99      },      {        "base_price": 13.99,        "discount_percentage": 0,        "quantity": 1,        "manufacturer": "Pyramidustries",        "tax_amount": 0,        "product_id": 13328,        "category": "Women's Accessories",        "sku": "ZO0201102011",        "taxless_price": 13.99,        "unit_discount_amount": 0,        "min_price": 6.86,        "_id": "sold_product_592097_13328",        "discount_amount": 0,        "created_on": "2016-12-31T23:31:12+00:00",        "product_name": "Across body bag - aqua ",        "price": 13.99,        "taxful_price": 13.99,        "base_unit_price": 13.99      }    ],    "sku": [      "ZO0265502655",      "ZO0201102011"    ],    "taxful_total_price": 42.98,    "taxless_total_price": 42.98,    "total_quantity": 2,    "total_unique_products": 2,    "type": "order",    "user": "sonya",    "geoip": {      "country_iso_code": "CO",      "location": {        "lon": -74.1,        "lat": 4.6      },      "region_name": "Bogota D.C.",      "continent_name": "South America",      "city_name": "Bogotu00e1"    },    "event": {      "dataset": "sample_ecommerce"    }  },  "fields": {    "order_date": [      "2021-03-06T23:31:12.000Z"    ],    "products.created_on": [      "2016-12-31T23:31:12.000Z",      "2016-12-31T23:31:12.000Z"    ]  },  "sort": [    1615073472000  ]}

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


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


Примечание: Для расчёта нужных признаков используем функции Elastic по агрегации: числовые значения считаем через products.quantity.sum и products.taxful_price.sum, а количество заказов order_id.value_count.



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



Эти данные будем записывать в индекс ecommerce_customers_outlier_detection. Документы в нём соответствуют строкам указанной выше таблицы, а столбцы полям в этих документах.



Чтобы просматривать индекс встроенными средствами Kibana, а не только через API, можно включить опцию "Create index template". Тогда соответствующий шаблон отображения индекса будет доступен в Kibana Discovery и при создании дашбордов в Kibana.


Опция "Continuous mode" включит выполнение трансформации в непрерывном режиме. Это обеспечит автоматическое обновление данных в индексе ecommerce_customers_outlier_detection с заданной периодичностью.


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


Документы в результирующем индексе ecommerce_customers_outlier_detection выглядят следующим образом
{  "_index": "ecommerce_customers_outlier_detection",  "_type": "_doc",  "_id": "QWoH6FA5JvsfN4JjO_LF32QAAAAAAAAA",  "_version": 1,  "_score": 0,  "_source": {    "customer_full_name": {      "keyword": "Abd Adams"    },    "order_id": {      "value_count": 2    },    "products": {      "taxful_price": {        "sum": 98.9765625      },      "quantity": {        "sum": 4      }    }  }}

Теперь самое интересное запускаем задачу машинного обучения (job в терминах Elastic ML). Мастер создания задачи позволяет отфильтровать данные для анализа с использованием встроенных в Elasticsearch языков запросов KQL (Kibana query language) или Lucene.



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



С помощью Advanced configuration параметров создания модели мы можем включить/выключить расчёт степени влияния признаков на модель (Compute feature influence), задать минимальное значение выброса для расчёта этого влияния (Feature influence threshold), а также объём выделенной под модель оперативной памяти (Model memory limit) и количество используемых заданием потоков процессора (Maximum number of threads), тем самым снижая или увеличивая нагрузку на кластер Elasticsearch.



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


  • математический алгоритм (Method) обнаружения отклонений (lof, ldof, distance_kth_nn, distance_knn) или использования ансамбля алгоритмов (ensemble), когда значения отклонений определяются путём комбинации и оценки их результатов;
  • количество используемых в расчётах соседей (N neighbors);
  • переключатель использования предварительной стандартизации значений (Standardization enabled).

Подробнее о параметрах и их значениях можно почитать в референсах на соответствующий эндпоинт API.


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



После запуска, задание проходит через этапы:


  • создание результирующего индекса и добавление в него исходных данных (reindexing);
  • загрузка данных из индекса (loading data);
  • анализ данных и расчёт оценок выбросов (analyzing);
  • запись значений оценок выбросов в результирующий индекс (writing results).


Результаты работы задания можно подробно рассмотреть через интерфейс Kibana Data frame analytics.



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


В итоговом индексе результат работы алгоритма выглядит следующим образом
 {  "_index": "ecommerce_customers_outlier_detection_results",  "_type": "_doc",  "_id": "RQzr5SwrcdFVVAr9s9NEOwAAAAAAAAAA",  "_version": 2,  "_score": 1,  "_source": {    "customer_full_name": {      "keyword": "Elyssa Tran"    },    "order_id": {      "value_count": 4    },    "products": {      "taxful_price": {        "sum": 223.9921875      },      "quantity": {        "sum": 5      }    },    "ml__incremental_id": 926,    "ml": {      "outlier_score": 0.9770675301551819,      "feature_influence": [        {          "feature_name": "order_id.value_count",          "influence": 0.9383776783943176        },        {          "feature_name": "products.quantity.sum",          "influence": 0.05973121151328087        },        {          "feature_name": "products.taxful_price.sum",          "influence": 0.0018910884391516447        }      ]    }  },  "sort": [    1,    0.9770675301551819  ]}

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



И включить отображение размера точек в соответствии со значением отклонения.



Примечание: Данные диаграммы разработаны с использованием языка Vega, доступного любому пользователю в конструкторе визуализаций Kibana.


Регрессия и классификация с учителем


Рассмотрим следующий набор функций Data frame analytics контролируемое обучение (обучение с учителем). Они предоставляют пользователю возможность обучить в Elastic свою собственную модель и использовать её для автоматического предсказания значений. Модель можно загружать и выгружать из системы, а также оценивать её качество. Кроме того, через Eland поддерживается импорт в Elastic моделей, обученных с помощью библиотек scikit-learn, XGBoost или LightGBM. Вместе с возможностями платформы по сбору и обработке данных эти функции помогают реализовать в ней подход CRISP-DM (Cross-Industry Standard Process for Data Mining).


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


Исходными данными (обучающим датасетом) для функции служит массив из уникальных записей (JSON документов). В каждой записи присутствует искомое поле (числовое для регрессии или категориальное для классификации) и поля признаков, влияющих на искомое поле. Значения искомого поля здесь используются для обучения модели и проверки её результатов. Результатом работы функции выступает обученная модель и новый массив данных, включающий исходный датасет, предсказанные значения и данными о степени влияния каждого признака. Датасет при этом можно использовать для оценки качества модели, а саму модель для анализа потока данных, поступающих в Elastic или ранее сохранённых в системе.


Схема реализации функций в Elastic


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


Обе функции используют собственные алгоритмы Elastic, построенные на базе градиентного бустинга деревьев решений XGBoost. Также возможно определение важности признаков по методу SHapley Additive exPlanations (SHAP).


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


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


Регрессия


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


Документы в исходном индексе выглядят так
{  "_index": "kibana_sample_data_flights",  "_type": "_doc",  "_id": "lmX0pHcB6S7rlhJI2kVr",  "_version": 1,  "_score": null,  "_source": {    "FlightNum": "6GZQTCH",    "DestCountry": "IT",    "OriginWeather": "Thunder & Lightning",    "OriginCityName": "Tokyo",    "AvgTicketPrice": 849.1194483923543,    "DistanceMiles": 6127.633563869634,    "FlightDelay": false,    "DestWeather": "Rain",    "Dest": "Pisa International Airport",    "FlightDelayType": "No Delay",    "OriginCountry": "JP",    "dayOfWeek": 2,    "DistanceKilometers": 9861.470310212213,    "timestamp": "2021-02-17T15:41:38",    "DestLocation": {      "lat": "43.683899",      "lon": "10.3927"    },    "DestAirportID": "PI05",    "Carrier": "ES-Air",    "Cancelled": false,    "FlightTimeMin": 493.07351551061066,    "Origin": "Narita International Airport",    "OriginLocation": {      "lat": "35.76470184",      "lon": "140.3860016"    },    "DestRegion": "IT-52",    "OriginAirportID": "NRT",    "OriginRegion": "SE-BD",    "DestCityName": "Pisa",    "FlightTimeHour": 8.217891925176845,    "FlightDelayMin": 0  },  "fields": {    "hour_of_day": [      15    ],    "timestamp": [      "2021-02-17T15:41:38.000Z"    ]  },  "sort": [    1613576498000  ]}

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



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



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



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


Следующий шаг после выбора признаков настройка параметров.



Advanced configuration:


  • количество признаков, для которых в результирующий индекс будет записано значение влияния соответствующего признака на результат предсказания (Feature importance values);
  • имя поля, в которое будет записан результат предсказания (Prediction field name);
  • лимит на объём используемой заданием оперативной памяти (Model memory limit);
  • максимальное количество используемых заданием потоков процессора (Maximum numbers of threads).

Hyperparameters:


  • коэффициент регуляризации Лямбда (Lambda);
  • максимальное количество деревьев для бустинга (Max trees);
  • коэффициент регуляризации Гамма (Gamma);
  • размер градиентного шага Эта (Eta);
  • доля выборки (Feature bag fraction);
  • псевдослучайное число, используемое при выборе из датасета документов для обучения модели (Randomize seed).

Примечание: Описание применения в Elastic этих и дополнительных гиперпараметров приведено в документации к API.


Теперь посмотрим на результаты работы алгоритма. Они записываются в итоговый индекс Elasticsearch и представлены в отчёте в табличном виде.



Здесь можно увидеть новые, по сравнению с датасетом, поля:


  1. Отметка об использовании данных для обучения (ml.is_training)
  2. Результаты предсказания задержки рейса (ml.FlightDelayMin_prediction)

Если при создании задания было указано количество признаков, для которых будет рассчитано значение их влияния на результат (Feature importance values), в таблице отобразятся соответствующие значения для каждого признака (ml.feature_importance), а в результатах бар-чарт средних значений по всему датасету.



При клике на поле ml.feature_importance увидим наглядный график принятия решения алгоритмом SHAP.



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


Результаты доступны для просмотра и другими средствами визуализации Kibana

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



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


В этом же отчете можно увидеть метрики качества модели:


  • среднеквадратическая ошибка (Mean Squared Error, MSE);
  • коэффициент детерминации (R-squared, R2 );
  • псевдо-функция потерь Хьюбера (Pseudo-Huber loss);
  • среднеквадратичная логарифмическая ошибка (Mean squared logarithmic error, MSLE).


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


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


  • анализ поступающих в Elasticsearch данных (Inference processor);
  • анализ ранее сохранённых в Elasticsearch данных (Inference aggregation).

Пример c Inference processor
POST /_ingest/pipeline/_simulate{  "pipeline" : {    "description" : "Flight delay prophecy",    "processors" : [       {          "inference": {           "model_id":"flights_delay_prophecy-1613827670191",           "inference_config": {             "regression": {               "results_field": "FlightDelayMin_prediction"             }           }         }       }    ]  },  "docs": [    {      "_index": "index",      "_id": "id",      "_source": {          "FlightNum" : "9HY9SWR",          "Origin" : "Frankfurt am Main Airport",          "OriginLocation" : {            "lon" : "8.570556",            "lat" : "50.033333"          },          "DestLocation" : {            "lon" : "151.177002",            "lat" : "-33.94609833"          },          "DistanceMiles" : 10247.856675613455,          "FlightTimeMin" : 1030.7704158599038,          "OriginWeather" : "Sunny",          "dayOfWeek" : 0,          "AvgTicketPrice" : 841.2656419677076,          "Carrier" : "Kibana Airlines",          "FlightDelayMin" : 0,          "OriginRegion" : "DE-HE",          "FlightDelayType" : "No Delay",          "DestAirportID" : "SYD",          "timestamp" : "2021-02-08T00:00:00",          "Dest" : "Sydney Kingsford Smith International Airport",          "FlightTimeHour" : 17.179506930998397,          "DistanceKilometers" : 16492.32665375846,          "OriginCityName" : "Frankfurt am Main",          "DestWeather" : "Rain",          "OriginCountry" : "DE",          "DestCountry" : "AU",          "DestRegion" : "SE-BD",          "OriginAirportID" : "FRA",          "DestCityName" : "Sydney"        }    }  ]}

Пример c Inference aggregation
GET kibana_sample_data_flights/_search{  "size":0,  "query": {    "term": {      "FlightNum": {        "value": "00HGV4F"      }    }  },   "aggs": {    "res": {       "composite": {         "size": 1,        "sources": [          {            "FlightNum": {              "terms": {                "field": "FlightNum"                              }            }          }        ]      },      "aggs" : {        "AvgTicketPrice": {          "max": {            "field": "AvgTicketPrice"          }        },       "Dest": {           "scripted_metric": {             "init_script": "state.Dest = ''",             "map_script": "state.Dest = params._source.Dest",             "combine_script": "return state.Dest",             "reduce_script": "for (d in states) if (d != null) return d"           }         },         "DestAirportID": {           "scripted_metric": {             "init_script": "state.DestAirportID = ''",             "map_script": "state.DestAirportID = params._source.DestAirportID",             "combine_script": "return state.DestAirportID",             "reduce_script": "for (d in states) if (d != null) return d"           }         },         "DestRegion": {           "scripted_metric": {             "init_script": "state.DestRegion = ''",             "map_script": "state.DestRegion = params._source.DestRegion",             "combine_script": "return state.DestRegion",             "reduce_script": "for (d in states) if (d != null) return d"           }         },         "DistanceKilometers": {          "max": {            "field": "DistanceKilometers"          }        },        "DistanceMiles": {          "max": {            "field": "DistanceMiles"          }        },        "FlightDelayType": {           "scripted_metric": {             "init_script": "state.FlightDelayType = ''",             "map_script": "state.FlightDelayType = params._source.FlightDelayType",             "combine_script": "return state.FlightDelayType",             "reduce_script": "for (d in states) if (d != null) return d"           }         },         "FlightTimeMin": {          "max": {            "field": "FlightTimeMin"          }        },        "Origin": {           "scripted_metric": {             "init_script": "state.Origin = ''",             "map_script": "state.Origin = params._source.Origin",             "combine_script": "return state.Origin",             "reduce_script": "for (d in states) if (d != null) return d"           }         },         "OriginAirportID": {           "scripted_metric": {             "init_script": "state.OriginAirportID = ''",             "map_script": "state.OriginAirportID = params._source.OriginAirportID",             "combine_script": "return state.OriginAirportID",             "reduce_script": "for (d in states) if (d != null) return d"           }         },        "OriginRegion": {           "scripted_metric": {             "init_script": "state.OriginRegion = ''",             "map_script": "state.OriginRegion = params._source.OriginRegion",             "combine_script": "return state.OriginRegion",             "reduce_script": "for (d in states) if (d != null) return d"           }         },        "FlightDelayMin_prediction" : {          "inference": {            "model_id": "flights_delay_prophecy-1613827670191",             "buckets_path": {               "AvgTicketPrice": "AvgTicketPrice",               "Dest": "Dest.value",               "DestAirportID": "DestAirportID.value",               "DestRegion": "DestRegion.value",               "DistanceKilometers": "DistanceKilometers",               "DistanceMiles": "DistanceMiles",               "FlightDelayType": "FlightDelayType.value",               "FlightTimeMin": "FlightTimeMin",               "Origin": "Origin.value",               "OriginAirportID": "OriginAirportID.value",               "OriginRegion": "OriginRegion.value"             }          }        }      }     }  }}

Классификация


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


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



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



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


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



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


  • отметка об использовании данных для обучения (ml.is_training);
  • предсказанный статус отмены рейса (ml.Cancelled_prediction);
  • вероятность предсказания (ml.prediction_probability);
  • влияние признаков на результат (ml.feature_importance);
  • оценка предсказания для всех искомых классов (ml.prediction_score).

Пример сохраненных результатов расчётов ml.prediction_score
"top_classes": [        {          "class_probability": 0.9617513617353418,          "class_score": 0.24080996012552122,          "class_name": false        },        {          "class_probability": 0.03824863826465814,          "class_score": 0.03824863826465814,          "class_name": true        }      ]

В понимании параметров оценки поможет документация Elastic.


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



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


  • матрица ошибок (Confusion matrix);
  • площадь кривой ошибок (area under receiver operating characteristic curve, AUC ROC).

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



Кривая ошибок и значение площади AUC ROC в версии 7.11 не отображается, но значения можно получить через API. В 7.12 такая возможность уже будет добавлена.


Пример запроса AUC ROC
POST _ml/data_frame/_evaluate{   "index": "cancelled_flights_prediction_2",   "evaluation": {      "classification": {          "actual_field": "Cancelled",          "predicted_field": "ml.Cancelled_prediction",          "metrics": {           "auc_roc": {             "class_name": "true"           }          }      }   }}

и ответа
{  "classification" : {    "auc_roc" : {      "value" : 0.8240223547611558    }  }}   

Сохранённая модель доступна для использования в Inference processor и Inference aggregation, как в предыдущем примере.


Заключение


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


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


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

Подробнее..

Сравнение ассортимента блюд трёх ресторанов Санкт-Петербурга

07.04.2021 20:14:16 | Автор: admin

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

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

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

Поделюсь самим парсером для одного из ресторанов.

import requestsfrom bs4 import BeautifulSoupimport pandas as pdimport datetimeprint("Начало парсинга Токио Сити: " + str(datetime.datetime.now()))#все страницы с информацией о менюurllist = ['https://www.tokyo-city.ru/spisok-product/goryachie-blyuda1.html',           'https://www.tokyo-city.ru/spisok-product/sushi.html',           'https://www.tokyo-city.ru/spisok-product/rolly.html',           'https://www.tokyo-city.ru/spisok-product/nabory.html',           'https://www.tokyo-city.ru/spisok-product/new_lunches.html',           'https://www.tokyo-city.ru/spisok-product/pitctca.html',           'https://www.tokyo-city.ru/spisok-product/salaty.html',           'https://www.tokyo-city.ru/spisok-product/-supy-.html',           'https://www.tokyo-city.ru/spisok-product/goryachie-zakuski1.html',           'https://www.tokyo-city.ru/spisok-product/wok.html',           'https://www.tokyo-city.ru/spisok-product/pasta.html',           'https://www.tokyo-city.ru/spisok-product/gamburgery-i-shaverma.html',           'https://www.tokyo-city.ru/spisok-product/Tokio-FIT.html',           'https://www.tokyo-city.ru/spisok-product/deserty.html',           'https://www.tokyo-city.ru/spisok-product/childrensmenu.html',           'https://www.tokyo-city.ru/spisok-product/napitki1.html',           'https://www.tokyo-city.ru/new/',           'https://www.tokyo-city.ru/spisok-product/postnoe-menyu.html',           'https://www.tokyo-city.ru/hit/',           'https://www.tokyo-city.ru/vegetarian/',           'https://www.tokyo-city.ru/hot/',           'https://www.tokyo-city.ru/offers/',           'https://www.tokyo-city.ru/spisok-product/sauces.html',           'https://www.tokyo-city.ru/spisok-product/Pirogi-torty.html']#создаем пустые списки для записи всех данныхnames_all = []descriptions_all = []prices_all = []categories_all = []url_all = []weight_all = []nutr_all = []#собираем данныеfor url in urllist:    response = requests.get(url).text    soup = BeautifulSoup(response, features="html.parser")    items = soup.find_all('a', class_='item__name')    itemsURL = []    n = 0    for n, i in enumerate(items, start=n):        itemnotfullURL = i.get('href')        itemURL = 'https://www.tokyo-city.ru' + itemnotfullURL        itemsURL.extend({itemURL})        m = 0        namesList = []        descriptionsList = []        pricesList = []        weightList = []        nutrList = []        itemResponse = requests.get(itemURL).text        itemsSoup = BeautifulSoup(itemResponse, features="html.parser")        itemsInfo = itemsSoup.find_all('div', class_='item__full-info')        for m, u in enumerate(itemsInfo, start=m):            if (u.find('h1', class_='item__name') == None):                itemName = 'No data'            else:                itemName = u.find('h1', class_='item__name').text.strip()            if (u.find('p', class_='item__desc') == None):                itemDescription = 'No data'            else:                itemDescription = u.find('p', class_='item__desc').text.strip()            if (u.find('span', class_='item__price-value') == None):                itemPrice = '0'            else:                itemPrice = u.find('span', class_='item__price-value').text            if (u.find('div', class_='nutr-value') == None):                itemNutr = 'No data'            else:                itemNutr = u.find('div', class_='nutr-value').text.strip()            if (u.find('div', class_='item__weight') == None):                itemWeight = '0'            else:                itemWeight = u.find('div', class_='item__weight').text.strip()            namesList.extend({itemName})            descriptionsList.extend({itemDescription})            pricesList.extend({itemPrice})            weightList.extend({itemWeight})            nutrList.extend({itemNutr})        df = pd.DataFrame((            {'Name': namesList,             'Description': descriptionsList,             'Price': pricesList,             'Weight': weightList,             'NutrInfo': nutrList             }))        names_all.extend(df['Name'])        descriptions_all.extend(df['Description'])        prices_all.extend(df['Price'])        weight_all.extend(df['Weight'])        nutr_all.extend(df['NutrInfo'])        df['Category'] = soup.find('div', class_='title__container').text.strip()        categories_all.extend(df['Category'])result = pd.DataFrame((    {'Name': names_all,     'Description': descriptions_all,     'Price': prices_all,     'Category': categories_all,     'NutrInfo': nutr_all,     'Weight': weight_all,     }))print("Парсинг Токио Сити окончен: " + str(datetime.datetime.now()))

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

А теперь к самому интересному - анализу полученной информации.

Начальные данные:

Наименование каждого блюда, его состав, цена, вес, калорийность, БЖУ и категория, к которой это блюдо относится.

Кусочек готовой к анализу таблицы с ассортиментом:

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

  • Токио City

Меню ресторана Токио City представлено 19 уникальными категориями и 5 дублирующимися, куда попадают блюда из других категорий, соответствующие определённому признаку (например, акционные блюда или подходящие вегетарианцам). Общее количество уникальных блюд - 351.

  • Евразия

Ассортимент блюд в Евразии несколько меньше - 13 категорий, 301 уникальное блюдо. Несмотря на то, что само название Токио City намекает на большое разнообразие японских блюд, этот ресторан предлагает почти на 40% меньше суши и роллов, чем, казалось бы, более универсальная кухня Евразии.

  • 2 Берега

Этот ресторан имеет самый маленький ассортимент из анализируемых - 241 уникальное блюдо в 15 категориях.

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

Вопрос 1: какую долю занимает фастфуд от всего меню уникальных блюд каждого ресторана?

К фастфуду относятся бургеры, пицца и разного рода стритфуд вроде шавермы.

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

Итог:

Выходит, 2 Берега - 1 по разнообразию пиццы в ассортименте. Это подтверждается, даже если просто сравнить количество блюд в категории Пицца во всех ресторанах (Токио City - 20, Евразия - 17 и 2 Берега - 51).

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

Вопрос 2: в каком из трёх ресторанов самые выгодные и сытные порции?

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

Посчитав цену за 100 грамм блюда в каждом ресторане, получаем следующие результаты:

У 2 Берега нет такой категории, как Горячие блюда. Есть ВОКи и паста, но традиционных горячих блюд вида гарнир + мясо нет. Поэтому в категории Горячие блюда сравниваются только Токио City и Евразия.

По всем категориям Токио City является безусловным лидером по соотношению цены и веса блюда. 2 Берега занимает почётное 2 место. Евразия оказывается в хвосте рейтинга. Даже если вычесть из средней цены за 100 грамм блюда в Евразии 30% (это максимальная скидка, которую предоставляет ресторан по картам лояльности), ресторан все равно ни в одной категории не сможет обогнать Токио City по выгоде.

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

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

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

А Токио City предлагает отличные порции горячих блюд.

Вопрос 3: какова средняя калорийность блюда в каждом из ресторанов?

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

Калорийность половины блюд в Токио City не превышает 205 калорий в 100 граммах, поэтому присуждаем ресторану одного толстого кота из трёх. Это достаточно позитивный показатель для тех, кто следит за своим весом. А вот у блюд ресторана 2 Берега этот показатель на 35% выше, поэтому он получает максимальное количество толстых котов. Впрочем, в этом нет ничего удивительного, если вспомнить, какую долю от всего меню этого ресторана занимает пицца.

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

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

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

БЖУ Евразии какое-то слишком равномерное, практически без выбросов, поэтому вызывает подозрения.

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


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

Подробнее..

Как системы ИИ преображают digital-маркетинг мнение эксперта и обсуждение проектов

03.04.2021 10:09:09 | Автор: admin

Сотрудники лаборатории машинного обучения Университета ИТМО занимаются не только теорией, но и прикладными проектами. Некоторым из них удается вдохновлять участников научного и профессионального сообщества по всему миру, преображать бизнес и цифровое пространство. Такую работу ведет Media Research Group под руководством профессора Александра Фарсеева. Сегодня он рассказывает об исследованиях и проектах его команды.

Профилирование пользователей в соцсетях

В Media Research Group, которая является частью лаборатории машинного обучения Университета ИТМО, мы работаем в нескольких исследовательских направлениях. Они связаны с использованием систем искусственного интеллекта в анализе данных соцсетей и генерации синтетического мультимедийного контента. Причем все наши проекты так или иначе находят практическое применение взять хотя бы профилирование в социальных сетях.

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

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

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

Скорее всего, как и наш алгоритм, вы бы подумали, что это кто-то намного моложе.

Фотография: History in HD. Источник: Unsplash.comФотография: History in HD. Источник: Unsplash.com

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

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

В ряде наших исследований мы прогнозировали характеристики пользователей соцсетей по шкале MBTI (Типология Майерс Бриггс), а в одном из них решили сосредоточиться на предсказании семейного статуса пользователей, так как эта характеристика во многом определяет интересы и поведение людей. Для исследования мы использовали собранную нами ещё в 2014 году базу данных NUS-MSS, которая содержит мультимодальные данные из трёх социальных сетей (Twitter, Foursquare и Instagram) и достоверные записи о семейном статусе пользователей из трёх регионов Сингапура, Нью-Йорка и Лондона. Чтобы получить предсказательную модель с количественными значениями, мы разделили пользователей NUS-MSS на состоящих и не состоящих в браке, а затем с помощью алгоритмов выбора признаков выявили коррелирующие с семейным статусом характеристики. Экстраполируя выводы, мы применили алгоритмы выбора признаков к двум получившимся группам. Средняя точность предсказательных способностей модели по трем локациям представлена в таблице.

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

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

Генерация контента

Специалисты по маркетингу тратят десятки часов на то, чтобы подготовить несколько вариаций того или иного контента. Ведь им важно попасть в нужную аудиторию, отразить фирменный стиль, и, в конце концов, сделать сам контент привлекательным для потребителей. Ещё его необходимо адаптировать для разных каналов (материал для Хабра != пост в Facebook), что также влечет дополнительную трату времени. Как раз с решением этой проблемы связано наше второе исследовательское направление с помощью поддержки со стороны технологий машинного обучения маркетологи могут сфокусироваться на творчестве и стратегических решениях. А генерацией контента займутся автоматизированные системы.

На фотографии: Maya. Источник: Instagram.comНа фотографии: Maya. Источник: Instagram.com

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

GANs технология будущего для индустрии digital-маркетинга, других профессий и сфер деятельности. Мы используем GANs и в наших коммерческих разработках например, задействовали одну из вариаций архитектуры при проектировании первого в мире инфлюенсера, работающего на базе системы ИИ, для PUMA Asia Pacific. Мы назвали этого персонажа Maya. Она делает селфи и живёт своей обычной виртуальной жизнью. Чтобы создать её, были сопоставлены миллионы лиц из различных источников, включая Instagram. Это позволило визуализировать несколько версий лица, ставших первым шагом для создания виртуального блогера.

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

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

В частности, техника Hill Climbing использовалась в одном из наших первых проектов по профилированию пользователей социальных сетей. Этому проекту посвящена статья Harvesting multiple sources for user profile learning: a big data study. Здесь мы осуществляем слияние данных, моделируя источники как линейную комбинацию предсказаний моделей машинного обучения, натренированных на каждом источнике по отдельности так называемый Late Fusion Ensemble. Понятно, что соединив источники с весами 1, мы не сможем добиться наилучших результатов. Ведь текстовые данные, например, из Twitter могут быть более полезными, чем те же самые текстовые данные, только из Foursquare (предназначена для обмена точками геоданных). Вот тут-то и нужны подходы вроде Hill Climbing для того, чтобы эффективно и быстро (не перебирая все комбинации источников) найти правильные веса каждой соцсети и модальности данных для достижения хороших результатов скомбинированной модели.

Профилирование и генерация

Синтетическим контентом можно пользоваться в тандеме с профилированием. В зависимости от интересов человека, ему будет предложено наиболее привлекательное автоматически сгенерированное рекламное объявление. Допустим, фастфуд выпустил баннер с рекламой нового бургера. Мы можем сгенерировать на его основе ещё сто версий баннера и найти среди них те, которые больше нравятся аудитории. Таким образом, профилирование пользователей и генерация контента органично дополняют друг друга. И SoMin.ai на практике объединяет два этих исследовательских направления в хороший маркетинговый инструмент. Руководствуясь типом личности MBTI, который автоматически определяется с помощью анализа контента из профилей соцсетей, SoMin.ai генерирует новый контент на основе предпочтений других пользователей с аналогичным типом личности. Вот так выглядит структура платформы SoMin.ai:

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

  1. Сбор контента от брендов.

  2. Сбор контента от пользователей и сбор фидбека.

  3. Тренировка моделей профилирования и генерации контента.

  4. Генерация контента на основе типа личности.

  5. Сбор фидбека от пользователей платформы.

Более полное описание работы платформы можно найти в статье, которую мы с коллегами из лаборатории опубликовали на WSDM 2020.


Бизнес понимает потенциал данных исследовательских направлений, а Media Research Group успешно раскрывает его. Я думаю, поэтому SoMin.ai стала партнером OpenAI, а моя команда получила доступ к GPT-3 для развития рекламных алгоритмов в соцсетях. Вероятно, по той же причине SoMin.ai удостоена престижной премии от Gartner Cool Vendors Award 2020. Но это еще не все. Совсем недавно мы представили новый проект SoPop.ai. Эта платформа анализирует публикации блогеров и определяет реакцию пользователей на них. Как и SoMin.ai, она помогает компаниям искать блоги, которые могут быть использованы в рекламных целях. Кроме того, SoPop.ai сотрудничает с банком Arival, чтобы сделать следующий шаг в развитии платформы создание цифрового банка для инфлюенсеров. Такая экосистема для блогеров и компаний будет не только искать возможности для рекламы, но и улучшать контент. О технологиях, на основе которых разработана платформа в этой научной статье.

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


Наши англоязычные хабрапосты по другим темам:


Подробнее..

Изучаем YELP с помощью Neo4j, python

12.05.2021 16:20:09 | Автор: admin

YELP зарубежная сеть, которая помогает людям находить местные предприятия и услуги, основываясь на отзывах, предпочтениях и рекомендациях. В текущей статей будет проведен определенный ее анализ с использованием платформы Neo4j, относящаяся к графовым СУБД, а также язык python.
Что посмотрим:
как работать с Neo4j и объемными датасетами на примере YELP;
чем может быть полезен YELP dataset;
частично: какие особенности в новых версиях Neo4j и почему книга Графовые алгоритмы 2019 года от O'REILLY уже устарела.


Что такое YELP и yelp dataset.


Сеть YELP на текущий момент охватывает 30 стран, РФ пока не входит в их число. Русский язык сетью не поддерживается. Сама сеть содержит достаточно объемное количество сведений о различного рода предприятиях, а также отзывах о них. Также yelp можно смело назвать социальной сетью, так как в ней имеются данные о пользователях, оставлявших отзывы. Никаких персональных данных там нет, только имена. Тем не менее пользователи образуют сообщества, группы или же могут быть в дальнейшем в эти группы и сообщества объединены по различным признакам. Например по количеству звезд (stars), которые поставили той точке (ресторану, заправке и т.п.), которую посетили.
Сама себя YELP описывает следующим образом:
-8,635,403 отзывов
-160,585 предприятий
-200,000 картинок
-8 мегаполисов
1,162,119 рекомендаций от 2,189,457 пользователей
Более 1.2 миллиона бизнес-атрибутики: часы работы, парковка, доступность и т.п.

С 2013 года Yelp регулярно проводит конкурс Yelp Dataset, призывая всех желающих
исследовать и изучать открытый набор данных Yelp.
Сам датасет доступен по ссылке
Датасет достаточно объемный и после распаковки представляет из себя 5 файлов формата json:


Все бы ничего, да вот только YELP выкладывает сырые (raw), необработанные данные и, чтобы начать с ними работать, потребуется предобработка.

Установка и быстрая настройка Neo4j.


Для анализа будет использоваться Neo4j, используем возможности графовой СУБД и их незамысловатый язык cypher для работы с датасетом.
О Neo4j как графовой СУБД неоднократно писали на Habrе (здесь и здесь статьи для начинающих), поэтому повторно представлять ее нет смысла.
Для того, чтобы начать работу с платформой, необходимо скачать desktop версию (около 500Mb) либо поработать в online песочнице. На момент написания статьи доступна Neo4j Enterprise 4.2.6 for Developers, а также иные, более ранние версии для установки.
Далее будет использоваться вариант работа в desktop версии в среде Windows (версии 4.2.5, 4.2.1).
Не смотря на то, что самая свежая версия 4.2.6, лучше ее пока не устанавливать, так как для нее еще не актуализированы все плагины, использующиеся в neo4j. Достаточно будет предыдущей версии 4.2.5.
После установки скачанного пакета, необходимо будет:
создать новую локальную БД, указав пользователя neo4j и пароль 123 (почему именно их, объясню ниже),
картинка


установить плагины, которые понадобятся APOC, Graph Data Science Library.
картинка


проверить, запускается ли БД и открывается ли браузер при нажатии на кнопку старт.
картинка




*- включить offline режим, чтобы БД истово не пыталась предлагать новые версии.
картинка



Загружаем данные в Neo4j.


Если с установкой Neo4j все прошло гладко, можно двигаться дальше и тут есть два пути.

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

и итоговой схемой:


Чтобы пройти первый путь, лучше ознакомиться сперва со статьей на medium.
*Большое человеческое спасибо за это TRAN Ngoc Thach.
И воспользоваться готовым jupyter notebookом (адаптирован мною под windows) ссылка.
Процесс импорта не из простых и занимает достаточно продолжительное время

Проблем с памятью при этом не возникает даже при наличии всего лишь 8Гб Ram, так как используется пакетный импорт.
Однако потребуется создать swap файл размером на 10Гб, так как при проверке импортированных данных jupyter крашится, об этом моменте есть упоминание в вышеуказанной тетрадке jupyter.

Второй путь самый быстрый и был обнаружен случайно. Он подразумевает копирование уже готовой БД neo4j в существующую БД neo4j напрямую. Из минусов (пока обнаруженных) нельзя произвести backup БД средствами Neo4j (neo4j-admin dump --database=neo4j --to=D:\neo4j\neo4j.dump). Однако, это может быть связано с различиями в версиях в версии 4.2.1 была скопирована БД от версии 4.2.5.
Как реализуется этот метод:
открыть вкладку Manage БД, куда будет произведен импорт
картинка




перейти в папку с БД и скопировать туда папку data, перезаписав возможные совпадения.
картинка


При этом сама БД, куда произведено копирование не должна быть запущена.
перезапустить Neo4j.
И вот здесь пригодятся логин-пароль, которые ранее были использованы (neo4j,123) для избежания конфликтов.
После старта скопированной БД будет доступна БД c yelp-датасетом:


Смотрим YELP.


Изучать YELP можно как из Neo4j браузера, так и отправляя запросы в БД из того же jupyter notebook.
Благодаря тому, что БД графовая, в браузере будет сопровождать приятная наглядная картинка, на которой эти графы и будут отображаться.
Приступая к ознакомлению с YELP необходимо оговориться, что в БД будут только 3 страны US,KG и CA:

Посмотреть схему БД можно написав запрос на языке cypher в браузере neo4j:
CALL db.schema.visualization()

И вот здесь, если мы пошли по пути импорта БД путем прямого копирования (второй путь) нас ждет совсем иная картинка:

На работоспособность БД это не влияет.
Однако будем ориентироваться на оригинальную схему


Как читать эту схему? Выглядит все следующим образом. Вершина User имеет связь сама с собой типа FRIENDS, а также связь WROTE с вершиной Review. Rewiew в свою очередь имеет связь REVIEWS с Business и так далее. Посмотреть на это можно наглядно после нажатия на одной из вершин (node labels), например на User:

БД выберет любых 25 пользователей и покажет их:

Если нажать на соответствующий значок прямо на пользователе, то будут показаны все идущие от него прямые связи, а так как связи у User двух типов FRIENDS и REVIEW, то все они появятся:

Это удобно и неудобно одновременно. С одной стороны о пользователе можно посмотреть всю информацию одним кликом, но в то же время этим кликом нельзя убрать лишнее.
Но здесь нет ничего страшного, можно по id найти этого пользователя и только всех его друзей:
MATCH p=(:User {user_id:"u-CFWELen3aWMSiLAa_9VANw"}) -[r:FRIENDS]->() RETURN p LIMIT 25


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

YELP хранит отзывы аж от 2010 года! Сомнительная полезность, но тем не менее.
Чтобы почитать эти отзывы необходимо переключиться в вид текста, нажав на А

Посмотрим на место, о котором писала Sandy 10 лет назад и найдем его на yelp.com
Такое место действительно существует www.yelp.com/biz/cafe-sushi-cambridge,
а вот и сама Sandy co своим отзывом www.yelp.com/biz/cafe-sushi-cambridge?q=I%20was%20really%20excited
картинка



Запросы на python из jupyter notebook.


Здесь будут частично использованы сведения из упомянутой свободно распространяемой книги Графовые алгоритмы 2019 года от O'REILLY. Частично, потому как синтаксис из книги во многих местах устарел.
База, с которой мы будем работать должна быть запущена, при этом сам neo4j браузер запускать нет необходимости.
Импорт библиотек:
from neo4j import GraphDatabaseimport pandas as pdfrom tabulate import tabulateimport matplotlibmatplotlib.use('TkAgg')import matplotlib.pyplot as plt

Подключение к БД:
driver = GraphDatabase.driver("bolt://localhost", auth=("neo4j", "123"))

Подсчитаем количество вершин для каждой метки в БД:
result = {"label": [], "count": []}with driver.session() as session:    labels = [row["label"] for row in session.run("CALL db.labels()")]    for label in labels:        query = f"MATCH (:`{label}`) RETURN count(*) as count"        count = session.run(query).single()["count"]        result["label"].append(label)        result["count"].append(count)df = pd.DataFrame(data=result)print(tabulate(df.sort_values("count"), headers='keys',tablefmt='psql', showindex=False))

На выходе:
+----------+---------+
| label | count |
|----------+---------|
| Country | 3 |
| Area | 15 |
| City | 355 |
| Category | 1330 |
| Business | 160585 |
| User | 2189457 |
| Review | 8635403 |
+----------+---------+
Похоже на правду, в нашей базе 3 страны, как мы увидели ранее через neo4j браузер.
А этот код подсчитает количество связей (ребер):
result = {"relType": [], "count": []}with driver.session() as session:    rel_types = [row["relationshipType"] for row in session.run    ("CALL db.relationshipTypes()")]    for rel_type in rel_types:        query = f"MATCH ()-[:`{rel_type}`]->() RETURN count(*) as count"        count = session.run(query).single()["count"]        result["relType"].append(rel_type)        result["count"].append(count)df = pd.DataFrame(data=result)print(tabulate(df.sort_values("count"), headers='keys',tablefmt='psql', showindex=False))

Выход:
+-------------+---------+
| relType | count |
|-------------+---------|
| IN_COUNTRY | 15 |
| IN_AREA | 355 |
| IN_CITY | 160585 |
| IN_CATEGORY | 708884 |
| REVIEWS | 8635403 |
| WROTE | 8635403 |
| FRIENDS | 8985774 |
+-------------+---------+
Думаю, принцип понятен. В завершение напишем запрос и визуализируем его.
Top 10 отелей Ванкувера с наибольшим количеством отзывов
# Find the 10 hotels with the most reviewsquery = """MATCH (review:Review)-[:REVIEWS]->(business:Business),      (business)-[:IN_CATEGORY]->(category:Category {category_id: $category}),      (business)-[:IN_CITY]->(:City {name: $city})RETURN business.name AS business, collect(review.stars) AS allReviewsORDER BY size(allReviews) DESCLIMIT 10"""#MATCH (review:Review)-[:REVIEWS]->(business:Business),#(business)-[:IN_CATEGORY]->(category:Category {category_id: "Hotels"}),#(business)-[:IN_CITY]->(:City {name: "Vancouver"})#RETURN business.name AS business, collect(review.stars) AS allReviews#ORDER BY size(allReviews) DESC#LIMIT 10fig = plt.figure()fig.set_size_inches(10.5, 14.5)fig.subplots_adjust(hspace=0.4, wspace=0.4)with driver.session() as session:    params = { "city": "Vancouver", "category": "Hotels"}    result = session.run(query, params)    for index, row in enumerate(result):                business = row["business"]        stars = pd.Series(row["allReviews"])        #print(dir(stars))        total = stars.count()        #s = pd.concat([pd.Series(x['A']) for x in data]).astype(float)        s = pd.concat([pd.Series(row['allReviews'])]).astype(float)        average_stars = s.mean().round(2)        # Calculate the star distribution        stars_histogram = stars.value_counts().sort_index()        stars_histogram /= float(stars_histogram.sum())        # Plot a bar chart showing the distribution of star ratings        ax = fig.add_subplot(5, 2, index+1)        stars_histogram.plot(kind="bar", legend=None, color="darkblue",                             title=f"{business}\nAve:{average_stars}, Total: {total}")                                    #print(business)        #print(stars)plt.tight_layout()plt.show()


Результат должен получиться следующий

Ось X представляет рейтинг отеля в звездах, а ось Y общий процент каждого рейтинга.

Чем может быть полезен YELP dataset

.
Из плюсов можно выделить следующие:
достаточно богатое информационное поле по содержательной составляющей. В частности можно просто насобирать отзывы со звездами 1.0 или 5.0 и заспамить какой-либо бизнес. Гм. Немного не в ту сторону, но вектор понятен;
датасет объемен, что создает дополнительные приятные трудности в плане тестирования производительности различных платформ по анализу данных;
представленные данные имеют определенную ретроспективу и в принципе возможно понять, как менялось предприятие, исходя из отзывов о нем;
данные можно использовать как ориентиры по предприятиям, учитывая, что имеются адреса;
пользователи в датасете зачастую образуют интересные взаимосвязанные структуры, которые можно брать как есть, не формируя пользователей в искусственную соц. сеть и не собирая данную сеть из иных существующих соц. сетей.
Из минусов:
всего лишь три страны представлены из 30-ти и есть подозрение, что и то не полностью,
отзывы хранятся по 10 лет, что может искажать и зачастую портить характеристику существующего бизнеса,
о пользователях мало данных, они обезличены, поэтому, рекомендательные системы на базе датасета будут явно хромать,
в связях FRIENDS используются направленные графы, то есть Аня дружит -> Петей. Получается, что Петя не дружит с Аней. Это решается программно, но все равно это неудобно.
датасет выкладывается сырой и требуется значительные усилия для его предобработки.

Несколько слов об особенностях новых версий Neo4j


Neo4j динамично обновляется и новая версия интерфейса, используемого в 4.2.6 не совсем удобна, на мой взгляд. В частности не хватает наглядности в части сведений о количестве нод и связей в БД, что было в предыдущих версиях. Кроме того, интерфейс перемещения по вкладкам при работе с БД был изменен и к нему тоже необходимо привыкнуть.
Главная неприятность в обновлениях интеграция графовых алгоритмов в плагин Graph Data Science Library. Ранее они именовались neo4j-graph-algorithms
После интеграции многие алгоритмы значительно изменили синтаксис. По этой причине, изучение книги Графовые алгоритмы 2019 года от O'REILLY может быть затруднено.

Обработанная БД yelp для neo4j для прямого копирования и последующего анализа будет выложена позднее.
Подробнее..

Как я заставил робота читать трейдерские и инвест-каналы вместо меня

08.05.2021 18:17:24 | Автор: admin

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

Предыстория

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

Знакомство мое с этой темой происходило в нескольких направлениях.

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

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

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

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

Проблема бесконечного потока информации

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

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

Что я тогда сделал

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

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

Теперь про код

Из библиотек нам понадобится по большому счету только telethon

from telethon import TelegramClient, events, syncfrom telethon.tl.functions.channels import JoinChannelRequestimport re

Чтобы сделать робота, который будет подключаться к телеграму по API нам понадобится зарегистрировать свое приложение на странице https://my.telegram.org/, войти в аккаунт, нажать на "API development tools", заполнить первые 2 поля, в Platform выбрать Desktop.

Скопировать App api_id, App api_hash в соответствующие переменные ниже. А в переменную PHONE_NUMBER ввести номер телефона, который привязан к аккаунту телеграмм.

API_ID = 1234567 # вставье свой api_idAPI_HASH = 'your_hash'PHONE_NUMBER = '+7xxxxxxxxxx'  

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

 CHANNELS = (             'channel1_name',  # здесь вводятся имена каналов              'channel2_name',  # без https://t.me, @ или ссылок - просто имя    'channel3_name                 )  

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

# мэппингnames = {    'channel1_to_post': ['interesting_text1',                          'interesting_text2'],    'channel2_to_post': ['other_channel_interesting_text1',                          'other_channel_interesting_text2',                          'other_channel_interesting_text3'],}# "разворачивание" под другой формат хранения + приведение к низкому региструd = {}for name in names.keys():    for t in names[name]:        d[t.lower()] = name.lower()print(d)

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

client = TelegramClient('session', API_ID, API_HASH)client.start()for channel in CHANNELS:    client(JoinChannelRequest(channel))

Далее собственно ожидание нового сообщения, проверка по шаблон и принятие решения, куда делать репост

# Ожидание новых постов и пересылка@client.on(events.NewMessage(CHANNELS))async def handler(event):    print(f'received text: {event.message.message}')        for tmp in d.keys():      await client.forward_messages(d[tmp], event.message)client.run_until_disconnected()

В итоге получилась целая сетка телеграм каналов (в каждом из которых выходит по паре твитов в день, в отличие от 150 в исходных каналах)

t.me/tesla_twits- Tesla
t.me/apple_twits- Apple
t.me/amazon_twits- Amazon
t.me/moderna_twits- Moderna
t.me/pfizer_twits- Pfizer
t.me/google_twits- Google
t.me/facebook_twits- Facebook
t.me/microsoft_twits- Microsoft
t.me/yandex_twits- Яндекс
t.me/mailru_twits- Mail.ru
t.me/mts_twits- МТС
t.me/aeroflot_twits- Аэрофлот
t.me/rosneft_twits- Роснефть
t.me/sber_twits- Сбер
t.me/gazprom_twits- Газпром
t.me/afk_twits- АФК Система
t.me/nornickel_twits- Норникель
t.me/vtb_twits- ВТБ
t.me/rusal_twits- Русал
t.me/lukoil_twits- Лукойл

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

Всем добра!

Подробнее..

Внедрение подхода Self-Service для самостоятельного анализа данных

08.04.2021 20:08:42 | Автор: admin
Инструменты Business Intelligence (BI) за последние несколько лет проникли почти во все виды бизнеса, а изучению данных уделяется все больше внимания и выделяется больше ресурсов. Если говорить об IT-компаниях, то здесь, наверное, большинству понятно предназначение Business Intelligence и то, какую ценность для компании представляет анализ внутренних данных.



В Playrix на подготовку и анализ данных выделяется значительное количество ресурсов, мы стараемся использовать передовые технологии и серьёзно подходим к обучению сотрудников. Компания входит в топ-3 разработчиков мобильных игр в мире, поэтому мы стараемся держать соответствующий уровень в анализе данных и конкретно в Business Intelligence. Ежедневно в наши игры играют более 27 млн пользователей, и эта цифра может дать примерное представление об объемах данных, генерируемых мобильными устройствами каждый день. Кроме этого, данные забираются из десятков сервисов в различных форматах, после чего они агрегируются и загружаются в наши хранилища. В качестве Data Lake мы работаем с AWS S3, а Data Warehouse на AWS Redshift и PostgreSQL применяется ограниченно. Эти базы данных мы используем для аналитики. Redshift быстрее, но дороже, поэтому там мы храним самые востребованные данные. PostgreSQL дешевле и медленнее, там хранятся либо небольшие объемы данных, либо данные, скорость чтения которых некритична. Для предагрегированных данных используем Hadoop кластер и Impala.

Основным инструментом BI в Playrix является Tableau. Этот продукт достаточно хорошо известен в мире, имеет широкие возможности для анализа и визуализации данных, работы с различными источниками. Кроме того, для простых задач анализа не приходится писать код, поэтому можно обучить пользователей разных отделов самостоятельно анализировать свои бизнес-данные. Сам вендор инструмента Tableau Software также позиционирует свой продукт как инструмент для самостоятельного анализа данных, то есть для Self-Service.

Есть два основных подхода анализа данных в BI:

  1. Reporting Factory. В этом подходе есть отдел и/или люди, разрабатывающие отчеты для бизнес-пользователей.
  2. Self-Service. В этом подходе бизнес-пользователи делают отчеты и строят аналитику своих процессов самостоятельно.

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

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

В Playrix подразделение Business Intelligence (BI Team) работает над задачами:

  1. Сбора, подготовки и хранения данных.
  2. Разработки внутренних сервисов аналитики.
  3. Интеграции с внешними сервисами.
  4. Разработки web-интерфейсов.
  5. Разработки отчетности в Tableau.

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


Мини-команды BI Team

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

В BI Team построен полный цикл разработки: от сбора требований до разворачивания на продуктовом окружении и последующей поддержки. В каждой мини-команде есть свой системный аналитик, разработчики и инженеры по тестированию. Они выполняют функцию Reporting Factory, подготавливая данные и отчеты для внутреннего использования.

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

Передача компетенций и запуск пилотного проекта


По нашему опыту работы и общения с другими компаниями основными проблемами при передаче data-компентенций бизнес-пользователям становятся:

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

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

Внедрение новой идеологии сразу во всей компании обычно требует много ресурсов и нервов, поэтому мы начали с пилота. Пилотный проект Self-Service запустили в отделе User Acquisition полтора года назад и в процессе пилота копили ошибки и опыт, чтобы передать их другим отделам в будущем.

Направление User Acquisition работает над задачами увеличения аудитории наших продуктов, анализирует пути закупки трафика и выбирает, в какие направления привлечения пользователей стоит инвестировать средства компании. Раньше для этого направления готовились отчеты командой BI, либо ребята сами обрабатывали выгрузки из базы при помощи Excel или Google Sheets. Но в динамичной среде развития такой анализ влечет задержки, а число анализируемых данных лимитировано возможностями этих инструментов.

На старте пилота мы провели базовое обучение сотрудников работе с Tableau, сделали первый общий источник данных таблицу в базе Redshift, в которой было более 500 млн строк и необходимые метрики. Следует отметить что Redshift это столбчатая (или колоночная) база данных, и эта база отдает данные намного быстрее реляционных БД. Пилотная таблица в Redshift была действительно большой для людей, которые никогда больше чем с 1 млн строк одновременно не работали. Но это был вызов для ребят, чтобы научиться работать с данными таких объемов.

Мы понимали, что проблемы с производительностью начнутся по мере усложнения этих отчетов. Доступа к самой БД пользователям мы не давали, но был реализован источник на сервере Tableau, подключенный в режиме live к таблице в Redshift. У пользователей были лицензии Creator, и они могли подключаться к этому источнику либо с сервера Tableau, разрабатывая отчеты там, либо с Tableau Desktop. Надо сказать, что при разработке отчетов в вебе (у Tableau есть режим web edit) на сервере есть некоторые ограничения. На Tableau Desktop же таких ограничений нет, поэтому мы преимущественно разрабатываем на Desktop. Кроме того, если анализ нужен только одному бизнес-пользователю, не обязательно такие проекты публиковать на сервере можно работать локально.

Обучение


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

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

Основным препятствием для освоения какого-то инструмента (да и вообще чего-то нового) обычно является страх того, что не получится разобраться и работать с этим функционалом. Поэтому обучение, пожалуй, является самым важным этапом внедрения подхода self-service BI. От него будет сильно зависеть результат внедрения этой модели приживется ли она в компании вообще и если да, то насколько быстро. На стартовых вебинарах как раз и надо снять барьеры использования Tableau.

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

  1. Стартовый набор знаний новичка:

    • Подключение к данным, типы соединений, типы данных, базовые преобразования данных, нормализация данных (1 час).
    • Базовые визуализации, агрегация данных, базовые вычисления (1 час).
  2. Сложные вычисления и базовые трюки/элементы, принятые в компании (2 часа).

В первом стартовом вебинаре мы рассматриваем все, что касается подключения к данным и преобразования данных в Tableau. Поскольку у людей обычно есть базовый уровень владения MS Excel, то здеcь важно объяснить, чем принципиально отличается работа в Excel от работы в Tableau. Это очень важный пункт, поскольку нужно переключить человека с логики таблиц с раскрашенными ячейками на логику нормализованных данных БД. На этом же вебинаре мы объясняем работу JOIN, UNION, PIVOT, также затрагиваем Blending. На первом вебинаре мы практически не затрагиваем визуализацию данных, его цель объяснить, как работать и преобразовывать свои данные для Tableau. Важно, чтобы люди понимали, что данные первичны и большинство проблем возникает на уровне данных, а не на уровне визуализаций.

Второй вебинар по Self-Service имеет целью рассказать о логике построения визуализаций в Tableau. Tableau сильно отличается от других BI инструментов именно тем, что имеет свой движок и свою логику. В других системах, например, в PowerBI, есть набор готовых визуалов (можно скачать дополнительные модули в магазине), но эти модули не кастомизируются. В Tableau же у вас есть фактически чистый лист, на котором можно строить все что угодно. Конечно же, в Tableau есть ShowMe меню базовых визуализаций, но все эти графики и диаграммы можно и нужно строить по логике работы Tableau. По нашему мнению, если хотите научить кого-то работать с Tableau, то не нужно использовать ShowMe для построения графиков большая их часть людям не пригодится на старте, а нужно учить именно логике построения визуализаций. Для бизнес-дашбордов достаточно знать, как построить:

  1. Time Series. Line/Area Charts (линейные графики),
  2. Bar Charts (столбчатые диаграммы),
  3. Scatter Plots (диаграммы разброса),
  4. Tables (таблицы).

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

Time Series: в бизнесе применяются очень часто, поскольку интересно сравнивать метрики в различные периоды времени. У нас в динамике результаты бизнеса смотрят, наверное, все сотрудники компании. Bar Charts используем для сравнения метрик по категориям. Scatter Plots (диаграмма разброса) используются редко, обычно для нахождения корреляций между метриками. Таблицы: то, от чего в бизнес-дашбордах полностью избавиться не удается, но по возможности стараемся минимизировать их число. В таблицах собираем числовые значения метрик по категориям.

То есть мы отправляем людей в свободное плавание после 1 часа обучения работы с данными и 1 часа обучения базовым вычислениям и визуализациям. Далее ребята сами работают со своими данными некоторое время, сталкиваются с проблемами, накапливают опыт, просто набивают руку. Этот этап в среднем занимает 2-4 недели. Естественно, в этот период есть возможность проконсультироваться с командой BI Team, если что-то не получается.

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

  1. Sheet Swapping (замена листов),
  2. Агрегация графиков при помощи параметров,
  3. Форматы дат и метрик,
  4. Отбрасывание неполных периодов при недельных/месячных агрегациях.

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

Таким образом, мы проводим только 4 часа вебинаров для старта Self-Service, и этого обычно достаточно, чтобы мотивированный человек начал работать с Tableau и самостоятельно анализировать данные. Кроме того, для дата-аналитиков у нас есть свои вебинары, они находятся в открытом доступе, можно знакомиться и с ними.

Разработка источников данных для Self-Service


После проведения пилотного проекта мы посчитали его успешным и расширили количество пользователей Self-Service. Одной из больших задач была подготовка источников данных для разных команд. Ребята в Self-Service могут работать с 200+ млн строк, поэтому команда Data Engineering должна была придумать, как реализовать такие источники данных. Для большинства аналитических задач мы используем Redshift из-за скорости чтения данных и удобства работы. Но выдавать доступ к базе каждому человеку из Self-Service было рискованно с точки зрения информационной безопасности.

Первой идеей было создание источников с живым подключением к БД, то есть на Tableau Server было опубликовано несколько источников, которые смотрели либо в таблицы, либо в подготовленные view Redshift. В этом случае мы не хранили данные на сервере Tableau, а пользователи через эти источники сами ходили со своих Tableau Desktop (клиентов) в базу. Это работает, когда таблицы небольшие (единицы миллионов) или запросы Tableau не слишком сложные. По мере развития ребята начали усложнять в Tableau свои дашборды, использовать LODы, кастомные сортировки, скрипты Python. Естественно, это привело к замедлению работы некоторых Self-Service дашбордов. Поэтому через несколько месяцев после старта Self-Service мы пересмотрели подход к работе с источниками.

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

  1. По ТЗ на источник со стороны Self-Service собираются данные в таблицах баз данных.
  2. Создается нематериализованное представление (view) в тестовой схеме БД Redshift.
  3. Представление тестируется на корректность данных командой QA.
  4. В случае положительного результата проверки представление поднимается на продовой схеме Redshift.
  5. Команда Data Engineering берет view на поддержку подключаются скрипты анализа валидности данных, сигналы алармирования ETL, выдаются права на чтение команде Self-Service.
  6. На Tableau Server публикуется источник (экстракт), подключенный к этому представлению.
  7. Заводятся сигналы ETL на запуск экстракта.
  8. Источник описывается в базе знаний.
  9. Описание источника, вся информация для подключения и работы передается команде Self-Service.

Немного про пункт 7. Нативно Tableau позволяет создавать экстракты по расписанию с минимальной разницей в 5 минут. Если вы точно знаете, что ваши таблицы в БД обновляются всегда в 4 часа утра, то вам можно просто поставить экстракт на 5 часов утра, чтобы ваши данные собрались. Это покрывает ряд задач. В нашем случае таблицы собираются по данным от различных провайдеров в том числе. Соответственно, если один провайдер либо наш внутренний сервис не успели обновить свою часть данных, то вся таблица считается невалидной. То есть нельзя просто установить расписание на фиксированное время. Поэтому мы используем API Tableau для запуска экстрактов по готовности таблиц. Сигналы запусков экстрактов формирует наш сервис ETL после того, как убедится в том, что все новые данные пришли и они валидны.

Такой подход позволяет иметь в экстракте свежие валидные данные с минимальной задержкой.

Публикация дашбордов Self-Service на Tableau Server


Мы сознательно не ограничиваем людей в экспериментах со своими данными и позволяем публиковать свои воркбуки, делиться ими. Внутри каждой команды, если человек посчитает, что его дашборд полезен другим, либо дашборд нужен этому сотруднику на сервере, он может его опубликовать. Команда BI не вмешивается во внутренние эксперименты команд, соответственно, всю логику работы дашбордов и вычисления они прорабатывают сами. Есть cлучаи, когда из Self-Service вырастает интересный проект, который потом полностью передается на поддержку команды BI и переходит на прод. Это как раз и есть тот самый эффект Self-Service, когда люди, хорошо разбираясь в своих бизнеc-задачах, начинают работать со своими данными и формируют новую стратегию своей работы. Исходя из этого мы сделали следующую схему проектов на сервере:


Схема проектов на Tableau Server

Каждый пользователь с лицензией Creator может публиковать свои воркбуки на сервер либо делать анализ локально. Для Self-Service мы сделали свою песочницу (Sandbox) со своими группами проектов.

Сайты в Tableau идеологически разделены так, чтобы пользователи одного сайта не видели контент другого, поэтому мы разделили сервер на сайты по направлениям, которые не пересекаются: например, игровая аналитика и финансы. Мы используем групповой доступ. В каждом сайте есть проекты, в которых права на их воркбуки и источники наследуются. То есть группa пользователей Group 1 видит только свои воркбуки и источники данных. Исключением из этого правила является сайт Sandbox, который имеет еще и подпроекты. Sandbox мы используем для прототипирования, разработки новых дашбордов, их тестирования и для нужд Self-Service. Все, у кого есть доступ на публикацию в своем проекте Sandbox, могут публиковать свои прототипы.

Мониторинг источников и дашбордов на Tableau Server


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

Мониторинг быстродействия дашбордов и быстродействия серверов Tableau задача, с которой сталкиваются средние и большие компании, поэтому про быстродействие дашбордов и его тюнинг написано достаточно много статей. Мы пионерами в этой области не стали, наш мониторинг это несколько дашбордов на базе внутренней БД PostgreSQL Tableau Server. Этот мониторинг работает со всем контентом, но можно выделить дашборды Self-Service и посмотреть их быстродействие.

Проблемы оптимизации дашбордов команда BI Team решает периодически. Пользователи иногда приходят с вопросом Почему медленно работает дашборд?, и нам нужно понимать, что такое медленно с точки зрения пользователя и какие числовые критерии могут характеризовать это медленно. Чтобы не интервьюировать пользователя и не отнимать его рабочее время для подробного пересказа проблем, мы мониторим и анализируем http-запросы, находим самые медленные и выясняем причины. После чего оптимизируем дашборды, если это может привести к увеличению производительности. Понятно что при живом подключении к источникам будут задержки, связанные с формированием view в базе задержки получения данных. Есть еще сетевые задержки, которые исследуем с нашей командой поддержки всей IT инфраструктуры, но в этой статье на них мы останавливаться не будем.

Немного о http requests


Каждое взаимодействие пользователя с дашбордом в браузере инициирует свой http request, передаваемый на Tableau Server. Вся история таких запросов хранится во внутренней БД PostgreSQL Tableau Server, срок хранения по умолчанию 7 дней. Этот срок можно увеличить изменениями настроек Tableau Server, но мы не хотели увеличивать таблицу http-запросов, поэтому просто собираем инкрементальный экстракт, в который укладываются только свежие данные каждый день, старые при этом не затираются. Это хороший способ с минимумом ресурсов держать в экстракте на сервере исторические данные, которых уже нет в базе.

Каждый http request имеет свой тип (action_type). Например, _bootstrap первоначальная загрузка view, relative-date-filter фильтр дат (слайдер). По названию можно определить большинство типов, поэтому понятно, что каждый пользователь делает с дашбордом: кто-то больше смотрит тултипы, кто-то меняет параметры, кто-то делает свои custom_view, а кто-то выгружает данные.

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


Дашборд мониторинга http-запросов

Мониторинг VizQL-сессий


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

По мере увеличения пользователей на сервере и внедрения Self-Service мы получили несколько пожеланий для увеличения лимитов сессий VizQL. Проблема пользователей была в том, что они открывали дашборды, устанавливали фильтры, что-то смотрели и переходили к другим своим задачам вне Tableau Server, после какого-то времени они возвращались к открытым дашбордам, но они сбрасывались на дефолтный вид, и приходилось заново их настраивать. Наша задача была сделать работу пользователей более комфортной и убедиться, что нагрузка на сервер не возрастает критически.

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

vizqlserver.session.expiry.minimum 5

Number of minutes of idle time after which a VizQL session is eligible to be discarded if the VizQL process starts to run out of memory.

vizqlserver.session.expiry.timeout 30 Number of minutes of idle time after which a VizQL session is discarded.

Поэтому мы решили сделать мониторинг VizQL сессий и отслеживать:

  1. Количество сессий,
  2. Количество сессий на пользователя,
  3. Среднюю длительность сессий,
  4. Максимальную длительность сессий.

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

Получился такой дашборд:


Дашборд мониторинга VizQL сессий

C начала января этого года мы стали постепенно увеличивать лимиты и мониторить длительность сессий и нагрузку. Средняя длина сессии увеличилась с 13 до 35 минут это видно на графиках средней длительности сессии. Конечные настройки такие:

vizqlserver.session.expiry.minimum 120vizqlserver.session.expiry.timeout 240

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

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

Изменение нагрузки на кластер CPU и RAM мы мониторим в Zabbix и AWS console. Значительных изменений нагрузки в процессе увеличения таймаутов мы не зафиксировали.

Если говорить о том, что может сильно нагнуть ваш Tableau сервер, то это может быть, например, неоптимизированный дашборд. Постройте, к примеру, в Tableau таблицу в десяток тысяч строк по категориям и id каких-нибудь событий, а в Measure используйте LOD вычисления на уровне id. С высокой вероятностью отображение таблицы на сервере не отработает, и вы получите вылет с Unexpected Error, поскольку все LODы в минимальной грануляции будут очень сильно потреблять память, и очень скоро процесс упрется в 100% потребления памяти.

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

Мониторинг источников данных сервера


Выше мы отмечали, что для Self-Service мы подготовили и опубликовали на сервере несколько источников данных. Все источники экстракты данных. Опубликованные источники сохраняются на сервере, и к ним предоставляется доступ ребятам, которые работают с Tableau Desktop.

В Tableau есть возможность помечать источники как сертифицированные. Так делает команда BI, когда готовит источники данных для Self-Service. Это гарантирует, что сам источник был протестирован.

Опубликованные источники могут достигать 200 млн строк и 100 полей. Для Self-Service это очень большой объем, поскольку не так много компаний имеет источники таких объемов для самостоятельной аналитики.

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

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


Дашборд мониторинга источников

Итог


Мы используем подход Self-Service 1,5 года. За это время 50 пользователей стали самостоятельно работать с данными. Это снизило нагрузку на BI Team и позволило ребятам не ждать, пока BI Team дойдет до конкретно их задачи по разработке дашборда. Примерно 5 месяцев назад мы стали подключать другие направления к самостоятельной аналитике.

В наших планах проведение обучения по data literacy и лучшим практикам визуализаций.

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

Популярность BPM в разных жанрах музыки. Анализ скорости исполнения 500 лучших песен

02.03.2021 02:04:15 | Автор: admin

Несколько лет назад, занимался изучением теории музыки, продавал и писал аудио-инструментал для аренды или заказов. Изначально, процесс явно творческий, но вскоре, мой интерес к коммерческой части превысил и возник вопрос: В каком же темпе создавать ритм музыки?.

Мною была замечена тенденция вариаций темпа популярных песен одного жанра, поэтому идея анализа крупной выборки лучших композиций, для определения популярного [часто: самого продаваемого] диапазонатемпа исполнения, не покидала с тех пор

BPM [в музыке] показатель, для определения скорости исполнения композиции, путём измерения количества тактовых долей в минуту.


1: Пролог

Устанавливаем Matplotlibи Pandas с необходимыми зависимостями через pip-менеджер в консоли/терминале.

python -m pip install -V matplotlib и pip install pandaspython -m pip install -V matplotlib и pip install pandas

Создаём директорию, а потом виртуальное окружение для проекта. После, подключаем библиотеки в IDE [в моём случае: PyCharm].

File Settings Project: [...] Python InterpreterFile Settings Project: [...] Python Interpreter

2: BPM

BPM будем вычислять через функцию Detect tempo в FL Studio и через сайт tunebat.com

ПКМ по верхней левой иконке на звуковой дорожке Detect tempo Выбрать диапазонПКМ по верхней левой иконке на звуковой дорожке Detect tempo Выбрать диапазон

3: DataSet

Начинаем создание DataSetа [выборки-коллекции данных] в Excel, для каждого жанра. Экспортируем в CSV-формат с настройками разделителя запятой. Следующие CSV-файлы создавал в IDE, так удобнее. Выборки перемещаем в директорию, где находится файл самой программы.

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

Параметры: name название трека; bpm темп; year год релизаПараметры: name название трека; bpm темп; year год релиза

4: Rap построение точечной диаграммы и гистограммы

Выборка взята здесь: rollingstone.com/100-greatest-hip-hop-songs-of-all-time
Сам CSV-DataSet: github.com/Rap.csv

На основе информации DataSet'а, создаём точечную диаграмму [Scatter Plots] для изучения взаимосвязи между BPM и годом выпуска, а также для отображения концентраций при ранжировании данных.

Видно, что с 1980 по 2005 гг. основным темпом был диапазон в 90-105 BPMВидно, что с 1980 по 2005 гг. основным темпом был диапазон в 90-105 BPMКод точечной диаграммы с комментариями
from matplotlib import pyplot as plt                              # Первый каноничный импортimport pandas as pd                                                    # Второй каноничный импорт для обработки DataSet'аplt.style.use('fivethirtyeight')                                         # Назначаем стилистику визуализацииdata_set = pd.read_csv('Rap.csv')                               # Считываем данные SCV-файла с DataSet'омbpm = data_set['bpm']                                                  # Переменная, для параметра BPM в каждой строкеyear = data_set['year']                                                  # Переменная, для параметра "год релиза" в каждой строкеplt.scatter(                                                                     # Построение точечного графика и его настройкаbpm, year,                                                                   # Данные для осей x и yc=bpm,                                                                        # Привязка цвета к нужной осиs=bpm*1.5,                                                                  # Зависимость размера точкиcmap='gist_heat',                                                        # Цветовая карта графикаedgecolor='black',                                                       # Цвет контура точкиlinewidth=.7                                                                 # Толщина контура точки)bar = plt.colorbar(                                                          # Построение шкалы BPMorientation='horizontal',                                            # Ориентация шкалыshrink=0.8,                                                               # Масштаб шкалыextend='both',                                                           # Скос краёв шкалыextendfrac=.1                                                           # Угол скоса краёв)bar.set_label('Шкала ударов в минуту', fontsize=18)   # Подпись шкалыplt.title('Популярность скорости '                                  # Заголовок графика  'исполнения в Rap\'е ', fontsize=25)plt.xlabel('BPM', fontsize=18)                                         # Ось абсциссplt.ylabel('Год релиза', fontsize=18)                               # Ось ординатplt.tight_layout()                                                              # Настройка параметров подзаголовков в области отображенияplt.show()                                                                        # Вывод на экран

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

Самый популярный диапазон: 80-100 BPMСамый популярный диапазон: 80-100 BPMКод гистограммы без комментариев
import pandas as pdfrom matplotlib import pyplot as pltfrom collections import Counterplt.style.use("fivethirtyeight")data_set = pd.read_csv('Rap end.csv')index = data_set['number']ranges = data_set['bpm_range']counter = Counter()for index in ranges:counter.update(index.split(';'))range_bpm = []value = []for item in counter.most_common(100):range_bpm.append(item[0])value.append(item[1])range_bpm.reverse()value.reverse()plt.barh(range_bpm, value,linewidth=.5,edgecolor='black',color='#e85b45',label='Количество точек на предыдущем графике')plt.legend()plt.title('Популярность интервала значений BPM в rap\'е', fontsize=25)plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)plt.ylabel('Диапазоны BPM', fontsize=18)plt.tight_layout()plt.show()

5: Рок

Выборка взята здесь: rockfm.ru/top100
Сам CSV-DataSet: github.com/Rock.csv

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

Код точечной диаграммы с комментариями
from matplotlib import pyplot as plt                              # Первый каноничный импортimport pandas as pd                                                    # Второй каноничный импорт для обработки DataSet'аplt.style.use('fivethirtyeight')                                         # Назначаем стилистику визуализацииdata_set = pd.read_csv('Rock.csv')                             # Считываем данные SCV-файла с DataSet'омbpm = data_set['bpm']                                                  # Переменная, для параметра BPM в каждой строкеyear = data_set['year']                                                  # Переменная, для параметра "год релиза" в каждой строкеplt.scatter(                                                                     # Построение точечного графика и его настройкаbpm, year,                                                                   # Данные для осей x и yc=bpm,                                                                        # Привязка цвета к нужной осиs=bpm*1.5,                                                                  # Зависимость размера точкиcmap='gist_heat',                                                        # Цветовая карта графикаedgecolor='black',                                                       # Цвет контура точкиlinewidth=.7                                                                 # Толщина контура точкиalpha=.7                                                                      # Прозрачность точки)bar = plt.colorbar(                                                          # Построение шкалы BPMorientation='horizontal',                                            # Ориентация шкалыshrink=0.8,                                                               # Масштаб шкалыextend='both',                                                           # Скос краёв шкалыextendfrac=.1                                                           # Угол скоса краёв)bar.set_label('Шкала ударов в минуту', fontsize=18)    # Подпись шкалыplt.title('Популярность скорости '                                   # Заголовок графика  'исполнения в роке', fontsize=25)plt.xlabel('BPM', fontsize=18)                                          # Ось абсциссplt.ylabel('Год релиза', fontsize=18)                                # Ось ординатplt.tight_layout()                                                               # Настройка параметров подзаголовков в области отображенияplt.show()                                                                         # Вывод на экран
Самые популярные диапазоны: 120-140 и 100-120 BPMСамые популярные диапазоны: 120-140 и 100-120 BPMКод гистограммы без комментариев
import pandas as pdfrom matplotlib import pyplot as pltfrom collections import Counterplt.style.use("fivethirtyeight")data_set = pd.read_csv('Rock end.csv')index = data_set['number']ranges = data_set['bpm_range']counter = Counter()for index in ranges:counter.update(index.split(';'))range_bpm = []value = []for item in counter.most_common(100):range_bpm.append(item[0])value.append(item[1])range_bpm.reverse()value.reverse()plt.barh(range_bpm, value,linewidth=.5,edgecolor='black',color='#e85b45',label='Количество точек на предыдущем графике')plt.legend()plt.title('Популярность интервала значений BPM в роке', fontsize=25)plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)plt.ylabel('Диапазоны BPM', fontsize=18)plt.tight_layout()plt.show()

6: Блюз

Выборка взята здесь: digitaldreamdoor.com/best_bluesong
Сам CSV-DataSet: github.com/Blues.csv

Видно высокую концентрацию использования темпа около 100 BPM в 90-хВидно высокую концентрацию использования темпа около 100 BPM в 90-хКод точечной диаграммы с комментариями
from matplotlib import pyplot as plt                              # Первый каноничный импортimport pandas as pd                                                    # Второй каноничный импорт для обработки DataSet'аplt.style.use('fivethirtyeight')                                         # Назначаем стилистику визуализацииdata_set = pd.read_csv('Blues.csv')                            # Считываем данные SCV-файла с DataSet'омbpm = data_set['bpm']                                                  # Переменная, для параметра BPM в каждой строкеyear = data_set['year']                                                  # Переменная, для параметра "год релиза" в каждой строкеplt.scatter(                                                                     # Построение точечного графика и его настройкаbpm, year,                                                                   # Данные для осей x и yc=bpm,                                                                        # Привязка цвета к нужной осиs=bpm*1.5,                                                                  # Зависимость размера точкиcmap='gist_heat',                                                        # Цветовая карта графикаedgecolor='black',                                                       # Цвет контура точкиlinewidth=.7                                                                 # Толщина контура точки)bar = plt.colorbar(                                                          # Построение шкалы BPMorientation='horizontal',                                            # Ориентация шкалыshrink=0.8,                                                               # Масштаб шкалыextend='both',                                                           # Скос краёв шкалыextendfrac=.1                                                           # Угол скоса краёв)bar.set_label('Шкала ударов в минуту', fontsize=18)    # Подпись шкалыplt.title('Популярность скорости '                                   # Заголовок графика  'исполнения в блюзе', fontsize=25)plt.xlabel('BPM', fontsize=18)                                          # Ось абсциссplt.ylabel('Год релиза', fontsize=18)                                # Ось ординатplt.tight_layout()                                                               # Настройка параметров подзаголовков в области отображенияplt.show()                                                                         # Вывод на экран
Самый популярный диапазон: 100-120 BPMСамый популярный диапазон: 100-120 BPMКод гистограммы без комментариев
import pandas as pdfrom matplotlib import pyplot as pltfrom collections import Counterplt.style.use("fivethirtyeight")data_set = pd.read_csv('Blues end.csv')index = data_set['number']ranges = data_set['bpm_range']counter = Counter()for index in ranges:counter.update(index.split(';'))range_bpm = []value = []for item in counter.most_common(100):range_bpm.append(item[0])value.append(item[1])range_bpm.reverse()value.reverse()plt.barh(range_bpm, value,linewidth=.5,edgecolor='black',color='#e85b45',label='Количество точек на предыдущем графике')plt.legend()plt.title('Популярность интервала значений BPM в блюзе', fontsize=25)plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)plt.ylabel('Диапазоны BPM', fontsize=18)plt.tight_layout()plt.show()

7: Chillout

Выборка взята здесь: open.spotify.com
Сам CSV-DataSet: github.com/Chillout.csv

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

Код точечной диаграммы с комментариями
from matplotlib import pyplot as plt                              # Первый каноничный импортimport pandas as pd                                                    # Второй каноничный импорт для обработки DataSet'аplt.style.use('fivethirtyeight')                                         # Назначаем стилистику визуализацииdata_set = pd.read_csv('Chillout.csv')                         # Считываем данные SCV-файла с DataSet'омbpm = data_set['bpm']                                                  # Переменная, для параметра BPM в каждой строкеyear = data_set['year']                                                  # Переменная, для параметра "год релиза" в каждой строкеplt.scatter(                                                                     # Построение точечного графика и его настройкаbpm, year,                                                                   # Данные для осей x и yc=bpm,                                                                        # Привязка цвета к нужной осиs=bpm*1.5,                                                                  # Зависимость размера точкиcmap='gist_heat',                                                        # Цветовая карта графикаedgecolor='black',                                                       # Цвет контура точкиlinewidth=.7                                                                 # Толщина контура точкиalpha=.5                                                                      # Прозрачность точки)bar = plt.colorbar(                                                          # Построение шкалы BPMorientation='horizontal',                                            # Ориентация шкалыshrink=0.8,                                                               # Масштаб шкалыextend='both',                                                           # Скос краёв шкалыextendfrac=.1                                                           # Угол скоса краёв)bar.set_label('Шкала ударов в минуту', fontsize=18)   # Подпись шкалыplt.title('Популярность скорости '                                  # Заголовок графика  'исполнения в Chillout', fontsize=25)plt.xlabel('BPM', fontsize=18)                                          # Ось абсциссplt.ylabel('Год релиза', fontsize=18)                               # Ось ординатplt.tight_layout()                                                               # Настройка параметров подзаголовков в области отображенияplt.show()                                                        # Вывод на экран
Самый популярный диапазон: 80-100Самый популярный диапазон: 80-100Код гистограммы без комментариев
import pandas as pdfrom matplotlib import pyplot as pltfrom collections import Counterplt.style.use("fivethirtyeight")data_set = pd.read_csv('Chillout end.csv')index = data_set['number']ranges = data_set['bpm_range']counter = Counter()for index in ranges:counter.update(index.split(';'))range_bpm = []value = []for item in counter.most_common(100):range_bpm.append(item[0])value.append(item[1])range_bpm.reverse()value.reverse()plt.barh(range_bpm, value,linewidth=.5,edgecolor='black',color='#e85b45',label='Количество точек на предыдущем графике')plt.legend()plt.title('Популярность интервала значений BPM в Chillout', fontsize=25)plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)plt.ylabel('Диапазоны BPM', fontsize=18)plt.tight_layout()plt.show()

8: EDM

Выборка взята здесь: edmcharts.net
Сам CSV-DataSet: github.com/EDM.csv

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

Довольно однозначно вышло...Довольно однозначно вышло...Код точечной диаграммы с комментариями
from matplotlib import pyplot as plt                              # Первый каноничный импортimport pandas as pd                                                    # Второй каноничный импорт для обработки DataSet'аplt.style.use('fivethirtyeight')                                         # Назначаем стилистику визуализацииdata_set = pd.read_csv('EDM.csv')                             # Считываем данные SCV-файла с DataSet'омbpm = data_set['bpm']                                                  # Переменная, для параметра BPM в каждой строкеyear = data_set['year']                                                  # Переменная, для параметра "год релиза" в каждой строкеplt.scatter(                                                                     # Построение точечного графика и его настройкаbpm, year,                                                                   # Данные для осей x и yc=bpm,                                                                        # Привязка цвета к нужной осиs=bpm*1.5,                                                                  # Зависимость размера точкиcmap='gist_heat',                                                        # Цветовая карта графикаedgecolor='black',                                                       # Цвет контура точкиlinewidth=.7                                                                 # Толщина контура точкиalpha=.2                                                                      # Прозрачность точки)bar = plt.colorbar(                                                          # Построение шкалы BPMorientation='horizontal',                                            # Ориентация шкалыshrink=0.8,                                                               # Масштаб шкалыextend='both',                                                           # Скос краёв шкалыextendfrac=.1                                                           # Угол скоса краёв)bar.set_label('Шкала ударов в минуту', fontsize=18)   # Подпись шкалыplt.title('Популярность скорости '                                  # Заголовок графика  'исполнения в EDM', fontsize=25)plt.xlabel('BPM', fontsize=18)                                          # Ось абсциссplt.ylabel('Год релиза', fontsize=18)                               # Ось ординатplt.tight_layout()                                                               # Настройка параметров подзаголовков в области отображенияplt.show()                                                        # Вывод на экран
Самый популярный диапазон: 120-140Самый популярный диапазон: 120-140Код гистограммы без комментариев
import pandas as pdfrom matplotlib import pyplot as pltfrom collections import Counterplt.style.use("fivethirtyeight")data_set = pd.read_csv('EDM end.csv')index = data_set['number']ranges = data_set['bpm_range']counter = Counter()for index in ranges:counter.update(index.split(';'))range_bpm = []value = []for item in counter.most_common(100):range_bpm.append(item[0])value.append(item[1])range_bpm.reverse()value.reverse()plt.barh(range_bpm, value,linewidth=.5,edgecolor='black',color='#e85b45',label='Количество точек на предыдущем графике')plt.legend()plt.title('Популярность интервала значений BPM в EDM', fontsize=25)plt.xlabel('Количество песен в диапазоне BPM', fontsize=18)plt.ylabel('Диапазоны BPM', fontsize=18)plt.tight_layout()plt.show()

9: Заключение

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

* такие жанры как ethnic, ambient, folk, dubstep, reggae и др, не удалось к сожалению разобрать из-за отсутствия качественной выборки...

BPM/Кол-во треков

<60

60-80

80-100

100-120

120-140

140-160

160-180

Blues

2

9

25

35

15

6

8

Chillout

11

35

18

19

12

5

EDM

1

3

21

67

6

2

Rap

5

61

20

7

4

3

Rock

6

20

25

27

11

11

Итог:

2

32

144

119

135

39

29

Простой код, простого графика
from matplotlib import pyplot as pltplt.style.use('fivethirtyeight')x = ['<60', '60-80', '80-100', '100-120', '120-140', '140-160', '160-180']y = [2, 32, 144, 119, 135, 39, 29]plt.plot(x, y, label='BPM', c='#e85b45')plt.legend()plt.title('Сравнение всех диапазонов BPM во всех жанрах', fontsize=25)plt.xlabel('Диапазон BPM', fontsize=18)plt.ylabel('Количество треков', fontsize=18)plt.tight_layout()plt.show()
Подробнее..

НИУ ВШЭ Петербург и JetBrains проведут школу по практическому программированию для старшеклассников

11.03.2021 14:15:49 | Автор: admin

Питерская Вышка и компания JetBrains приглашают учащихся 10 и 11 классов на школу по практическому программированию и анализу данных. Среди лекторов ведущие преподаватели Петербурга и специалисты IT-компаний: Сергей Копелиович, Егор Суворов, Иван Ямщиков, Михаил Дворкин, Алексей Шпильман и другие.

Школа пройдет в два этапа: первый этап состоится с 22 по 28 марта в онлайн-формате. Второй этап будет очным, участники встретятся в Санкт-Петербурге с 5 по 10 мая. Участие в школе бесплатное.

Александр Омельченко, декан факультета Санкт-Петербургская школа физико-математических и компьютерных наук:

Наша школа это первый шаг на пути к самостоятельной работе в IT-компании. Мы не будем заниматься решением олимпиадных задач или подготовкой к ЕГЭ. Наша цель показать, как работать в команде, попробовать свои силы в исследовательском проекте в области машинного обучения, языков программирования, в реальной промышленной разработке. Участники смогут реализовать свой первый проект и понять, готовы ли они заниматься machine learning или software engineering.

Первый этап: с 22 по 28 марта, дистанционно

На этом этапе участников ждет продвинутый курс по алгоритмам от Сергея Копелиовича. Сергей окончил МатМех СПбГУ и учился в Академическом университете. Со школьных лет занимался олимпиадным программированием и математикой. Золотой медалист IOI 2005, 2006 и ACM ICPC 2009. Работал программистом в Яндексе, Вконтакте и ЦРТ. С 2009 года преподает алгоритмы в университетах и образовательных центрах (СПбГУ, СПбАУ, НИУ ВШЭ Петербург, Computer Science Center).Также участникам прочитают обзорные лекции по C++, Python, применению машинного обучения и облачным технологиям. Подробная программа доступна по ссылке.

Второй этап: с 5 по 10 мая, Санкт-Петербург

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

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

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

Подробности по ссылке. Регистрация завершится 20-го марта.

Подробнее..

Computer Science Center открыл приём заявок на новый учебный год

24.03.2021 16:21:32 | Автор: admin

До 10 апреля продолжается набор на вечерние курсы по математике и программированию в CS центре. Computer Science Center это совместный проект Школы анализа данных Яндекса, JetBrains и Computer Science клуба при ПОМИ РАН. Курсы проходят очно в Санкт-Петербурге и Новосибирске, жители других городов могут заниматься дистанционно. Обучение в Computer Science Center бесплатное.

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

Большинство наших студентов учатся в вузах или работают, поэтому расписание составлено так, чтобы занятия можно было совмещать с основной деятельностью. Однако будьте осторожны: на учёбу в Computer Science Center придется тратить не менее 15 часов в неделю. Если у вас недостаточно времени (или мотивации), советуем начать с онлайн-курсов на платформе Stepik.

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

  • Computer Science,

  • Data Science,

  • Software Engineering.

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

Чтобы стать студентом или студенткой CS центра, нужно справиться с вступительными испытаниями:

  • заполните анкету на сайте до 10 апреля,

  • решите задания онлайн-теста до 11 апреля,

  • участвуйте в онлайн-экзамене в конце апреля-начале мая,

  • пройдите собеседование в мае-июне.

Для кандидатов, которые успешно прошли отбор, занятия начнутся в сентябре 2021 года.

Если вы еще не решили, стоит ли ввязываться в эту авантюру, посмотрите на отзывы выпускников:

Станислав Гордеев, разработчик игрового движка в People Can Fly (Варшава), выпускник 2018 года направления Software Engineering:

Когда-то давно, в сентябре 2014, будучи ещё студентом-физиком, я случайно наткнулся на хабро-статью про онлайн-курсы на Stepik, заинтересовался и прошёл курсы по C++ и алгоритмам, кроме того, узнал о CSC. На тот момент у меня помимо интереса появилась довольно амбициозная цель попасть в большой gamedev. Поступление оказалось совсем не лёгким и до последнего дня с письмом о зачислении я не верил, что всё получится. Моё обучение началось в 2016, и с тех пор я семимильными шагами приближался к своей цели. А все из-за неповторимой атмосферы знаний, амбиций, дружелюбия, которая не позволяет сидеть на месте, которая заставляет поверить в себя. Сейчас я с уверенностью могу сказать, что моя цель осуществилась в первую очередь благодаря CS центру, потому что это больше, чем просто курсы. Старайтесь, и у вас всё получится.

Анна Атаманова, разработчица в Яндексе, выпускница 2016 года направления Data Science:

Почему СS центр это дико круто:

курсы! (всё новое и интересное по основным направлением центра тут-тут-тут);

увлечённые своим делом преподаватели (таких людей в любом случае приятно слушать);

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

проекты! стажировки! (опыт, реальные задачи);

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

Артемий Пестрецов, разработчик в JetBrains, преподаватель CS центра, выпускник 2019 года направлений Data Science и Software Engineering:

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

Все отзывы можно посмотреть на этой странице.


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

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

Ждем будущих студентов Computer Science Center!

Подробнее..

Перевод 5 разных библиотек Python, которые сэкономят ваше время

12.06.2021 18:20:44 | Автор: admin

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


PyForest

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

Вот почему PyForest это одна из самых удобных библиотек, которые я знаю. С её помощью в ваш блокнот Jupyter можно импортировать более 40 популярнейших библиотек (Pandas, Matplotlib, Seaborn, Tensorflow, Sklearn, NLTK, XGBoost, Plotly, Keras, Numpy и другие) при помощи всего одной строки кода.

Выполните pip install pyforest. Для импорта библиотек в ваш блокнот введите команду from pyforest import *, и можно начинать. Чтобы узнать, какие библиотеки импортированы, выполните lazy_imports().

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

Emot

Эта библиотека может повысить качество вашего проекта по обработке естественного языка. Она преобразует эмотиконы в их описание. Представьте, например, что кто-то оставил в Твиттере сообщение I [здесь в оригинале эмодзи "красное сердце", новый редактор Хабра вырезает его] Python. Человек не написал слово люблю, вместо него вставив эмодзи. Если твит задействован в проекте, придётся удалить эмодзи, а значит, потерять часть информации.

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

Чтобы установить Emot, выполните команду pip install emot, а затем командой import emot импортируйте её в свой блокнот. Нужно решить, с чем вы хотите работать, то есть с эмотиконами или с эмодзи. В случае эмодзи код будет таким: emot.emoji(your_text). Посмотрим на emot в деле.

Выше видно предложение I [эмодзи "красное сердце"] Python, обёрнутое в метод Emot, чтобы разобраться со значениями. Код выводит словарь со значением, описанием и расположением символов. Как всегда, из словаря можно получить слайс и сосредоточиться на необходимой информации, например, если я напишу ans['mean'], вернётся только описание эмодзи.

Geemap

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

Установите geemap командой pip install geemap из терминала, затем импортируйте в блокнот командой import geemap. Для демонстрации я создам интерактивную карту на основе folium:

import geemap.eefolium as geemapMap = geemap.Map(center=[40,-100], zoom=4)Map

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

Dabl

Позвольте мне рассказать об основах. Dabl создан, чтобы упростить работу с моделями ML для новичков. Чтобы установить её, выполните pip install dabl, импортируйте пакет командой import dabl и можно начинать. Выполните также строчку dabl.clean(data), чтобы получить информацию о признаках, например о том, есть ли какие-то бесполезные признаки. Она также показывает непрерывные, категориальные признаки и признаки с высокой кардинальностью.

Чтобы визуализировать конкретный признак, можно выполнить dabl.plot(data).

Наконец, одной строчкой кода вы можете создать несколько моделей вот так: dabl.AnyClassifier, или так: dabl.Simplefier(), как это делается в scikit-learn. Но на этом шаге придётся предпринять некоторые обычные шаги, такие как создание тренировочного и тестового набора данных, вызов, обучение модели и вывод её прогноза.

# Setting X and y variablesX, y = load_digits(return_X_y=True)# Splitting the dataset into train and test setsX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)# Calling the modelsc = dabl.SimpleClassifier().fit(X_train, y_train)# Evaluating accuracy scoreprint(Accuracy score, sc.score(X_test, y_test))

Как видите, Dabl итеративно проходит через множество моделей, включая Dummy Classifier (фиктивный классификатор), GaussianNB (гауссовский наивный Байес), деревья решений различной глубины и логистическую регрессию. В конце библиотека показывает лучшую модель. Все модели отрабатывают примерно за 10 секунд. Круто, правда? Я решил протестировать последнюю модель при помощи scikit-learn, чтобы больше доверять результату:

Я получил точность 0,968 с обычным подходом к прогнозированию и 0,971 с помощью Dabl. Для меня это достаточно близко! Обратите внимание, что я не импортировал модель логистической регрессии из scikit-learn, поскольку это уже сделано через PyForest. Должен признаться, что предпочитаю LazyPredict, но Dabl стоит попробовать.

SweetViz

Это low-code библиотека, которая генерирует прекрасные визуализации, чтобы вывести ваш исследовательский анализ данных на новый уровень при помощи всего двух строк кода. Вывод библиотеки интерактивный файл HTML. Давайте посмотрим на неё в общем и целом. Установить её можно так: pip install sweetviz, а импортировать в блокнот строкой import sweetviz as sv. И вот пример кода:

my_report = sv.analyze(dataframe)my_report.show_html()

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

Заключение

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

Этот материал не только даёт представление о полезных пакетах экосистемы Python, но и напоминает о широте и разнообразии проектов, в которых можно работать на этом языке. Python предельно лаконичен, он позволяет экономить время и в процессе написания кода, выражать идеи максимально быстро и эффективно, то есть беречь силы, чтобы придумывать новые подходы и решения задач, в том числе в области искусственного интеллекта, получить широкое и глубокое представление о котором вы можете на нашем курсе "Machine Learning и Deep Learning".

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

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

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

29.03.2021 20:20:50 | Автор: admin

Tom, но без Jerry

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

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

Индекс загруженности

Индекс TomTom отражает степень загруженности городов. В 2019 году Бангалор, Индия (Бангалор) и Манила (Филиппины) заняли лидирующие позиции, при этом из-за загруженности дорог в этих городах время в пути в среднем увеличивалось на 71 процент.

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

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

Общий рейтинг оказался практически бессмысленным: Москва возглавила рейтинг 2020 года с 54%, но это не потому что время в пути по Москве увеличилось по сравнению с 2019 годом(фактически, они упали на 5 процентов), а скорее Бангалор и Манила опустились в рейтинге, потому что Индия столкнулась с более строгими ограничениями по пандемии.

 Лидеры 2020 года по индексу загруженности Лидеры 2020 года по индексу загруженности

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

Географические особенности

Гийс Петерс, специалист по обработке данных TomTom, описывает пандемию через призму трафика:

Когда Ухань был заблокирован, движение там прекратилось, говорит он. Здесь, в Европе, все было по-прежнему нормально. Затем мы наблюдали за распространением вируса, отслеживая данные о трафике. Транспортное движение прекратилось в Милане, затем в Риме и остальной Италии, а потом и в других европейских странах.

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

Разница в между 2019 и 2020 в РоссииРазница в между 2019 и 2020 в РоссииИ разница между 2019 и 2020 в ВеликобританииИ разница между 2019 и 2020 в Великобритании

Питерс отмечает, что изменения автомобильного движения в Соединенных Штатах сильно различались от города к городу:

В Миннеаполисе были более строгие ограничения по сравнению с другими городами США. Пробки в апреле снизились вдвое и все еще остаются очень низкими , говорит он. Однако во Флориде, где изоляция закончилась первого июня, движение, похоже, вернулось в норму.

Между тем, в Сан-Хосе и в районе залива Сан-Франциско мы заметили, что движение транспорта снизилось в преддверии объявления локдауна: как только работодатели решили перевести сотрудников на удаленку. Так что, хотя вы видите, что трафик во многих крупных городах США в последние месяцы увеличивается, трафик вокруг Сан-Хосе по-прежнему очень низкий.

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

Какие выводы стоит сделать

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

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

Например, Петерс говорит: Когда я смотрю на [Нидерланды], общее количество пройденных километров в апреле составило около 50 процентов от ожидаемого, а заторов почти не осталось. В ноябре, после второй волны, пробок все еще почти не было, но мы обратили внимание, что количество пройденных километров выросло до 8090 процентов от нормы. Это говорит о том, что если мы сможем сократить наш трафик на 10-15 процентов, мы сможем снизить и, возможно, полностью предотвратить перегрузку .

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

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

Подробнее..

Обзор современных инструментов дата-аналитика

16.02.2021 18:22:34 | Автор: admin
image

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

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


1. Языки программирования



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

Python
Python служит главным инструментом в руках data scientists, не имеет строгой типизации и предназначен для быстрой разработки прототипов или написания коротких сценариев или скриптов. Люди разбирающиеся в программировании и computer science его часто критикуют за то, что алгоритмы написанные на чистом python оказываются не оптимальными в отношении своей производительности и требованиям к памяти.
Но тем не менее у данного языка программирования есть много плюсов. Среди них я бы отметил то, что python преподают уже практически везде, в связи с чем сравнительно легко найти аналитика знающего python. Второе преимущество это библиотеки для работы с данными и машинного обучения, имеющие удобный интерфейс. Например, на основе библиотеки sklearn легко собирать конвейеры предварительной обработки данных и построения моделей. Все алгоритмы и настройки машинного обучения инкапсулированы внутри классов и объектов, что делает код очень простым.

R
До недавнего времени основным конкурентом python был язык R. Пожелания к знанию R и сейчас изредка встречаются в описаниях вакансий по крайней мере в разделе преимущества. До середины 2018-го года я и сам программировал на R. И при попытке автоматизировать часть своей работы по машинному обучению чуть не изобрел велосипед, пытаясь на R создать конвейеры подготовки данных и обучения моделей. Чуть позже узнал, что такие конвейеры уже давно существуют в библиотеке sklearn и называются pipeline.

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

MatLab
Язык MatLab встроен в одноименный пакет программ и интерактивную среду инженерных расчетов. Правда предназначен данный язык в большей степени для решения технических задач, а не для выполнения финансового или бизнес-анализа. Например, мне посчастливилось применять MatLab дважды: в процессе исследования сигналов акустической эмиссии в конструкциях, а также при обработке человеческой речи.
Существует ряд библиотек машинного обучения с API для других языков программирования, таких как Java, JavaScript, Scala и т.д. Но останавливаться на них не буду поскольку цель статьи немного иная.

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

2. AutoML и визуальные конструкторы


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

Ящик под названием AutoML выглядит либо как библиотека машинного обучения, либо как веб-сервис куда заливаются данные.
Если это библиотека, то она отличается от sklearn тем, что наш привычный код в 20-30 строк сжимается до 5 строк. Известный пример такой библиотеки H2O.
Другой пример библиотека MLBox. Про нее в интернете можно найти истории, о том как применение MLBox позволило попасть в топовые 5% на соревнованиях kaggle.

Теперь несколько слов об облачных сервисах AutoML. Во первых, свои технические решения спешат представить все основные цифровые гиганты. Вот некоторые из них: Google AutoML Tables, Azure Machine Learning (Microsoft), SageMaker Autopilot (Amazon). Перечисленные сервисы должны быть интересны в первую очередь тем компаниям, которые разрабатывают аналитические системы на облачных платформах. Очень удобно, когда и инфраструктуру данных, и вычислительные ресурсы, и готовые алгоритмы машинного обучения предоставляет один и тот же провайдер. Интеграция получается поистине бесшовной.
Помимо цифровых гигантов на рынке AutoML появляются и игроки поменьше. Например, непосредственно в настоящий момент в компании Bell Integrator идет активная работа над платформой neuton.ai.

В этом же разделе стоит вспомнить про системы машинного обучения, занимающие промежуточные позиции между непосредственным программированием на R и Python и полностью упакованным в коробку AutoML. Это так называемые конструкторы workflow. Два типичных примера: конструктор машинного обучения Azure от Microsoft и платформа SberDS Сбербанка.
Конструктор представляет собой набор кубиков, из которых можно собрать весь конвейер машинного обучения, включая финальную проверку работоспособности модели. Это несомненно красивое решение для людей с визуальным типом мышления, которым удобно представлять процесс машинного обучения и тестирования моделей в виде схем.

3. Инструменты BI


Здесь бы я хотел рассмотреть несколько BI решений в области аналитики: Power BI, Tableau, Qlick Sense, Qlick View и Excel.

Power BI
Power BI это набор аналитических инструментов от Microsoft, которые доступны в виде десктопных приложений и облачных сервисов. Существуют корпоративные решения, работающие на закрытой it-инфраструктуре компании. Работа в Power BI Desktop или Power BI Services не требует навыков программирования. Предусмотрена возможность онлайн-интеграции с внешними источниками данных, а также загрузка данных в формате csv.
Power BI способен решать задачи машинного обучения посредством AutoML, то есть для построения модели классификации или регрессии писать программный код как на питоне не придется. Кроме стандартных задач анализа табличных данных в функционал встроены технологии анализа тональности, извлечения ключевых фраз, распознавания языка и добавления тегов к изображению.

Tableau
Tableau также представляет собой целое семейство онлайн и десктопных приложений, как и Power BI. Данные приложения имеют простой визуальный интерфейс и позволяют работать методом перетаскивания drag-and-drop. Красивые графики строятся буквально за несколько кликов. Также данные можно анализировать в табличном виде и применять к ним различные фильтры.
Tableau позволяет решать и задачи машинного обучения, такие как регрессия, прогнозирование временных рядов, кластерный анализ. А главное, Tableau способен интегрироваться с внешними скриптами на R и Python. Получается легко расширяемый инструмент.

Qlick Sence и Qlick View
Qlick Sence и Qlick View по позиционированию и интерфейсу отличаются между собой, но по сути и по алгоритмам решения задач построены на одном движке. Qlick View корпоративная платформа, которой управляют it-специалисты, Qlick Sence инструмент для личного использования без необходимости обращаться за помощью в тех. поддержку.
При первом же знакомстве бросается в глаза красота и легкость визуализации. Это тот самый инструмент, если надо построить приятный глазу дашборд для руководства. С моей точки зрения особенно зрелищным выглядит возможность менять масштаб при анализе географических карт и кластеров на двухмерных графиках. Вспоминаются кадры из фильмов, где на фото со спутников пытаются разглядеть номер автомобиля или выделить человека из толпы на площади.
Еще одна интересная опция наличие мобильного приложения для выполнения анализа со смартфона. Так и представляется топ-менеджер сети ритейла, спешащий на очередной рейс в аэропорту и получивший неожиданное сообщение в мессенджере со ссылкой на дашборд.
Qlick Sence интегрируется с Python, а следовательно и с машинным обучением.

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

4. Изюминка на торте. Автоматическая генерация кода на основе AI.


Как-то раз при знакомстве в сети мне задали вопрос ты программируешь на python?. И когда я ответил Да, продолжение было совершенно неожиданным.
А ты знаешь про это и далее шла ссылка на ролик в Youtube
https://www.youtube.com/watch?v=fZSFNUT6iY8&t=4s&ab_channel=FazilBabu.
Речь идет о генеративной текстовой модели от OpenAI, обученной на репозитории GitHub. На конкретных примерах показана способность модели генерировать код на Python на основании заголовка функции и ее краткого описания.
А что будет, если такую модель удастся хорошо обучить на скриптах data scientists? Это вопрос для размышлений ))
Подробнее..

Перевод Clustergram визуализация кластерного анализа на Python

28.05.2021 14:21:34 | Автор: admin

В этой статье, переводом которой мы решили поделиться специально к старту курса о Data Science, автор представляет новый пакет Python для генерации кластерограмм из решений кластеризации. Библиотека была разработана в рамках исследовательского проекта Urban Grammar и совместима со scikit-learn и библиотеками с поддержкой GPU, такими как cuML или cuDF в рамках RAPIDS.AI.


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

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

Маттиас Шонлау предложил другой подход кластерограмму. Кластерограмма это двухмерный график, отражающий потоки наблюдений между классами по мере добавления кластеров. Это говорит вам о том, как перетасовываются ваши данные и насколько хороши ваши сплиты. Тал Галили позже реализовал кластерограмму для k-средних в R. Я использовал реализацию Таля, перенёс ее на Python и создал clustergram пакет Python для создания кластерограмм.

clustergram в настоящее время поддерживает метод k-средних, использование scikit-learn (включая реализацию Mini-Batch) и RAPIDS.AI cuML (если у вас есть GPU с поддержкой CUDA), Gaussian Mixture Model (только scikit-learn) и иерархическую кластеризацию на основе scipy.hierarchy. В качестве альтернативы мы можем создать кластерограмму на основе меток и данных, полученных с помощью альтернативных пользовательских алгоритмов кластеризации. Пакет предоставляет API, подобный sklearn, и строит кластерные диаграммы с помощью matplotlib, что даёт ему широкий выбор вариантов оформления в соответствии со стилем вашей публикации.

Установка

Установить clustergram можно при помощи conda или pip:

conda install clustergram -c conda-forge

или

pip install clustergram

В любом случае вам нужно установить выбранный бэкенд (scikit-learn и scipy или cuML).

from clustergram import Clustergramimport urbangrammar_graphics as uggimport seaborn as snsimport matplotlib.pyplot as pltfrom sklearn.preprocessing import scalesns.set(style='whitegrid')

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

Набор данных о цветке ириса

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

iris = sns.load_dataset("iris")g = sns.pairplot(iris, hue="species", palette=ugg.COLORS[1:4])g.fig.suptitle("Iris flowers", y=1.01)

Похоже, что setosa относительно чётко определённая группа, тогда как разница между versicolor и virginica меньше, поскольку они частично перекрываются (или, в случае ширины чашелистика, полностью).

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

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

data = scale(iris.drop(columns=['species']))cgram = Clustergram(range(1, 10), n_init=1000)cgram.fit(data)ax = cgram.plot(    figsize=(10, 8),    line_style=dict(color=ugg.COLORS[1]),    cluster_style={"color": ugg.COLORS[2]},)ax.yaxis.grid(False)sns.despine(offset=10)ax.set_title('K-Means (scikit-learn)')

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

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

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

fig, axs = plt.subplots(2, figsize=(10, 10), sharex=True)cgram.silhouette_score().plot(    xlabel="Number of clusters (k)",    ylabel="Silhouette score",    color=ugg.COLORS[1],    ax=axs[0],)cgram.calinski_harabasz_score().plot(    xlabel="Number of clusters (k)",    ylabel="Calinski-Harabasz score",    color=ugg.COLORS[1],    ax=axs[1],)sns.despine(offset=10)

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

Набор данных о пингвинах со станции Палмера

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

penguins = sns.load_dataset("penguins")g = sns.pairplot(penguins, hue="species", palette=ugg.COLORS[3:])g.fig.suptitle("Palmer penguins", y=1.01)

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

data = scale(penguins.drop(columns=['species', 'island', 'sex']).dropna())cgram = Clustergram(range(1, 10), n_init=1000)cgram.fit(data)ax = cgram.plot(    figsize=(10, 8),    line_style=dict(color=ugg.COLORS[1]),    cluster_style={"color": ugg.COLORS[2]},)ax.yaxis.grid(False)sns.despine(offset=10)ax.set_title("K-Means (scikit-learn)")

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

Можно ли сказать, что их три? Поскольку мы знаем, что их должно быть три... Ну, не совсем. Разница между разделениями 23 и 34 незначительна. Однако здесь виновником является метод K ближайших соседей, а не кластерограмма. Он просто не может правильно кластеризовать эти данные из-за наложений и общей структуры. Давайте посмотрим, как работает смешанная Гауссова модель (Gaussian Mixture).

cgram = Clustergram(range(1, 10), n_init=100, method="gmm")cgram.fit(data)ax = cgram.plot(    figsize=(10, 8),    line_style=dict(color=ugg.COLORS[1]),    cluster_style={"color": ugg.COLORS[2]},)ax.yaxis.grid(False)sns.despine(offset=10)ax.set_title("Gaussian Mixture Model (scikit-learn)")

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

Подобная ситуация случается очень часто. Идеального случая не существует. В конечном счёте нам необходимо принять решение об оптимальном количестве кластеров. Clustergam даёт нам дополнительные сведения о том, что происходит между различными вариантами, как они расходятся. Можно сказать, что вариант с четырьмя кластерами в данных Iris не помогает. Также можно сказать, что пингвины Палмера могут быть сложными для кластеризации с помощью k-средних, что нет решающего правильного решения. Кластерограмма не даёт простого ответа, но она даёт нам лучшее понимание, и только от нас зависит, как мы её [кластерограмму] интерпретируем.

Установить clustergram можно с помощью conda install clustergram -c conda-forge или pip install clustergram. В любом случае вам всё равно придётся установить бэкенд кластеризации: либо scikit-learn, либо cuML. Документация доступна здесь, а исходный код здесь, он выпущен под лицензией MIT.

Если вы хотите поиграть с примерами из этой статьи, блокнот Jupyter находится на GitHub. Вы также можете запустить его в среде interactive binder в браузере. Более подробную информацию можно найти в блоге Тала Галили и оригинальных статьях Матиаса Шонлау.

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

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

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

Перевод Визуализация и анализ белков в Biopython

10.03.2021 22:06:24 | Автор: admin

Биология человека невероятно сложная наука. Даже учитывая, что с каждым годом мы открываем всё больше секретов человеческого тела, получаемые нами ответы порождают всё большее количество вопросов. Завершение проекта "Геном человека" придало многим учёным уверенность в том, что с помощью геномики человечество сможет решить важные биологические проблемы. Однако, чем больше биологических тайн мы раскрываем, тем более отчётливо понимаем, что на использование генома организма влияют другие факторы. Соответственно, для решения задач в этих взаимосвязанных областях, в том числе транскриптомике (изучение мРНК) и протеомике (изучение белков) были созданы новые направления научных исследований, в которых начали использовать Python.

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


Проект Biopython набор инструментов Python для вычислительной биологии и биоинформатики используется для визуализации и анализа последовательностей ДНК и РНК. С помощью набора инструментов Biopython также можно выполнять анализ белковых структур! Познакомимся с ним более подробно.

Банк белковых структур (PDB) единая база данных для изучения и загрузки последовательностей белка. Для работы с PDB был создан специальный файловый формат, естественно, получивший название .pdb. Но по мере того как учёным приходилось анализировать более крупные и сложные белковые структуры, были разработаны другие форматы - CIF и mmCIF. Файл кристаллографической информации CIF (Crystallographic Information File) был разработан для архивирования данных кристаллографического исследования малых молекул. В рамках таких исследований изучается расположение атомов в кристаллических твердых телах. Со временем формат CIF стал использоваться для анализа более крупных молекул (макромолекул, отсюда обозначение mm), получил название mmCIF и в итоге заместил формат PDB. [1]

Визуализация данных с помощью формата PDB

Несмотря на то что в настоящее время общепринятым стандартом является формат mmCIF, многие системы по-прежнему поддерживают файлы старого формата PDB.

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

Импортируйте необходимые пакеты:

from Bio.PDB import *import nglview as nvimport ipywidgets

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

pdb_parser = PDBParser()structure = pdb_parser.get_structure("PHA-L", "Data/1FAT.pdb")view = nv.show_biopython(structure)

Визуализация данных с помощью формата CIF

Процедура для файлов CIF практически такая же, за тем исключением, что нужно использовать экземпляр MMCIF Parser! Здесь мы визуализируем более крупную белковую структуру 6EBK, или канал paddle chimera Kv1.2-2.1 в липидных нанодисках (даже произносить трудно).

cif_parser = MMCIFParser()structure = cif_parser.get_structure("6EBK", "fa/6ebk.cif")view = nv.show_biopython(structure)

Доступ к информации о белковой структуре

Заголовок

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

mmcif_dict = MMCIFDict.MMCIFDict("fa/1fat.cif")len(mmcif_dict) # 689

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

Последовательности остатков

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

Объект Structure в нашем файле построен в архитектуре SMCRA (СМЦОА) в соответствии со схемой родитель дочерний элемент:

  • Структура состоит из моделей.

  • Модель состоит из цепочек.

  • Цепочка состоит из остатков (аминокислот).

  • Остаток состоит из Атомов.

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

# .get_residues() method in a loopfor model in structure:    for residue in model.get_residues():        print(residue)# .get_residues() method as generator objectresidues = structure.get_residues() # returns a generator object[item for item in residues]# .unfold_entities - keyword for each level of the SMCRA structureSelection.unfold_entities(structure, "R") # R is for residues

Создание полипептидов

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

polypeptide_builder = CaPPBuilder()counter = 1for polypeptide in polypeptide_builder.build_peptides(structure):    seq = polypeptide.get_sequence()    print(f"Sequence: {counter}, Length: {len(seq)}")    print(seq)    counter += 1# Sequence: 1, Length: 36# SNDIYFNFQRFNETNLILQRDASVSSSGQLRLTNLN# Sequence: 2, Length: 196# NGEPRVGSLGRAFYSAPIQIWDNTTGTVASFATSFT...ASKLS# Sequence: 3, Length: 233# SNDIYFNFQRFNETNLILQRDASVSSSGQLRLTNLN...ASKLS# Sequence: 4, Length: 36# SNDIYFNFQRFNETNLILQRDASVSSSGQLRLTNLN# Sequence: 5, Length: 196# NGEPRVGSLGRAFYSAPIQIWDNTTGTVASFATSFT...ASKLS# Sequence: 6, Length: 35# SNDIYFNFQRFNETNLILQRDASVSSSGQLRLTNL# Sequence: 7, Length: 196# NGEPRVGSLGRAFYSAPIQIWDNTTGTVASFATSFT...ASKLS

Анализ последовательностей остатков

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

from Bio.SeqUtils.ProtParam import ProteinAnalysis

Единственное предостережение: вызов процедуры .get_sequences() возвращает объект Biopython Seq(), см. предыдущую запись в моем блоге, где приведено более подробное описание объектов Seq() и их функциональности ProteinAnalysis требует строкового значения.

analyzed_seq = ProteinAnalysis(str(seq))

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

Молекулярный вес

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

analyzed_seq.molecular_weight()# 4176.51669

GRAVY

Белок GRAVY возвращает значение GRAVY (общее среднее значение гидропатии) для введённых белковых последовательностей. Значение GRAVY вычисляется путём сложения значения гидропатии для каждого остатка и деления на длину последовательности (Kyte и Doolittle; 1982). [2]

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

analyzed_seq.gravy()# -0.5611

Подсчёт количества аминокислот

Количество аминокислот каждого типа можно легко подсчитать.

analyzed_seq.count_amino_acids()# {'A': 1, 'C': 0, 'D': 2, 'E': 1, 'F': 3, 'G': 1, 'H': 0, 'I': 2, 'K': 0, 'L': 5, 'M': 0, 'N': 6, 'P': 0, 'Q': 3, 'R': 3, 'S': 5, 'T': 2, 'V': 1, 'W': 0, 'Y': 1}

Процент аминокислот

А также процентную долю каждой аминокислоты в последовательности!вставка с кодом

Вторичная структура

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

analyzed_seq.secondary_structure_fraction() # helix, turn, sheet# (0.3333333333333333, 0.3333333333333333, 0.19444444444444445)

Протеиновые весы

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

from Bio.SeqUtils.ProtParam import ProtParamData

Вот некоторые распространённые весы:

Документацию по некоторым распространённым весам можно найти здесь.

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

kd = {"A": 1.8, "R": -4.5, "N": -3.5, "D": -3.5, "C": 2.5,       "Q": -3.5, "E": -3.5, "G": -0.4, "H": -3.2, "I": 4.5,       "L": 3.8, "K": -3.9, "M": 1.9, "F": 2.8, "P": -1.6,       "S": -0.8, "T": -0.7, "W": -0.9, "Y": -1.3, "V": 4.2}

Положительные значения означают гидрофобность. Изолейцин (I) и валин (V) наиболее гидрофобны, а аргинин (R) и лизин (K) наиболее гидрофильны. Гидрофобные остатки, как правило, находятся внутри полипептида, а гидрофильные остатки за его пределами, поэтому эти весы также дают представление о том, как может складываться такой полипептид.

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

analysed_seq.protein_scale(window=7, param_dict=ProtParamData.kd)# [-0.7571428571428572, -0.2428571428571429, -0.24285714285714288, -0.38571428571428573, -0.6285714285714287, -0.942857142857143, -1.842857142857143, -1.442857142857143, -2.3428571428571425, -1.3000000000000003, -0.01428571428571433, 0.1285714285714285, 0.1285714285714285, -0.014285714285714235, -0.4142857142857143, 0.3428571428571428, -0.31428571428571417, -0.35714285714285715, -1.014285714285714, -0.6285714285714284, -0.10000000000000002, 0.3428571428571429, -0.4142857142857142, 0.24285714285714285, -1.0, -0.34285714285714286, -0.32857142857142857, -0.7142857142857143, -0.1142857142857144, -0.11428571428571435]

Попробуем вместе

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

# Create empty list for chainsall_seqs = []counter = 1# For each polypeptide in the structure, run protein analysis methods and store in dictfor pp in ppb.build_peptides(structure):    seq_info = {} # create an empty dict    seq = pp.get_sequence() # get the sequence like above    analyzed_seq = ProteinAnalysis(str(seq)) # needs to be a str     # Specify dict keys and values        seq_info['Sequence Number'] = counter # set sequence id    seq_info['Sequence'] = seq # store BioPython Seq() object    seq_info['Sequence Length'] = len(seq) # length of seq    seq_info['Molecular Weight'] = analyzed_seq.molecular_weight()    seq_info['GRAVY'] = analyzed_seq.gravy() # hydrophobicity     seq_info['AA Count'] = analyzed_seq.count_amino_acids()     seq_info['AA Percent'] = analyzed_seq.get_amino_acids_percent()    # tuple of (helix, turn, sheet)    seq_info['Secondary Structure'] = \        analyzed_seq.secondary_structure_fraction()        # Update all_seqs list and increase counter    all_seqs.append(seq_info)    counter += 1

Выбор первой последовательности возвращает словарь с нашими анализами и значениями!

all_seqs[0] # select the first sequence# {'Sequence Number': 1, 'Sequence': Seq('SNDIYFNFQRFNETNLILQRDASVSSSGQLRLTNLN'), 'Sequence Length': 36, 'Molecular Weight': 4176.52, 'GRAVY': -0.5611, 'Amino Acid Count': {'A': 1,  'C': 0,  'D': 2,  'E': 1,  'F': 3,  'G': 1,  'H': 0,  'I': 2,  'K': 0,  'L': 5,  'M': 0,  'N': 6,  'P': 0,  'Q': 3,  'R': 3,  'S': 5,  'T': 2,  'V': 1,  'W': 0,  'Y': 1}, 'Amino Acid Percent': {'A': 0.027777777777777776,  'C': 0.0,  'D': 0.05555555555555555,  'E': 0.027777777777777776,  'F': 0.08333333333333333,  'G': 0.027777777777777776,  'H': 0.0,  'I': 0.05555555555555555,  'K': 0.0,  'L': 0.1388888888888889,  'M': 0.0,  'N': 0.16666666666666666,  'P': 0.0,  'Q': 0.08333333333333333,  'R': 0.08333333333333333,  'S': 0.1388888888888889,  'T': 0.05555555555555555,  'V': 0.027777777777777776,  'W': 0.0,  'Y': 0.027777777777777776}, 'Secondary Structure': (0.3333333333333333,  0.3333333333333333,  0.19444444444444445)}

Можно легко выбирать конкретные значения.

all_seqs[0]['Sequence']# Seq('SNDIYFNFQRFNETNLILQRDASVSSSGQLRLTNLN')all_seqs[0]['Molecular Weight']# 4176.52

Заключение

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

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

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

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

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

Главная причина дискриминации в ML

12.04.2021 22:14:50 | Автор: admin

Из предыдущего поста вы узнали, что в ML существует дискриминация. Отлично! Таким образом вы уже разбираетесь в Этике машинного обучения лучше, чем многие инженеры МL. Благодаря примерам (из медицины, анализа твиттов, распознавания лиц) вы наверняка уже сделали вывод, что существуют разные виды предвзятости.

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

Три кита дискриминации

Есть три характеристики людей, на которых основываются большинство предвзятостей в real-world алгоритмах:

  • Гендер

  • Раса

  • Возраст

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

Одним словом: практически всё, к чему обычный человек может проявить дискриминацию. Эти характеристики называют чувствительными атрибутами (sensitive attributes) особенности, по отношению которых проявляется дискриминация.

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

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

"Man is to Computer Programmer as a Woman is to Homemaker"Здесь вы можете увидеть распределение уже "справедливых" word-embeddings: сверху гендерно-нейтральные слова, снизу специальные для каждого гендера. "Man is to Computer Programmer as a Woman is to Homemaker"Здесь вы можете увидеть распределение уже "справедливых" word-embeddings: сверху гендерно-нейтральные слова, снизу специальные для каждого гендера.

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

Примеры дискриминации по половому признаку из алгоритмов машинного обучения:

  1. Word embeddings, полученные из статьей с Google News (где материал довольно строго курируется), отражают большое количество гендерных стереотипов (Man is to Computer Programmer as Woman is to Homemaker)

  2. Точность алгоритмов распознавания лица IBMs и Face++ значительно ниже для женщин по сравнению с мужчинами (Gender Shades)

  3. Некоторые алгоритмы допускают серьёзные погрешности во время перевода женского голоса в текст ( Where is Female Synthetic Speech).

Предвзятость, связанная с расой, очень удручает многих специалистов в области технологий. Пару лет назад некоторые американские клиники предоставляли темнокожим пациентам почти в два раза меньше средств для специальной медицинской помощи. Используемый алгоритм предсказывал, что темнокожие меньше нуждались в особом наблюдении (https://science.sciencemag.org/content/366/6464/447.abstract) Другой алгоритм, COMPAS, который использовали в американских судах, выдавал в два раза больше ложноположительных (false positive) прогнозов о рецидивизме по отношению к темнокожим, нежели к светлокожим. (https://www.propublica.org/article/how-we-analyzed-the-compas-recidivism-algorithm) Есть еще масса примеров biasа, который основывается на расе.

Так почему это происходит?

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

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

Поэтому возникает вопрос: так разве можно утверждать, что результаты, полученные с помощью такого (объективного) подхода, несправедливы?

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

Подробнее..

Инструменты для алготрейдинга на Python. Расчет дневного изменения цены

27.05.2021 16:21:56 | Автор: admin

Привет, Хабр! Сегодня я хочу начать свой цикл статей по алготрейдингу.

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

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

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

Перейдем к практике:

Для проведения расчетов нам понадобится:

  1. Данные об изменениях цен (вполне сойдет API Мосбиржи)

  2. Знание Python и его библиотек Pandas и Matplotlib

  3. Трейдерская чуйка (уверен, если вы читаете эту статью, то она у вас есть)

Весь код я приведу в ноутбуке на google colab

Далее я буду рассказывать о дневном изменении стоимости ценных бумаг за период с 1 января 2021г. по 25 мая 2021г.

Для примера, возьмем акции компании Лукойл (тикер LKOH). Для них распределение дневного изменения цены выглядит следующим образом:

Для акций Лукойла за период с 1 января 2021 года по 25 мая 2021 года мы имеем медиану, равную 0,26%. Это означает, что если завтра не предвидится никаких хороших или плохих новостей, то мы можем ожидать рост стоимости акций на 0,26%

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

ticker

median

q005

q05

q25

q75

q95

q995

LKOH

0.0026

-0.036

-0.026

-0.01

0.011

0.032

0.035

Рассчитав квантили q25 и q75 мы видим, что 50% всех значений дневного изменения цены лежат в диапазоне [-1%; 1,1%]. Т.е., согласно статистике, в 5 из 10 торговых сессиях, цена акции Лукойла упадет не более чем на -1% или вырастет не более чем на 1,1%.

Рассчитав квантили q005 и q995 мы видим, что 99% всех значений дневного изменения цены лежат в диапазоне [-3,6%; 3,5%]. Т.е., согласно статистике, почти во всех торговых сессиях, цена акции Лукойла упадет не более чем на -3,6% или вырастет не более чем на 3,5%.

Рассчитав квантили q05 и q95 мы видим, что 90% всех значений дневного изменения цены лежат в диапазоне [-2,6%; 3,2%]. Т.е., согласно статистике, в 9 из 10 торговых сессиях, цена акции Лукойла упадет не более чем на -2,6% или вырастет не более чем на 3,2%.

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

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

month

ticker

median

q005

q05

q25

q75

q95

q995

2021-01-01

LKOH

0.0032

-0.022

-0.029

-0.007

0.011

0.033

0.032

2021-02-01

LKOH

0.0041

-0.027

-0.028

-0.010

0.014

0.027

0.027

2021-03-01

LKOH

0.0029

-0.028

-0.027

-0.006

0.014

0.034

0.035

2021-04-01

LKOH

-0.0005

-0.019

-0.019

-0.011

0.005

0.015

0.015

2021-05-01

LKOH

0.0023

-0.022

-0.024

-0.013

0.016

0.027

0.022

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

В следующей статье расскажу про индикатор "Полосы Боллинджера".

Подробнее..

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Подробнее..

Как я предсказал LGD на хакатоне и устроился на работу

11.06.2021 14:22:51 | Автор: admin

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

Вступление прошлая жизнь ипервые шаги вData Science

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

Впериод начала пандемии уменя освободилось время засчет отсутствия поездок доофиса, которое удалось использовать для изучения основ языка Python. Постигать азы начал спрочтения первого тома Лутца Изучаем Python. Летом 2020я попрощался сработой, чтобы перезарядить батарейки иуйти вперестройку. Выбрал онлайн курс поData Science иначал учиться.

Для себя ясформулировал, что хочу работать вкрупной компании, чтобы быть частью большого сообщества после учебы поставил себе цель найти подходящую позицию вСбере. Яотслеживал информацию оконференциях имероприятиях, вкоторых компания участвует. Благодаря странице https://ict2go.ru/companies/19/, яузнал, что Сбер участвует вконференции ScoringDay Весна 2021 икэтой конференции приурочен хакатон наплощадке dsbattle.com под названием LGD Prediction. Призеры соревнования (топ-3) получают бесплатный билет наконференцию ивозможность присоединиться ккоманде блока Риски. Нучтож, вызов принят!

Тяжело вучении, легко вбою!

0. Дрожащими руками, терзаемый сомнениями смогули я?, открыл ссылку сbaseline-решением наколабе. Посмотрел. Смогу. Визуальное знакомство сданными показало, что вцелом такие задачки решать яумею. Обычные табличные данные, задача регрессии, призовем CatBoost. Отмечу, что натот момент опыта участия всоревнованиях, кроме как вТитанике наKaggle, уменя небыло.

Ниже разберу основные шаги решения, которые позволили занять заветную вторую строчку иотправиться вМоскву наконференцию. Также прикладываю ссылку наgithub иcolab.

Целью задания было построить модель машинного обучения, предсказывающую LGD (Loss Given Default), другими словами, тудолю отвыданного кредита, которую банк потеряет вслучае дефолта заемщика. Для оценки качества модели использовалась метрика MAE mean absolute error, средний модуль отклонений.

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

1. После знакомства сдатасетом яразбил 35признаков для обучения на2группы: первая группа 24признака это финансовые показатели (выручка, чистая прибыль, совокупные активы ит.п.), вторая группа 11признаков различные прочие характеристики предприятия (срок ведения бизнеса, величина уставного капитала, объект взалоге).

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

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

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

Кроме того, япроверял данные надубликаты построкам (ихнебыло) ипостолбцам (были).

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

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

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

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

Заметно, что средний имедианный LGD укомпаний сфинансовыми данными существенно ниже, чем уоставшихся компаний.

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

Все пропуски вфинансовых данных язаполнил нулями.

Затем обратился кисследованию признаков выручка ивеличина уставного капитала. Пообоим столбцам япопытался выделить крупные компании вотдельную категорию. Исследовав медиану исредние при различных вариантах, остановился награнице в50млн руб. для выручки (больше категория corporation) и100тыс. руб. для уставного капитала (больше категория big).

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

Далее ярешил построить pairplot для признаков, которые есть увсех объектов это срок ведения бизнеса, срок смомента регистрации ОГРН, сгруппировав объекты покатегории залога.

Этот график позволил сделать следующие выводы:

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

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

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

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

Получилось 100 таких компаний вобучающей выборке.

3. Потом ярешил посоздавать количественные признаки наоснове данных финансовой отчетности. Нопоскольку таких объектов было меньшинство исами финансовые данные были зашумлены (совокупные активы небыли равны совокупным обязательствам икапиталу, например), результативность таких действий была низкой. Однако мне удалось выделить два признака, повысивших качество модели.

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

Так моя обучающая выборка содержала всего 9признаков: 4количественных и5категориальных. Ярешил использовать признак выручка (ar_revenue), так как онвзначительной степени характеризует величину компании иявляется определяющим для получения денежных потоков.

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

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

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

Заметно, что самые серьезные ошибки возникали тогда, когда модель выдавала LGD = 1, когда это небыло нужно, инепредсказывала0, когда это было нужно.

Затем ясделал предсказания для тестовой выборки, исистема показала, что ихкачество около 0.087: налицо было переобучение, нопоиграв сколичеством итераций вCatBoost ирегуляризацией, ядобился лишь небольшого улучшения 0.086. Так или иначе, оценка качества модели, сделанной пометоду берем только необходимое, оказалась выше, чем модель отбрасываем ненужное.

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

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

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

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

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

Большой итог

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

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

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

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

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

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

  4. Лучше мало хороших признаков, чем много плохих.

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

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

Спасибо, что дочитали доконца! Буду рад выслушать конструктивную критику решения иответить навопросы!

Подробнее..

Винный гид России. Аналитика

11.03.2021 20:12:02 | Автор: admin

Эта статья, как ни странно, про российское вино.

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

Месяц назад Роскачество презентовало очередной выпуск ежегодника "Винный гид России". Он посвящен (внезапно!) российским винам. Но не всем, а лишь находящимся в ценовом сегменте до 1000 рублей и широко представленным в обычных продуктовых сетях. В общем, винные снобы могут сразу пройти мимо, речь пойдет о самом что ни на есть масс-маркете.

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

1. Какова картина в целом? Большинство вин откровенно плохи? Или наоборот прекрасны?

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

3. Как цена влияет на качество? Есть ли разница между вином за 150 рублей и за 500? А за 500 vs 1000?

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

Так что все те, кому интересен мир российского вина, и кто не воротит нос при фразе "вино дешевле 1000 за бутылку", добро пожаловать под кат!

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

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

Оглавление

Пара слов о методологиях

Общая картина

Рейтинг виноделен

Как влияет цена на оценку?

Итоги

Пара слов о методологиях.Ю

Предупреждение о рекламе (её отсутствии)

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

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

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

дегустация была слепой, вино оценивалось до 100-балльной шкале (не Паркера, но похожей). Чем выше балл, тем лучше: 81 балл и больше очень хорошо, 71 и меньше очень плохо. Всё вино российское, из масс-маркета, ценник <=1000 рублей. Исследовались: тихие красные, белые, розовые; игристые, ликерные.

Методология исследования Роскачества (краткое изложение)

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

Всего 5 категорий: тихие красные, тихие белые, тихие розовые; игристые, ликерные.

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

После закупки проводилась слепая дегустация от группы экспертов, на основе которой выставлялась оценка по 100-балльной шкале. Нет, это не шкала Паркера, как можно было бы подумать, а шкала из ГОСТ32051-2013 Продукция винодельческая. Методы органолептического анализа. И трактовка у нее (по версии Роскачества) тоже своя:

  • менее 71 балла вина с явными недостатками;

  • менее 78 простые "плоские" вина без явных недостатков;

  • менее 81 нормальные вина "на каждый день";

  • 81 и выше хорошее вино, на которое стоит обратить внимание

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

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

Все данные были взяты мною с сайта Роскачества, никак не изменялись и не модифицировались. Исключение названия брендов, они были приведены к единообразию (удалил разные варианты названий одного и того же бренда: например, "ZB" и "Золотая балка" стали просто "ZB" и т.д.). Гид доступен за три года 2018-2020, я брал данные всех трех лет, поскольку вина в разных годах не повторяются.

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

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

Напоследок стандартное для моих статей примечание:

Стандартное примечание

Здесь и далее речь идет лишь о данных, указанных в "Винном гиде России". Выборка не является репрезентативной для всех вин России и тем более других стран. Приведенные оценки вин не являются истиной в последней инстанции. На другом конкурсе 70-балльное вино из Гида может получить под 100 очков, а конкретно вам не понравиться настолько, что вы его выльете в раковину. Это нормально.

Для удобства я буду говорить вина в среднем стоят N рублей и получают R баллов. Но в действительности это означает: вина, включенные в Винный гид России, в среднем по информации из Винного гида России стоят N рублей и получают по оценке экспертов Винного гида России R баллов

Общая картина

Для начала посмотрим, какие вообще вина участвовали в исследовании:

Распределение вин по типу и уровню сахараРаспределение вин по типу и уровню сахара

Больше всего, как и ожидалось, красных, белых и игристых (суммарно почти тысяча образцов). Откровенно сладких среди них почти не встречается, а вот полусладких еще достаточно. Особенно среди игристых (традиционно для российского рынка). Тем не менее, две трети белых/розовых и 80% красных вина сухие, что не может не радовать.

Про сахар

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

Какие же оценки ставились этим винам?

Распределение оценок вин по типам. Линии нижняя граница уровней вин согласно классификации РоскачестваРаспределение оценок вин по типам. Линии нижняя граница уровней вин согласно классификации Роскачества

Ликерные в среднем получают оценки чуть выше (вероятно, связано с многолетним опытом виноделов в этой сфере Солнечная долина, Массандра занимаются креплёными винами с позапрошлого века). У остальных все четко: 1-2 квартили простые вина, 2-3 повседневные, 4 хорошие. Согласно трактовке оценок от Роскачества, конечно же.

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

Может, оценки ГОСТа настолько жесткие, что 90 это уже великое вино, а всё что выше недостижимые высоты, вин для которых еще не создали? Но на самом деле, согласно самому ГОСТу (а не Роскачеству) градация оценок следующая:

  • 71 и выше хорошо

  • 86 и выше очень хорошо

  • 100 превосходно (я не понял, зачем делать целый уровень под одну оценку, ну да ладно).

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

Тогда, может, вина у нас в исследовании больно дешевые, а потому посредственные, вот и не смог ни один образец из 1000 дойти даже до 90 баллов?

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

Распределение цены за 0.75л (руб.)Распределение цены за 0.75л (руб.)

Но вот, например, трехсотрублевый брют от Фанагории получает 90 баллов на авторитетном Decanter World Wine Awards (к вопросу о том, что недорогие вина не бывают хорошими). А в нашем рейтинге он получает всего 80.73! Почти 10 баллов разницы! И если посмотреть результаты конкурса, можно найти и кучу других примеров недорогих российских вин с высокими оценками (например, Саперави от Шато Тамань за те же 300рэ с теми же 90 баллов).

Итак, у меня нет ответа на вопрос, почему оценки Гида настолько консервативны. Лишь гипотезы:

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

  • недорогие вина в большинстве своем очень средние и ожидаемо не дотягивают до уровня "очень хорошо". На международные конкурсы при этом посылается какое-то особое вино, которое берет медали. В эту гипотезу верится слабо: уж из 1000 образцов хоть парочка, да должна быть за 90, а про "подложные вина" и вовсе похоже на теорию заговора;

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

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

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

Рейтинг виноделен

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

Белое вино

В топе не нуждающиеся в особенном представлении "зубры" с юга материковой России Мысхако, многострадальная Юбилейная (надеюсь, недавнее вхождение в концерн Абрау даст ей новую жизнь), Фанагория и Шато Тамань. Выделяется Поместье Голубицкое, ибо по объемам производства оно сильно уступает вышеозвученным конкурентам. Первая крымская винодельня встречается на 6 месте и замыкает число тех, кто перевалил за 80 баллов. Причем, обратите внимание, какой высокий относительно остальных у Alma Valley разброс оценок. Связано это с их заигрываниями с полусладкими и сладкими винами, которые и "тянут вниз" в плане оценок (зато, уверен, "тянут вверх" в плане выручки). Поэтому на второй вкладке я отдельно составил рейтинг без учета сладких и полусладких вин, так сравнение будет более честным. Альма сразу же и поднимается повыше, и СКО уменьшает.

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

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

Красное

Знакомые всё лица! На этот раз в топе еще одни крымчане Esse, а также Усадьба Мысхако. Её не стоит принимать за обычное "Мысхако". "Усадьба..." старое название новой гравитационной винодельни Chateau Pinot. Я был у них недавно на экскурсии (остался очень доволен увиденным), и именно поэтому знаю об этих перипетиях с названиями, иначе точно запутался бы.

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

Alma valley. Фото из недавней поездкиAlma valley. Фото из недавней поездки

Розовое вино

Розовых вин мало, поэтому разбивать на отдельные вкладки не буду. Комментировать тоже не буду.

Игристые

Без сюрпризов, в топе Шато Тамань, знаменитое Абрау-Дюрсо, Фанагория. Новое лицо Aristov (на самом деле это подбренд Кубань-вино, но объединять их я посчитал неправильным). Крымчане Инкерман и Золотая Балка замыкают ТОП "восьмидесятников" наравне с Мысхако.

Ликерные

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

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

Итого

Если вам лень запоминать какая винодельня в каком вине хороша, то абсолютными чемпионами во всех основных категориях (красное, белое, игристое) являются идущие ноздря-в-ноздрю Фанагория, Мысхако и Шато Тамань:

.

Зависимость оценки от цены

Зависит ли оценка от цены за бутылку? Линейная регрессия говорит нам, что очень слабо:

У розового и ликерного коэффициенты и вовсе не значимы, у других вин хоть и значимы, но R-squared нигде не поднимается выше 0.1

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

Более того, в принципе нельзя ожидать связи "вино в 7 раз дороже значит будет в 7 раз лучше". Минимальная граница не дефектного вина по ГОСТу 56 баллов. А максимально можно набрать не более 100. Получается, что наибольшая разница в оценке, которую мы можем зафиксировать между минимально приемлемым и великим вином 2 раза. При том, что цена на них может отличаться на порядки.

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

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

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

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

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

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

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

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

Различия стат значимы (t-test, MW, p_value<0.01; правда, для белых вин t-тест выдал p_value=0.03, но не будем придираться).

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

Итоги

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

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

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

Если же говорить об утилитарных целях исследования, то абсолютными лидерами в общем зачете стали такие винодельни как Фанагория, Мысхако и Chateau Tamagne. Что не исключает лидерства других производителей в отдельных категориях Голубицкое, Альма, Абрау-Дюрсо и др.

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

Так что идеальный выбор вина на основании представленных данных бутылка сухого от Фанагории за 500 рублей. Шучу, конечно. Идеальный выбор у каждого свой.

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

Спасибо за внимание. Пейте российское любое хорошее вино и помните: in vino veritas, in aqua sanitas!

Подробнее..

Бесплатный удобный ETL инструмент с открытым кодом на основе Python фантастика или нет?

04.03.2021 12:16:30 | Автор: admin

Мы давно ищем идеальный ETL инструмент для наших проектов. Ни один из существующих инструментов нас полностью не удовлетворял, и мы попробовали собрать из open-source компонентов идеальный инструмент для извлечения и обработки данных. Кажется, у нас это получилось! По крайней мере, уже многие аналитики попробовали эту технологию и отзываются очень позитивно. Сборку мы назвали ViXtract и опубликовали на GitHub под BSD лицензией. Под катом рассуждения о том, каким должен быть идеальный ETL, рассказ о том, почему его лучше делать на Python (и почему это совсем не сложно) и примеры решения реальных задач на ViXtract. Приглашаю всех заинтересованных к дискуссии, обсуждению, использованию и развитию нового решения для старых проблем!

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

80% времени аналитика уходит на преобразование, очистку, выгрузку и сверку данных80% времени аналитика уходит на преобразование, очистку, выгрузку и сверку данных

Мы в Visiology в основном работаем с крупными предприятиями, промышленностью и госорганизациями, но в разговорах с коллегами я убедился, что проблемы везде одни и те же. Аналитики могут уделить анализу и визуализации только 20% своего времени, потому что 80% уходит на преобразование, очистку, выгрузку и сверку данных. Чтобы эффективно решать эту проблему, мы постоянно ищем новые методы и инструменты работы с данными, тестируем, пробуем на реальных задачах. Что же мы называем идеальным ETL инструментом?

Итак, вот 5 основных критериев, которым должен соответствовать идеальный ETL (Extract-Transform-Load) инструмент:

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

  2. В нём должно быть предусмотрено максимальное количество готовых коннекторов. Ведь в сущности, мы все пользуемся плюс-минус одними и теми же системами: от 1С до SAP, Oracle, AmoCRM, Google Analytics. И никто не хочет программировать коннекторы к ним с нуля.

  3. Инструмент должен быть универсальным и работать с разными BI системами. Это облегчает переход аналитиков и разработчиков из одной компании в другую если на прошлом месте работы, например, использовали QlikView, а на новом Visiology, желательно сохранить возможность пользоваться тем же ETL-инструментом.

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

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

Что может предложить нам рынок?

В поиске ответа на этот вопрос для себя самих и для наших клиентов. мы отметили на диаграмме наиболее известные решения, подходящие для этой задачи. Они расположены от бесплатных к дорогим, от простых до корпоративных систем Enterprise-класса.

В категории наиболее сложных и дорогих систем доминируют Oracle и Informatica. Microsoft SSIS чуть более демократичный. Рядом с ними Apache Airflow. Это открытый продукт, не требующий оплаты, но зато кривая входа для него оказывается довольно крутой. Кроме этого существуют ETL-инструменты, встроенные или связанные с конкретными BI-системами. В их число входят, например, Tableau Prep или Power Query, который используется совместно с Power BI. В числе бесплатных и демократичных решений Pentaho Data Integration, бывший Kettle, и Loginom.

Но, увы, ни одна из этих систем не удовлетворяет перечисленным 5 критериям. Oracle и Informatica оказываются слишком дорогими и сложными. С Airflow не так уж просто сразу начать работать. EasyMorph не дотягивает по функциональности, а все инструменты, оказавшиеся в центре нашей диаграммы, прекрасно работают, но не являются универсальными. Фактически, я называл бы достаточно сбалансированными решениями Loginom и Pentaho, но тут возникает ещё один важный момент, о котором обязательно нужно поговорить.

Визуальный или скриптовый ETL?

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

Выбор между визуальным и скриптовым ETL это настоящий холивар, достойный противостояния Android vs iOS. Лично я отношусь к той категории, которая считает, что за скриптовыми ETL будущее. Конечно, визуальный ETL имеет свои преимущества это наглядность и простота, но только на первом этапе. Как только возникает потребность сделать что-то сложное, картинки становятся слишком запутанными, и мы все равно начинаем писать код. А поскольку в визуальных ETL нет отладчиков и других полезных примочек для кодинга, делать это приходится в откровенно неудобных условиях.

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

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

Скриптовый - значит, должен быть основан на Python!

Если мы хотим, чтобы ETL был открытым, бесплатным и уже с экосистемой, значит инструмент должен быть на Python. Почему? Потому что, во-первых, Python это простой язык, сейчас даже дети учатся программировать на Python чуть ли ни с первого класса. Например, в Алгоритмике начинают курс программирования именно с Python, а не с Basic или визуального языка Google. Так что подрастающее поколение разработчиков уже знакомо с ним. Во-вторых,огромная экосистема готовых технологий и библиотек уже создана: от каких-то банальных коннекторов до очень серьёзных вещей, связанных с Data Science и так далее. Можно начинать развиваться в этом направлении: здесь ограничений никаких нет.

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

Решение = JupyterHub + PETL + Cronicle

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

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

  2. Библиотека PETL была разработана на Python специально для обработки данных. Она берёт на себя огромное количество рутинных задач, например, разбор CSV файлов различных форматов или создание схемы в БД при выгрузке данных.

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

Чтобы всем этим было проще пользоваться, мы объединили три инструмента в ViXtract. Речь идет о сборке набора open-source технологий, которая позволяет легко установить решение одной командой и использовать ETL, не заморачиваясь по поводу Linux, по поводу прав, нюансов интеграций и других тонкостей.

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

И еще несколько слов о самой оболочке

Давайте посмотрим на интерфейс нашего инструмента. На стартовой странице находятся кнопки запуска редактора, планировщика и переходы на полезные ресурсы сайт, telegram-канал, сообщество и библиотека PETL. Это документация, в которой описаны все функции преобразования, загрузки файлов. Когда вы начинаете работать с ViXtract, эту страницу логично держать всё время под рукой. Сейчас документация на английском, но одно из направлений развития это перевод всего набора информации на русский язык.

В ViXtract имеется сразу несколько ядер (aka настроенных окружений). Например, одно из них можно использовать для разработки, а другое для продуктива. Таким образом, вы можете установить много различных библиотек в одном окружении, а для продуктива оставить только проверенные. Окружения можно легко добавлять и изменять, а если вам интересно узнать о самом процессе работы с данными через ViXTract, вы всегда можете задать вопрос в Telegram сообществе ViXtract.

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

Загрузка данных

PETLподдерживает множество источников данных, мы рассмотрим несколько типовых примеров. Эти же примеры доступны в виде готовых тетрадок на GitHub или в установленном ViXtract, там их можно попробовать.

  • Загрузка из xlsx-файла

  • Использование открытых источников через API

  • Работа с базой данных

Данные из xlsx-файла

Рассмотрим работу сpetlна наборе результатов летних олимпиад по странам. Нам понадобится файлdatasets/summer_olympics.xlsx, посмотрим на первые строки, пока не сохраняя таблицу в переменную.

etl.fromxlsx('datasets/summer_olympics.xlsx')

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

olympics = etl.fromxlsx('datasets/summer_olympics.xlsx').skip(1)

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

olympics2 = olympics.setheader(['country','games','gold','silver','bronze'])

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

olympics2 = olympics.setheader(['country','games','gold','silver','bronze']).sort('gold', reverse=True)

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

Мы также применим мощный инструмент Python -Анонимные функции.Анонимная функция(функция без имени) - это запись видаlambda x: <функция от x>. Читается как: "То, что было подано на вход этого выражения, будет положено вx, а результатом исполнения будет<функция от x>. В PETL это часто применяется, чтобы выполнить быстрое преобразования значения какого-либо из полей. Например, если нужно все значения таблицыtableв полеfieldумножить на два, это можно написать какtable.convert('field', lambda x : x * 2). В примере ниже функция применяется не к отдельным значениям, а к строке целиком.

olympics2.addfield('total', lambda row : row['gold'] + row['silver'] + row['bronze'])

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

olympics3 = olympics2\    .addfield('total', lambda x: int(x['gold']) + int(x['silver']) + int(x['bronze']))\    .sort('total', reverse=True)

Видим, что в таблице есть сумма по всем странам, что нас не интересует в данной задаче. Можем выбрать из таблицы все строки, кроме строки со значениемcountry == Totals. Воспользуемся функциейselect.

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

olympics4 = olympics3\    .select(lambda x: x.country != 'Totals')\    .addfield('effectiveness', lambda x: round(x['total'] / float(x['games']), 2))

Сохраним полученные результаты в новый xlsx-файл.

olympics4.toxlsx('olympics.xlsx')

Готово! Теперь обработанный файл можно скачать или загрузить в BI-систему.

Данные из открытого источника рынка акций

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

response = requests.get('https://www.quandl.com/api/v3/datasets/WIKI/AAPL.json?start_date=2017-05-01&end_date=2017-07-01')

Посмотрим, что мы получили в ответ. Мы увидим данные в формате JSON, которые нужно будет промотать до конца

stock_prices_json = response.json()stock_prices_json

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

stock_prices_json['dataset'].keys()

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

  • Транспонируем содержимоеdata, чтобы превратить строки в столбцы

  • Используемcolumn_namesв качестве значения параметраheaderфункцииfromcolumns

stock_prices = etl.fromcolumns(stock_prices_json['dataset']['data']).skip(1)\    .transpose()\    .setheader(stock_prices_json['dataset']['column_names'])

Уберём часть столбцов, все, содержащие'Adj', переведём все значения в числа (где это возможно), вычислим разницу курса на определённую дату.

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

List comprehension- это запись вида(<функция от x> for x in <список> if <условие от x), которая читается как: "Возьми все элементы из<список>, отбери те их них, для которых истинно<условие от x>, выполни над каждым<функция от x>и верни результаты в виде списка. Например, есть массив чиселarrи нужно отобрать из него четные числа и разделить их на 4. Это можно записать как(x/4 for x in arr if x % 2 == 0)

stock_prices2 = stock_prices\    .cutout(*(x for x in stock_prices.fieldnames() if 'Adj' in x))\    .convertnumbers()\    .addfield('Difference', lambda row: round(row.Close - row.Open, 2))stock_prices2

Сохраним полученную табличку в csv-файл.

stock_prices2.tocsv('stock.csv')

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

Данные из БД (PostgreSQL)

В состав ViXtract входит предустановленная СУБД PostgreSQL, её удобно использовать как промежуточное хранилище данных, из которого их уже забирает BI-система. Похожие подходы могут быть использованы и с любой другой СУБД.

Рассмотрим следующий пример.
Доступны данные о состояниях различных типов транспортных средств. В базе есть 2 таблицы:

  • status_tsсодержит информацию о состояниях различных ТС

  • ts_typesсодержит наименования типов ТС

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

  • В данных не должно быть пропусков

  • Время указано в формате datetime

  • Кроме данных по бульдозерам других нет

  • Все состояния, кроме отсутствия данных

  • Для каждого состояния рассчитана продолжительность

statuses = etl.fromdb(connection, 'SELECT * FROM status_ts')ts_types = etl.fromdb(connection, 'SELECT * FROM ts_types')# Вспомогательные функции# Определяем фильтр для исключения строк с пустыми значениямиrow_without_nones = lambda x: all(x[field] != '' for field in statuses.fieldnames())# Перевод отметки времени в формат datetimeto_datetime = lambda x: dt.fromtimestamp(int(x))

Чтобы исключить строки с пропусками, используем функциюselectи определенный выше фильтрrow_without_nones

statuses.select(row_without_nones)

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

statuses.\    convert('Начало', to_datetime).\    convert('Окончание', to_datetime).\    addfield('Продолжительность', lambda x: x['Окончание'] - x['Начало'])

Объединим обе таблицы и выберем данные только по бульдозерам, сразу уберём строки с состоянием "Отсутствие данных".

statuses.\    join(ts_types, lkey='id ТС', rkey='id').\    select(lambda x: 'Бульдозер' in x['Тип ТС'] and x['Состояние'] != 'Отсутствие данных')

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

В дополнение ко всему отсортируем таблицу по времени начала состояний, применивsort.

result = statuses.\    join(ts_types, lkey='id ТС', rkey='id').\    select(lambda x: 'Бульдозер' in x['Тип ТС'] and x['Состояние'] != 'Отсутствие данных').\    select(row_without_nones).\    convert('Начало', to_datetime).\    convert('Окончание', to_datetime).\    addfield('Продолжительность', lambda x: x['Окончание'] - x['Начало']).\    convert('Начало', str).convert('Окончание', str).convert('Продолжительность', str).\    cutout('id ТС').\    sort('Начало')
# Импортируем библиотеку, позволяющую создавать таблицы в БДimport sqlalchemy as db# Подготовим подключение_user = 'demo'_pass = 'demo'_host = 'localhost'_port = 5432target_db = db.create_engine(f"postgres://{_user}:{_pass}@{_host}:{_port}/etl")# Пробуем пересоздать таблицу (удалить и создать заново). Если таблицы нет - просто создаем новую.try:    result.todb(target_db, 'status_cleaned', create=True, drop=True, sample=0)except:    result.todb(target_db, 'status_cleaned', create=True, sample=0)

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

etl.fromdb(connection, 'SELECT * FROM status_cleaned')

Так мы не зря выбрали Python?

Я по-прежнему часто слышу мнение: Python, вся эта экосистема это ужас какой-то, это что-то необъятное!. Но на самом деле для того, чтобы выгружать данные, требуется лишь небольшое подмножество этого Python, примерно такое же, как с любым другим ETL-инструментом. Когда вы разберетесь с теми функциями, которые действительно нужны, появляется возможность развиваться дальше, переходить к обработке больших данных, потому что все стеки Big Data уже имеют обёртки на Python качественные, нативные и удобные. А те технологии, которые используются в ViXtract, применяются и для обработки больших данных, за исключением, может быть, PETL, который ориентирован на средние объёмы информации.

Кстати, продвинутая аналитика и Data Science тоже строятся на экосистеме Python. И если что-то было предварительно создано на Python, результаты можно легко передать разработчику уже для внедрения в продуктив. Другими словами, проведенная в ViXtract работа на Python может быть дальше использована в AirFlow для развития в Enterprise-системе. Возможно, разработчику нужно будет переписать код в соответствии со стандартами продуктива, но затраты на коммуникации уменьшаются на порядок.

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

Сайт ViXtract, на котором можно посмотреть видео-демонстрацию и попробовать ViXtract без установки на свой сервер - https://vixtract.ru/

Ссылка на GitHub - https://github.com/visiologyofficial/vixtract

Telegram сообщество ViXtract - https://t.me/vixtract_ru

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru