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

Учебный процесс

Перевод Память в JavaScript без утечек

22.06.2020 22:22:51 | Автор: admin
image


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

Вступление


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

Любовный треугольник


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

Это выглядит так:

image

Так что это наш романтический треугольник Процессор -> Шина -> Память

Поддерживать здоровые отношения в трио сложно


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

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

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

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

Таким образом, у ЦП будет меньше недовольства на то, насколько медленная память и, следовательно, у ЦП будет меньше времени простоя.

Ссоры являются частью любых отношений


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

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

image

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

Хорошо, но я JavaScript разработчик, почему меня это должно волновать?


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

Я поверю в это, когда увижу это!!!

Справедливо. Давайте посмотрим на пример.

Вот класс под названием Boom.

class Boom {  constructor(id) {    this.id = id;  }  setPosition(x, y) {    this.x = x;    this.y = y;  }}

Этот класс (Boom) имеет всего 3 свойства id, x и y.

Теперь давайте создадим метод, который заполняет x и y.

Давайте зададим данные:

const ROWS = 1000;const COLS = 1000;const repeats = 100;const arr = new Array(ROWS * COLS).fill(0).map((a, i) => new Boom(i));

Теперь мы будем использовать эти данные в методе:

function localAccess() {  for (let i = 0; i < ROWS; i++) {    for (let j = 0; j < COLS; j++) {      arr[i * ROWS + j].x = 0;    }  }}

Что делает localAccess, так это линейно проходит по массиву и устанавливает x равным 0.

Если мы повторим эту функцию 100 раз (посмотрите на константу repeats), мы можем измерить, сколько времени потребуется для выполнения:

function repeat(cb, type) {  console.log(`%c Started data ${type}`, 'color: red');  const start = performance.now();  for (let i = 0; i < repeats; i++) {    cb();  }  const end = performance.now();  console.log('Finished data locality test run in ', ((end-start) / 1000).toFixed(4), ' seconds');  return end-start;}repeat(localAccess, 'Local');

Вывод журнала:

image

Цена за промах кэша


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

function farAccess() {  for (let i = 0; i < COLS; i++) {    for (let j = 0; j < ROWS; j++) {      arr[j * ROWS + i].x = 0;    }  }}

Здесь происходит то, что на каждой итерации мы обращаемся к индексу, который находится на расстоянии ROWS от последней итерации. Поэтому, если ROWS равен 1000 (как в нашем случае), мы получаем следующую итерацию: [0, 1000, 2000,, 1, 1001, 2001,].

Давайте добавим это в наш тест скорости:

repeat(localAccess, 'Local');setTimeout(() => {  repeat(farAccess, 'Non Local');}, 2000);

И вот конечный результат:

image

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

Так какую цену вы платите? Все зависит от размера ваших данных.

Хорошо, я клянусь, я никогда этого не сделаю!


Возможно, вы об этом не думаете, но есть случаи, когда вы хотите получить доступ к массиву с некоторой логикой, которая не является линейной (например, 1,2,3,4,5) или не является условной (например, for(let i = 0; i <n; i + = 1000)).

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

Вот иллюстрация, которая (надеюсь) прояснит ситуацию:

image

Исходные данные в памяти vs отсортированные данные в памяти. Числа обозначают индексы объектов в исходном массиве.

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

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

О нет! Все потеряно!!!


Нет, не совсем.

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

Мы организуем такие данные:

const diffArr = new Array(ROWS * COLS).fill(0);for (let col = 0; col < COLS; col++) {  for (let row = 0; row < ROWS; row++) {    diffArr[row * ROWS + col] = arr[col * COLS + row];  }}

Так что теперь, в diffArr, объекты, которые находятся в индексах [0,1,2,] в исходном массиве, теперь установлены следующим образом [0,1000,2000,, 1, 1001, 2001,, 2, 1002, 2002, ...]. Цифры обозначают индекс объекта. Это имитирует сортировку массива, что является одним из способов реализации шаблона проектирования Data Locality.

Чтобы легко это проверить, мы немного изменим нашу функцию farAccess, чтобы получить кастомный массив:

function farAccess(array) {  let data = arr;  if (array) {    data = array;  }  for (let i = 0; i < COLS; i++) {    for (let j = 0; j < ROWS; j++) {      data[j * ROWS + i].x = 0;    }  }}

А теперь добавьте сценарий к нашему тесту:

repeat(localAccess, 'Local');setTimeout(() => {  repeat(farAccess, 'Non Local')  setTimeout(() => {    repeat(() => farAccess(diffArr), 'Non Local Sorted')  }, 2000);}, 2000);

Мы запускаем это, и мы получаем:

image

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

Полный пример приведен тут.

Вывод


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

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

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Абстракция ключ к простому коду

29.06.2020 12:20:00 | Автор: admin
image


Есть ли способ улучшить свои навыки в 10 раз? Есть ли какой-то волшебный секрет, который если бы вы только знали это открыл бы для вас совершенно новый мир мастерства и производительности в разработке программного обеспечения?

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

Да! Есть!

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

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

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

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

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

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

Абстракция ключ к простому коду


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

Простота это вычитание очевидного и добавление значимого.
Джон Маэда: The Laws of Simplicity


Абстракция это не улица с односторонним движением. Она сформирована двумя дополнительными понятиями:

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


Рассмотрим следующий код:

const doubleList = list => {  const newList = [];  for (var i = 0; i < list.length; i++) {    newList[i] = list[i] * 2;  }  return newList;};


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

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


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

Если вы трогаете одну вещь с глубоким осознанием, вы касаетесь всего.
Тхих Нхат Хань


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

const doubleList = list => list.map(x => x * 2);


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

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

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

Джереми Ашкенас сделал несколько таких операций популярными в JavaScript и проложил путь для многих великолепных синтаксических ярлыков, которые мы теперь считаем само собой разумеющимся в JavaScript, впервые применив их в CoffeeScript. Он создал Underscore, которая породила Lodash (все еще самый популярный инструмент для функционального программирования в JavaScript) и Backbone, который популяризировал архитектуру MVC в JavaScript и заложил основу для Angular и React.

Джон Резиг сделал jQuery, который был настолько популярным и влиятельным, что он сформировал самую большую коллекцию повторно инкапсулированных модулей JavaScript (плагинов jQuery), пока через несколько лет не появились стандартные модули Node и модули ES6. API селектора jQuery был настолько влиятельным, что стал основой современного API DOM. Я почти ежедневно получаю пользу от этого API, когда я тестирую компоненты React.

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

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

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


Ключ к простоте: секрет, который мы ищем, это как уменьшить объем кода, который мы создаем, как сделать намного больше с гораздо меньшим количеством. Когда вы овладеете этим, вы станете программистом в 10 раз лучше. Я гарантирую это.



image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Учебный проект на Python интерфейс в 40 строк кода (часть 2)

03.07.2020 08:04:12 | Автор: admin
image

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

Streamlit


Streamlit это веб-фреймворк, предназначенный для исследователей данных для простого развертывания моделей и визуализаций с использованием Python. Это быстро и минималистично, а также красиво и удобно. Есть встроенные виджеты для пользовательского ввода, такие как загрузка изображений, ползунки, ввод текста и другие знакомые элементы HTML, такие как флажки и переключатели. Всякий раз, когда пользователь взаимодействует с потоковым приложением, сценарий python перезапускается сверху вниз, что важно учитывать при рассмотрении различных состояний вашего приложения.
Вы можете установить Streamlit с помощью pip:

pip install streamlit


И запустите streamlit в скрипте Python:

streamlit run app.py


Варианты использования


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

Во-первых, давайте создадим пользовательский интерфейс для загрузчика изображений и возможность использовать изображение по умолчанию. Мы можем добавить вывод текста, используя такие функции, как st.write() или st.title(). Мы храним динамически загруженный файл, используя функцию st.file_uploader(). Наконец, st.checkbox() вернет логическое значение в зависимости от того, установил ли пользователь флажок.

import streamlit as stimport cv2import matplotlib.pyplot as pltimport numpy as npimport mazest.title('Maze Solver')uploaded_file = st.file_uploader("Choose an image", ["jpg","jpeg","png"]) #image uploaderst.write('Or')use_default_image = st.checkbox('Use default maze')


Результат:

image

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

if use_default_image:    opencv_image = cv2.imread('maze5.jpg')elif uploaded_file is not None:    file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)    opencv_image = cv2.imdecode(file_bytes, 1)


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

if opencv_image is not None:    st.subheader('Use the sliders on the left to position the start and end points')    start_x = st.sidebar.slider("Start X", value= 24 if use_default_image  else 50, min_value=0, max_value=opencv_image.shape[1], key='sx')    start_y = st.sidebar.slider("Start Y", value= 332 if use_default_image  else 100, min_value=0, max_value=opencv_image.shape[0], key='sy')    finish_x = st.sidebar.slider("Finish X", value= 309 if use_default_image  else 100, min_value=0, max_value=opencv_image.shape[1], key='fx')    finish_y = st.sidebar.slider("Finish Y", value= 330 if use_default_image  else 100, min_value=0, max_value=opencv_image.shape[0], key='fy')    marked_image = opencv_image.copy()    circle_thickness=(marked_image.shape[0]+marked_image.shape[0])//2//100 #circle thickness based on img size    cv2.circle(marked_image, (start_x, start_y), circle_thickness, (0,255,0),-1)    cv2.circle(marked_image, (finish_x, finish_y), circle_thickness, (255,0,0),-1)    st.image(marked_image, channels="RGB", width=800)


image

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

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

if marked_image is not None:    if st.button('Solve Maze'):        with st.spinner('Solving your maze'):            path = maze.find_shortest_path(opencv_image,(start_x, start_y),(finish_x, finish_y))        pathed_image = opencv_image.copy()        path_thickness = (pathed_image.shape[0]+pathed_image.shape[0])//200        maze.drawPath(pathed_image, path, path_thickness)        st.image(pathed_image, channels="RGB", width=800)


image

Кнопка

image

Вывод решения

Вывод


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

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Шпаргалка по сортировке для Data Science

16.06.2020 20:21:53 | Автор: admin
image

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

Выбор библиотеки и типа алгоритма сортировки не всегда прост, а нововведения меняются в быстром темпе. На данный момент документация Pandas не соответствует коду (хотя лично мое PR-обновление сортировочных опций было самым последним).

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

UPD 17 июля 2019: В результаты оценки теста скорости теперь входят реализации GPU PyTorch и TensorFlow. TensorFlow также включает в себя результаты CPU как при tensorflow==2.0.0-beta1, так и при tensorflow-gpu==2.0.0-beta1. Интересные наблюдения: графический процессор PyTorch буквально летает, а GPU TensorFlow оказался медленнее CPU TensorFlow.

Контекст


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

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

image

За многие годы алгоритмы сортировки изменились в большинстве библиотек. Для анализа в этой статье я взял следующие версии ПО.

python 3.6.8
numpy 1.16.4
pandas 0.24.2
tensorflow==2.0.0-beta1 #tensorflow-gpu==2.0.0-beta1 slows sorting
pytorch 1.1


Начнем с основ.

Python (vanilla)


Python содержит два встроенных метода сортировки.

  • my_list.sort() сортирует список на месте, при этом исходный список заменяется на сортированный. sort() возвращает None.
  • sorted(my_list) возвращает отсортированную копию для каждой итерации. sorted() возвращает отсортированную итерацию. sort()не изменяет исходный список.

