4 полезных приема работы с Python
Перевод статьи «4 Ways To Level Up Your Python Code».
Один из плюсов Python — с его помощью можно заставить работать что угодно.
Еще один плюс — множество скрытых фишек, которые не только облегчают написание кода, но и делают код «чище» и удобнее для чтения.
В этой статье мы разберем фишки, которые помогут вам отточить ваши навыки.
1. Забудьте о range(len()). Наш выбор — enumerate()
Функция enumerate возвращает enumerate-объект, который хранит в себе и индексы элементов, и их значения.
С помощью этой функции вы облегчите доступ и к индексам, и к значениям.
Допустим, мы объявили словарь:
Например, при попытке получить доступ к несуществующему значению ‘место жительства’ мы получим ошибку KeyError :
3. Облегчите перебор нескольких списков с помощью zip()
Порой возникают ситуации, когда у нас есть несколько коллекций (например, списков) и все их нужно перебрать.
Как видите, в результате мы получаем список, содержащий кортежи с элементами из каждого списка.
Этот способ, конечно, рабочий. Но если коллекций станет слишком много, код выйдет громоздким.
С помощью встроенной функции zip() мы можем все немного упростить.
А теперь рассмотрим тот же пример и снова вернем список кортежей:
Выглядит намного лучше, не так ли?
Также вы можете преобразовывать коллекции в словари напрямую. Но обратите внимание — коллекций должно быть только две.
4. Используем f-строки для упрощения вывода информации в консоль
Вместо этого вы можете написать:
Изменение это небольшое, но довольно важное. Благодаря ему вы не просто избавитесь от повторений в коде, но и упростите его чтение.
Заключение
Возьмите все эти четыре совета на заметку : благодаря им ваш код будет стабильнее. Еще один плюс — ваш код будет выглядеть гораздо совершеннее и утонченнее.
Питонистический подход к циклам for: range() и enumerate()
Автор заметки, перевод которой мы сегодня публикуем, хочет рассказать о некоторых особенностях использования циклов for в Python.
Цикл for — это один из краеугольных камней программирования. С этими циклами будущие программисты знакомятся в самом начале учёбы и, после первого знакомства, пользуются ими постоянно.
Если вы занялись разработкой на Python, имея опыт работы с другим популярным языком программирования, вроде PHP или JavaScript, то вам знакома методика применения переменной-счётчика, хранящей, например, индекс текущего элемента массива, обрабатываемого в цикле. Вот пример работы с циклом, написанный на JavaScript:
Работая с циклами for очень важно понимать то, что эти циклы не перебирают массивы. Они лишь дают программисту механизм для работы с переменной-счётчиком, которая используется для обращения к элементам обрабатываемых массивов.
Старый (неудачный) способ работы с массивами
В результате вы можете обнаружить функцию range() и написать на Python нечто подобное следующему:
Проблема этого цикла заключается в том, что он не очень хорошо соответствует идеологии Python. В нём мы не перебираем список, а, вместо этого, используем вспомогательную переменную i для обращения к элементам списка.
Использование функции enumerate()
Эта функция принимает два аргумента: итерируемый объект и необязательное начальное значение счётчика.
Такой код получился гораздо чище кода из предыдущего примера. Мы ушли от работы со списком индексов, мы перебираем сами значения, получая к ним прямой доступ в цикле for, и видим значения, с которыми работаем, в объявлении цикла.
Итоги
Надеюсь, этот небольшой рассказ о циклах for в Python позволил вам узнать что-то новое об этом языке.
Python для начинающих: all, any, zip, enumerate, filter, map
В руководстве речь пойдет о шести полезных в разработке встроенных функциях Python. Вне зависимости от того, насколько вы опытны в программировании, эти шесть функций определенно сэкономят время и усилия. Поэтому не помешает их повторить или выучить.
1. all(iterable)
2. any(iterable)
3. zip (interable1, interable2, interable3, …)
Функция zip() принимает любое количество итерабельных объектов. Помните, что итерабельный объект — это любая коллекция, такая как список, кортеж, множество словарь или диапазон. Снова обратите внимание, что при обработке словаря функция просматривает только ключ, но не значения.
Объект zip можно обойти в цикле следующим образом:
4. enumerate (iterable, start=0)
Объект enumerate можно обойти в цикле следующим образом:
5. filter (function, iterable)
При желании напишите лямбда-выражение вместо функции, выступающей в качестве условия для фильтрации итерабельного объекта.
6. map (function, iterable)
Как и ранее, вместо функции можно написать лямбда-выражение.
Рассмотрите внимательно пример перебора функцией map нескольких итерабельных объектов:
В примере функция map() возвращает список с суммами чисел из разных коллекций по общим индексам.
Выводы
Скорее всего, шесть рассмотренных функций принесут вам пользу в разработке проектов на Python. При правильном использовании они, безусловно, ускорят процесс разработки и сделают код чище. Большое спасибо за прочтение!
Трюки Pandas от RealPython
К старту флагманского курса по Data Science делимся сокращённым переводом из блога RealPython о трюках с Pandas, материал начинается с конфигурирования запуска библиотеки и заканчиваются примерами работы с операторами и их приоритетом. Затрагивается тема экономии памяти, сжатие фреймов, интроспекция GroupBy через итерацию и другие темы. Подробности, как всегда, под катом.
1. Параметры запуска интерпретатора
Запустив сеанс интерпретатора, вы увидите, что сценарий запуска выполнен и Pandas автоматически импортируется с вашим набором опций:
Воспользуемся данными abalone в репозитории машинного обучения UCI, чтобы продемонстрировать заданное в файле запуска форматирование. Сократим данные до 14 строк с точностью до 4 цифр для чисел с плавающей точкой:
Позже вы увидите этот набор данных и в других примерах.
2. Игрушечные cтруктуры данных с помощью модуля тестирования Pandas
В модуле Pandas testing скрыт ряд удобных функций для быстрого построения квазиреалистичных Series и фреймов данных:
Их около 30, полный список можно увидеть, вызвав dir() на объекте модуля. Вот несколько вариантов:
Они полезны для бенчмаркинга, тестирования утверждений и экспериментов с не очень хорошо знакомыми методами Pandas.
3. Используйте преимущества методов доступа
Возможно, вы слышали о термине акcессор, который чем-то напоминает геттер (хотя геттеры и сеттеры используются в Python нечасто). В нашей статье будем называть аксессором свойство, которое служит интерфейсом для дополнительных методов. В Series [на момент написания оригинальной статьи] их три, сегодня их 4:
Да, приведённое выше определение многозначно, поэтому до обсуждения внутреннего устройства посмотрим на примеры.
.cat — для категориальных данных;
.str — для строковых (объектных) данных;
.dt — для данных, подобных времени.
4. Создание индекса времени даты из столбцов компонентов
Наконец, вы можете отказаться от старых отдельных столбцов и преобразовать их в Series:
Интуитивно суть передачи фрейма данных в том, что DataFrame похож на словарь Python, где имена столбцов — это ключи, а отдельные столбцы (Series) — значения словаря. Поэтому pd.to_datetime (df[datecols].to_dict (orient=’list’)) здесь также будет работать.
5. Использование категориальных данных для экономии времени и места
А что если бы мы могли взять перечисленные выше уникальные цвета и отобразить каждый из них в занимающее меньше места целое число? Наивная реализация:
Другой способ сделать то же самое в Pandas — pd.factorize (colors) :
Так или иначе объект кодируется как перечислимый тип (категориальная переменная).
«Использование памяти Categorical пропорционально количеству категорий плюс длина данных. Напротив, object dtype — это константа, умноженная на длину данных» (Источник).
В colors выше есть соотношение двух значений на каждое уникальное значение, то есть на категорию:
Экономия памяти от преобразования в Categorical хороша, но невелика:
Но, если у вас будет, например, много демографических данных, где мало уникальных значений, объём требуемой памяти уменьшится в 10 раз:
Можно воспроизвести что-то похожее на пример выше, который делался вручную:
Всё, что вам нужно сделать, чтобы в точности повторить предыдущий ручной вывод, — это изменить порядок кодов:
Обратите внимание, что dtype — это int8 NumPy, 8-битное знаковое целое, которое может принимать значения от −127 до 128. Для представления значения в памяти требуется только один байт. 64-битные знаковые int были бы излишеством с точки зрения потребления памяти. Грубый пример привёл к данным int64 по умолчанию, тогда как Pandas достаточно умна, чтобы привести категориальные данные к минимально возможному числовому dtype.
6. Интроспекция объектов Groupby через итерацию
При вызове df.groupby (‘x’) результирующие объекты Pandas groupby могут быть немного непрозрачными. Этот объект инстанцируется лениво и сам по себе не имеет никакого осмысленного представления. Продемонстрируем это на наборе данных abalone из первого примера:
7. Используйте этот трюк с отображением для бининга
Представьте: есть Series и соответствующая «таблица сопоставления», где каждое значение принадлежит к многочленной группе или вообще не принадлежит ни одной группе:
Другими словами, вам нужно сопоставить countries со следующим результатом:
Код значительно быстрее, чем вложенный цикл Python по группам для каждой страны:
Задача — сопоставить каждую группу в groups целому числу. Однако Series.map() не распознаёт ‘ab’ — ему нужна разбитая версия, где каждый символ из каждой группы отображён на целое число. Это делается охватом словаря:
Этот словарь может передаваться в s.map() для сопоставления или «перевода» его значений в соответствующие индексы групп.
8. Загрузка данных из буфера обмена
Это позволяет копировать структурированный текст непосредственно в DataFrame или Series. В Excel данные будут выглядеть примерно так:
Его текстовое представление может выглядеть так:
Просто выделите и скопируйте текст выше и вызовите pd.read_clipboard() :
9. Запись объектов Pandas в сжатый формат
Этот короткий пример завершает список. Начиная с версии Pandas 0.21.0 вы можете записывать объекты Pandas непосредственно для сжатия gzip, bz2, zip или xz, а не хранить несжатый файл в памяти и преобразовывать его. Вот пример, использующий данные abalone из первого трюка:
Коэффициент разницы в размерах равен 11,6:
Data Science — это не только статистика, но и написание кода, который с учётом работы с большими данными должен быть эффективным. В этом одна из причин высокой зарплаты специалиста в науке о данных, стать которым мы можем помочь вам на нашем курсе. Также вы можете узнать, как начать карьеру аналитика или инженера данных, начать с нуля или прокачаться в других направлениях, например, в Fullstack-разработке на Python:
Data Science и Machine Learning
Python + OpenCV + Keras: делаем распознавалку текста за полчаса
После экспериментов с многим известной базой из 60000 рукописных цифр MNIST возник логичный вопрос, есть ли что-то похожее, но с поддержкой не только цифр, но и букв. Как оказалось, есть, и называется такая база, как можно догадаться, Extended MNIST (EMNIST).
Если кому интересно, как с помощью этой базы можно сделать несложную распознавалку текста, добро пожаловать под кат.
Примечание: данный пример экспериментальный и учебный, мне было просто интересно посмотреть, что из этого получится. Делать второй FineReader я не планировал и не планирую, так что многие вещи тут, разумеется, не реализованы. Поэтому претензии в стиле «зачем», «уже есть лучше» и пр, не принимаются. Наверно готовые OCR-библиотеки для Python уже есть, но было интересно сделать самому. Кстати, для тех кто хочет посмотреть, как делался настоящий FineReader, есть две статьи в их блоге на Хабре за 2014 год: 1 и 2 (но разумеется, без исходников и подробностей, как и в любом корпоративном блоге). Ну а мы приступим, здесь все открыто и все open source.
Для примера мы возьмем простой текст. Вот такой:
HELLO WORLD
И посмотрим что с ним можно сделать.
Разбиение текста на буквы
Первым шагом разобьем текст на отдельные буквы. Для этого пригодится OpenCV, точнее его функция findContours.
Откроем изображение (cv2.imread), переведем его в ч/б (cv2.cvtColor + cv2.threshold), слегка увеличим (cv2.erode) и найдем контуры.
Мы получаем иерархическое дерево контуров (параметр cv2.RETR_TREE). Первым идет общий контур картинки, затем контуры букв, затем внутренние контуры. Нам нужны только контуры букв, поэтому я проверяю что «родительским» является общий контур. Это упрощенный подход, и для реальных сканов это может не сработать, хотя для распознавания скриншотов это некритично.
Следующим шагом сохраним каждую букву, предварительно отмасштабировав её до квадрата 28х28 (именно в таком формате хранится база MNIST). OpenCV построен на базе numpy, так что мы можем использовать функции работы с массивами для кропа и масштабирования.
В конце мы сортируем буквы по Х-координате, также как можно видеть, мы сохраняем результаты в виде tuple (x, w, letter), чтобы из промежутков между буквами потом выделить пробелы.
Убеждаемся что все работает:
Буквы готовы для распознавания, распознавать их мы будем с помощью сверточной сети — этот тип сетей неплохо подходит для таких задач.
Нейронная сеть (CNN) для распознавания
Исходный датасет EMNIST имеет 62 разных символа (A..Z, 0..9 и пр):
Нейронная сеть соответственно, имеет 62 выхода, на входе она будет получать изображения 28х28, после распознавания «1» будет на соответствующем выходе сети.
Создаем модель сети.
Как можно видеть, это классическая сверточная сеть, выделяющая определенные признаки изображения (количество фильтров 32 и 64), к «выходу» которой подсоединена «линейная» сеть MLP, формирующая окончательный результат.
Обучение нейронной сети
Переходим к самому продолжительному этапу — обучению сети. Для этого мы возьмем базу EMNIST, скачать которую можно по ссылке (размер архива 536Мб).
Для чтения базы воспользуемся библиотекой idx2numpy. Подготовим данные для обучения и валидации.
Мы подготовили два набора, для обучения и валидации. Сами символы представляют собой обычные массивы, которые несложно вывести на экран:
Также мы используем лишь 1/10 датасета для обучения (параметр k), в противном случае процесс займет не менее 10 часов.
Запускаем обучение сети, в конце процесса сохраняем обученную модель на диск.
Сам процесс обучения занимает около получаса:
Это нужно сделать только один раз, дальше мы будем пользоваться уже сохраненным файлом модели. Когда обучение закончено, все готово, можно распознавать текст.
Распознавание
Для распознавания мы загружаем модель и вызываем функцию predict_classes.
Как оказалось, изображения в датасете изначально были повернуты, так что нам приходится повернуть картинку перед распознаванием.
Окончательная функция, которая на входе получает файл с изображением, а на выходе дает строку, занимает всего 10 строк кода:
Здесь мы используем сохраненную ранее ширину символа, чтобы добавлять пробелы, если промежуток между буквами более 1/4 символа.
Результат:
Забавная особенность — нейронная сеть «перепутала» букву «О» и цифру «0», что впрочем, неудивительно т.к. исходный набор EMNIST содержит рукописные буквы и цифры, которые не совсем похожи на печатные. В идеале, для распознавания экранных текстов нужно подготовить отдельный набор на базе экранных шрифтов, и уже на нем обучать нейросеть.
Заключение
Как можно видеть, не боги горшки обжигают, и то что казалось когда-то «магией», с помощью современных библиотек делается вполне несложно.
Поскольку Python является кроссплатформенным, работать код будет везде, на Windows, Linux и OSX. Вроде Keras портирован и на iOS/Android, так что теоретически, обученную модель можно использовать и на мобильных устройствах.
Для желающих поэкспериментировать самостоятельно, исходный код под спойлером.







