- •Об авторе
- •Предисловие
- •Для кого эта книга
- •О чем эта книга
- •Что вам потребуется при чтении этой книги
- •Условные обозначения
- •От издательства
- •Глава 1. Обзор алгоритмов
- •Что такое алгоритм
- •Этапы алгоритма
- •Определение логики алгоритма
- •Псевдокод
- •Использование сниппетов
- •Создание плана выполнения
- •Введение в библиотеки Python
- •Библиотеки Python
- •Реализация Python с помощью Jupyter Notebook
- •Методы разработки алгоритмов
- •Параметры данных
- •Параметры вычислений
- •Анализ производительности
- •Анализ пространственной сложности
- •Анализ временной сложности
- •Оценка эффективности
- •Выбор алгоритма
- •«О-большое»
- •Проверка алгоритма
- •Точные, приближенные и рандомизированные алгоритмы
- •Объяснимость алгоритма
- •Резюме
- •Глава 2. Структуры данных, используемые в алгоритмах
- •Структуры данных в Python
- •Список
- •Кортеж
- •Словарь
- •Множество
- •DataFrame
- •Матрица
- •Абстрактные типы данных
- •Вектор
- •Стек
- •Очередь
- •Базовый принцип использования стеков и очередей
- •Дерево
- •Резюме
- •Глава 3. Алгоритмы сортировки и поиска
- •Алгоритмы сортировки
- •Обмен значений переменных в Python
- •Сортировка пузырьком
- •Сортировка вставками
- •Сортировка слиянием
- •Сортировка Шелла
- •Сортировка выбором
- •Алгоритмы поиска
- •Линейный поиск
- •Бинарный поиск
- •Интерполяционный поиск
- •Практическое применение
- •Резюме
- •Глава 4. Разработка алгоритмов
- •Знакомство с основными концепциями разработки алгоритма
- •Вопрос 1. Даст ли разработанный алгоритм ожидаемый результат?
- •Вопрос 2. Является ли данный алгоритм оптимальным способом получения результата?
- •Вопрос 3. Как алгоритм будет работать с большими наборами данных?
- •Понимание алгоритмических стратегий
- •Стратегия «разделяй и властвуй»
- •Стратегия динамического программирования
- •Жадные алгоритмы
- •Практическое применение — решение задачи коммивояжера
- •Использование стратегии полного перебора
- •Использование жадного алгоритма
- •Алгоритм PageRank
- •Постановка задачи
- •Реализация алгоритма PageRank
- •Знакомство с линейным программированием
- •Практическое применение — планирование производства с помощью линейного программирования
- •Резюме
- •Глава 5. Графовые алгоритмы
- •Представление графов
- •Типы графов
- •Особые типы ребер
- •Эгоцентрические сети
- •Анализ социальных сетей
- •Введение в теорию сетевого анализа
- •Кратчайший путь
- •Создание окрестностей
- •Показатели центральности
- •Вычисление показателей центральности с помощью Python
- •Понятие обхода графа
- •BFS — поиск в ширину
- •DFS — поиск в глубину
- •Практический пример — выявление мошенничества
- •Простой анализ мошенничества
- •Анализ мошенничества методом сторожевой башни
- •Резюме
- •Глава 6. Алгоритмы машинного обучения без учителя
- •Обучение без учителя
- •Обучение без учителя в жизненном цикле майнинга данных
- •Современные тенденции исследований в области обучения без учителя
- •Практические примеры
- •Алгоритмы кластеризации
- •Количественная оценка сходства
- •Иерархическая кластеризация
- •Оценка кластеров
- •Применение кластеризации
- •Снижение размерности
- •Метод главных компонент (PCA)
- •Ограничения PCA
- •Поиск ассоциативных правил
- •Примеры использования
- •Анализ рыночной корзины
- •Ассоциативные правила
- •Оценка качества правила
- •Алгоритмы анализа ассоциаций
- •Практический пример — объединение похожих твитов в кластеры
- •Тематическое моделирование
- •Кластеризация
- •Алгоритмы обнаружения выбросов (аномалий)
- •Использование кластеризации
- •Обнаружение аномалий на основе плотности
- •Метод опорных векторов
- •Резюме
- •Глава 7. Традиционные алгоритмы обучения с учителем
- •Машинное обучение с учителем
- •Терминология машинного обучения с учителем
- •Благоприятные условия
- •Различие между классификаторами и регрессорами
- •Алгоритмы классификации
- •Задача классификации
- •Оценка классификаторов
- •Этапы классификации
- •Алгоритм дерева решений
- •Ансамблевые методы
- •Логистическая регрессия
- •Метод опорных векторов (SVM)
- •Наивный байесовский алгоритм
- •Алгоритмы регрессии
- •Задача регрессии
- •Линейная регрессия
- •Алгоритм дерева регрессии
- •Алгоритм градиентного бустинга для регрессии
- •Среди алгоритмов регрессии победителем становится...
- •Практический пример — как предсказать погоду
- •Резюме
- •Глава 8. Алгоритмы нейронных сетей
- •Введение в ИНС
- •Эволюция ИНС
- •Обучение нейронной сети
- •Анатомия нейронной сети
- •Градиентный спуск
- •Функции активации
- •Инструменты и фреймворки
- •Keras
- •Знакомство с TensorFlow
- •Типы нейронных сетей
- •Перенос обучения
- •Практический пример — использование глубокого обучения для выявления мошенничества
- •Методология
- •Резюме
- •Глава 9. Алгоритмы обработки естественного языка
- •Знакомство с NLP
- •Терминология NLP
- •Библиотека NLTK
- •Мешок слов (BoW)
- •Эмбеддинги слов
- •Окружение слова
- •Свойства эмбеддингов слов
- •Рекуррентные нейросети в NLP
- •Использование NLP для анализа эмоциональной окраски текста
- •Практический пример — анализ тональности в отзывах на фильмы
- •Резюме
- •Глава 10. Рекомендательные системы
- •Введение в рекомендательные системы
- •Типы рекомендательных систем
- •Рекомендательные системы на основе контента
- •Рекомендательные системы на основе коллаборативной фильтрации
- •Гибридные рекомендательные системы
- •Ограничения рекомендательных систем
- •Проблема холодного старта
- •Требования к метаданным
- •Проблема разреженности данных
- •Предвзятость из-за социального влияния
- •Ограниченные данные
- •Области практического применения
- •Практический пример — создание рекомендательной системы
- •Резюме
- •Глава 11. Алгоритмы обработки данных
- •Знакомство с алгоритмами обработки данных
- •Классификация данных
- •Алгоритмы хранения данных
- •Стратегии хранения данных
- •Алгоритмы потоковой передачи данных
- •Применение потоковой передачи
- •Алгоритмы сжатия данных
- •Алгоритмы сжатия без потерь
- •Практический пример — анализ тональности твитов в режиме реального времени
- •Резюме
- •Глава 12. Криптография
- •Введение в криптографию
- •Понимание важности самого слабого звена
- •Основная терминология
- •Требования безопасности
- •Базовое устройство шифров
- •Типы криптографических методов
- •Криптографические хеш-функции
- •Симметричное шифрование
- •Асимметричное шифрование
- •Практический пример — проблемы безопасности при развертывании модели МО
- •Атака посредника (MITM)
- •Избежание маскарадинга
- •Шифрование данных и моделей
- •Резюме
- •Глава 13. Крупномасштабные алгоритмы
- •Введение в крупномасштабные алгоритмы
- •Определение эффективного крупномасштабного алгоритма
- •Терминология
- •Разработка параллельных алгоритмов
- •Закон Амдала
- •Гранулярность задачи
- •Балансировка нагрузки
- •Проблема расположения
- •Запуск параллельной обработки на Python
- •Разработка стратегии мультипроцессорной обработки
- •Введение в CUDA
- •Кластерные вычисления
- •Гибридная стратегия
- •Резюме
- •Глава 14. Практические рекомендации
- •Введение в практические рекомендации
- •Печальная история ИИ-бота в Твиттере
- •Объяснимость алгоритма
- •Алгоритмы машинного обучения и объяснимость
- •Этика и алгоритмы
- •Проблемы обучающихся алгоритмов
- •Понимание этических аспектов
- •Снижение предвзятости в моделях
- •Решение NP-трудных задач
- •Упрощение задачи
- •Адаптация известного решения аналогичной задачи
- •Вероятностный метод
- •Когда следует использовать алгоритмы
- •Практический пример — события типа «черный лебедь»
- •Резюме
Структуры данных в Python |
51 |
СТРУКТУРЫ ДАННЫХ В PYTHON
Влюбом языке программирования структуры данных используются для хранения и управления сложными данными. В Python структуры данных — это контейнеры, позволяющие эффективно управлять данными, организо вывать их и осуществлять поиск. Они организованы в коллекции — группы элементов данных, которые требуется хранить и обрабатывать совместно.
ВPython существуют пять различных структур данных для хранения кол лекций:
zz Список (List). Упорядоченная изменяемая последовательность элементов.
zz Кортеж (Tuple). Упорядоченная неизменяемая последовательность элемен тов.
zz Множество (Set). Неупорядоченная последовательность элементов.
zz Словарь (Dictionary). Неупорядоченная последовательность пар «ключ — значение».
zzDataFrame. Двумерная структура для хранения двумерных данных.
Давайте рассмотрим их более подробно.
Список
В Python список — это основная структура данных, используемая для хранения изменяемой последовательности элементов.
Элементы данных в списке могут быть разных типов.
Чтобы создать список, элементы нужно заключить в квадратные скобки [ ] и разделить запятыми. Ниже представлен пример кода, который создает список из четырех элементов данных разных типов:
>>>aList = ["John", 33,"Toronto", True]
>>>print(aList)
['John', 33, 'Toronto', True]Ex
Список в Python — это удобный способ создания одномерных изменяемых структур данных, необходимых главным образом на различных внутренних этапах алгоритма.
52 |
Глава 2. Структуры данных, используемые в алгоритмах |
Использование списков
При работе со списками мы получаем полезные инструменты для управления данными.
Давайте посмотрим, что можно делать со списками.
zz Индексация списка. Поскольку положение каждого элемента в списке детер минировано, к нему можно получить доступ с помощью индекса. Следующий код демонстрирует этот принцип:
>>>bin_colors=['Red','Green','Blue','Yellow']
>>>bin_colors[1]
'Green'
Список из четырех элементов, созданный этим кодом, показан на рис. 2.1.
Значения
Индексы
Рис. 2.1
Обратите внимание, что индексация начинается с 0, поэтому второй элемент Green извлекается с помощью индекса 1: bin_color[1].
zz Срез списка. Извлечение подмножества элементов списка путем указания диапазона индексов называется срезом. Пример кода среза:
>>>bin_colors=['Red','Green','Blue','Yellow']
>>>bin_colors[0:2]
['Red', 'Green']
Cписок — одна из самых популярных одномерных структур данных в Python.
При срезе списка диапазон указывается следующим образом: первое число (включительно) и второе число (не включительно). Напри мер, bin_colors[0:2] будет включать bin_color[0] и bin_color[1], но не bin_color[2]. Следует учитывать это при использовании списков; не которые пользователи Python жалуются, что это не слишком очевидно.
Структуры данных в Python |
53 |
Рассмотрим следующий сниппет:
>>>bin_colors=['Red','Green','Blue','Yellow']
>>>bin_colors[2:]
['Blue', 'Yellow']
>>> bin_colors[:2]
['Red', 'Green']
Если в квадратных скобках не указан первый индекс‚ это означает начало списка, а если пропущен второй — конец списка. Выше мы видим пример та кого кода.
zz Отрицательная индексация. В Python имеются и отрицательные индек сы, которые отсчитываются от конца списка. Это показано в следующем коде:
>>>bin_colors=['Red','Green','Blue','Yellow']
>>>bin_colors[:-1]
['Red', 'Green', 'Blue']
>>>bin_colors[:-2]
['Red', 'Green']
>>>bin_colors[-2:-1]
['Blue']
Отрицательные индексы особенно полезны, когда в качестве точки отсчета мы хотим использовать последний элемент вместо первого.
zz Вложенность. Элемент списка может относиться к простому или сложному типу данных. Это позволяет создавать вложенные списки и дает возможность использовать потенциал итеративных и рекурсивных алгоритмов.
Рассмотрим пример списка внутри списка (вложенность):
>>>a = [1,2,[100,200,300],6]
>>>max(a[2])
300
>>> a[2][1]
200
zz Итерация. Python позволяет выполнять итерацию для каждого элемента в списке с помощью цикла for.
Это показано в следующем примере:
>>>bin_colors=['Red','Green','Blue','Yellow']
>>>for aColor in bin_colors:
print(aColor + " Square")
Red Square
Green Square
Blue Square Yellow Square
54 |
Глава 2. Структуры данных, используемые в алгоритмах |
Обратите внимание, что данный код выполняет итерацию по списку и ото бражает каждый элемент.
Лямбда-функции
Существует множество лямбда-функций, которые можно использовать в списках. Они особенно полезны в работе с алгоритмами и позволяют создавать функцию на лету. Иногда в литературе их также называют анонимными функциями. Рас смотрим их применение:
zz Фильтрация данных. Для фильтрации данных мы должны определить пре дикат — функцию, которая тестирует каждый аргумент и возвращает логи ческое значение. Пример использования такой функции:
>>> list(filter(lambda x: x > 100, [-5, 200, 300, -10, 10, 1000]))
[200, 300, 1000]
В данном коде мы фильтруем список с помощью лямбда-функции, которая задает критерии фильтрации. Функция filter() предназначена для отбора элементов из последовательности на основе определенного критерия и обыч но используется вместе с лямбда-функцией. Ее также можно применять для фильтрации элементов кортежей или наборов. В нашем примере заданным критерием является x > 100. Код проверяет все элементы списка и отсеивает те из них, которые не соответствуют этому критерию.
zz Преобразование данных. Функция map() используется для преобразования данных с помощью лямбда-функции. Пример:
>>> list(map(lambda x: x ** 2, [11, 22, 33, 44,55]))
[121, 484, 1089, 1936, 3025]
Использование функции map()вместе с лямбда-функцией открывает большие возможности. При этом лямбда-функция задает преобразователь, изменяющий каждый элемент последовательности. В приведенном примере преобразова телем выступает возведение во вторую степень. Таким образом, мы использу ем функцию map() для получения квадрата каждого элемента в списке.
zz Агрегирование данных. Для агрегирования данных используется reduce(), которая рекурсивно применяет функцию к паре значений для каждого эле мента списка:
from functools import reduce def doSum(x1,x2):
return x1+x2
x = reduce(doSum, [100, 122, 33, 4, 5, 6])
Структуры данных в Python |
55 |
Обратите внимание, что для reduce() необходимо определить функцию агрегирования данных. В приведенном примере кода такой функцией явля ется functools. Она определяет, как именно нужно агрегировать элементы данного списка. Агрегирование начинается с первых двух элементов, а его результат заменяет эти два элемента. Процесс сокращения будет происходить до тех пор, пока не останется одно агрегированное число. x1 и x2 в функции doSum() представляют собой пару чисел для каждой итерации; doSum() яв ляется критерием агрегирования.
В результате мы получаем единое значение (равное 270).
Функция range
С помощью функции range()можно легко сгенерировать большой список чисел. Она используется для автоматического добавления последовательностей чисел в список.
Функцию range() очень просто использовать — нужно только указать коли чество элементов, которые мы хотим видеть в списке. По умолчанию после довательность начинается с нуля и далее увеличивается с шагом, равным единице:
>>>x = range(6)
>>>x
[0,1,2,3,4,5]
Мы также можем указать конечное число и шаг, например:
>>>oddNum = range(3,29,2)
>>>oddNum
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27]
В результате получим нечетные числа от 3 до 27.
Временная сложность списков
Временную сложность различных функций списка можно обобщить, используя нотацию «О-большое» (табл. 2.1).
Чем больше список, тем больше времени требуется на выполнение операций, представленных в таблице. Это не касается только вставки элемента. По мере увеличения списка влияние на производительность становится все более вы раженным.