По идее, sort() должен быть быстрее, так как сортировка происходит на месте. На удивление, особой разницы между ними нет. К тому же, sort() стоит использовать аккуратно, так как он изменяет исходные данные без сохранения.

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

Что касается нашего случая, чтобы изменить порядок сортировки на нисходящий в Vanilla Python, нужно задать reverse=True.

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

Единственный алгоритм сортировки, используемый в Vanilla Python Timsort. Посредством данного алгоритма сортировка данных производится по их основным критериям. Например, если требуется сортировать короткий список, используется сортировка вставками. Дополнительную информацию о Timsort см. в большой статье Брэндона Скерритта.

Timsort и, соответственно, Vanilla Python, постоянны. То есть, если исходные значение одинаковы, то и обработанные значения будут аналогичны и расположены в том же порядке.
Чтобы напомнить разницу между sort() и sorted(), я лишь замечу, что sorted() это более сложная команда, чем sort(), и что sorted() займет объективно больше времени, ведь при этом сохраняются и исходные данные, и копия. И пусть результаты тестов неоднозначны, мнемоника наше все.

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

Numpy


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

  • my_array.sort () изменяет массив на месте и возвращает отсортированный массив;
  • np.sort (my_array) возвращает копию отсортированного массива, при этом не изменяя исходные данные.

Аргументы, используемые дополнительно:

  • axis: int, optional ось, по которой производится сортировка. По умолчанию -1 сортировка по последней оси.
  • kind: {quicksort, mergesort, heapsort, stable} алгоритм сортировки. По умолчанию используется quicksort быстрая сортировка. Далее я расскажу об этом подробнее.
  • order: str или list of str когда a является массивом с определенными границами, этот аргумент указывает, в каком порядке эти границы сравниваются. Одно поле может быть задано в виде строки, дальнейшие поля можно не конкретизировать. Они в любом случе будут использоваться в dtype для перебивок.

Откровенно говоря, на данным момент алгоритмы сортировки фактически соответствуют их названиям. Команда kind=quicksort буквально означает, что сортировка начинается с интроспективной сортировки. Подробнее здесь.

В случае, если удовлетворительного результата нет, происходит переключение на алгоритм heapsort. В худшем случае сортировка происходит по быстрому циклу O(n* log (n)).

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

Timsort применяется на предварительно подготовленных или близких к финальной сортировке данных. По случайным данным timsort практически идентичен mergesort. На данный момент он используется для конкретной сортировки, в то время как быстрая сортировка по-прежнему реализуется по умолчанию, и если конкретного выбора нет mergesort и stable выполняются для целочисленных типов данных автоматически.
Из документов Numpy (после парочки моих правок)


Один из важнейших выводов: Numpy позволяет управлять параметрами сортировки более свободно, чем Vanilla Python. Второй вывод, не менее важный: ключевое слово kind совершенно не обязательно соответствует используемому типу сортировки. И наконец, финальный итог, если можно так сказать, заключается в том, что mergesort и stable являются определнными сортировками, а quicksort и heapsort нет.

В нашем списке Numpy единственный метод, не имеющий ключевого слова для изменения порядка сортировки. На наше счастье, сделать это можно своеобразным переворотом массива: my_arr[::-1].

Все функции Numpy также доступны в куда более удобном для использования Pandas.

Pandas


Проводить сортировку можно в Pandas DataFrame с df.sort_values (by=my_column). Для удобства здесь имеется несколько ключевых слов.

  • by: str или list of str обязательное имя или список имен для сортировки. Если ось = 0 или конкретному значению, то она может содержать уровни значений/имена столбцов. Если ось приравнивается 1 или столбцу, то она может содержать уровни столбцов и/или метки значений.
  • axis: {0 или индекс, 1 или столбец}, по умолчанию 0 ось для сортировки.
  • ascending: bool или список bool, значение по умолчанию True сортировка по возрастанию или по убыванию. Укажите список для нескольких порядков сортировки. Если это список болтов, должен соответствовать длине аргумента by.
  • inplace: bool, по умолчанию False если назначить True, операция выполняется на месте.
  • kind: {quicksort, mergesort, heapsort или stable}, по умолчанию quicksort выбор алгоритма сортировки. Для получения дополнительной информации можно посмотреть ndarray.np.sort. Для DataFrames этот параметр применяется только при сортировке по одному столбцу или метке.
  • na_position: {first, last}, по умолчанию last first ставит NaNs в начале, last ставит NaNs в конце.


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

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

При сортировке по одному столбцу в Numpy по умолчанию используется quicksort. Как вы помните, quicksort теперь фактически является вводной и переходит в пирамидальную, если процесс сортировки идет медленно. Pandas заявляют, что сортировка по нескольким столбцам использует mergesort Numpy. mergesort в Numpy фактически использует алгоритмы сортировки Timsort или Radix. Это стабильные алгоритмы сортировки, что необходимо при сортировке по нескольким столбцам.

Для Pandas есть несколько ключевых моментов, которые стоит запомнить:

  • Имя функции: sort_values().
  • Необходимо заявить by=column_name или список имен столбцов.
  • ascending ключевое слово для реверса.
  • Для стабильной сортировки используйте mergesort.


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

for c in df.columns:    print(f"---- {c} ---")    print(df[c].value_counts().head())


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

Сортировка в Pandas это хороший выбор для предварительной сортировки небольших объемов данных. Если же вы имеете большой объем данных и хотите параллельно работать с GPU, стоит обратить внимание на TensorFlow или PyTorch.

TensorFlow


TensorFlow самая популярная среда для deep learning. Больше о глубоком изучении можно узнать в моей статье по ссылке здесь. Приведенная ниже информация актуальна для GPU TensorFlow 2.0.

tf.sort(my_tensor) возвращает отсортированную копию тензора. Опциональные аргументы:

  • axis: {int} Ось, по которой производится сортировка. По умолчанию равянется -1 и сортирует последнюю ось.
  • direction: {ascending или descending} направление сортировки значений.
  • name: {str} имя для операции.


tf.sort по сути использует top_k(). Для top_k() используется библиотека CUB для CUDA GPU, что упрощает параллельную реализацию. В документации говорится, что CUB предоставляет современные и повторяемые программные компоненты для каждого уровня модели программирования CUDA. TensorFlow использует основную сортировку на GPU через CUB (обсуждение).

Информацию по TensorFlow GPU можно найти здесь. Чтобы активировать возможности графического процессора с TensorFlow 2.0, вам необходимо прописать !pip3 install tensorflow-gpu==2.0.0-beta1. Ниже будет видно, что вы можете следовать по пути tensorflow==2.0.0-beta1, если вы только лишь сортируете данные (что маловероятно).

Для проверки кода на CPU и GPU используйте следующую строку:

tf.debugging.set_log_device_placement(True)

Чтобы указать, что вы хотите использовать GPU, нужно воспользоваться таким блоком:

with tf.device('/GPU:0'):
%time tf.sort(my_tf_tensor)


Для использования CPU: with tf.device('/CPU:0').

tf.sort() это интуитивно понятный метод при работе в TensorFlow. Просто запомните, что direction=descending нужен для изменения порядки сортировки.

PyTorch


torch.sort(my_tensor) возвращает отсортированную копию тензора. Необязательные аргументы:

  • dim: {int} объем сортировки.
  • descending: {bool} управляет порядком сортировки (по возрастанию или по убыванию).
  • out: {tuple} выходное сопровождение (Tensor, LongTensor), которое может использоваться в качестве выходных буферов.


Если вы хотите использовать GPU для сортировки, прикрепите .cuda () к концу вашего тензора.

gpu_tensor=my_pytorch_tensor.cuda()
%time torch.sort(gpu_tensor)


Исследования показали, что PyTorch использует сегментированную параллельную сортировку через Thrust, если сортируется набор данных размером более 1 миллиона строк на 100 000 столбцов.

К сожалению, у меня не хватило памяти, когда я пытался создать произвольные данные размером 1.1 миллиона на 100 тысяч через Numpy в Google Colab. После этого я попробовал GCP с 416 МБ ОЗУ, и мне вновь не хватило памяти.

Сегментированная сортировка и сортировка по местоположению это высокопроизводительные варианты сортировки слиянием, которые работают с неоднородными случайными данными. Сегментированная сортировка позволяет сортировать множество массивов переменной длины параллельно. https://moderngpu.github.io/segsort.html


Thrust это библиотека параллельных алгоритмов, которая обеспечивает совместимость производительности GPU и многояденых CPU. Она предоставляет сортировочную основу, которая автоматически выбирает наиболее эффективный метод реализации. Библиотека CUB, используемая TensorFlow, облегчает нагрузку. PyTorch и TensorFlow используют аналогичные алгоритмы для сортировки GPU независимо от того, какой применяется подход.

Как и TensorFlow, метод сортировки в PyTorch довольно прост для запоминания: torch.sort(). Единственное, что нужно запомнить, это направление отсортированных значений: TensorFlow использует direction, а PyTorch descending. И не забудьте использовать .cuda(), чтобы максимально увеличить скорость при работе с большим объемом данных.

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

SQL


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

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

Другие варианты SQL используют разные алгоритмы сортировки. Например, Google BigQuery использует внутреннюю сортировку с некоторыми приемами, вроде тех, что представлены в ответе на Stack Overflow.

Сортировка в SQL выполняется командой ORDER BY. Этот синтаксис отличается от Python, где предпочитают использовать ту или иную форму слова sort. Лично мне запомнилось, что ORDER BY используется в синтаксисе SQL, так как это довольно необычно.

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

SELECT Names FROM CustomersORDER BY Names DESC;


Сравнение


Для каждой из вышеперечисленных библиотек Python я провел анализ, сортируя 1 000 000 точек данных в одном столбце, массиве или списке. Я использовал ноутбук Google Colab Jupyter с GPU K80 и Intel Xeon CPU с тактовой частотой 2,30 ГГц.

image

Наблюдения


  • PyTorch с GPU максимально быстрый.
  • Как для Numpy, так и для Pandas, сортировка на месте, как правило, быстрее, чем с копированием данных.
  • Быстрая сортировка Pandas по умолчанию довольно быстрая.
  • Большинство функций Pandas сравнительно медленнее, чем их аналоги в Numpy.
  • Процессор TensorFlow довольно быстрый. Установка GPU замедляет работу TensorFlow даже при использовании CPU. Сортировка GPU довольно медленная. Этот вариант не слишком эффективен
  • В Vanilla Python сортировка на месте происходит на удивление медленно почти в 100 раз медленнее, чем сортировка с поддержкой графического процессора PyTorch. Я посторил опыт несколько раз (с разными данными), чтобы перепроверить, что это не аномалия.


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

Подведем итоги


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

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

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

  • Используйте Pandas sort_values() по умолчанию для исследования относительно небольших наборов данных.
  • Для больших наборов данных или когда скорость достаточно высока, попробуйте встроенную сортировку Numpy на месте, параллельную реализацию GPU PyTorch или TensorFlow, или SQL.


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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Что я узнал после более чем 1000 code review

19.06.2020 20:14:58 | Автор: admin
За последние 3 года я рассмотрел более 1000 pull (merge) requestов. За это время я многому научился в основном тому, как не проверять код, как сделать процесс менее болезненным, что делает код хорошего качества и так далее.

