
- •Об авторе
- •Предисловие
- •Для кого эта книга
- •О чем эта книга
- •Что вам потребуется при чтении этой книги
- •Условные обозначения
- •От издательства
- •Глава 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-трудных задач
- •Упрощение задачи
- •Адаптация известного решения аналогичной задачи
- •Вероятностный метод
- •Когда следует использовать алгоритмы
- •Практический пример — события типа «черный лебедь»
- •Резюме
56 |
Глава 2. Структуры данных, используемые в алгоритмах |
Таблица 2.1 |
|
|
|
Операция |
Временная сложность |
|
|
Вставить элемент |
O(1) |
|
|
Удалить элемент |
O(n) (так как в худшем случае, возможно, придется |
|
перебрать весь список) |
|
|
Срез списка |
O(n) |
|
|
Извлечение |
O(n) |
элемента |
|
|
|
Копирование |
O(n) |
|
|
Кортеж
Еще одна структура данных, которую можно использовать для хранения кол лекции, — кортеж. В отличие от списков, кортежи являются неизменяемыми (доступными только для чтения) структурами данных. Кортежи состоят из нескольких элементов, заключенных в круглые скобки ( ).
Кортежи, как и списки, могут включать в себя элементы разных типов, в том числе сложные типы данных — внутри кортежа может быть еще один кортеж. Таким образом, мы можем создавать вложенные структуры. Это особенно по лезно для работы с итеративными и рекурсивными алгоритмами.
В данном коде показано, как создавать кортежи:
>>>bin_colors=('Red','Green','Blue','Yellow')
>>>bin_colors[1]
'Green'
>>>bin_colors[2:]
('Blue', 'Yellow')
>>>bin_colors[:-1]
('Red', 'Green', 'Blue')
# Nested Tuple Data structure (вложенный кортеж)
>>>a = (1,2,(100,200,300),6)
>>>max(a[2])
300
>>> a[2][1]
200
Обратите внимание, что в представленном выше коде а[2] относится к третье му элементу, который является кортежем: (100,200,300); a[2][1] относится ко второму элементу внутри этого кортежа, который является числом 200.

Структуры данных в Python |
57 |
По возможности старайтесь использовать неизменяемые структуры данных вместо изменяемых (например, кортежи вместо списков), так как это улучшит производительность. В особенности это касается обработки больших данных: неизменяемые структуры работают зна чительно быстрее, чем изменяемые. Мы платим определенную цену за возможность изменять элементы данных в списке. Нужно понять, действительно ли это необходимо или же можно использовать кортеж, что будет намного быстрее.
Временная сложность кортежей
Временную сложность различных функций кортежей можно обобщить с по мощью «O-большого» (табл. 2.2).
Таблица 2.2
Функция |
Временная сложность |
|
|
Append() |
O(1) |
|
|
Append() — это функция, которая добавляет элемент в конец уже существую щего кортежа. Ее сложность равна O(1).
Словарь
Хранение данных в виде пар «ключ — значение» особенно полезно при работе с распределенными алгоритмами. В Python коллекция пар «ключ — значение» хранится в виде структуры данных, называемой словарем. Чтобы создать сло варь, в качестве атрибута следует выбрать ключ, лучше всего подходящий для идентификации данных во время обработки. Значением ключа может быть элемент любого типа, например число или строка. В Python в качестве значе ний также используются сложные типы данных, например списки. Если ис пользовать в качестве значения ключа словарь, можно создавать вложенные словари.
Чтобы создать простой словарь, который присваивает цвета различным пере менным, пары «ключ — значение» должны быть заключены в фигурные скобки { }. Например, следующий код создает простой словарь, состоящий из трех пар «ключ — значение»:
>>> bin_colors ={ "manual_color": "Yellow",

58 Глава 2. Структуры данных, используемые в алгоритмах
"approved_color": "Green", "refused_color": "Red"
}
>>> print(bin_colors)
{'manual_color': 'Yellow', 'approved_color': 'Green', 'refused_color': 'Red'}
Три пары «ключ — значение», созданные предыдущим фрагментом кода, также проиллюстрированы на рис. 2.2.
Ключи |
Значения |
Рис. 2.2
Теперь давайте посмотрим, как получить и обновить значение, связанное с ключом.
1.Чтобы получить значение, связанное с ключом, можно использовать либо функцию get(), либо ключ в качестве индекса:
>>>bin_colors.get('approved_color')
'Green'
>>>bin_colors['approved_color']
'Green'
2.Чтобы обновить значение, связанное с ключом, используйте следующий код:
>>>bin_colors['approved_color']="Purple"
>>>print(bin_colors)
{'manual_color': 'Yellow', 'approved_color': 'Purple', 'refused_color': 'Red'}
Данный код показывает, как обновить значение, связанное с определенным ключом в словаре.
Структуры данных в Python |
59 |
Временная сложность словаря
В табл. 2.3 приведена временная сложность словаря с использованием «O-большого».
Таблица 2.3
Операция |
Временная сложность |
|
|
Получить значение или ключ |
O(1) |
|
|
Установить значение или ключ |
O(1) |
|
|
Скопировать словарь |
O(n) |
|
|
Из анализа сложности словаря следует важный вывод: время, необходимое для получения или установки значения ключа, никак не зависит от размера словаря. Это означает, что время, затраченное на добавление пары «ключ — значение» в словарь размером три (например), равно времени, затраченному на добавление пары «ключ — значение» в словарь размером один миллион.
Множество
Множество — это коллекция элементов одного или разных типов. Элементы заключены в фигурные скобки { }. Взгляните на следующий сниппет:
>>>green = {'grass', 'leaves'}
>>>print(green)
{'grass', 'leaves'}
Отличительной особенностью множества является то, что в нем хранится толь ко уникальное значение каждого элемента. Если мы попытаемся добавить дубль, он будет проигнорирован:
>>>green = {'grass', 'leaves','leaves'}
>>>print(green)
{'grass', 'leaves'}
Рассмотрим операции над множествами. Для этого возьмем два множества:
zz множество с именем yellow, в котором содержатся вещи желтого цвета; zzмножество с именем red, в котором содержатся вещи красного цвета.

60 |
Глава 2. Структуры данных, используемые в алгоритмах |
Обратите внимание, что некоторые вещи содержатся в обоих множествах. Эти два множества и их взаимосвязь можно представить с помощью диаграммы Венна (рис. 2.3).
Рис. 2.3 (dandelions — одуванчики, leaves — листья, fire hydrant — пожарный кран, rose — роза, blood — кровь)
Реализация этих множеств в Python выглядит следующим образом:
>>>yellow = {'dandelions', 'fire hydrant', 'leaves'}
>>>red = {'fire hydrant', 'blood', 'rose', 'leaves'}
Теперь рассмотрим код, который демонстрирует операции на множествах с ис пользованием Python:
>>> yellow|red
{'dandelions', 'fire hydrant', 'blood', 'rose', 'leaves'}
>>> yellow&red
{'fire hydrant'}
В данном примере продемонстрированы две операции: объединение и пересе чение. Объединение совмещает все элементы обоих множеств, а пересечение дает набор общих элементов для двух множеств. Обратите внимание:
zz yellow|red используется для объединения двух множеств;
zz yellow&red используется для получения пересечения yellow и red.
Анализ временной сложности множеств
В табл. 2.4 приведен анализ временной сложности для множеств.