Pull request должен делать только одну вещь


Это самая важная вещь, на которую стоит обратить внимание.

Делая code review, вы должны держать в голове много вещей. Что за этим стоит?, Как это согласуется с остальной частью кода? и Будет ли это хорошо работать? Вот лишь некоторые из вопросов, на которые нужно ответить. Таким образом, когда у вас есть pull request, который пытается решить одну проблему, на некоторые из этих вопросов легче ответить.

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

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

Лучше всего разбить pull requestы на осмысленные части один запрос должен решить только одну вещь.


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

Автоматизируйте как можно больше проверок


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

Хорошо, что есть довольно простое решение интегрируйте все проверки в CI. Тогда у вас будут запускаться все проверки всякий раз, когда кто-то отправляет pull request, и не разрешает слияние пока все проверки не пройдут успешно. Вам как рецензенту больше никогда не придется беспокоиться о форматировании.

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

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

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

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

Сядьте с автором, чтобы просмотреть код


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

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

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

Будьте внимательны при написании отзывов


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

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

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

Добавьте флаг Я запускал этот код локально


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

Бонус: это наш шаблон, который должен заполнить каждый разработчик при создании pull requesta:

Описание Merge Requesta
Что нового?

Реализовано
Что изменилось?

Изменено
ЧЕК-ЛИСТ
[] Я запускал этот код локально
[] Я написал необходимые тесты
[] Я покрыл свой код тайп хинтами
[] Я обновил CHANGELOG
Трелло карта
trello.com/c

Должен знать о
Есть что-нибудь еще, что должно быть известно?
Любые замечания по развертыванию?
Любая дополнительная документация?


image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Практическое функциональное программирование

25.06.2020 22:10:00 | Автор: admin
image


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

40 лет назад, 17 октября 1977 года, премия Тьюринга была вручена Джону Бакусу за его вклад в разработку систем программирования высокого уровня, прежде всего языка программирования Fortran. Всем лауреатам премии Тьюринга предоставляется возможность выступить с лекцией по выбранной ими теме в течение года, в котором они получили премию. Как создатель языка программирования Фортран, можно было ожидать, что Бакус выступит с лекцией о преимуществах Фортрана и будущих разработках в этом языке. Вместо этого он прочитал лекцию под названием Можно ли освободить программирование от стиля фон Неймана? в котором он критиковал некоторые из основных языков того времени, включая Фортран, за их недостатки. Он также предложил альтернативу: функциональный стиль программирования.

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

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

Давайте начнем с рассмотрения функции, которая действительно хорошо скомпонована:

String addFooter(String message) {  return message.concat(" - Sent from LinkedIn");}

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

boolean validMessage(String message) {  return characterCount(addFooter(message)) <= 140;}


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

Теперь давайте взглянем на функцию, которая не так хорошо скомпонована:

String firstWord(String message) {  String[] words = message.split(' ');  if (words.length > 0) {    return words[0];  } else {    return null;  }}


А затем попробуйте скомпоновать ее с другой функции:

// Hello world -> HelloHelloduplicate(firstWord(message));


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

String duplicateBad(String word) {  if (word == null) {    return null;  } else {    return word.concat(word);  }}

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

Нулевые объекты плохо компонуются.


Давайте рассмотрим альтернативную реализацию, в которой используется тип Java 8 Optional (также называемый Option или Maybe на других языках):

Optional<String> firstWord(String message) {  String[] words = message.split(' ');  if (words.length > 0) {    return Optional.of(words[0]);  } else {    return Optional.empty();  }}


Теперь мы попытаемся скомпоновать ее с неизмененной функцией dublicate:

// "Hello World" -> Optional.of("HelloHello")firstWord(input).map(this::duplicate)


Оно работает! Опциональный тип заботится о том, что firstWord иногда не возвращает значение. Если Optional.empty() возвращается из firstWord, то функция .map просто пропустит запуск функции dublicate. Мы смогли легко объединить функции без необходимости модифицировать dublicate. Сравните это с null случаем, когда нам нужно было создать функцию duplicateBad. Другими словами: нулевые объекты плохо компонуются, а опционалы хорошо.

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

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

getData(function(a) {      getMoreData(a, function(b) {        getMoreData(b, function(c) {             getMoreData(c, function(d) {                 getMoreData(d, function(e) {                     // ...                });            });        });    });});


Например, в более крупном веб-приложении это приводит к очень вложенному спагетти-коду. Представьте себе попытку выделить одну из функций getMoreData в ее собственный метод. Или представьте, что вы пытаетесь добавить обработку ошибок к этой вложенной функции. Причина, по которой она не может быть скомпонована, состоит в том, что к каждому блоку кода предъявляется много контекстных требований: для самого внутреннего блока требуется доступ к результатам из a, b, c и т. д. и т. д.

Значения легче компоновать вместе, чем функции


Давайте посмотрим на инструментарий функционального программиста чтобы найти альтернативу: Promise (иногда называемое Future на других языках). Вот как выглядит код сейчас:

getData()  .then(getMoreData)  .then(getMoreData)  .then(getMoreData)  .catch(errorHandler)


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

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

// ["hello", "world"] -> ["hello!", "world!"]List<String> addExcitement(List<String> words) {  List<String> output = new LinkedList<>();  for (int i = 0; i < words.size(); i++) {    output.add(words.get(i) + !);  }  return output;}// ["hello", "world"] -> ["hello!!", "world!!"]List<String> addMoreExcitement(List<String> words) {  return addExcitement(addExcitement(words));}


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

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

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


Ответ функционального программиста (по крайней мере, в Java 8) это Stream. Stream по умолчанию ленив, что означает, что он проходит через данные только тогда, когда это необходимо. Другими словами, ленивая функция: она начинает выполнять работу только тогда, когда ее просят о результате (функциональный язык программирования Haskell построен на концепции лени). Давайте перепишем приведенный выше пример, используя вместо этого Stream:

String addExcitement(String word) {  return word + "!";}list.toStream()  .map(this::addExcitement)  .map(this::addExcitement)  .collect(Collectors.toList())


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

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

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

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

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

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


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

Мы можем видеть это в реальных примерах:

  • API Apache Spark для выполнения вычислений на больших наборах данных абстрагирует детали того, на каких машинах он будет работать и где хранятся данные
  • React.js описывает представление и делает преобразование DOM эффективным алгоритмом

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод 8 трюков в Python, используемых опытными программистами

30.06.2020 18:10:31 | Автор: admin
image

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

1. Сортировка объектов по нескольким ключам


Предположим, мы хотим отсортировать следующий список словарей:

people = [{ 'name': 'John', "age": 64 },{ 'name': 'Janet', "age": 34 },{ 'name': 'Ed', "age": 24 },{ 'name': 'Sara', "age": 64 },{ 'name': 'John', "age": 32 },{ 'name': 'Jane', "age": 34 },{ 'name': 'John', "age": 99 },]


Но мы не просто хотим сортировать их по имени или возрасту, мы хотим отсортировать их по обоим полям. В SQL это будет такой запрос:

SELECT * FROM people ORDER by name, age


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

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

import operatorpeople.sort(key=operator.itemgetter('age'))people.sort(key=operator.itemgetter('name'))


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

Это дает нам результат, который мы хотели:

[ {'name': 'Ed',   'age': 24}, {'name': 'Jane', 'age': 34}, {'name': 'Janet','age': 34}, {'name': 'John', 'age': 32}, {'name': 'John', 'age': 64}, {'name': 'John', 'age': 99}, {'name': 'Sara', 'age': 64}]


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

Источник вдохновения вопрос со StackOverflow.

2. Списковые включения (Генератор списка)


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

[ expression for item in list if conditional ]


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

mylist = [i for i in range(10)]print(mylist)# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


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

squares = [x**2 for x in range(10)]print(squares)# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


Или даже вызвать внешнюю функцию:

def some_function(a):    return (a + 5) / 2    my_formula = [some_function(i) for i in range(10)]print(my_formula)# [2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0]


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

filtered = [i for i in range(20) if i%2==0]print(filtered)# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]


3. Проверьте использование памяти ваших объектов


С помощью sys.getsizeof() вы можете проверить использование памяти объектом:

import sysmylist = range(0, 10000)print(sys.getsizeof(mylist))# 48


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

import sysmyreallist = [x for x in range(0, 10000)]print(sys.getsizeof(myreallist))# 87632


Итак, поиграв с sys.getsizeof(), вы можете больше узнать о Python и использовании вашей памяти.

4. Классы данных


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

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


Вот пример класса данных в работе:

from dataclasses import dataclass@dataclassclass Card:    rank: str    suit: str    card = Card("Q", "hearts")print(card == card)# Trueprint(card.rank)# 'Q'print(card)Card(rank='Q', suit='hearts')


Подробное руководство можно найти здесь.

5. Пакет attrs


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

  • Вы используете версию Python старше 3.7
  • Вы хотите больше возможностей


Пакет attrs поддерживает все основные версии Python, включая CPython 2.7 и PyPy. Некоторые из дополнительных атрибутов, предлагаемых attrs по сравнению с обычными классами данных, являются валидаторами и конвертерами. Давайте посмотрим на пример кода:

@attrsclass Person(object):    name = attrib(default='John')    surname = attrib(default='Doe')    age = attrib(init=False)    p = Person()print(p)p = Person('Bill', 'Gates')p.age = 60print(p)# Output: #   Person(name='John', surname='Doe', age=NOTHING)#   Person(name='Bill', surname='Gates', age=60)


Авторы attrs фактически работали в PEP, которые ввели классы данных. Классы данных намеренно хранятся проще (легче для понимания), в то время как attrs предлагает полный набор функций, которые вам могут понадобиться!

Дополнительные примеры можно найти на странице примеров attrs.

6. Объединение словарей (Python 3.5+)


Начиная с Python 3.5, легче объединять словари:

dict1 = { 'a': 1, 'b': 2 }dict2 = { 'b': 3, 'c': 4 }merged = { **dict1, **dict2 }print (merged)# {'a': 1, 'b': 3, 'c': 4}


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

В Python 3.9 объединение словарей становится еще чище. Вышеупомянутое слияние в Python 3.9 может быть переписано как:

merged = dict1 | dict2


7. Поиск наиболее часто встречающегося значение


Чтобы найти наиболее часто встречающееся значение в списке или строке:

test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]print(max(set(test), key = test.count))# 4


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

Вы даже попытались, не так ли? Я все равно скажу вам:

  • max() вернет самое большое значение в списке. Аргумент key принимает функцию единственного аргумента для настройки порядка сортировки, в данном случае это test.count. Функция применяется к каждому элементу итерируемого.
  • test.count встроенная функция списка. Она принимает аргумент и будет подсчитывать количество вхождений для этого аргумента. Таким образом, test.count(1) вернет 2, а test.count(4) вернет 4.
  • set(test) возвращает все уникальные значения из test, поэтому {1, 2, 3, 4}


Итак, в этой единственной строке кода мы принимаем все уникальные значения теста, который равен {1, 2, 3, 4}. Далее max применит к ним функцию list.count и вернет максимальное значение.
И нет я не изобрел этот однострочник.

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

from collections import CounterCounter(test).most_common(1)# [4: 4]


8. Возврат нескольких значений


Функции в Python могут возвращать более одной переменной без словаря, списка или класса. Это работает так:

def get_user(id):    # fetch user from database    # ....    return name, birthdatename, birthdate = get_user(4)


Это нормально для ограниченного числа возвращаемых значений. Но все, что превышает 3 значения, должно быть помещено в (data) класс.

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод - recovery mode Учебный проект на Python алгоритм Дейкстры, OpenCV и UI ( часть 1)

02.07.2020 20:17:59 | Автор: admin
Лабиринты это распространенная головоломка для людей, но они представляют из себя интересную задачу для программирования, которую мы можем решить, используя методы кратчайшего пути, такие как алгоритм Дейкстры.

Вспоминаем алгоритм Дейкстры


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

Сначала мы присваиваем значение расстояния от источника всем узлам. Узел s получает значение 0, потому что это источник; остальные получают значения для начала.

image

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

image

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

image

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

image

image

image

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

Концептуализация изображений лабиринта


image

Мы можем представить себе изображение как матрицу пикселей. Каждый пиксель (для простоты) имеет значение RGB 0,0,0 (черный) или 255,255,255 (белый). Наша цель создать кратчайший путь, который начинается на белом и не переходит на чёрные границы. Чтобы представить эту цель, мы можем рассматривать каждый пиксель как узел и рисовать ребра между соседними пикселями с длиной ребер, основанной на разнице значений RGB. Мы будем использовать формулу евклидова квадратного расстояния и добавим 0,1, чтобы гарантировать отсутствие длины пути 0 (требование для алгоритма Дейкстры):

image

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

image

Реализация


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

import cv2import matplotlib.pyplot as pltimport numpy as npimg = cv2.imread('maze.png') # read an image from a file usingcv2.circle(img,(5,220), 3, (255,0,0), -1) # add a circle at (5, 220)cv2.circle(img, (25,5), 3, (0,0,255), -1) # add a circle at (5,5)plt.figure(figsize=(7,7))plt.imshow(img) # show the imageplt.show()


image


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

class Vertex:    def __init__(self,x_coord,y_coord):        self.x=x_coord        self.y=y_coord        self.d=float('inf') #current distance from source node        self.parent_x=None        self.parent_y=None        self.processed=False        self.index_in_queue=None


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

def find_shortest_path(img,src,dst):    pq=[] #min-heap priority queue    imagerows,imagecols=img.shape[0],img.shape[1]    matrix = np.full((imagerows, imagecols), None)     #access matrix elements by matrix[row][col]    #fill matrix with vertices    for r in range(imagerows):        for c in range(imagecols):            matrix[r][c]=Vertex(c,r)            matrix[r][c].index_in_queue=len(pq)            pq.append(matrix[r][c])    #set source distance value to 0    matrix[source_y][source_x].d=0    #maintain min-heap invariant (minimum d Vertex at list index 0)    pq = bubble_up(pq, matrix[source_y][source_x].index_in_queue)


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

#Implement euclidean squared distance formuladef get_distance(img,u,v):    return 0.1 + (float(img[v][0])-float(img[u][0]))**2+(float(img[v][1])-float(img[u][1]))**2+(float(img[v][2])-float(img[u][2]))**2#Return neighbor directly above, below, right, and leftdef get_neighbors(mat,r,c):    shape=mat.shape    neighbors=[]    #ensure neighbors are within image boundaries    if r > 0 and not mat[r-1][c].processed:         neighbors.append(mat[r-1][c])    if r < shape[0] - 1 and not mat[r+1][c].processed:            neighbors.append(mat[r+1][c])    if c > 0 and not mat[r][c-1].processed:        neighbors.append(mat[r][c-1])    if c < shape[1] - 1 and not mat[r][c+1].processed:            neighbors.append(mat[r][c+1])    return neighbors


Теперь мы можем реализовать алгоритм Дейкстры и присвоить значения расстояния (d) всем вершинам пикселей в изображении лабиринта:

while len(pq) > 0:    u=pq[0] #smallest-value unprocessed node    #remove node of interest from the queue    pq[0]=pq[-1]     pq[0].index_in_queue=0    pq.pop()    pq=bubble_down(pq,0) #min-heap function, see source code         u.processed=True    neighbors = get_neighbors(matrix,u.y,u.x)    for v in neighbors:        dist=get_distance(img,(u.y,u.x),(v.y,v.x))        if u.d + dist < v.d:            v.d = u.d+dist            v.parent_x=u.x #keep track of the shortest path            v.parent_y=u.y            idx=v.index_in_queue            pq=bubble_down(pq,idx)             pq=bubble_up(pq,idx)


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

img = cv2.imread('maze.png') # read an image from a file using opencv (cv2) libraryp = find_shortest_path(img, (25,5), (5,220))drawPath(img,p)plt.figure(figsize=(7,7))plt.imshow(img) # show the image on the screen plt.show()


image

image

Давайте попробуем другие лабиринты со всего Интернета.

image

image

image

image

Полный исходный код доступен на GitHub здесь.

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Чеклист для проекта по машинному обучению

07.07.2020 12:09:02 | Автор: admin
image

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

Зачем мне вообще нужен чеклист?

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

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

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

Как говорит Атул Гаванде в своей книге The Checklist Manifesto,
объем и сложность того, что мы знаем, превзошли нашу индивидуальную способность правильно, безопасно и надежно предоставлять свои преимущества.
Итак, позвольте мне провести вас по этому четкому и краткому списку действий, которые уменьшат вашу рабочую нагрузку и улучшат ваши результаты

Чеклист проектов по машинному обучению


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

1. Определите проблему с точки зрения высокого уровня


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

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

2. Определите источники данных и получите данные


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

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

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

3. Первоначальная разведка данных


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

Шаги:

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

4. Исследовательский анализ данных для подготовки данных


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

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

5. Разработайте базовую модель, а затем изучите другие модели, чтобы отобрать лучшие


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

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

6. Точно настройте свои модели из шорт-листа и проверьте наличие методов ансамбля


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

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

7. Документируйте код и сообщайте свое решение


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

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

8. Разверните свою модель в продакшен, мониторинг


Если ваш проект требует тестирования развертывания на реальных данных, вы должны создать веб-приложение или REST API для использования на всех платформах (web, Android, iOS). Основные пункты (будут варьироваться в зависимости от проекта) включают в себя:

  • Сохраните вашу окончательную обученную модель в файл h5 или pickle.
  • Обслуживайте свою модель с помощью веб-сервисов, Вы можете использовать Flask для разработки этих веб-сервисов.
  • Подключите источники входных данных и настройте конвейеры ETL.
  • Управляйте зависимостями с помощью pipenv, docker/Kubernetes (на основе требований масштабирования)
  • Вы можете использовать AWS, Azure или Google Cloud Platform для развертывания своего сервиса.
  • Делайте мониторинг производительности на реальных данных или просто для людей, чтобы они могли использовать вашу модель со своими данными.

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Интерактивная визуализация данных при помощи Plotly строим красивые графики с Express и Cufflinks

25.06.2020 22:10:00 | Автор: admin
image


Если Вы все еще используете Matplotlib для создания графиков в Python, самое время взглянуть на мир с высоты альтернативной библиотеки интерактивной визуализации.

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

Вот камни преткновения, которые могут появиться на пути авантюристов, решивших покорить эту гору:

  • непонятная начальная настройка для работы оффлайн без аккаунта;
  • неимоверное количество строк кода;
  • устаревшая документация;
  • множество различных инструментов Plotly, в которых можно заблудиться (Dash, Express, Chart Studio и Cufflinks).

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

Plotly


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

Plotly.py основывается на JavaScript-библиотеке D3.js. Также в Plotly есть API-обертки для R, Julia и многих других языков программирования. Стоит отметить, что документация представлена не на всех языках.

image

Примеры библиотек от Plotly

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

cufflinks                0.15jupyterlab             0.35.5plotly                   3.8.1     plotly-express       0.1.7


Убедитесь, что используется cufflinks 0.15 (0.13 не очень дружит с последними обновлениями Plotly).
ПРАВКА (май 2020): самая свежая версия Plotly 4.7.1. Большая часть представленных ниже инструкций все так же применима к последней версии программы. Обратите внимание, что экспресс-модуль импортируется как часть пакета Plotly.

plotly.py


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

Установите простой модуль plotly.py с conda или воспользуйтесь pip install plotly.

Импортируйте модуль и сконфигурируйте его для использования в оффлайн-режиме:

import plotly.offline as pypy.init_notebook_mode(connected=False)


Теперь программа не будет требовать у Вас создать аккаунт. Так мы и преодолели первую преграду на пути к вершине горы Plotly.

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

image

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

import pandas as pdimport numpy as npimport plotly.offline as pyimport plotly.graph_objs as goimport jsonpy.init_notebook_mode(connected=False)izip = zipdf = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/globe_contours.csv')df.head()contours = []scl = ['rgb(213,62,79)','rgb(244,109,67)','rgb(253,174,97)',\       'rgb(254,224,139)','rgb(255,255,191)','rgb(230,245,152)',\       'rgb(171,221,164)','rgb(102,194,165)','rgb(50,136,189)']def pairwise(iterable):    a = iter(iterable)    return izip(a, a)i=0for lat, lon in pairwise(df.columns):    contours.append( dict(        type = 'scattergeo',        lon = df[lon],        lat = df[lat],        mode = 'lines',        line = dict(            width = 2,            color = scl[i]        )    ) )    i = 0 if i+1 >= len(df.columns)/4 else i+1    layout = dict(        margin = dict( t = 0, l = 0, r = 0, b = 0 ),        showlegend = False,                 geo = dict(            showland = True,            showlakes = True,            showcountries = True,            showocean = True,            countrywidth = 0.5,            landcolor = 'rgb(230, 145, 56)',            lakecolor = 'rgb(0, 255, 255)',            oceancolor = 'rgb(0, 255, 255)',            projection = dict(                 type = 'orthographic',                rotation = dict(lon = 0, lat = 0, roll = 0 )                        ),            lonaxis = dict(                 showgrid = True,                gridcolor = 'rgb(102, 102, 102)',                gridwidth = 0.5            ),            lataxis = dict(                 showgrid = True,                gridcolor = 'rgb(102, 102, 102)',                gridwidth = 0.5            )        )    )sliders = []lon_range = np.arange(-180, 180, 10)lat_range = np.arange(-90, 90, 10)sliders.append(     dict(        active = len(lon_range)/2,        currentvalue = {"prefix": "Longitude: "},        pad = {"t": 0},        steps = [{                'method':'relayout',                 'label':str(i),                'args':['geo.projection.rotation.lon', i]} for i in lon_range]    )      )sliders.append(     dict(        active = len(lat_range)/2,        currentvalue = {"prefix": "Latitude: "},        pad = {"t": 100},        steps = [{                'method':'relayout',                 'label':str(i),                'args':['geo.projection.rotation.lat', i]} for i in lat_range]    )      )projections = [ "equirectangular", "mercator", "orthographic", "natural earth","kavrayskiy7",                "miller", "robinson", "eckert4", "azimuthal equal area","azimuthal equidistant",                "conic equal area", "conic conformal", "conic equidistant", "gnomonic", "stereographic",                "mollweide", "hammer", "transverse mercator", "albers usa", "winkel tripel" ]buttons = [ dict( args=['geo.projection.type', p], label=p, method='relayout' ) for p in projections ]annot = list([ dict( x=0.1, y=0.8, text='Projection', yanchor='bottom',                     xref='paper', xanchor='right', showarrow=False )])# Update Layout Objectlayout[ 'updatemenus' ] = list([ dict( x=0.1, y=0.8, buttons=buttons, yanchor='top' )])layout[ 'annotations' ] = annotlayout[ 'sliders' ] = slidersfig = dict( data=contours, layout=layout )py.iplot( fig)

Не уверена, как этот пример сюда запихнуть, не размазав его по нескольким страницам.

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

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

Следующие два продукта от Plotly, на которые мы обратим внимание, предлагают высокоуровневые обертки, упрощающие программный интерфейс plotly.py. Они помогут сэкономить время, если вы работаете с библиотекой Pandas. Давайте рассмотрим их поподробнее.

Express


Модуль Plotly Express был выпущен в марте 2019 года и находится в процессе активной разработки. Компания работает над созданием условий поддержки новых графиков и собирается выпустить Plotly 4.0 летом 2019 года.

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

Установите Express с помощью pip install plotly_express.

Чтобы использовать эту библиотеку в записной книжке Jupyter, введите следующий код в командную строку:

jupyter labextension install @jupyterlab/plotly-extension

Данный код позволит создать гистограмму из таблицы с традиционным Express импортом:

import plotly_express as px         px.bar(my_df, x='my_x_column', y='my_y_column')


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

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

px.bar(my_df, x='my_x_column', y='my_y_column', title='My Chart Title")


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

_my_fig = px.bar(my_df, x='my_x_column', y='my_y_column', title='My Chart Title')_my_fig.data[0].update(    text=my_df['my_y_column'],      textposition='inside',    textfont=dict(size=10))_my_fig.iplot()


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

Cufflinks


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

Установите ее с помощью pip install cufflinks.

Импортируйте модуль и настройте файл для автономного использования.

import cufflinks as cfcf.set_config_file(offline=True)


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

image

Пример гистограммы с накоплением, созданной с помощью Cufflinks.

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

df = pd.DataFrame(np.random.rand(6, 3), columns=['A', 'B', 'C'])df.iplot(kind='bar', barmode='stack', title='Stacked Bar Chart with Random Data')


Обратите внимание, что для создания диаграмм с помощью Cufflinks Вам нужно использовать .iplot().

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

my_fig = df.iplot(kind='bar', barmode='stack', title='Stacked Bar Chart with Random Data', asFigure=True)_fig.layout.yaxis = dict(title='Members', range=[0, 600])

Вот документация Cufflinks.

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

Сравнение трех вариантов


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

plotly.py


image

Пример диаграммы рассеяния, выполненной с plotly.py

fig = {    'data': [        {            'x': df2007.gdpPercap,             'y': df2007.lifeExp,             'text': df2007.country,             'mode': 'markers',             'name': '2007'},    ],    'layout': {        'title': "Example Scatter Plot with Vanilla plotly.py"    }}py.iplot(fig)


Express


image

Пример диаграммы рассеяния, выполненной с Plotly Express

px.scatter(    df2007,     x="gdpPercap",     y="lifeExp",     title='Example Scatter Plot with Plotly Express')


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

Cufflinks


image

Пример диаграммы рассеяния, выполненной с Cufflinks

df2007.iplot(    kind='scatter',     mode='markers',     x='gdpPercap',     y='lifeExp',     title='Example Scatter Plot with Cufflinks')


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

Давайте посмотрим, как можно вернуть и обратиться к основной информации.

Обновление графиков Cufflinks и Express


Давайте перейдем к макету графика, созданного с Cufflinks, и добавим названия осей.

image

Пример диаграммы рассеяния, выполненной с Cufflinks Доступ к исходному графику

fig = df2007.iplot(    kind='scatter',     mode='markers',     x='gdpPercap',     y='lifeExp',     asFigure=True,    title='Example Scatter Plot with Cufflinks - Access Underlying Figure')fig.layout.xaxis.title = "GDP per Capita"fig.layout.yaxis.title = "Life Expectancy"fig.iplot()


Вот как сделать то же самое с Express. Не забывайте, что в данной библиотеке не нужно уточнять asFigure=True.

image

Пример диаграммы рассеяния, выполненной с Plotly Express Доступ к исходному графику

fig = px.scatter(    df2007,     x="gdpPercap",     y="lifeExp",     title='Example Scatter Plot with Plotly Express - Access Underlying Figure')fig.layout.xaxis.title = "GDP per Capita"fig.layout.yaxis.title = "Life Expectancy"fig.iplot()


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

fig.data[0].update(text=df2007['gdpPercap'],textposition=inside,textfont=dict(size=10))


Что выбрать: Plotly.py, Express или Cufflinks


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

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

К сожалению, ни один высокоуровневый API на данный момент не дает возможность создавать графики любого типа. Однако лично я точно постараюсь максимально избегать использования ванильного python.py и предпочту Cufflinks или Express.

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

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

df.iplot(kind=scatter, mode=markers, x=X, y=Y, title=Random Data, categories=Z)


image

Диаграмма рассеяния по умолчанию с Cufflinks

А вот что мы получим с Express-кодом:

px.scatter(df, x=X, y=Y, color=Z, title=Random Data)


image

Другие пресеты с Express

Заметная разница!

Сохранение файлов


Закончив работы с диаграммой, Вы можете навести на нее мышку и щелкнуть по значку камеры, чтобы экспортировать ее в формате .png, или нажать Экспортировать в plot.ly, чтобы сохранить интерактивное изображение на сервер Plotly. Помимо этого, Вы можете скачать файлы в интерактивном HTML-формате следующим образом:

py.offline.plot(my_fig, filename=my_example_file.html)


Если нужны другие форматы изображения, Вы можете воспользоваться пакетом orca и скачивать файлы в форматах .png, .jpg и .pdf. Данный пакет на данный момент недоступен на pypi.org, поэтому установить его с помощью pip не получится. Вы можете управлять пакетом с помощью conda или установить ОС-специфичную версию orca со страницы GitHub. После этого Вам не нужно будет импортировать библиотеку orca. Узнать больше о программе orca можно здесь.

Вот код для создания png-файла после установки orca:

import plotly as plotlyplotly.io.write_image(fig, file='my_figure_file.png', format='png')


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

Dash


С Plotly Dash Вы можете создавать дашборды для своей команды или для других людей. Есть версия с открытым кодом доступа, у которой к 1 мая 2019 года насчитывалось практически 9000 звезд GitHub. Plotly также предлагает целый ряд дополнений. Может, в будущем я напишу статью и об этом. Подписывайтесь, чтобы не пропустить.

Chart Studio


Plotly Chart Studio позволяет легко создавать и редактировать графики в браузере. Plotly рекламирует данную программу как самый умный редактор для создания D3.js- и WebGL-диаграмм. Не надо ничего кодировать вручную. Есть бесплатная версия, но если хотите сохранить свои графики, то придется отдать 99$ за год использования.

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

Бонус: другие варианты библиотек визуализации данных от Python


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

image

Хотите делать графики по старинке обратитесь к ванильной библиотеке Matplotlib API.

image

Pandas Matplotlib позволяет создавать неплохие простенькие графики. Может создавать стандартные Matplotlib объекты.

image

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

image

Bokeh конкурент Plotly. Программа с открытым исходным кодом, интерактивная, работает с Python.

image

Holoviews высокоуровневая обертка, работающая с Matplotlib, Bokeh, а теперь и с Plotly. Знаю ребят, которые пользуются именно ей.

image

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

image

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

image

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

Большинство ПО для создания интерактивных графиков используют библиотеку D3.js. Она очень популярна.

Выводы и полезные ресурсы


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

Возможно, когда-нибудь появится универсальная библиотека, позволяющая создавать все, что захотите, используя высокоуровневые API-опции Plotly. А пока, если хотите сэкономить время и сделать крутые графики, предлагаю обращаться к Pandas с Cufflinks или Express.



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

image

Образец цветов

color_list = ["#E69F00", "#56B4E9", "#009E73", "#F0E442", "#D55E00", "#0072B2",  "#CC79A7"]


image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод В чем разница между Data Analytics и статистикой

18.06.2020 12:21:50 | Автор: admin
Разбираемся в ценности двух совершенно разных профессий.

image

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

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

Человеческие поисковые системы


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

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

image

Даже дети без труда могут найти факты в интернете. Мы наблюдаем демократизацию дата сайнс. Хотите знать, холоднее ли сегодня в Нью-Йорке, чем в Рейкьявике? Вы можете почти мгновенно удовлетворить свое любопытство. Это так просто, что мы даже больше не называем этот процесс аналитикой, хотя по сути это она и есть. А теперь представьте, что вам нужно было бы получить эту информацию сто лет назад. (Вот именно.)

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


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

Искатели вдохновения


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

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

У тебя есть интернет, найди там что-нибудь полезное.


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

image

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

Бросаясь в пучину неизвестного


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

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

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


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

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

Аналитика помогает вам сформулировать гипотезы. Это улучшает качество ваших вопросов.


Статистика помогает вам проверить гипотезы. Это улучшает качество ваших ответов.


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

Аналитик добывает информацию в конкретном наборе данных.

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


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

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

Вам нужно и то и другое


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

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


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

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


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

Перевод: Диана Шеремьёва

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Data Science на пальцах. Статистика это наука менять свой взгляд на вещи в условиях неопределенности

22.06.2020 12:13:23 | Автор: admin
Сотрудница Google объясняет статистику на пальцах для гуманитариев, которые хотят стать Data Scientists.

image

Что такое статистика? Какой-то устаревший способ погрязнуть в данных. Ага. На 100% технически правильное определение. Теперь давайте посмотрим, что есть статистика как дисциплина.

Статистика это наука о том, как менять свои представления.

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

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

Байесианцы меняют свое мнение насчет представлений.

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

Приверженцы частотной статистики меняют свое мнение насчет действий.

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

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

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

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

Быстрая проверка: Мои доказательства превращают нулевую гипотезу в нелепость?

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

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

Р-значение в периодической таблице элемент неожиданности.

P-значение говорит: Если я живу в мире, в котором должен принимать такое-то действие по умолчанию, насколько тогда не удивительны мои доказательства? Чем ниже p-значение, тем больше данные кричат: Ого, это же удивительно! Может, вам стоит изменить ваше мнение!

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

image

Как использовать p-значения, чтобы узнать результат проверки гипотезы. (Никто не заподозрит, что мой xkcd-подделка)

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

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

Хотя техническое значение термина достоверный интервал немного странновато (я расскажу вам подробно о нем в следующем посте, он определенно не так прост как доверительный интервал, с которым мы познакомились ранее), он также обладает двумя полезными свойствами, которые аналитики любят использовать при описании своих данных: (1) всегда есть лучшее предположение и (2) с появлением данных интервал становится уже. Берегитесь, ни интервал, ни p-значение не были созданы не для того, чтобы говорить о них было приятно, поэтому не ожидайте содержательных определений. Это просто способ обобщить результаты тестов. (Если вы ходили на занятия и не могли запомнить определения, то вот оно почему. От имени статистики: это не вы, это все я).

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

Математика это построение игрушечной модели вселенной нулевых гипотез. Так вы получаете p-значение.

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

К чему все эти безумные формулы, вероятности и распределения? Благодаря им мы излагаем правила, регулирующие вселенную нулевой гипотезы. Мы можем выяснить, является ли эта вселенная местом, которое выдает данные, похожие на те, что вы получили в реальной жизни. Если нет, то вы кричите: Смешно! Голову с плеч! А если да, то просто пожимаете плечами и ничего нового не получаете. Подробнее об этом я расскажу в следующем посте. А пока, просто поразмыслите о математике, как об инструменте создания маленьких игрушечных миров, чтобы мы могли посмотреть, выглядит ли наш набор данных в них разумным. P-значение и достоверный интервал это способы обобщить всю эту информацию для, поэтому вам не нужно жмуриться от многословного описания вселенной. Здесь кроется развязка: используйте их, чтобы проверить, стоит ли следовать действиям по умолчанию. И работа сделана!

А мы сделали домашнее задание? Вот в чем меры мощности.

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

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

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

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

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

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

Ошибка I типа отказаться по глупости от действия по умолчанию. Эй, вы же говорили, что вам было удобно следовать действию по умолчанию, и теперь, после всех своих расчетов, отказались от него. Ой! Ошибка II типа по глупости не отказаться от действий по умолчанию. (Мы, статистики, крайне изобретательны в придумывании названий. Угадайте, какая ошибка хуже. Тип I? Ага. Очень креативно.)

Ошибка I типа поменять мнения, когда не следовало бы.

Ошибка II типа не поменять мнения, когда следовало бы.

Ошибка I типа похожа на осуждение невиновного, а ошибка II типа на неспособность осудить виновного. Это равновесно вероятные ошибки (что упрощает суд над виновным, также упрощает его и над невиновным), если только у вас не будет больше доказательств (данных!), тогда уже вероятность допустить ошибку становится ниже, и дела идут на поправку. Вот почему статистики хотят, чтобы у вас было много, РЕАЛЬНО МНОГО данных! Всё идет хорошо, когда вы располагаете большим количеством данных.

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

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

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

Что такое ошибка III типа? Это своего рода статистическая шутка: она относится к правильному отклонению неправильной нулевой гипотезы. Другими словами, использование правильной математики для ответа на неправильный вопрос.

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

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Философия преподавания Data Science и Deep Learning от fast.ai

23.06.2020 14:06:23 | Автор: admin
image

Рейчел Томас, соосновательница fast.ai, профессор USF Data Institute

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

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

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

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

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

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

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


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

В книге, которая нас вдохновляет, Дэвид Перкинс профессор Гарвардского университета с докторской степенью из МТИ (Массачусетского технологического института) в области искусственного интеллекта называет болезнью elementitis подход, при котором человек не приступает к сложной работе пока сперва не выучит все элементы по-отдельности. Это во многом похоже на тренировку с мячом, не имея представления о бейсболе. Элементы могут казаться скучными или бессмысленными, когда не знаешь, как они вписываются в большую картину. И довольно сложно оставаться мотивированным, когда ты даже не можешь решать волнующие тебя проблемы или понимать, как технические детали вписываются в целое. Возможно, именно поэтому исследования показали спад внутренней мотивации школьников, начиная с 3-его по 8-ой классы (единственный изученный диапазон лет).

Качественное образование дает вам возможность работать над интересующими вас вопросами


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

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


Вы уже посмотрели, как Джереми внедряет современные методы оптимизации глубокого обучения в Excel? Ещё нет? Тогда посмотрите (начало на 4:50 минуте в видео) и возвращайтесь. Это считается сложной темой, но после нескольких недель упорной работы Джереми смог упросить её до такой степени, что она стала максимально понятной. Если вы действительно разбираетесь в чем-то, вы также можете дать и доступное объяснение, а может и внедрить это в Excel! Запутанный жаргон и бестолковые технические определения возникают из-за лени или же когда говорящий не уверен в сути того, что говорит и просто прячется за своими периферийными знаниями.

Качественное образование инклюзивно


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

Качественное образование мотивирует изучение базовых технических концепций


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

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

Качественное образование поощряет ошибки


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

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

Качественное образование использует уже существующие ресурсы


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

Качественное образование поощряет креативность


image

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

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

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


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

Качественное образование основано на фактических данных


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

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Как создать свой первый open source проект на Python (17 шагов)

22.06.2020 18:15:30 | Автор: admin
Каждый разработчик ПО должен знать как создать библиотеку с нуля. В процессе работы Вы можете многому научиться. Только не забудьте запастись временем и терпением.

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

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

Шаг 1: Составьте план


Мы планируем создать простую библиотеку для использования в Python. Данная библиотека позволит пользователю легко конвертировать блокнот Jupyter в HTML-файл или Python-скрипт.
Первая итерация нашей библиотеки позволит вызвать функцию, которая выведет определенное сообщение.

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

Шаг 2: Дайте имя библиотеке


Придумывать имена сложно. Они должны быть короткими, уникальными и запоминающимися. Также они должны быть написаны строчными буквами, без прочерков и прочих знаков препинания. Подчеркивание не рекомендуется. В процессе создания библиотеки убедитесь, что придуманное Вами имя доступно на GitHub, Google и PyPi.

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

Шаг 3. Настройте среду


Убедитесь, что у вас установлены и настроены Python 3.7, GitHub и Homebrew. Если вам нужно что-то из этого, вот подробности:

Python


Скачайте Python 3.7 здесь и установите его.

GitHub


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

Homebrew


Homebrew менеджер библиотек для Mac. Инструкции по установке найдете здесь.

Venv


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

Начиная с версии Python 3.3 venv входит в систему по умолчанию. Обратите внимание, что venv устанавливает pip и setuptools начиная с Python 3.4.

Создайте виртуальную среду Python 3.7 с помощью следующей команды:

python3.7 -m venv my_env

Замените my_env вашим именем. Активируйте среду таким образом:

source my_env/bin/activate

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

Когда закончите работу, деактивируйте виртуальную среду с помощью deactivate.

Теперь давайте настроим GitHub.

Шаг 4: Создайте организацию в GitHub


GitHub лидер на рынке реестров контроля версий. Еще две популярные опции GitLab и Bitbucket. В данном гиде мы будем использовать именно GitHub.

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

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

image

Шаг 5: Настройте GitHub Repo


Создайте новый репозиторий. Я назвал свой notebookc.

image

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

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

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

image

Шаг 6: Клонируйте и добавьте директории


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

git clone https://github.com/notebooktoall/notebookc.git

Подставьте свою организацию и репозиторий.

Перейдите в папку проекта с помощью десктопного графического интерфейса или редактора кода. Или используйте командную строку с cd my-project и после просмотрите файлы с ls A.

Ваши исходные папки и файлы должны выглядеть так:

.git
.gitignore
LICENSE
README.rst


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

Создайте файл с именем __init__.py в основной вложенной папке. Этот файл пока останется пустым. Он необходим для импорта файлов.

Создайте еще один файл с таким же именем, как у основной вложенной папки, и добавьте .py. Мой файл называется notebookc.py. Вы можете назвать этот Python-файл как захотите. Пользователи библиотеки при импорте модуля будут ссылаться на имя этого файла.

Содержимое моей директории notebookc выглядит следующим образом:

.git
.gitignore
LICENSE
README.rst
notebookc/__init__.py
notebookc/notebookc.py


Шаг 7: Скачайте и установите requirements_dev.txt


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

В файле укажите, что должны быть установлены pip и wheel.

pip==19.0.3
wheel==0.33.1


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

Закрепите версии вашей библиотеку в requirements_dev.txt

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

В вашей активированной виртуальной среде установите библиотеку в файл needs_dev.txt с помощью следующей команды:

pip install -r requirements_dev.txt

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

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

Шаг 8: Поработайте с кодом


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

Вбейте следующее в Ваш основной файл (для меня это notebookc/notebookc/notebookc.py):

def convert(my_name):    """    Print a line about converting a notebook.    Args:        my_name (str): person's name    Returns:        None    """    print(f"I'll convert a notebook for you some day, {my_name}.")


Вот наша функция во всей красе.

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

Шаг 9: Создайте setup.py


Файл setup.py это скрипт сборки для вашей библиотеки. Функция setup из Setuptools создаст библиотеку для загрузки в PyPI. Setuptools содержит информацию о вашей библиотеке, номере версии и о том, какие другие библиотеки требуются для пользователей.

Вот мой пример файла setup.py:

from setuptools import setup, find_packageswith open("README.md", "r") as readme_file:    readme = readme_file.read()requirements = ["ipython>=6", "nbformat>=4", "nbconvert>=5", "requests>=2"]setup(    name="notebookc",    version="0.0.1",    author="Jeff Hale",    author_email="jeffmshale@gmail.com",    description="A package to convert your Jupyter Notebook",    long_description=readme,    long_description_content_type="text/markdown",    url="http://personeltest.ru/aways/github.com/your_package/homepage/",    packages=find_packages(),    install_requires=requirements,    classifiers=[        "Programming Language :: Python :: 3.7",        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",    ],)


Обратите внимание, что long_description установлен на содержимое файла README.md. Список требований (requirements), указанный в setuptools.setup.install_requires, включает в себя все необходимые зависимости для работы вашей библиотеки.

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

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

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

Сохраните свой код в локальном репозитории Git. Пора переходить к созданию библиотеки!

Шаг 10: Соберите первую версию


Twine это набор утилит для безопасной публикации библиотек Python на PyPI. Добавьте библиотеку Twine в следующую пустую строку файла require_dev.txt таким образом:

twine==1.13.0


Затем закрепите Twine в Вашей виртуальной среде, переустановив библиотеки needs_dev.txt.

pip install -r requirements_dev.txt


Затем выполните следующую команду, чтобы создать файлы библиотеки:

python setup.py sdist bdist_wheel


Необходимо создать несколько скрытых папок: dist, build и в моем случае notebookc.egg-info. Давайте посмотрим на файлы в папке dist. Файл .whl это файл Wheel встроенный дистрибутив. Файл .tar.gz является исходным архивом.

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

Шаг 11: Создайте учётную запись TestPyPI


PyPI каталог библиотек Python (Python Package Index). Это официальный менеджер библиотек Python. Если файлы не установлены локально, pip получает их оттуда.

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

Шаг 12: Опубликуйте библиотеку в PyPI


Используйте Twine для безопасной публикации вашей библиотеки в TestPyPI. Введите следующую команду никаких изменений не требуется.

twine upload --repository-url https://test.pypi.org/legacy/ dist/*


Вам будет предложено ввести имя пользователя и пароль. Не забывайте, что TestPyPI и PyPI имеют разные пароли!

При необходимости исправьте все ошибки, создайте новый номер версии в файле setup.py и удалите старые артефакты сборки: папки build, dist и egg. Перестройте задачу с помощью python setup.py sdist bdist_wheel и повторно загрузите с помощью Twine. Наличие номеров версий в TestPyPI, которые ничего не значат, особой роли не играют Вы единственный, кто будет использовать эти версии библиотек.

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

Шаг 13: Проверьте и используйте установленную библиотеку


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

python3.7 -m venv my_env


Активируйте ее.

source my_env/bin/activate


Если Вы уже загрузили свою библиотеку на официальный сайт PyPI, то сможете выполнить команду pip install your-package. Мы можем извлечь библиотеку из TestPyPI и установить его с помощью измененной команды.

Вот официальные инструкции по установке вашей библиотеки из TestPyPI:

Вы можете заставить pip загружать библиотеки из TestPyPI вместо PyPI, указав это в index-url.

pip install --index-url https://test.pypi.org/simple/ my_package


Если хотите, чтобы pip также извлекал и другие библиотеки из PyPI, Вы можете добавить extra-index-url для указания на PyPI. Это полезно, когда тестируемая библиотека имеет зависимости:

pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple my_package



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

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

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

python


Импортируйте свою функцию и вызовите ее со строковым аргументом. Вот как выглядит мой код:

from notebookc.notebookc import convert


convert(Jeff)


После я получаю следующий вывод:

Ill convert a notebook for you some day, Jeff.

(Когда-нибудь я конвертирую для тебя блокнот, Джефф)

Я в Вас верю.

Шаг 14: Залейте код на PyPI


Залейте Ваш код на настоящий сайт PyPI, чтобы люди могли скачать его с помощью pip install my_package.

Загрузить код можно так:

twine upload dist/*


Обратите внимание, что Вам нужно обновить номер версии в setup.py, если Вы хотите залить новую версию в PyPI.

Отлично, теперь давайте загрузим нашу работу на GitHub.

Шаг 15: Залейте библиотеку на GitHub


Убедитесь, что Ваш код сохранен.

Моя папка проекта notebookc выглядит так:

.git.gitignoreLICENSEREADME.mdrequirements_dev.txtsetup.pynotebookc/__init__.pynotebookc/notebookc.py


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

Переместите вашу локальную ветку на GitHub с помощью git push origin my_branch.

Шаг 16: Создайте и объедините PR


В браузере перейдите к GitHub. У Вас должна появиться опция сделать pull-запрос. Нажимайте на зеленые кнопки, чтобы создать, объединить PR и чтобы убрать удаленную ветку.
Вернувшись в терминал, удалите локальную ветку с git branch -d my_feature_branch.

Шаг 17: Обновите рабочую версию на GitHub


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

На сегодня достаточно!

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

Итог: 17 шагов к рабочей библиотеке



  1. Составьте план.
  2. Дайте имя библиотеке.
  3. Настройте среду.
  4. Создайте организацию в GitHub.
  5. Настройте GitHub Repo.
  6. Клонируйте и добавьте директории.
  7. Скачайте и установите requirements_dev.txt.
  8. Поработайте с кодом.
  9. Создайте setup.py.
  10. Соберите первую версию.
  11. Создайте учётную запись TestPyPI.
  12. Опубликуйте библиотеку в PyPI.
  13. Проверьте и используйте установленную библиотеку.
  14. Залейте код на PyPI.
  15. Залейте библиотеку на GitHub.
  16. Создайте и объедините PR.
  17. Обновите рабочую версию на GitHub.


image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Повелевать Webом с помощью Python

03.07.2020 20:16:17 | Автор: admin
Путешествие в простую веб-автоматизацию

image


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

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

image


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

Здесь я рассмотрю решение, разработанное мной для автоматической (и правильной) отправки моих заданий. Попутно мы рассмотрим основы использования Python и selenium для программного управления вебом. Хотя эта программа работает (я использую ее каждый день!), она довольно индивидуальна, поэтому вы не сможете скопировать и вставить код для своего приложения. Тем не менее, общие методы здесь могут быть применены к неограниченному числу ситуаций. (Если вы хотите увидеть полный код, он доступен на GitHub).

Подход


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

image

File structure (слева) и Complete Assignment (справа).

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

# os for file managementimport os# Build tuple of (class, file) to turn insubmission_dir = 'completed_assignments'dir_list = list(os.listdir(submission_dir))for directory in dir_list:    file_list = list(os.listdir(os.path.join(submission_dir, directory)))    if len(file_list) != 0:        file_tup = (directory, file_list[0])    print(file_tup)


('EECS491', 'Assignment 3 Inference in Larger Graphical Models.txt')

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

Веб-контроль с Selenium


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

import selenium# Using Chrome to access webdriver = webdriver.Chrome()# Open the websitedriver.get('https://canvas.case.edu')


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

image

Представьте, что веб-драйвер это человек, который никогда раньше не видел веб-страницу: нам нужно точно сказать, куда нажимать, что печатать и какие кнопки нажимать. Есть несколько способов сообщить нашему веб-драйверу, какие элементы найти, и все они используют селекторы. Селектор это уникальный идентификатор элемента на веб-странице. Чтобы найти селектор для определенного элемента, скажем, поле CWRU ID, нам нужно посмотреть код веб-страницы. В Chrome это можно сделать, нажав Ctrl + Shift + I или щелкнув правой кнопкой мыши на любом элементе и выбрав Посмотреть код. Это открывает инструменты разработчика Chrome, чрезвычайно полезное приложение, которое показывает HTML, лежащий в основе любой веб-страницы.

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

image

Этот HTML может выглядеть подавляющим, но мы можем игнорировать большую часть информации и сосредоточиться на частях id = "username" и name = "username". (они известны как атрибуты тега HTML).
Чтобы выбрать поле id с помощью нашего веб-драйвера, мы можем использовать атрибут id или name, который мы нашли в инструментах разработчика. Веб-драйверы в Selenium имеют много разных способов выбора элементов на веб-странице, и часто есть несколько способов выбрать один и тот же элемент:

# Select the id boxid_box = driver.find_element_by_name('username')# Equivalent Outcome! id_box = driver.find_element_by_id('username')


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

# Send id informationid_box.send_keys('my_username')


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

# Find password boxpass_box = driver.find_element_by_name('password')# Send passwordpass_box.send_keys('my_password')# Find login buttonlogin_button = driver.find_element_by_name('submit')# Click loginlogin_button.click()

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

image

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

# Find and click on list of coursescourses_button = driver.find_element_by_id('global_nav_courses_link')courses_button.click()# Get the name of the folderfolder = file_tup[0]    # Class to select depends on folderif folder == 'EECS491':    class_select = driver.find_element_by_link_text('Artificial Intelligence: Probabilistic Graphical Models (100/10039)')elif folder == 'EECS531':    class_select = driver.find_element_by_link_text('Computer Vision (100/10040)')# Click on the specific classclass_select.click()


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

image

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

image

В этот момент я мог видеть финишную черту, но изначально этот экран меня озадачил. Я мог бы довольно легко нажать на поле Выбрать файл, но как я должен был выбрать нужный файл для загрузки? Ответ оказывается невероятно простым! Мы находим поле Choose File с помощью селектора и используем метод send_keys для передачи точного пути к файлу (называемого file_location в приведенном ниже коде) к блоку:

# Choose File buttonchoose_file = driver.find_element_by_name('attachments[0][uploaded_data]')# Complete path of the filefile_location = os.path.join(submission_dir, folder, file_name)# Send the file location to the buttonchoose_file.send_keys(file_location)


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

image

Теперь мы выбираем кнопку Отправить задание, нажимаем, и наше задание отправлено!

# Locate submit button and clicksubmit_assignment = driver.find_element_by_id('submit_file_button')submit_assignent.click()


image


Уборка


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

# Location of files after submissionsubmitted_file_location = os.path.join(submitted_dir, submitted_file_name)# Rename essentially copies and pastes filesos.rename(file_location, submitted_file_location)


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

Вот как это выглядит, когда я запускаю программу:

image

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

image

Пока программа работает, я могу наблюдать, как Python работает на меня:

image

Выводы


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

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

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Python для начинающих как повелевать Webом

03.07.2020 22:11:07 | Автор: admin
Путешествие в простую веб-автоматизацию

image


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

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

image


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

Здесь я рассмотрю решение, разработанное мной для автоматической (и правильной) отправки моих заданий. Попутно мы рассмотрим основы использования Python и selenium для программного управления вебом. Хотя эта программа работает (я использую ее каждый день!), она довольно индивидуальна, поэтому вы не сможете скопировать и вставить код для своего приложения. Тем не менее, общие методы здесь могут быть применены к неограниченному числу ситуаций. (Если вы хотите увидеть полный код, он доступен на GitHub).

Подход


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

image

File structure (слева) и Complete Assignment (справа).

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

# os for file managementimport os# Build tuple of (class, file) to turn insubmission_dir = 'completed_assignments'dir_list = list(os.listdir(submission_dir))for directory in dir_list:    file_list = list(os.listdir(os.path.join(submission_dir, directory)))    if len(file_list) != 0:        file_tup = (directory, file_list[0])    print(file_tup)


('EECS491', 'Assignment 3 Inference in Larger Graphical Models.txt')

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

Веб-контроль с Selenium


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

import selenium# Using Chrome to access webdriver = webdriver.Chrome()# Open the websitedriver.get('https://canvas.case.edu')


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

image

Представьте, что веб-драйвер это человек, который никогда раньше не видел веб-страницу: нам нужно точно сказать, куда нажимать, что печатать и какие кнопки нажимать. Есть несколько способов сообщить нашему веб-драйверу, какие элементы найти, и все они используют селекторы. Селектор это уникальный идентификатор элемента на веб-странице. Чтобы найти селектор для определенного элемента, скажем, поле CWRU ID, нам нужно посмотреть код веб-страницы. В Chrome это можно сделать, нажав Ctrl + Shift + I или щелкнув правой кнопкой мыши на любом элементе и выбрав Посмотреть код. Это открывает инструменты разработчика Chrome, чрезвычайно полезное приложение, которое показывает HTML, лежащий в основе любой веб-страницы.

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

image

Этот HTML может выглядеть подавляющим, но мы можем игнорировать большую часть информации и сосредоточиться на частях id = "username" и name = "username". (они известны как атрибуты тега HTML).
Чтобы выбрать поле id с помощью нашего веб-драйвера, мы можем использовать атрибут id или name, который мы нашли в инструментах разработчика. Веб-драйверы в Selenium имеют много разных способов выбора элементов на веб-странице, и часто есть несколько способов выбрать один и тот же элемент:

# Select the id boxid_box = driver.find_element_by_name('username')# Equivalent Outcome! id_box = driver.find_element_by_id('username')


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

# Send id informationid_box.send_keys('my_username')


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

# Find password boxpass_box = driver.find_element_by_name('password')# Send passwordpass_box.send_keys('my_password')# Find login buttonlogin_button = driver.find_element_by_name('submit')# Click loginlogin_button.click()

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

image

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

# Find and click on list of coursescourses_button = driver.find_element_by_id('global_nav_courses_link')courses_button.click()# Get the name of the folderfolder = file_tup[0]    # Class to select depends on folderif folder == 'EECS491':    class_select = driver.find_element_by_link_text('Artificial Intelligence: Probabilistic Graphical Models (100/10039)')elif folder == 'EECS531':    class_select = driver.find_element_by_link_text('Computer Vision (100/10040)')# Click on the specific classclass_select.click()


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

image

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

image

В этот момент я мог видеть финишную черту, но изначально этот экран меня озадачил. Я мог бы довольно легко нажать на поле Выбрать файл, но как я должен был выбрать нужный файл для загрузки? Ответ оказывается невероятно простым! Мы находим поле Choose File с помощью селектора и используем метод send_keys для передачи точного пути к файлу (называемого file_location в приведенном ниже коде) к блоку:

# Choose File buttonchoose_file = driver.find_element_by_name('attachments[0][uploaded_data]')# Complete path of the filefile_location = os.path.join(submission_dir, folder, file_name)# Send the file location to the buttonchoose_file.send_keys(file_location)


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

image

Теперь мы выбираем кнопку Отправить задание, нажимаем, и наше задание отправлено!

# Locate submit button and clicksubmit_assignment = driver.find_element_by_id('submit_file_button')submit_assignent.click()


image


Уборка


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

# Location of files after submissionsubmitted_file_location = os.path.join(submitted_dir, submitted_file_name)# Rename essentially copies and pastes filesos.rename(file_location, submitted_file_location)


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

Вот как это выглядит, когда я запускаю программу:

image

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

image

Пока программа работает, я могу наблюдать, как Python работает на меня:

image

Выводы


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

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

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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Мобильная разработка индивидуально или в команде?

18.06.2020 18:21:58 | Автор: admin


Привет! Как многим известно, Mail.ru Group ведет образовательные проекты для студентов в 9 вузах: МГТУ им. Баумана, МГУ, МИФИ, МФТИ, СпбПУ, Мосполитех, МАИ, ВГУ и ПГУ. Среди 70 дисциплин есть курсы по мобильной разработке под платформы Android и iOS.

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

Как работает индивидуальный подход?


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

Среди недостатков индивидуального обучения можно выделить отсутствие обмена опытом. Работая в одиночку можно полагаться только на свой опыт, которого определенно меньше, чем у команды из 34 человек. Кроме того, работая в одиночку, нельзя повысить уровень технических навыков для работы в команде. Например, работа с gitом упрощается до add, commit, push. И нет шанса испытать ни реального git flow, ни проблем которых он решает, ни проблем, которые встретятся в реальных проектах.



Как работает командный подход?


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

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

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

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

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

При этом у командного подхода тоже можно выделить некоторые минусы.

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

Подводим итоги

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

Перевод - recovery mode Что должен знать Data Scientist про когнитивные искажения ИИ

25.06.2020 16:23:50 | Автор: admin
image

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

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

  • В статистике: искажение (bias) это разница между ожиданием оцениваемой величины и ее значением. Такое определение жутко формально, так что позвольте мне его перевести. Искажение описывает результаты, которые систематически не соответствуют ожиданиям. Представьте себе стрельбу из лука, у которого сбит прицел. Высокий уровень искажения не означает, что вы стреляете куда угодно (в этом случае речь идет о дисперсии), суть будет заключаться в том, что даже идеальный лучник будет постоянно промахиваться. В данном контексте слово искажение несет в себе небольшой эмоциональный оттенок.
  • В сборе данных (а также в статистике): когда вы собираете данные, ваша выборка может не являться репрезентативной для интересующей вас совокупности. Искажение выборки в данном случае формальный термин. Такое искажение означает, что ваши статистические результаты могут содержать ошибки.
  • В когнитивной психологии: систематическое искажение от рационального. Каждое слово в этом содержательном определении, кроме от, заряжено нюансами, специфическими для данной области. Перевод на понятный язык: речь идет об удивительном факте, заключающемся в том, что ваш мозг развил определенные способы реакции на различные объекты, и психологи изначально сочли эти реакции искажениями. Список когнитивных искажений поражает.
  • В нейросетевых алгоритмах: По сути, речь идет об отрезке, отсекаемом с координатной оси. (искажение звучит круче, чем школьные математические термины, да?)
  • В социальных и физических науках: Любое из множества явлений, связанных с чрезмерным влиянием прошлых/актуальных условий на решения, принимаемые в настоящее время. Примерами также являются культурные предрассудки и инфраструктурная предвзятость.
  • В электронике: Фиксированное постоянное напряжение или ток, приложенные в цепи с переменным током.
  • В географии: Биас, в Западной Вирджинии. (от англ. Bias) (Я слышал, что Биас есть и в Франции).
  • В мифологии: Любой из этих древних греков.
  • О чем думает большинство экспертов по ИИ: речь об алгоритмических искажение идет тогда, когда компьютерная система отражает подсознательные ценности человека, который ее создал (разве не все, что создают люди, отражает подсознательные ценности?).
  • О чем думает большинство людей? О том, что наш опыт искажает наше восприятие и реакцию на информацию, особенно в контексте несправедливого отношения к другим людям и плохих поступков вообще. Некоторые люди используют это слово как синоним предрассудков.


Ох. У термина искажение много значений, и некоторые из них более острые, чем другие.

О чем идет речь в области машинного обучения и ИИ?


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

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

Весь смысл ИИ в том, чтобы дать вам возможность объяснить свои пожелания компьютеру на примерах (данных!), а не в инструкциях. Каких примерах? Это ваш выбор в качестве учителя. Датасеты это учебники, по которым ваш ученик может учиться. И знаете что? У учебников есть авторы-люди, как и у наборов данных.

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


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

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

Искажения исходят не от алгоритмов ИИ, они исходят от людей.


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

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Как стать Data Scientist без онлайн-курсов

17.06.2020 14:20:13 | Автор: admin
image

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

Хотите стать data scientists?

Я познакомился с более 50-ю data scientists и с еще парочкой поработал лично.

Здесь я расскажу, как эти люди пришли в Data Science. Без онлайн-курсов.

1. Решите задачу с помощью машинного обучения


Выберите реальную проблему, и решите ее с помощью машинного обучения.

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

Вот примеры задач, которые вы можете попробовать разрешить:

  • Распознавание фейковых новостей
  • Прогнозирование стоимости жилья в вашем районе
  • Подбор домашних питомцев в зависимости от образа жизни потенциальных хозяев

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

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

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

2. Найдите ментора эксперта по искусственному интеллекту


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

Именно так мне удалось ворваться в науку о данных.

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

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

Чтобы найти новых менторов по науке о данных, я делал следующее.

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

3. Пройдите стажировку по машинному обучению


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

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

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

Крайне важно, чтобы в вашем резюме было упоминание о работе с ИИ.

4. Начните заниматься Data Scienсe уже на вашей нынешней работе


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

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

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

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

5. Организуйте буткемп по Data Science


Посетите платный буткемп по Data Science.

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

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

В чем польза буткемпов.

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

Тем не менее, не каждый выпускник получает работу.

6. Сначала станьте программным инженером


Я писал об этом здесь.

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

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

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

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

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


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


У вас есть 2 года или 6 лет, чтобы отучиться? У меня лично нет.

Но большинство моих знакомых- исследователей данных, пошли по этому пути.

Они либо:

  • получили степень магистра в области, связанной с ИИ
  • защитили кандидатскую ( PhD) в технической области (не обязательно близкой к ИИ)

Я бы не посоветовал возвращаться в школу(универ), чтобы заняться Data Science. Но если сейчас вы учитесь в какой-то школе, вы можете продолжить свое обучение и получить степень в области ИИ. Как ни странно, но самые высокие зарплаты в сфере ИИ получают люди с высшим образованием.

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

А что там с онлайн-курсами?


Да, онлайн курсы имеют место БТЬ. Но не для того, чтобы получить работу.

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

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

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

У вас есть примеры того, как люди пришли в Data Science? Давайте обсудим.

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Перевод Видеоигры это будущее образования (размышления программиста из Palantir)

28.06.2020 02:16:08 | Автор: admin
Подписывайтесь на канал @META ОБУЧЕНИЕ, где я делюсь своими самыми полезными находками про образование и роль ИТ/игр в образовании (а так же мыслями на эту тему Антона Макаренко, Сеймура Пейперта, Пола Грэма, Джозефа Ликлайдера, Алана Кея)

В подростковом возрасте моё реальное образование складывалось из:

  1. книг, которые я сам выбирал
  2. обучения программированию (самостоятельного)
  3. видеоигр (которые находил сам)
  4. математики (из школьной программы)

Пункты 1-3 не связаны с формальным школьным образованием и сформировались даже скорее вопреки ему. О нечто подобном писал Пол Грэм:



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

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

Поэтому я считаю, что:

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



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

  • Компьютерная игра Kerbal Space Program знаменита тем, что делает своих игроков экспертами в астродинамике.
  • Авиасимуляторы и симуляторы боевых действий готовят пилотов и военнослужащих.
  • Игра Factorio обучает вас законам капитализма, производства и экономики.
  • Среды программирования это симуляции вселенной языка программирования с быстрой обратной связью (написать код -> отладить код).


image

Видеоигра это просто:

(а) симуляция реальности
(б) с быстрой обратной связью.

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

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

(Кстати, это работает не только для абстрактных концепций, таких как астродинамика, но и для этических норм. К примеру, мое понимание героизма по сей день сформировано играми Final Fantasy и Metal Gear Solid. Также можно объяснить и ценность художественной литературы: можно получить телесные знания об отчаянии, прочитав Достоевского, и о ревности, прочитав В сторону Свана и др.)

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



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

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

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

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

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



Одно высказывание об интернете особенно хорошо мне запомнилось. Оно принадлежит Эвану Уильямсу, основателю Twitter/Blogger/Medium. Он как-то сказал, что лучший способ создать гигантскую интернет-компанию это взять то, что люди хотят сделать, и сделать это в 10 раз проще.

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

Нам кажется, что интернет позволяет делать что-то новое", говорит Уильямс. Но люди просто хотят делать то же, что и всегда.

(...)

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


Упростить создание вещей это мегатренд эпохи интернета:

  • Blogger/Medium/Wordpress (и Хабр) позволяют легко писать в интернете;
  • Subpack позволяет легко настраивать информационные рассылки
  • YouTube и TikTok позволяют легко создавать видео;
  • Ableton позволяет легко делать музыку и т. д.


Другой момент связан с тем, что упрощение имеет нелинейный эффект. Упрощение чего-либо в 10 раз приводит к тому, что что-то появляется в 1000-кратном количестве. Отсюда и взрыв онлайн-творчества на YouTube: множество видео по шахматам, Minecraft, математике, Академии Хана, стримы на Twitch, Soundcloud и др.; вы убираете некоторые сложности и получаете грандиозный результат.

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

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

Несколько важных замечаний:

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

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

И последнее: именно поэтому ИИ имеет важное значение для производительности человека. В основном речь идет о том, как ИИ заменит людей. Я придерживаюсь позиции Ликлайдера: симбиоз человека и компьютера. ИИ сделает людей более эффективными, автоматизируя утомительные задачи. Например, люди могут использовать текстовый ИИ, такой как GPT-3, чтобы генерировать идеи/шаблонное письмо, чтобы избежать страха перед пустой страницей, а затем выбирать лучшие примеры и их дорабатывать/итерировать. (AI Dril, который был создан на основе GPT-2, как раз был таким ранним примером). По мере того как искусственный интеллект будет совершенствоваться, вспомогательное творчество станет все более употребимым явлением, позволяющим людям создавать сложные артефакты (в том числе видеоигры!) как никогда проще и лучше.

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

Спасибо Саку П за то, что он прочитал мой черновик.

Обновление: интересные обсуждения на Hacker News.



Подписывайтесь на канал @META ОБУЧЕНИЕ, где я делюсь своими самыми полезными находками про образование и роль ИТ/игр в образовании (а так же мыслями на эту тему Антона Макаренко, Сеймура Пейперта, Пола Грэма, Джозефа Ликлайдера, Алана Кея)

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:



Читать еще


Подробнее..

Категории

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

© 2006-2020, personeltest.ru