Programmers ­‑ ‑‑, ‑,,,, ­­­­­ ­­­­­­‑‑‑‑‑‑‑ ­­­­­­­‑‑‑‑‑‑‑2020 ббк



Download 0,77 Mb.
bet18/20
Sana22.02.2022
Hajmi0,77 Mb.
#80758
1   ...   12   13   14   15   16   17   18   19   20
Bog'liq
kk


Глава 14. Машинное обучение: классификация, регрессия и кластеризация
зации можно выводить наборы данных с тремя переменными на трехмерных диаграммах. Но как вывести данные с большим количеством измерений? Например, в наборе данных Digits каждый образец имеет 64 признака и целевое значение. Между тем в больших данных образцы могут иметь сотни, тысячи и даже миллионы признаков.
Чтобы представить набор данных со множеством признаков (то есть множеством измерений), сначала сократим его размерность до двух или трех. Для этого будет использоваться метод машинного обучения без учителя, называемый понижением размерности. При выводе полученной информации на диаграмме могут быть выявлены закономерности в данных, которые помогут выбрать наиболее подходящие алгоритмы машинного обучения. Например, если визуализация содержит кластеры точек данных, это может указывать на наличие обособленных классов информации в наборе; в такой ситуации классификационный алгоритм может оказаться уместным. Конечно, сначала необходимо определить класс образцов в каждом кластере. Для этого может потребоваться анализ образцов, входящих в кластер, и выявление сходства между ними.
Понижение размерности также служит другим целям. Обучение оценщиков на больших данных со значительным количеством измерений может занять часы, дни, недели и даже более. Кроме того, человеку трудно представить себе данные с большим количеством измерений — это называется «проклятием размерности». Если данные содержат сильно коррелированные признаки, то некоторые из них могут быть исключены посредством понижения размерности для повышения эффективности обучения. Это, однако, может привести к потере точности модели.
Вспомним, что набор данных Digits уже помечен 10 классами, соответствующими цифрам 0–9. Проигнорируем эти метки и воспользуемся понижением размерности, чтобы свести признаки набора данных к двум измерениям для визуализации результатов.
Загрузка набора данных Digits
Запустите IPython следующей командой:
ipython --matplotlib
и загрузите набор данных:
In [1]: from sklearn.datasets import load_digits
In [2]: digits = load_digits()
14.6. Практический пример: машинное обучение без учителя, часть 1 669
Создание оценщика TSNE для понижения размерности
Теперь воспользуемся оценщиком TSNE (из модуля sklearn.manifold) для выполнения понижения размерности. Этот оценщик использует алгоритм, называемый методом нелинейного понижения размерности и виртуализации многомерных переменных (t-SNE)1 для анализа признаков набора данных и сведения их к заданному числу измерений. Сначала мы попытались воспользоваться популярным оценщиком PCA (анализ главных компонент, Principal Components Analysis), но полученные результаты нас не устроили, поэтому мы переключились на TSNE (оценщик PCA продемонстрирован позднее).
Создадим объект TSNE для сведения признаков набора данных к двум измерениям, на что указывает ключевой аргумент n_components. Как и в случае с другими оценщиками, упоминавшимися ранее, использован ключевой аргумент random_state, обеспечивающий воспроизводимость «последовательности вывода» при выводе кластеров цифр:
In [3]: from sklearn.manifold import TSNE
In [4]: tsne = TSNE(n_components=2, random_state=11)
Сведение признаков набора данных Digits к двум измерениям
Понижение размерности в scikit-learn обычно состоит из двух шагов — обучения оценщика на наборе данных и последующего использования оценщика для преобразования данных к заданному количеству измерений. Эти шаги могут выполняться по отдельности методами fit и transform оценщика TSNE или же одной командой с использованием метода fit_transform:2
In [5]: reduced_data = tsne.fit_transform(digits.data)
Метод fit_transform оценщика TSNE какое-то время обучает оценщика, а затем выполняет понижение размерности. В нашей системе это заняло около 20 секунд. Когда метод завершает свою операцию, он возвращает массив с таким же количеством строк, что и у digits.data, но только двумя столбцами. Чтобы убедиться в этом, достаточно проверить размеры reduced_data:
In [6]: reduced_data.shape
Out[6]: (1797, 2)
1 Подробности устройства алгоритма выходят за рамки этой книги. За дополнительной информацией обращайтесь по адресу https://scikit-learn.org/stable/modules/manifold.html#t-sne.
2 Каждый вызов fit_transform выполняет обучение оценщика. Если вы хотите многократно использовать оценщика для сокращения размерности образцов, вызовите fit для однократного обучения оценщика, а затем вызывайте transform для понижения размерности Этот прием будет использован с PCA позднее в этой главе.
670 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Визуализация данных с пониженной размерностью
Итак, исходный набор данных был сведен до двух измерений, и мы можем построить диаграмму разброса данных. На этот раз вместо функции scatterplot библиотеки Seaborn будет использоваться функция scatter библиотеки Matplotlib, потому что она возвращает коллекцию элементов, нанесенных на диаграмму. Вскоре она будет использована на второй диаграмме разброса:
In [7]: import matplotlib.pyplot as plt
In [8]: dots = plt.scatter(reduced_data[:, 0], reduced_data[:, 1],
...: c='black')
...:
Первые два аргумента scatter содержат столбцы reduced_data (0 и 1) с данными по осям x и y. Ключевой аргумент c='black' задает цвет точек. Мы не пометили оси, потому что они не соответствуют конкретным признакам исходного набора данных. Новые признаки, сгенерированные оценщиком TSNE, могут заметно отличаться от исходных признаков набора данных.
Следующая диаграмма выводит полученную диаграмму разброса. Очевидно, на диаграмме присутствуют кластеры взаимосвязанных точек данных, хотя основных кластеров одиннадцать, а не десять. Также существуют «свободные» точки данных, которые не являются частью конкретных кластеров. На основании предшествующего изучения набора данных Digits эта картина выглядит разумно из-за трудностей с классификацией некоторых цифр.
14.6. Практический пример: машинное обучение без учителя, часть 1 671
Визуализация данных после понижения размерности с разными цветами
Хотя на предыдущей диаграмме видны скопления точек, мы не знаем, представляют ли все точки в каждом кластере одну и ту же цифру. Если они представляют разные цифры, то от кластеров особой пользы не будет. Воспользуемся известными целевыми значениями в наборе данных Digits и раскрасим все точки, чтобы было видно, действительно ли кластеры представляют конкретные цифры:
In [9]: dots = plt.scatter(reduced_data[:, 0], reduced_data[:, 1],
...: c=digits.target, cmap=plt.cm.get_cmap('nipy_spectral_r', 10))
...:
...:
В этом случае ключевой аргумент c=digits.target функции scatter указывает, что целевые значения определяют цвета точек. Добавленный ключевой аргумент
cmap=plt.cm.get_cmap('nipy_spectral_r', 10)
задает цветовую карту, используемую для выбора цветов точек. В данном случае известно, что окрашиваются 10 цифр, поэтому воспользуемся методом get_cmap объекта cm библиотеки Matplotlib (из модуля matplotlib.pyplot) для загрузки цветовой карты ('nipy_spectral_r') и выбора 10 четко различающихся цветов из цветовой карты.
Следующая команда добавляет справа от диаграммы цветную полоску для расшифровки цветов, чтобы вы видели, какую цифру представляет каждый цвет:
In [10]: colorbar = plt.colorbar(dots)
На диаграмме хорошо видны 10 кластеров, соответствующих цифрам 0–9. И снова остаются меньшие группы точек, не входящие ни в один кластер. На основании этого можно решить, что метод обучения с учителем, такой как метод k ближайших соседей, хорошо подойдет для этих данных. Для эксперимента также можно воспользоваться классом Axes3D библиотеки Matplotlib, предоставляющим оси x, y и z для построения пространственных диаграмм.
672 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
14.7. Практический пример: машинное обучение без учителя, часть 2 — кластеризация методом k средних
В этом разделе будет представлен, пожалуй, самый простой из алгоритмов машинного обучения без учителя — кластеризация методом k средних. Алгоритм анализирует непомеченные образцы и пытается объединить их в кластеры. Поясним, что k в «методе k средних» представляет количество кластеров, на которые предполагается разбить данные.
Алгоритм распределяет образцы на заранее заданное количество кластеров, используя метрики расстояния, сходные с метриками алгоритма кластеризации k ближайших соседей. Каждый кластер группируется вокруг центроида — центральной точки кластера. Изначально алгоритм выбирает k случайных центроидов среди образцов набора данных, после чего остальные образцы распределяются по кластерам с ближайшим центроидом. Далее выполняется итеративный пересчет центроидов, а образцы перераспределяются по кластерам, пока для всех кластеров расстояние от заданного центроида до образцов, входящих в его кластер, не будет минимизировано. В результате выполнения алгоритма формируется одномерный массив меток, обозначающих кластер,
14.7. Практический пример: машинное обучение без учителя, часть 2 673
к которому относится каждый образец, а также двумерный массив центроидов, представляющих центр каждого кластера.
Набор данных Iris
Поработаем с популярным набором данных Iris1, входящим в поставку scikit-learn. Этот набор часто анализируется при классификации и кластеризации. И хотя набор данных помечен, мы не будем использовать эти метки, чтобы продемонстрировать кластеризацию. Затем метки будут использованы для определения того, насколько хорошо алгоритм k средних выполняет кластеризацию образцов.
Набор данных Iris относится к «игрушечным» наборам данных, поскольку состоит только из 150 образцов и четырех признаков. Набор данных описывает 50 образцов трех видов цветов ириса — Iris setosa, Iris versicolor и Iris virginica (см. фотографии ниже). Признаки образцов: длина наружной доли околоцветника (sepal length), ширина наружной доли околоцветника (sepal width), длина внутренней доли околоцветника (petal length) и ширина внутренней доли околоцветника (petal width), измеряемые в сантиметрах.
Iris setosa. Credit: Courtesy of Nation Park services
1 Fisher, R.A., «The use of multiple measurements in taxonomic problems», Annual Eugenics, 7, Part II, 179–188 (1936); также «Contributions to Mathematical Statistics» (John Wiley, NY, 1950).
674 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Iris versicolor. Credit: Courtesy of Jefficus
Iris virginica. Credit: Christer T Johansson
14.7.1. Загрузка набора данных Iris
Запустите IPython командой ipython --matplotlib, после чего воспользуйтесь функцией load_iris модуля sklearn.datasets для получения объекта Bunch с набором данных:
14.7. Практический пример: машинное обучение без учителя, часть 2 675
In [1]: from sklearn.datasets import load_iris
In [2]: iris = load_iris()
Атрибут DESCR объекта Bunch показывает, что набор данных состоит из 150 образцов (Number of Instances), каждый из которых обладает четырьмя признаками (Number of Attributes). В наборе данных нет отсутствующих значений. Образцы классифицируются целыми числами 0, 1 и 2, представляющими Iris setosa, Iris versicolor и Iris virginica соответственно. Проигнорируем метки и поручим определение классов образцов алгоритму кластеризации методом k средних. Ключевая информация DESCR выделена жирным шрифтом:
In [3]: print(iris.DESCR)
.. _iris_dataset:
Iris plants dataset
--------------------
**Data Set Characteristics:**
:Number of Instances: 150 (50 in each of three classes)
:Number of Attributes: 4 numeric, predictive attributes and the class
:Attribute Information:
- sepal length in cm
- sepal width in cm
- petal length in cm
- petal width in cm
- class:
- Iris-Setosa
- Iris-Versicolour
- Iris-Virginica
:Summary Statistics:
============== ==== ==== ======= ===== ====================
Min Max Mean SD Class Correlation
============== ==== ==== ======= ===== ====================
sepal length: 4.3 7.9 5.84 0.83 0.7826
sepal width: 2.0 4.4 3.05 0.43 -0.4194
petal length: 1.0 6.9 3.76 1.76 0.9490 (high!)
petal width: 0.1 2.5 1.20 0.76 0.9565 (high!)
============== ==== ==== ======= ===== ====================
:Missing Attribute Values: None
:Class Distribution: 33.3% for each of 3 classes.
:Creator: R.A. Fisher
:Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)
:Date: July, 1988
...
676 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Проверка количества образцов, признаков
и целевых значений
Количество образцов и признаков можно узнать из атрибута shape массива data, а количество целевых значений — из атрибута shape массива target:
In [4]: iris.data.shape
Out[4]: (150, 4)
In [5]: iris.target.shape
Out[5]: (150,)
Массив target_names содержит имена числовых меток массива. Выражение target — dtype='In [6]: iris.target_names
Out[6]: array(['setosa', 'versicolor', 'virginica'], dtype='Массив feature_names содержит список строковых имен для каждого столбца в массиве data:
In [7]: iris.feature_names
Out[7]:
['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']
14.7.2. Исследование набора данных Iris: описательная статистика в Pandas
Используем коллекцию DataFrame для исследования набора данных Iris. Как и в случае с набором данных California Housing, зададим параметры pandas для форматирования столбцового вывода:
In [8]: import pandas as pd
In [9]: pd.set_option('max_columns', 5)
In [10]: pd.set_option('display.width', None)
14.7. Практический пример: машинное обучение без учителя, часть 2 677
Создадим коллекцию DataFrame с содержимым массива data, используя содержимое массива feature_names как имена столбцов:
In [11]: iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
Затем добавим столбец с названием вида для каждого из образцов. Трансформация списка в следующем фрагменте использует каждое значение в массиве target для поиска соответствующего названия в массиве target_names:
In [12]: iris_df['species'] = [iris.target_names[i] for i in iris.target]
Воспользуемся pandas для идентификации нескольких образцов. Как и прежде, если pandas выводит \ справа от имени столбца, это означает, что в выводе остаются столбцы, которые будут выведены ниже:
In [13]: iris_df.head()
Out[13]:
sepal length (cm) sepal width (cm) petal length (cm) \
0 5.1 3.5 1.4
1 4.9 3.0 1.4
2 4.7 3.2 1.3
3 4.6 3.1 1.5
4 5.0 3.6 1.4
petal width (cm) species
0 0.2 setosa
1 0.2 setosa
2 0.2 setosa
3 0.2 setosa
4 0.2 setosa
Вычислим некоторые показатели описательной статистики для числовых столбцов:
In [14]: pd.set_option('precision', 2)
In [15]: iris_df.describe()
Out[15]:
sepal length (cm) sepal width (cm) petal length (cm) \
count 150.00 150.00 150.00
mean 5.84 3.06 3.76
std 0.83 0.44 1.77
min 4.30 2.00 1.00
25% 5.10 2.80 1.60
50% 5.80 3.00 4.35
75% 6.40 3.30 5.10
max 7.90 4.40 6.90
678 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
petal width (cm)
count 150.00
mean 1.20
std 0.76
min 0.10
25% 0.30
50% 1.30
75% 1.80
max 2.50
Вызов метода describe для столбца 'species' подтверждает, что он содержит три уникальных значения. Нам заранее известно, что данные состоят из трех классов, к которым относятся образцы, хотя в машинном обучении без учителя это и не всегда так.
In [16]: iris_df['species'].describe()
Out[16]:
count 150
unique 3
top setosa
freq 50
Name: species, dtype: object
14.7.3. Визуализация набора данных функцией pairplot
Проведем визуализацию признаков в этом наборе данных. Один из способов извлечь информацию о ваших данных — посмотреть, как признаки связаны друг с другом. Набор данных имеет четыре признака. Мы не сможем построить диаграмму соответствия одного признака с тремя другими на одной диаграмме. Тем не менее можно построить диаграмму, на которой будет представлено соответствие между двумя признаками. Фрагмент [20] использует функцию pairplot библиотеки Seaborn для создания таблицы диаграмм, на которых каждый признак сопоставляется с одним из других признаков:
In [17]: import seaborn as sns
In [18]: sns.set(font_scale=1.1)
In [19]: sns.set_style('whitegrid')
In [20]: grid = sns.pairplot(data=iris_df, vars=iris_df.columns[0:4],
...: hue='species')
...:
14.7. Практический пример: машинное обучение без учителя, часть 2 679
Ключевые аргументы:
ØØ
data — коллекция DataFrame1 с набором данных, наносимым на диаграмму;
ØØ
vars — последовательность с именами переменных, наносимых на диаграмму. Для коллекции DataFrame она содержит имена столбцов. В данном случае используются первые четыре столбца DataFrame, представляющие длину (ширину) наружной доли околоцветника и длину (ширину) внутренней доли околоцветника соответственно;
ØØ
hue — столбец коллекции DataFrame, используемый для определения цветов данных, наносимых на диаграмму. В данном случае данные окрашиваются в зависимости от вида ирисов.
Предыдущий вызов pairplot строит следующую таблицу диаграмм 4 × 4:
1 Также может использоваться двумерный массив или список.
680 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Диаграммы на диагонали, ведущей из левого верхнего в правый нижний угол, показывают распределение признака, выведенного в этом столбце, с диапазоном значений (слева направо) и количеством образцов с этими значениями (сверху вниз). Возьмем распределение длины наружной доли околоцветника:
Самая высокая закрашенная область указывает, что диапазон значений длины наружной доли околоцветника (по оси x) для вида Iris setosa составляет приблизительно 4–6 см, а у большинства образцов Iris setosa значения лежат в середине этого диапазона (приблизительно 5 см). Крайняя правая закрашенная область указывает, что диапазон значений длины наружной доли околоцветника (по оси x) для вида Iris virginica составляет приблизительно 4–8,5 см, а у большинства образцов Iris virginica значения лежат между 6 и 7 см.
На других диаграммах в столбце представлены диаграммы разброса данных других признаков относительно признака по оси x. В первом столбце на первых трех диаграммах по оси y представлены ширина наружной доли околоцветника, длина внутренней доли околоцветника и ширина внутренней доли околоцветника соответственно, а на оси x — длина наружной доли околоцветника.
При выполнении этого кода на экране появляется цветное изображение, показывающее отношения между разными видами ирисов на уровне отдельных признаков. Интересно, что на всех диаграммах синие точки Iris setosa четко отделяются от оранжевых и зеленых точек других видов; это говорит о том, что Iris setosa действительно является отдельным классом. Также можно заметить, что других два вида иногда можно перепутать, на что указывают перекрывающиеся оранжевые и зеленые точки. Например, по диаграмме ширины и длины наружной доли околоцветника видно, что точки Iris versicolor и Iris virginica смешиваются. Это говорит о том, что если доступны только измерения наружной доли околоцветника, то различить эти два вида будет сложно.
14.7. Практический пример: машинное обучение без учителя, часть 2 681
Вывод результатов pairplot в одном цвете
Если убрать ключевой аргумент hue, то функция pairplot использует только один цвет для вывода всех данных, потому что она не знает, как различать виды при выводе:
In [21]: grid = sns.pairplot(data=iris_df, vars=iris_df.columns[0:4])
Как видно из следующей диаграммы, в данном случае диаграммы на диагонали представляют собой гистограммы с распределениями всех значений этого признака независимо от вида. При изучении диаграмм может показаться, что существуют всего два кластера, хотя мы знаем, что в наборе содержатся данные трех видов. Если количество кластеров неизвестно заранее, то можно обратиться к эксперту предметной области, хорошо знакомому с данными. Эксперт может знать, что в наборе данных присутствуют три вида; эта информация может пригодиться при проведении машинного обучения с данными.
682 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Диаграммы pairplot хорошо работают при малом количестве признаков или подмножестве признаков, чтобы количество строк и столбцов было ограниченным, и при относительно небольшом количестве образцов, чтобы были видны точки данных. С ростом количества признаков и образцов диаграммы разброса данных становятся слишком мелкими для чтения данных. В больших наборах данных можно нанести на диаграмму подмножество признаков и, возможно, случайно выбранное подмножество образцов, чтобы получить некоторое представление о данных.
14.7.4. Использование оценщика KMeans
В этом разделе будет применена кластеризация методом k средних с оценщиком KMeans библиотеки scikit-learn (из модуля sklearn.cluster) для распределения образцов набора данных Iris по кластерам. Как и с другими оценщиками, которыми мы пользовались ранее, оценщик KMeans скрывает от вас сложные математические подробности реализации алгоритма, чтобы им было удобно пользоваться.
Создание оценщика
Создадим объект KMeans:
In [22]: from sklearn.cluster import KMeans
In [23]: kmeans = KMeans(n_clusters=3, random_state=11)
Ключевой аргумент n_clusters определяет гиперпараметр k алгоритма кластеризации методом k средних, необходимый KMeans для вычисления кластеров и пометки образцов. В процессе обучения оценщика KMeans алгоритм вычисляет для каждого кластера центроид, представляющий центральную точку данных этого кластера.
По умолчанию значение параметра n_clusters равно 8. Нередко для выбора подходящего значения k приходится полагаться на знания экспертов предметной области. Тем не менее настройка гиперпараметра позволяет получить оценку оптимального значения k, как это будет сделано позднее. В данном случае мы знаем, что набор содержит данные трех видов, поэтому для проверки эффективности KMeans при пометке образцов ирисов используется значение n_clusters=3. И снова ключевое слово random_state используется для обеспечения воспроизводимости результатов.
14.7. Практический пример: машинное обучение без учителя, часть 2 683
Подгонка модели
Затем происходит обучение оценщика, для чего вызывается метод fit объекта KMeans и выполняется алгоритм k средних, рассмотренный ранее:
In [24]: kmeans.fit(iris.data)
Out[24]:
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=3, n_init=10, n_jobs=None, precompute_distances='auto',
random_state=11, tol=0.0001, verbose=0)
Как и у других оценщиков, метод fit возвращает объект оценщика, а IPython выводит его строковое представление. Список аргументов по умолчанию для KMeans можно просмотреть по адресу:
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html
Когда обучение завершено, объект KMeans содержит:
ØØ
Массив labels_ со значениями от 0 до n_clusters - 1 (в данном случае 0–2), обозначающими кластеры, к которым принадлежат образцы.
ØØ
Массив cluster_centers_, каждая строка которого представляет центроид.
Сравнение меток кластеров с целевыми значениями из набора данных
Так как набор Iris размечен, мы можем проверить значения из его массива target, чтобы составить представление о том, насколько эффективно алгоритм k средних выполняет кластеризацию для трех видов ирисов. С непомеченными данными вам придется обратиться к эксперту предметной области, который поможет оценить разумность прогнозируемых классов.
В этом наборе данных первые 50 образцов относятся к виду Iris setosa, следующие 50 — к виду Iris versicolor, а последние 50 — к виду Iris virginica. Массив target набора данных Iris представляет образцы со значениями 0–2. Если оценщик KMeans выбрал кластеры идеально, то все группы из 50 элементов массива labels_ оценщика будут обладать разными метками. При изучении приведенных ниже результатов следует заметить, что оценщик KMeans использует значения от 0 до k – 1 для пометки кластеров, но эти значения не связаны со значениями из массива target набора данных Iris.
684 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Сегментация поможет оценить результаты кластеризации для каждой группы из 50 образцов ирисов. Следующий фрагмент показывает, что первые 50 образцов были объединены в кластер 1:
In [25]: print(kmeans.labels_[0:50])
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1]
Следующие 50 образцов должны быть помещены во второй кластер. Фрагмент показывает, что большинство из них попало в кластер 0, но два образца были отнесены к кластеру 2:
In [26]: print(kmeans.labels_[50:100])
[0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Аналогичным образом последние 50 образцов должны быть помещены в третий кластер. Следующий фрагмент показывает, что многие из этих образцов попали в кластер 2, но 14 из них были помещены в кластер 0; алгоритм решил, что они принадлежат к другому кластеру:
In [27]: print(kmeans.labels_[100:150])
[2 0 2 2 2 2 0 2 2 2 2 2 2 0 0 2 2 2 2 0 2 0 2 0 2 2 0 0 2 2 2 2 2 0 2 2
2 2 0 2 2 2 0 2 2 2 0 2 2 0]
Результаты этих трех фрагментов подтверждают то, что мы уже видели на диаграммах pairplot ранее в этом разделе, — Iris setosa выделяется в обособленный класс, а Iris versicolor можно спутать с Iris virginica.
14.7.5. Понижение размерности методом анализа главных компонент
Затем воспользуемся оценщиком PCA (из модуля sklearn.decomposition) для выполнения понижения размерности. Этот оценщик использует алгоритм, называемый анализом главных компонент1, для анализа признаков набора данных и их сведения к заданному количеству измерений. Для набора данных
1 Подробности алгоритма выходят за рамки книги. За дополнительной информацией обращайтесь по адресу: https://scikit-learn.org/stable/modules/decomposition.html#pca.
14.7. Практический пример: машинное обучение без учителя, часть 2 685
Iris мы сначала применили оценщик TSNE, упоминавшийся ранее, но полученные результаты нас не устроили. По этой причине мы перешли на PCA для следующей демонстрации.
Создание объекта PCA
Как и оценщик TSNE, оценщик PCA использует ключевой аргумент n_components для определения количества измерений:
In [28]: from sklearn.decomposition import PCA
In [29]: pca = PCA(n_components=2, random_state=11)
Преобразование признаков набора данных Iris к двум измерениям
Обучим оценщика и получим данные сокращенной размерности вызовом методов fit и transform оценщика PCA:
In [30]: pca.fit(iris.data)
Out[30]:
PCA(copy=True, iterated_power='auto', n_components=2, random_state=11,
svd_solver='auto', tol=0.0, whiten=False)
In [31]: iris_pca = pca.transform(iris.data)
Когда метод завершит свою задачу, он возвращает массив с таким же количеством строк, как у iris.data, но только с двумя столбцами. Чтобы убедиться в этом, проверим атрибут shape объекта iris_pca:
In [32]: iris_pca.shape
Out[32]: (150, 2)
Обратите внимание: на этот раз мы вызываем методы fit и transform оценщика PCA вместо метода fit_transform, как при использовании оценщика TSNE. В этом примере мы повторно используем обученного оценщика (полученного вызовом fit) для выполнения второго преобразования с целью сокращения центроидов кластеров от четырех измерений до двух. Это позволит нам нанести на диаграмму местоположения центроидов для каждого кластера.
686 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
Визуализация данных с пониженной размерностью
Теперь, когда исходный набор данных был сокращен до двух измерений, воспользуемся диаграммой разброса данных для вывода. Для этого применим функцию scatterplot библиотеки Seaborn. Начнем с преобразования данных с пониженной размерностью в DataFrame и добавления столбца species, который будет использоваться для определения цветов точек:
In [33]: iris_pca_df = pd.DataFrame(iris_pca,
...: columns=['Component1', 'Component2'])
...:
In [34]: iris_pca_df['species'] = iris_df.species
Данные выводятся на диаграмме вызовом scatterplot:
In [35]: axes = sns.scatterplot(data=iris_pca_df, x='Component1',
...: y='Component2', hue='species', legend='brief',
...: palette='cool')
...:
Каждый центроид из массива cluster_centers_ объекта KMeans имеет такое же количество признаков, как и исходный набор данных (4 — в данном случае). Чтобы нанести на диаграмму центроиды, необходимо понизить их размерность. Центроид можно рассматривать как «усредненный» образец в кластере. Таким образом, каждый центроид должен быть преобразован тем же оценщиком PCA, который использовался для понижения размерности других образцов в этом кластере:
In [36]: iris_centers = pca.transform(kmeans.cluster_centers_)
Теперь нанесем центроиды трех кластеров в виде черных точек большего размера. Вместо того чтобы преобразовывать массив iris_centers в DataFrame, используем функцию scatter библиотеки Matplotlib для нанесения на диаграмму трех центроидов:
In [37]: import matplotlib.pyplot as plt
In [38]: dots = plt.scatter(iris_centers[:,0], iris_centers[:,1],
...: s=100, c='k')
...:
Ключевой аргумент s=100 задает размер точек на диаграмме, а ключевой аргумент c='k'указывает, что точки должны выводиться черным цветом.
14.7. Практический пример: машинное обучение без учителя, часть 2 687
14.7.6. Выбор оптимального оценщика для кластеризации
Как и в примерах классификации и регрессии, выполним несколько алгоритмов кластеризации и посмотрим, как они справляются с кластеризацией цветов ириса. Попытаемся провести кластеризацию образцов набора данных Iris с объектом kmeans, который был создан ранее1, а также с объектами scikit-learn DBSCAN, MeanShift, SpectralClustering и AgglomerativeClustering. Как и в случае с KMeans, количество кластеров для оценщиков SpectralClustering и AgglomerativeClustering задается заранее:
In [39]: from sklearn.cluster import DBSCAN, MeanShift,\
...: SpectralClustering, AgglomerativeClustering
In [40]: estimators = {
...: 'KMeans': kmeans,
...: 'DBSCAN': DBSCAN(),
...: 'MeanShift': MeanShift(),
...: 'SpectralClustering': SpectralClustering(n_clusters=3),
1 Здесь KMeans применяется к небольшому набору данных Iris. Если вы столкнетесь с проблемами быстродействия, используя KMeans с большими наборами данных, рассмотрите возможность использования MiniBatchKMeans. В документации scikit-learn сказано, что MiniBatchKMeans быстрее работает с большими наборами данных практически с тем же качеством результатов.
688 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
...: 'AgglomerativeClustering':
...: AgglomerativeClustering(n_clusters=3)
...: }
Каждая итерация следующего цикла вызывает метод fit одного оценщика с аргументом iris.data, после чего использует функцию unique библиотеки NumPy для получения меток и численности кластеров для трех групп по 50 образцов, после чего выводит результаты. Вспомните, что для оценщиков DBSCAN и MeanShift количество кластеров не указывалось заранее. Интересно, что DBSCAN правильно прогнозирует наличие трех кластеров (с метками –1, 0 и 1), хотя и помещает 84 из 100 образцов Iris virginica и Iris versicolor в один кластер. С другой стороны, оценщик MeanShift прогнозирует всего два кластера (с метками 0 и 1) и помещает 99 из 100 образцов Iris virginica и Iris versicolor в один кластер:
In [41]: import numpy as np
In [42]: for name, estimator in estimators.items():
...: estimator.fit(iris.data)
...: print(f'\n{name}:')
...: for i in range(0, 101, 50):
...: labels, counts = np.unique(
...: estimator.labels_[i:i+50], return_counts=True)
...: print(f'{i}-{i+50}:')
...: for label, count in zip(labels, counts):
...: print(f' label={label}, count={count}')
...:
KMeans:
0-50:
label=1, count=50
50-100:
label=0, count=48
label=2, count=2
100-150:
label=0, count=14
label=2, count=36
DBSCAN:
0-50:
label=-1, count=1
label=0, count=49
50-100:
label=-1, count=6
14.7. Практический пример: машинное обучение без учителя, часть 2 689
label=1, count=44
100-150:
label=-1, count=10
label=1, count=40
MeanShift:
0-50:
label=1, count=50
50-100:
label=0, count=49
label=1, count=1
100-150:
label=0, count=50
SpectralClustering:
0-50:
label=2, count=50
50-100:
label=1, count=50
100-150:
label=0, count=35
label=1, count=15
AgglomerativeClustering:
0-50:
label=1, count=50
50-100:
label=0, count=49
label=2, count=1
100-150:
label=0, count=15
label=2, count=35
Хотя эти алгоритмы помечают каждый образец, метки всего лишь отражают принадлежность к определенному кластеру. Что делать с информацией о кластерах, когда она у вас появится? Если вы стремитесь к тому, чтобы использовать данные в машинном обучении с учителем, то обычно анализируете образцы в каждом кластере, пытаетесь определить, как они связаны друг с другом, и помечаете их соответствующим образом. Как будет показано в следующей главе, обучение без учителя часто применяется в приложениях глубокого обучения. Примерами непомеченных данных, обрабатываемых средствами обучения без учителя, могут послужить твиты из Twitter, сообщения в Facebook, видеоролики, фотографии, новостные статьи, обзоры на продукты от потребителей, отзывы о фильмах и т. д.
690 Глава 14. Машинное обучение: классификация, регрессия и кластеризация
14.8. Итоги
В этой главе началось ваше знакомство с машинным обучением с использованием популярной библиотеки scikit-learn. Вы узнали, что машинное обучение делится на два типа: машинное обучение с учителем, работающее с помеченными данными, и машинное обучение без учителя, работающее с непомеченными данными. В этой главе снова широко применялась визуализация средствами Matplotlib и Seaborn, особенно для целей изучения данных. Вы узнали, как scikit-learn упаковывает алгоритмы машинного обучения в объекты-оценщики. Каждый оценщик инкапсулирован, что позволяет быстро создавать модели с минимальным объемом кода, даже если вам неизвестны все тонкости работы этих алгоритмов.
Сначала было рассмотрено машинное обучение с учителем для классификации, затем регрессия. Мы воспользовались одним из простейших алгоритмов классификации, методом k ближайших соседей, для анализа набора данных Digits, входящего в поставку scikit-learn. Было показано, что алгоритмы классификации прогнозируют классы, к которым относятся образцы. При бинарной классификации используются два класса (например, «спам» или «не спам»), а при множественной — более чем два класса (например, 10 классов в наборе данных Digits).
Были рассмотрены основные этапы типичного исследования в области машинного обучения, включая загрузку набора данных, изучение данных средствами pandas и визуализацию, разбиение данных для обучения и тестирования, создание модели, обучение модели и построение прогнозов. Вы узнали, почему данные разбиваются на обучающий и тестовый наборы и то, как оценить точность классификационного оценщика при помощи матрицы несоответствий и классификационного отчета.
Мы упоминали о том, что трудно заранее определить, какая модель(-и) покажет наилучшие результаты с вашими данными, поэтому обычно исследователь опробует много моделей и выбирает ту, которая показала лучшие результаты. Мы показали, что исследователь может легко выполнить несколько оценщиков. Также настройка гиперпараметра с k-проходной перекрестной проверкой использовалась для выбора лучшего значения k в алгоритме k-NN.
Затем мы вернулись к временным рядам и примеру линейной регрессии из раздела «Введение в data science» главы 10; на этот раз он реализован с использованием оценщика LinearRegression из scikit-learn. Оценщик LinearRegression использован для выполнения множественной линейной регрессии с набором
14.8. Итоги 691
данных California Housing, входящим в поставку scikit-learn. Вы узнали, что оценщик LinearRegression по умолчанию использует все числовые признаки в наборе данных для построения более сложных прогнозов, чем возможно при простой линейной регрессии. И снова мы выполнили несколько оценщиков scikit-learn, чтобы сравнить их эффективность и выбрать лучший вариант.
Затем мы представили машинное обучение без учителя, которое обычно реализуется с применением алгоритмов кластеризации. Был описан метод понижения размерности (с оценщиком TSNE библиотеки scikit-learn), который был применен для сокращения 64 признаков набора данных Digits до двух при создании визуализации. Это позволило наглядно увидеть кластеризацию данных цифр.
Далее мы описали один из простейших алгоритмов машинного обучения без учителя, алгоритм кластеризации методом k средних. Кластеризация продемонстрирована на примере набора данных Iris, также входящего в поставку scikit-learn. Посредством понижения размерности (с оценщиком PCA библиотеки scikit-learnestimator) четыре признака набора данных Iris сокращены до двух, чтобы выполнить визуализацию и продемонстрировать кластеризацию трех видов ирисов из набора данных, а также положения центроидов. Наконец, мы выполнили несколько оценщиков кластеризации, сравнив их эффективность по разметке образцов набора данных Iris на три кластера.
В следующей главе наше изучение технологий машинного обучения продолжится в области глубинного обучения. Мы рассмотрим некоторые интересные и непростые задачи.
15
Глубокое обучение
В этой главе:
•• Концепция нейронных сетей и ее применение при глубоком обучении.
•• Создание нейронных сетей Keras.
•• Уровни Keras, функции активации, функции потерь и оптимизаторы.
•• Применение сверточной нейронной сети Keras (CNN), обученной на наборе
данных MNIST, для распознавания рукописных цифр.
•• Применение рекуррентной нейронной сети Keras (RNN), обученной на на-
боре данных IMDb, для выполнения бинарной классификации положитель-
ных и отрицательных отзывов о фильмах.
•• Применение TensorBoard для визуализации хода глубокого обучения сетей.
•• Предварительно обученные нейронные сети, поставляемые с Keras.
•• Полезность моделей, обученных на наборе данных ImageNet, в приложени-
ях распознавания образов.
15.1. Введение 693
15.1. Введение
Одной из самых интересных областей искусственного интеллекта (AI) является глубокое обучение — перспективное направление машинного обучения, которое позволило добиться впечатляющих результатов в распознавании образов и многих других областях за последние несколько лет. Благодаря доступности больших данных, значительным вычислительным мощностям, повышению скорости интернета и достижениям в области программного и аппаратного оборудования параллельных вычислений, появляется все больше организаций и физических лиц, которые берутся за ресурсоемкие решения в области глубокого обучения.
Keras и TensorFlow
В предыдущей главе библиотека scikit-learn позволяла вам легко определять модели машинного обучения всего в одной команде. Модели глубокого обучения требуют более сложной подготовки, в которой чаще всего задействовано несколько разных объектов, называемых уровнями (layers). Мы будем строить модели глубокого обучения на базе библиотеки Keras, предоставляющей удобный интерфейс к библиотеке Google TensorFlow — самой популярной библиотеке глубокого обучения1. Франсуа Шолле (François Chollet) из команды Google Mind разработал Keras, чтобы сделать средства глубокого обучения более доступными. Его книга «Deep Learning with Python» обязательна к прочтению2. В настоящее время в компании Google ведутся тысячи проектов TensorFlow и Keras, и это количество стремительно растет3,4.
Модели
Модели глубокого обучения сложны, а для понимания их внутренних механизмов необходима серьезная математическая подготовка. Как и в предыдущих главах, мы постараемся избежать сложной теории, ограничившись объяснени1
Keras также предоставляет удобный интерфейс к инструментарию Microsoft CNTK и библиотеке Theano, разработанной в Монреальском университете (разработка которой была прекращена в 2017 году). Среди других популярных фреймворков глубокого обучения также стоит упомянуть Caffe (http://caffe.berkeleyvision.org/), Apache MXNet (https://mxnet.apache.org/) и PyTorch (https://pytorch.org/).
2 Шолле Франсуа. Глубокое обучение на Python. — СПб.: Питер, 2020. — 400 с.: ил.
3 http://theweek.com/speedreads/654463/google-more-than-1000-artificial-intelligence-projects-works.
4 https://www.zdnet.com/article/google-says-exponential-growth-of-ai-is-changing-nature-of-compute/.
694 Глава 15. Глубокое обучение
ями. Для глубокого обучения Keras играет ту же роль, что и scikit-learn — для машинного обучения. Каждая библиотека инкапсулирует сложные вычисления, и разработчикам остается только определять и параметризовать объекты, а также выполнять с ними нужные операции. Благодаря Keras вы строите свои модели из готовых компонентов и быстро параметризуете эти компоненты в соответствии со своими уникальными требованиями. В этой книге мы называли такую методологию объектно-базированным программированием.
Эксперименты с вашими моделями
Машинное обучение и глубокое обучение — области скорее эмпирические, нежели теоретические. Вы экспериментируете со многими моделями и настраиваете их, пока не найдете модели, лучше всего подходящие для ваших приложений. Keras упрощает подобные эксперименты.
Размеры наборов данных
Глубокое обучение хорошо работает при больших объемах данных, но может быть эффективным при меньших объемах данных в сочетании с такими методами, как перенос обучения1,2 и приращение данных.3,4 Перенос обучения использует существующие знания, полученные от ранее обученной модели, как фундамент для создания новой модели. Приращение данных добавляет в набор новые данные, выведенные на основании существующих данных. Например, в наборе данных графических изображений изображения можно поворачивать, чтобы модель могла узнать об объектах в разных ориентациях. Тем не менее в общем случае чем больше у вас данных, тем лучше вы сможете обучить модель глубокого обучения.
Вычислительные мощности
Глубокое обучение может требовать значительных вычислительных мощностей. Обучение сложных моделей на наборах больших данных может занять часы, дни и более. Модели, представленные в этой главе, обучаются от
1 https://towardsdatascience.com/transfer-learning-from-pre-trained-models-f2393f124751.
2 https://medium.com/nanonets/nanonets-how-to-use-deep-learning-when-you-have-limited-data-f68c0b512cab.
3 https://towardsdatascience.com/data-augmentation-and-images-7aca9bd0dbe8.
4 https://medium.com/nanonets/how-to-use-deep-learning-when-you-have-limited-data-part-2-data-augmentation-c26971dc8ced.
15.1. Введение 695
нескольких минут до часа на компьютерах с обычным процессором. Все, что потребуется, — это сколько-нибудь современный персональный компьютер. В этой главе мы обсудим специальное высокопроизводительное оборудование: графические процессоры (GPU) и тензорные процессоры (TPU), разработанные NVIDIA и Google для удовлетворения высоких потребностей современных приложений глубокого обучения.
Наборы данных
В поставку Keras включены некоторые популярные наборы данных. Два таких набора задействованы в примерах этой главы. Для каждого из этих наборов в интернете можно найти много других исследований Keras, в том числе и проекты с другими подходами. Так, в главе 14 использовался набор данных Digits библиотеки scikit-learn из 1797 изображений рукописных цифр, выбранных из гораздо более обширного набора данных MNIST (60 000 обучающих и 10 000 тестовых изображений1). В этой главе мы будем работать с полным набором данных MNIST и построим сверточную нейронную сеть (CNN) Keras, которая достигнет высокой эффективности в распознавании изображений цифр из тестового набора. Сверточные нейронные сети особенно хорошо подходят для задач распознавания образов, например распознавания рукописных цифр и букв или распознавания объектов (включая лица) в изображениях и видеороликах. Поработаем мы и с рекуррентной нейронной сетью Keras. В этом примере будет рассматриваться анализ эмоциональной окраски в наборе данных с обзорами фильмов на IMDb, где отзывы в обучающем и тестовом наборе помечаются как положительные или отрицательные.
Будущее глубокого обучения
Более новые автоматизированные средства глубокого обучения еще больше упрощают построение решений. К их числу относятся: Auto-Keras2 от лаборатории DATA Техасского университета A&M, Baidu EZDL3 и Google AutoML4.
1 «The MNIST Database». MNIST Handwritten Digit Database, Yann LeCun, Corinna Cortes and Chris Burges. http://yann.lecun.com/exdb/mnist/.
2 https://autokeras.com/.
3 https://ai.baidu.com/ezdl/.
4 https://cloud.google.com/automl/.
696 Глава 15. Глубокое обучение
15.1.1. Практическое применение глубокого обучения
Глубокое обучение используется во многих практических областях, в числе которых:
ØØ
Компьютерные игры.
ØØ
Распознавание образов: распознавание объектов, выявление закономерностей, распознавание лиц.
ØØ
Автономные автомобили.
ØØ
Робототехника.
ØØ
Повышение качества обслуживания.
ØØ
Чат-боты.
ØØ
Медицинская диагностика.
ØØ
Поиск в Google.
ØØ
Автоматизированное генерирование подписей к изображениям и субтитров.
ØØ
Улучшение разрешения графических изображений.
ØØ
Распознавание речи.
ØØ
Перевод на другие языки.
ØØ
Прогнозирование результатов выборов.
ØØ
Прогнозирование землетрясений и погодных условий.
ØØ
Сервис Google Sunroof для проверки возможности размещения солнечных батарей на крыше.
ØØ
Генерирующие приложения — генерирование новых изображений, обработка существующих изображений в стиле конкретного художника, раскрашивание черно-белых изображений и видео, создание музыки, создание текста (книги, поэзия) и многое другое.
15.1.2. Демонстрационные приложения глубокого обучения
Опробуйте следующие четыре демонстрационных приложения и поищите в интернете информацию о многих других, включая практическое применение в областях, перечисленных в предыдущем разделе:
15.2. Встроенные наборы данных Keras 697
ØØ
DeepArt.io — преобразует фотографию в картину применением художественного стиля к фотографии: https://deepart.io/.
ØØ
DeepWarp Demo — анализирует фотографию человека и заставляет его глаза перемещаться в разных направлениях: https://sites.skoltech.ru/sites/compvision_wiki/static_pages/projects/deepwarp/.
ØØ
Image-to-Image Demo — преобразует штриховой рисунок в картину: https://affinelayer.com/pixsrv/.
ØØ
Google Translate Mobile App (загрузите из магазина приложений на смартфон) — переводит текст на фотографии на другой язык (например, можно сделать фотографию знака или ресторанного меню на испанском языке и перевести текст на английский).
15.1.3. Ресурсы Keras
Вот некоторые источники информации, которые могут вам пригодиться в ходе знакомства с глубоким обучением:
ØØ
Чтобы получить ответы на вопросы, посетите slack-канал команды Keras по адресу https://kerasteam.slack.com.
ØØ
За статьями и учебниками обращайтесь по адресу https://blog.keras.io.
ØØ
Документация Keras доступна по адресу http://keras.io.
ØØ
Если вы ищете темы для курсовой или дипломной работы или даже диссертации, то посетите сайт arXiv по адресу https://arXiv.org. Здесь люди публикуют свои исследовательские работы и получают быструю обратную связь от коллег. На этом сайте вы получите доступ к материалам новейших исследований.
15.2. Встроенные наборы данных Keras
Ниже перечислены некоторые наборы данных Keras (из модуля tensorflow.keras.datasets1) для экспериментов с глубоким обучением. Мы используем пару этих наборов в примерах главы:
1 В автономной библиотеке Keras имена модулей начинаются с префикса keras вместо tensorflow.keras.
698 Глава 15. Глубокое обучение
База данных рукописных цифр MNIST1 — используется для классификации рукописных изображений цифр. Набор данных содержит изображения цифр размера 28 × 28 в оттенках серого, снабженные метками от 0 до 9; 60 000 изображений используются для обучения, а 10 000 — для тестирования. Этот набор будет использован в разделе 15.6, когда мы займемся изучением сверточных нейронных сетей.
База данных модных товаров Fashion-MNIST2 — используется для классификации изображений одежды. Набор данных содержит изображения модных товаров размера 28 × 28 в оттенках серого, снабженные метками 10 категорий3; 60 000 изображений используются для обучения, а 10 000 — для тестирования. Модель, построенную для использования с MNIST, можно повторно использовать с Fashion-MNIST, изменив лишь несколько команд.
Обзоры фильмов на IMDb4 — это набор, используемый для анализа эмоциональной окраски; он содержит обзоры, помеченные как положительные (1) или отрицательные (0); 25 000 обзоров предназначены для обучения и 25 000 — для тестирования. Этот набор данных используется в разделе 15.9 при изучении рекуррентных нейронных сетей.
CIFAR105 — используется для классификации малых изображений. Набор содержит цветные изображения 32 × 32, помеченные 10 категориями; 50 000 изображений предназначены для обучения и 10 000 — для тестирования.
CIFAR1006 — этот набор данных, также используемый для классификации малых изображений, содержит цветные изображения 32 × 32, помеченные 100 категориями; 50 000 изображений предназначены для обучения и 10 000 — для тестирования.
1 «The MNIST Database». MNIST Handwritten Digit Database, Yann LeCun, Corinna Cortes and Chris Burges. http://yann.lecun.com/exdb/mnist/.
2 Han Xiao and Kashif Rasul and Roland Vollgraf, Fashion-MNIST: a Novel Image Dataset for Benchmarking Machine Learning Algorithms, arXiv, cs.LG/1708.07747.
3 https://keras.io/datasets/#fashion-mnist-database-of-fashion-articles.
4 Andrew L. Maas, Raymond E. Daly, Peter T. Pham, Dan Huang, Andrew Y. Ng, and Christopher Potts. (2011). Learning Word Vectors for Sentiment Analysis. The 49th Annual Meeting of the Association for Computational Linguistics (ACL 2011).
5 https://www.cs.toronto.edu/~kriz/cifar.html.
6 https://www.cs.toronto.edu/~kriz/cifar.html.
15.3. Нестандартные среды Anaconda 699
15.3. Нестандартные среды Anaconda
Прежде чем запускать примеры этой главы, необходимо установить используемые библиотеки. В примерах этой главы мы будем использовать версию Keras из библиотеки глубокого обучения TensorFlow1. На момент написания книги TensorFlow еще не поддерживает Python 3.7. Следовательно, для выполнения примеров этой главы потребуется Python 3.6.x. Мы покажем, как настроить специализированную среду для работы с Keras и TensorFlow.
Нестандартные среды в Anaconda
Дистрибутив Anaconda Python позволяет легко создавать нестандартные среды — конфигурации, в которых можно устанавливать разные библиотеки и разные версии библиотек. Они помогут обеспечить воспроизводимость, если ваш код зависит от конкретных версий Python или библиотек2.
Среда по умолчанию в Anaconda называется базовой средой. Она создается автоматически при установке Anaconda. Все библиотеки Python, поставляемые с Anaconda, устанавливаются в базовой среде; все дополнительные устанавливаемые библиотеки также размещаются в ней, если явно не указано обратное. Нестандартные среды предоставляют средства управления конкретными библиотеками, которые должны устанавливаться для конкретных задач.
Создание среды Anaconda
Среда создается командой conda create. Создадим среду TensorFlow и присвоим ей имя tf_env (выберите любое имя по своему усмотрению). Выпол1
Также существует автономная версия, которая позволяет выбрать между TensorFlow, Microsoft CNTK или библиотекой Theano Монреальского университета (разработка которой завершилась в 2017 году).
2 В следующей главе будет представлена технология Docker как еще один механизм обеспечения воспроизводимости и удобное средство для формирования сложных сред на вашем локальном компьютере.
700 Глава 15. Глубокое обучение
ните следующую команду в терминале, командной оболочке или командном приглашении Anaconda1,2:
conda create -n tf_env tensorflow anaconda ipython jupyterlab
scikit-learn matplotlib seaborn h5py pydot graphviz
Команда определит зависимости перечисленных библиотек, после чего выведет все библиотеки, которые будут установлены в новой среде. Зависимостей много, поэтому перечисление может занять несколько минут. Когда появится приглашение:
Proceed ([y]/n)?
нажмите клавишу Enter, чтобы создать среду и установить библиотеки3.
Активация альтернативной среды Anaconda
Чтобы использовать нестандартную среду, выполните команду conda activate:
conda activate tf_env
Команда действует только на текущий терминал, командную оболочку или приглашение командной строки Anaconda. Когда вы активируете нестандартную среду и устанавливаете новые библиотеки, они становятся частью активированной, но не базовой среды. Если вы открыли отдельные терминалы, командные оболочки или приглашения Anaconda, то по умолчанию они будут использовать базовую среду Anaconda.
Деактивация альтернативной среды Anaconda
Завершив работу с нестандартной средой, вернитесь к базовой среде в текущем терминале, командной оболочке или приглашении Anaconda следующей командой:
conda deactivate
1 Пользователи Windows должны запустить приглашение командной строки Anaconda с правами администратора.
2 Если ваш компьютер оснащен графическим процессором NVIDIA, совместимым с TensorFlow, вы можете заменить библиотеку tensorflow на tensorflow-gpu для улучшения быстродействия. За дополнительной информацией обращайтесь по адресу https://www.tensorflow.org/install/gpu. Некоторые графические процессоры AMD также могут использоваться с TensorFlow: http://timdettmers.com/2018/11/05/which-gpu-for-deep-learning/.
3 При создании нестандартной среды команда conda устанавливает Python 3.6.7 — новейшую версию Python, совместимую с библиотекой tensorflow.
15.4. Нейронные сети 701
Документы Jupyter Notebook и JupyterLab
Примеры этой главы предоставляются только в форме документов Jupyter Notebook, упрощающих эксперименты с примерами. Вы можете настроить параметры и повторно выполнить документы Notebook. Для примеров этой главы JupyterLab следует запускать из папки ch15 (см. раздел 1.5.3).
15.4. Нейронные сети
Глубокое обучение — разновидность машинного обучения, использующая нейронные сети для обучения. Искусственная нейронная сеть (или просто нейронная сеть) представляет собой программную конструкцию, которая работает примерно по тем же принципам, по каким работает наш мозг. Управление нашей биологической нервной системой осуществляется по нейронам1, которые взаимодействуют друг с другом по каналам, называемым синапсами2. По мере обучения конкретные нейроны для выполнения конкретной задачи (например, ходьба) взаимодействуют друг с другом более эффективно. В дальнейшем эти нейроны активизируются каждый раз, когда вы собираетесь идти3.
Искусственные нейроны
В нейронной сети взаимосвязанные искусственные нейроны моделируют работу нейронов человеческого мозга для обучения сети. В процессе обучения связи между конкретными нейронами укрепляются для достижения желаемого результата. В глубоком обучении с учителем, которое используется в этой главе, мы стремимся спрогнозировать целевые метки, прилагаемые к образцам данных. Для этого проводится обучение модели обобщенной нейронной сети, которая затем может использоваться для прогнозирования на основании неизвестных данных4.
Диаграмма искусственной нейронной сети
На следующей диаграмме изображена трехуровневая нейронная сеть. Каждый кружок представляет нейрон, а строки между ними моделируют синапсы.
1 https://ru.wikipedia.org/wiki/Нейрон.
2 https://ru.wikipedia.org/wiki/Синапс.
3 https://www.sciencenewsforstudents.org/article/learning-rewires-brain.
4 Как и в области машинного обучения, можно создать сеть глубокого обучения без учителя, но эта тема выходит за рамки книги.
702 Глава 15. Глубокое обучение
Выход одного нейрона становится входом другого нейрона, отсюда и термин «нейронная сеть». На этой конкретной диаграмме показана полносвязная сеть — каждый нейрон в заданном уровне соединяется со всеми нейронами следующего уровня:
􀈼􀉯􀉨
􀉞􀉧􀉨􀉣􀉭􀉪􀉨􀉜􀉟􀉧􀉶􀉋􀉤􀉪􀉵􀉬􀉵􀉣􀉭􀉪􀉨􀉜􀉟􀉧􀉶􀈼􀉵􀉯􀉨􀉞􀉧􀉨􀉣􀉭􀉪􀉨􀉜􀉟􀉧􀉶􀉇􀉟􀉣􀉪􀉨􀉧􀉫􀉢􀉧􀉚􀉩􀉫
Обучение как итеративный процесс
Когда вы были ребенком, вы не научились ходить в один момент. Вы изучали этот процесс со временем, повторяя его снова и снова. В вашем мозге формировались меньшие компоненты движений, из которых состоит ходьба: вы учились стоять, удерживать равновесие, для того чтобы оставаться в вертикальном положении, поднимать ногу и перемещать ее вперед, и т. д. При этом вы получали обратную связь от своей среды. Когда вы делали успешный шаг, ваши родители улыбались и хлопали, а когда падали — могли удариться и ощутить боль.
Обучение нейронных сетей также происходит по итеративному принципу. Каждая итерация называется эпохой (epoch); каждый образец в обучающем наборе данных обрабатывается по одному разу. «Правильного» количества эпох не существует. Это гиперпараметр, который вам, возможно, придется настраивать с учетом обучающих данных и модели. Входными данными сети являются признаки обучающих образцов. Одни уровни изучают новые признаки по выходу предыдущих уровней, другие интерпретируют эти признаки для прогнозирования.
15.4. Нейронные сети 703
Как искусственные нейроны принимают решение об активации синапсов
В фазе обучения сеть вычисляет значения, называемые весами, для каждой связи между нейронами одного уровня и нейронами следующего уровня. На уровне отдельных нейронов каждое входное значение умножается на вес соответствующей связи, после чего сумма взвешенных входов передается функции активации нейрона. Вывод функции определяет, какие нейроны должны активироваться на основании входных данных — по аналогии с тем, как нейроны в мозге передают информацию в ответ на входные импульсы, поступающие от глаз, носа, ушей и т. д. На следующей диаграмме изображен нейрон с тремя входами (черные точки) и одним выводом (незакрашенный круг), который будет передан всем нейронам (или их части) следующего уровня в зависимости от типов уровней нейронной сети:
􀈼􀉯􀉨
􀉞􀉵􀉇􀉟􀉣􀉪􀉨􀉧􀈼􀉵􀉯􀉨􀉞􀁚􀀔􀁚􀀕􀁚􀀖
Значения w1, w2 и w3 называются весами. В новой модели, которая обучается «с нуля», эти значения инициализируются моделью случайным образом. В процессе обучения сеть пытается минимизировать пропорцию ошибок между прогнозируемыми метками модели и фактическими метками образцов. Доля ошибок называется потерями, а формула для определения величины потерь называется функцией потерь. В процессе обучения сеть определяет величину, вносимую каждым нейроном в общие потери, после чего проходит по уровням в обратном направлении и регулирует веса, стараясь минимизировать потери. Этот прием называется обратным распространением. Оптимизация весов происходит постепенно — чаще всего в процессе, называемом градиентным спуском.
704 Глава 15. Глубокое обучение
15.5. Тензоры
Библиотеки глубокого обучения обычно работают с данными в форме тензоров. Тензор по сути представляет собой многомерный массив. Такие библиотеки, как TensorFlow, упаковывают данные в один или несколько массивов, которые используются для выполнения математических вычислений, обеспечивающих обучение нейронной сети. Тензоры могут быть довольно большими, и количество измерений растет с повышением насыщенности данных (например, изображения, аудио и видео обладают большей насыщенностью, чем текст). Шолле обсуждает типы тензоров, часто встречающиеся в глубоком обучении1:
ØØ
0D- (0-мерный) тензор — отдельное значение, также называемое скаляром.
ØØ
1D-тензор — аналог одномерного массива, также называемого вектором. 1D-тензор может представлять последовательность, например почасовые показания температуры от датчика или слова одного обзора кинофильма.
ØØ
2D-тензор — аналог двумерного массива, также называемого матрицей. 2D-тензор может представлять изображение в оттенках серого, в котором два измерения тензора представляют ширину и высоту изображения в пикселах, а значение каждого элемента — интенсивность этого пиксела.
ØØ
3D-тензор — аналог трехмерного массива, который может использоваться для представления цветного изображения. Первые два измерения представляют ширину и высоту изображения в пикселах, а глубина каждой точки — составляющие RGB (интенсивности красной, зеленой и синей составляющей) цвета заданного пиксела. 3D-тензор также может представлять коллекцию 2D-тензоров, содержащих изображения в оттенках серого.
ØØ
4D-тензор — может использоваться для представления коллекции цветных изображений в 3D-тензорах. Также может использоваться для представления одного видеоролика. Каждый кадр видео фактически представляет цветное изображение.
1 Chollet, François. Deep Learning with Python. Section 2.2. Shelter Island, NY: Manning Publications, 2018.
15.5. Тензоры 705
ØØ
5D-тензор — может использоваться для представления коллекции 4D-тензоров, содержащих видеоролики.
Форма тензора представляется в виде кортежа значений, в котором количество элементов задает количество измерений тензора, а каждое значение в кортеже — размер соответствующего измерения тензора.
Предположим, мы создаем сеть глубокого обучения для выявления и отслеживания объектов в видео 4K (высокое разрешение) с 30 кадрами в секунду. Каждый кадр видео 4K имеет размер 3840 × 2160 пикселов. Теперь предположим, что пикселы представлены красной, зеленой и синей составляющими цвета. Таким образом, каждый кадр будет представлен 3D-тензором, содержащим 24 883 200 элементов (3840 × 2160 × 3), а каждый видеоролик будет представлен 4D-тензором, содержащим последовательность кадров. Если продолжительность видео превышает минуту, то тензор будет содержать не менее 44 789 760 000 элементов!
Между тем каждую минуту на YouTube загружаются более 600 часов видео1. Таким образом, всего за одну минуту на Google может сформироваться тензор, содержащий 1 612 431 360 000 000 элементов для моделей глубокого обучения, бесспорно, это большие данные. Как вы вскоре увидите, тензоры быстро разрастаются до гигантских размеров, поэтому так важно эффективно работать с ними. Это — одна из ключевых причин, по которым большая часть глубокого обучения выполняется на графических процессорах (GPU). Недавно компания Google создала тензорные процессоры (TPU) специально для операций с тензорами. Они в разы превосходят GPU по скорости.
Высокопроизводительные процессоры
Для реальных задач глубокого обучения необходимы мощные процессоры, потому что размер тензоров может быть огромным, а операции с большими тензорами могут создать непосильную нагрузку на процессор. Перечислим процессоры, чаще всего используемые для глубокого обучения:
ØØ
NVIDIA GPU — изначально разработанные такими компаниями, как NVIDIA, для компьютерных игр, графические процессоры значительно превосходят традиционные процессоры при обработке больших объемов
1 https://www.inc.com/tom-popomaronis/youtube-analyzed-trillions-of-data-points-in-2018-revealing-5-eye-opening-behavioral-statistics.html.
706 Глава 15. Глубокое обучение
данных. Это позволяет разработчикам обучать, проверять и тестировать модели глубокого обучения с большей эффективностью, а следовательно, экспериментировать с большим количеством таких моделей. Графические процессоры оптимизированы для математических матричных операций, часто выполняемых с тензорами; это важный аспект внутренней реализации глубокого обучения. Процессоры NVIDIA Volta Tensor Core специально проектировались для глубокого обучения1,2. Многие NVIDIA GPU совместимы с TensorFlow (а следовательно, и с Keras) и могут повысить эффективность моделей глубокого обучения3.
ØØ
Google TPU — понимая, что глубокое обучение играет важнейшую роль в ее будущем, компания Google разработала тензорные процессоры (TPU), которые в настоящее время используются в облачном сервисе Cloud TPU, способном «обеспечить производительность до 11,5 петафлопса в одном блоке4» (то есть 11,5 квадриллиона операций с плавающей точкой в секунду). Кроме того, TPU проектировались с расчетом на исключительную эффективность энергопотребления. Данный фактор крайне важен для таких компаний, как Google, уже имеющих гигантские вычислительные кластеры, которые растут с экспоненциальной скоростью и потребляют колоссальные объемы энергии.
15.6. Сверточные нейронные сети
для распознавания образов; множественная классификация с набором данных MNIST
В главе 14 мы классифицировали рукописные цифры по изображениям низкого разрешения 8 × 8 пикселов из набора данных Digits, входящего в поставку scikit-learn. Набор данных базируется на подмножестве набора данных рукописных цифр MNIST с более высоким разрешением. В этой главе набор MNIST будет использоваться для исследования глубокого обучения на базе сверточной нейронной сети5 (CNN). Сверточные нейронные сети часто приме1
https://www.nvidia.com/en-us/data-center/tensorcore/.
2 https://devblogs.nvidia.com/tensor-core-ai-performance-milestones/.
3 https://www.tensorflow.org/install/gpu.
4 https://cloud.google.com/tpu/.
5 https://en.wikipedia.org/wiki/Convolutional_neural_network.
15.6. Сверточные нейронные сети для распознавания образов 707
няются в приложениях распознавания образов, например при распознавании рукописных цифр и символов, а также распознавании объектов в графических изображениях и видео. Кроме того, они могут применяться и в других классах приложений, например в обработке естественных языков и рекомендательных системах.
Набор данных Digits содержит всего 1797 образцов, тогда как набор MNIST содержит 70 000 помеченных образцов с изображениями цифр — 60 000 для обучения и 10 000 для тестирования. Каждый образец представляет собой изображение 28 × 28 пикселов (всего 784 признака) в оттенках серого, представленное в виде массива NumPy. Каждый пиксел является значением от 0 до 255, представляющим интенсивность (оттенок) этого пиксела — набор данных Digits использует менее точные оттенки со значениями от 0 до 16. Метки MNIST являются целыми значениями от 0 до 9 и обозначают цифры, представляемые каждым изображением.
Модель машинного обучения, использованная в предыдущей главе, выдавала на выходе прогнозируемый класс изображения цифры — целое число в диапазоне 0–9. Модель сверточной нейронной сети, которую мы построим, будет выполнять вероятностную классификацию1. Для каждого изображения цифры модель будет выдавать массив из 10 вероятностей, каждая из которых обозначает вероятность принадлежности цифры к классам от 0 до 9. Класс с наивысшей вероятностью становится прогнозируемым значением.
Воспроизводимость результатов в Keras
и глубокое обучение
В этой книге уже неоднократно говорилось о важности воспроизводимости результатов. В области глубокого обучения обеспечить воспроизводимость сложнее, потому что библиотеки интенсивно используют параллельные операции с плавающей точкой. При разных запусках операции могут выполняться в разном порядке, что может привести к различающимся результатам. Получение воспроизводимых результатов в Keras требует особого сочетания настроек среды и конфигурации кода, описанных в Keras FAQ:
https://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development
1 https://en.wikipedia.org/wiki/Probabilistic_classification.
708 Глава 15. Глубокое обучение
Базовая нейронная сеть Keras
Нейронная сеть Keras состоит из следующих компонентов:
ØØ
Сеть (также называемая моделью) — серия уровней с нейронами, используемыми для обучения на образцах. Нейроны каждого уровня получают входные данные, обрабатывают их (с использованием функции активации) и генерируют выходные данные. Эти данные подаются в сеть через входной уровень, определяющий размерность данных образца. За ним следуют скрытые уровни нейронов, реализующие обучение, и выходной уровень, генерирующий прогнозы. Чем больше уровней объединяет модель, тем глубже сеть — отсюда и термин «глубокое обучение».
ØØ
Функция потерь — вычисляет метрику эффективности прогнозирования сетью целевых значений. Более низкие значения соответствуют более качественным прогнозам.
ØØ
Оптимизатор — стремится минимизировать значения, сгенерированные функцией потерь, для оптимизации сети с целью повышения качества прогнозов.
Запуск JupyterLab
Этот раздел предполагает, что вы активировали среду Anaconda tf_env, созданную в разделе 15.3, после чего запустили JupyterLab из каталога ch15. Либо откройте файл MNIST_CNN.ipynb в JupyterLab и выполните готовый код в ячейках, либо создайте новый документ Notebook и введите код самостоятельно. При желании вы можете работать в командной строке IPython; тем не менее размещение кода в Jupyter Notebook существенно упрощает повторное выполнение кода примеров этой главы.
Напомним, что вы можете сбросить документ Jupyter Notebook и удалить его вывод командой Restart Kernel and Clear All Outputs… из меню JupyterLab Kernel. Команда завершает выполнение документа и стирает его вывод. Например, это можно сделать, если ваша модель работает недостаточно хорошо и вы хотите опробовать другие гиперпараметры или изменить структуру нейронной сети1. После этого можно снова выполнить документ Notebook по одной ячейке за раз или выполнить весь документ командой Run All из меню JupyterLab Run.
1 Мы обнаружили, что для очистки вывода иногда нам приходилось выполнять эту команду дважды.
15.6. Сверточные нейронные сети для распознавания образов 709
15.6.1. Загрузка набора данных MNIST
Импортируем модуль tensorflow.keras.datasets.mnist, чтобы загрузить набор данных:
[1]: from tensorflow.keras.datasets import mnist
Обратите внимание: так как мы используем версию Keras, встроенную в TensorFlow, имена модулей Keras начинаются с префикса "tensorflow.". В автономной версии Keras имена модулей начинаются с "keras.", поэтому будет использоваться имя keras.datasets. Keras использует TensorFlow для выполнения моделей глубокого обучения.
Функция load_data модуля mnist загружает обучающие и тестовые наборы MNIST:
[2]: (X_train, y_train), (X_test, y_test) = mnist.load_data()
При вызове load_data набор данных MNIST будет загружен в вашей системе. Функция возвращает кортеж из двух элементов, содержащих обучающие и тестовые наборы. Каждый элемент сам по себе является кортежем, содержащим образцы и метки соответственно.
15.6.2. Исследование данных
Познакомимся поближе с данными, перед тем как работать с ними. Сначала проверим размеры изображений обучающего набора (X_train), меток обучающего набора (y_train), изображений тестового набора (X_test) и меток тестового набора (y_test):
[3]: X_train.shape
[3]: (60000, 28, 28)
[4]: y_train.shape
[4]: (60000,)
[5]: X_test.shape
[5]: (10000, 28, 28)
[6]: y_test.shape
[6]: (10000,)
Из размеров X_train и X_test видно, что изображения имеют более высокое разрешение, чем изображения из набора данных Digits библиотеки scikit-learn (8 × 8).
710 Глава 15. Глубокое обучение
Визуализация цифр
Выведем некоторые изображения цифр. Подключите Matplotlib в документе Notebook, импортируйте Matplotlib и Seaborn, а затем выберите масштаб шрифта:
[7]: %matplotlib inline
[8]: import matplotlib.pyplot as plt
[9]: import seaborn as sns
[10]: sns.set(font_scale=2)
Магическая команда IPython
%matplotlib inline
означает, что графика на базе Matplotlib должна выводиться в документе Notebook, а не в отдельных окнах. За описаниями других магических команд IPython, которые могут использоваться в документах Jupyter Notebook, обращайтесь по адресу:
https://ipython.readthedocs.io/en/stable/interactive/magics.html
Затем мы выведем случайно выбранный набор из 24 изображений обучающего набора MNIST. Вспомните, о чем говорилось в главе 5: при индексировании массива NumPy можно передать последовательность индексов, чтобы выбрать только элементы массива с этими индексами. Здесь мы воспользуемся этой возможностью, чтобы выбрать элементы с одинаковыми индексами в массивах X_train и y_train. Это гарантирует, что для каждого случайно выбранного изображения будет выбрана правильная метка.
Функция choice библиотеки NumPy (из модуля numpy.random) случайным образом выбирает количество элементов, заданное вторым аргументом (24) из массива значений, заданного первым аргументом (в данном случае массив, содержащий диапазон индексов X_train). Функция возвращает массив, содержащий выбранные значения, который мы сохраняем в переменной index. Выражения X_train[index] и y_train[index] используют index для получения соответствующих элементов из обоих массивов. Остальные ячейки в коде визуализации из примера предыдущей главы:
[11]: import numpy as np
index = np.random.choice(np.arange(len(X_train)), 24, replace=False)
15.6. Сверточные нейронные сети для распознавания образов 711
figure, axes = plt.subplots(nrows=4, ncols=6, figsize=(16, 9))
for item in zip(axes.ravel(), X_train[index], y_train[index]):
axes, image, target = item
axes.imshow(image, cmap=plt.cm.gray_r)
axes.set_xticks([]) # remove x-axis tick marks
axes.set_yticks([]) # remove y-axis tick marks
axes.set_title(target)
plt.tight_layout()
Из следующего вывода видно, что изображения цифр MNIST имеют более высокое разрешение, чем изображения из набора данных Digits библиотеки scikit-learn.
Присмотревшись к цифрам, вы поймете, почему распознавание рукописных цифр стало такой трудной задачей:
ØØ
Одни люди пишут «открытые» цифры 4 (как в первой и третьей строке), другие используют «закрытый» вариант написания (как во второй строке). И хотя все разновидности «четверки» обладают сходными характеристики, все они отличаются друг от друга.
ØØ
Цифра 3 во второй строке выглядит странно — она напоминает гибрид 6 и 7. Сравните с намного более четко прописанной цифрой 3 в четвертой строке.
ØØ
Цифру 5 во второй строке легко можно принять за 6.
ØØ
Кроме того, люди пишут цифры под разными углами, как видно из четырех цифр 6 в третьей и четвертой строках — две цифры располагаются прямо, одна наклонена влево, а другая вправо.
712 Глава 15. Глубокое обучение
Если выполнить приведенный фрагмент несколько раз, то каждый раз будут выводиться случайно выбранные цифры1. Вероятно, вы увидите, что без меток над каждой цифрой вам будет нелегко распознать некоторые цифры. Вскоре вы увидите, насколько точно наша первая сверточная нейронная сеть будет распознавать цифры в тестовом наборе MNIST.
15.6.3. Подготовка данных
Как упоминалось в главе 14, упакованные наборы данных scikit-learn были предварительно обработаны по размерам нужных моделей. В реальных исследованиях вам обычно придется заниматься подготовкой данных самостоятельно (частично или полностью). Набор данных MNIST требует определенной подготовки для использования в сверточной нейронной сети Keras.
Переформатирование изображений
Сверточные нейронные сети Keras должны получать входные массивы NumPy, у которых каждый образец имеет следующий формат:
(ширина, высота, каналы)
В наборе MNIST ширина и высота каждого изображения равны 28 пикселам, при этом каждый пиксел имеет один канал (оттенок серого от 0 до 255), так что формат каждого образца будет выглядеть так:
(28, 28, 1)
Полноцветные изображения со значениями RGB (красный/зеленый/синий) каждого пиксела будут иметь три канала — по одному для красной, зеленой и синей составляющей.
По мере того как нейронная сеть обучается на основании изображений, она может создать еще много каналов. Вместо оттенков цвета каналы могут представлять более сложные признаки, например контуры, кривые и линии, что в конечном итоге позволит сети распознавать цифры на основании этих дополнительных признаков и их сочетаний.
1 При многократном выполнении кода ячейки номер фрагмента рядом с ячейкой будет каждый раз увеличиваться, как это происходит в IPython в командной строке.
15.6. Сверточные нейронные сети для распознавания образов 713
Преобразуем 60 000 обучающих и 10 000 тестовых изображений к правильным размерам для использования в нашей сверточной нейронной сети. Напомним, что метод reshape массива NumPy получает кортеж, представляющий новую конфигурацию массива:
[12]: X_train = X_train.reshape((60000, 28, 28, 1))
[13]: X_train.shape
[13]: (60000, 28, 28, 1)
[14]: X_test = X_test.reshape((10000, 28, 28, 1))
[15]: X_test.shape
[15]: (10000, 28, 28, 1)
Нормализация данных изображений
Числовые признаки в образцах данных могут иметь сильно различающиеся диапазоны значений. Сети глубокого обучения лучше работают с данными, масштабированными в диапазоне от 0,0 до 1,0 или в диапазоне с математическим ожиданием 0,0 и стандартным отклонением 1,01. Преобразование данных в одну из этих форм называется нормализацией.
В MNIST каждый пиксел представлен целым числом в диапазоне 0–255. Следующие команды преобразуют значения в 32-разрядные (4-байтовые) числа с плавающей точкой при помощи метода astype массива NumPy, после чего каждый элемент полученного массива делится на 255 с получением нормализованных значений в диапазоне 0,0–1,0:
[16]: X_train = X_train.astype('float32') / 255
[17]: X_test = X_test.astype('float32') / 255
Прямое унитарное кодирование: преобразование меток из целых чисел в категорийные данные
Как упоминалось ранее, прогноз сверточной нейронной сети для каждой цифры будет представлять собой массив из 10 вероятностей, обозначающих
1 S. Ioffe and Szegedy, C. «Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift». https://arxiv.org/abs/1502.03167
714 Глава 15. Глубокое обучение
принадлежность цифры к одному из классов от 0 до 9. При оценке точности модели Keras сравнивает прогнозы модели с метками. Для этого Keras требует, чтобы значения имели одинаковую размерность, но метка MNIST для каждой цифры представляет собой целое значение в диапазоне 0–9. Следовательно, метки необходимо преобразовать в категорийные данные, то есть массивы категорий, соответствующие формату прогнозов. Для этого будет использоваться процесс, называемый прямым унитарным кодированием 1: данные преобразуются в массивы значений 1.0 и 0.0, в котором только один элемент равен 1.0, а остальные равны 0.0. Для MNIST в результате прямого унитарного кодирования будут получены 10-элементные массивы, представляющие категории от 0 до 9. Прямое унитарное кодирование также может применяться к другим типам данных.
Мы точно знаем, к какой категории относится каждая цифра, так что категорийное представление метки цифры будет состоять из 1.0 в элементе с индексом цифры и 0.0 во всех остальных элементах (напомним, во внутренней реализации Keras используются числа с плавающей точкой). Таким образом, категорийное представление 7 будет выглядеть так:
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]
а представление 3 — так:
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Модуль tensorflow.keras.utils предоставляет функцию to_categorical для выполнения прямого унитарного кодирования. Функция подсчитывает уникальные категории, а затем для каждого закодированного элемента создает массив соответствующей длины со значением 1.0 в нужной позиции. Преобразуем y_train и y_test из одномерных массивов со значениями 0–9 в двумерные массивы категорийных данных. После этого строки массивов будут выглядеть так, как показано выше. Фрагмент [21] выводит категорийные данные одного образца для цифры 5 (напомним, что NumPy выводит точку, но не выводит завершающие нули в значениях с плавающей точкой):
[18]: from tensorflow.keras.utils import to_categorical
[19]: y_train = to_categorical(y_train)
1 Этот термин происходит от некоторых цифровых схем, у которых в группе битов может быть установлен только один бит (то есть только один бит может иметь значение 1). https://en.wikipedia.org/wiki/One-hot.
15.6. Сверточные нейронные сети для распознавания образов 715
[20]: y_train.shape
[20]: (60000, 10)
[21]: y_train[0]
[21]: array([ 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
dtype=float32)
[22]: y_test = to_categorical(y_test)
[23]: y_test.shape
[23]: (10000, 10)
15.6.4. Создание нейронной сети
Итак, данные подготовлены, и мы можем переходить к настройке сверточной нейронной сети. Начнем с модели Keras Sequential из модуля tensorflow.keras.models:
[24]: from tensorflow.keras.models import Sequential
[25]: cnn = Sequential()
Полученная сеть будет выполнять свои уровни последовательно — выход одного уровня станет входом другого; такие сети также называются сетями прямого распространения. Как будет показано при обсуждении рекуррентных нейронных сетей, не все нейронные сети работают по этому принципу.
Добавление уровней в сеть
Типичная сверточная нейронная сеть состоит из нескольких уровней — входного уровня, получающего обучающие образцы скрытых уровней, которые обучаются по образцам, и выходного уровня, генерирующего вероятности прогнозов. Теперь создадим простейшую сверточную сеть. Импортируем из модуля tensorflow.keras.layers классы уровней, которые будут использоваться в этом примере:
[26]: from tensorflow.keras.layers import Conv2D, Dense, Flatten,
MaxPooling2D
Все разновидности уровней рассматриваются ниже.
716 Глава 15. Глубокое обучение
Свертка
Наша сеть будет начинаться со сверточного уровня, который использует отношения между пикселами, расположенными поблизости друг к другу, для выявления полезных признаков (или закономерностей) для малых областей каждого образца. Эти признаки станут входными данными последующих уровней.
Малые области, на которых обучается сверточная нейронная сеть, называются ядрами (kernels) или участками (patches). Рассмотрим свертку на примере изображения 6 × 6. На диаграмме слева закрашенный квадрат 3 × 3 представляет ядро — числа просто определяют порядок посещения и обработки ядер:
􀉙􀉞􀉪􀉨
􀀙􀀃􀁛􀀃􀀙􀀃􀉞􀉨􀀃􀉫􀉜􀉟􀉪􀉬􀉤􀉢􀀗􀀃􀁛􀀃􀀗􀀃􀉩􀉨􀉫􀉥􀉟􀀃􀉫􀉜􀉟􀉪􀉬􀉤􀉢􀀔􀀗􀀖􀀕􀈼􀉯􀉨􀉞􀀃􀉫􀉜􀉟􀉪􀉬􀉨􀉱􀉧􀉨􀉝􀉨􀀃􀉭􀉪􀉨􀉜􀉧􀉹􀈼􀉵􀉯􀉨􀉞􀀃􀉫􀉜􀉟􀉪􀉬􀉨􀉱􀉧􀉨􀉝􀉨􀀃􀉭􀉪􀉨􀉜􀉧􀉹􀀘􀀛􀀚􀀙􀀜􀀔􀀕􀀔􀀔􀀔􀀓􀀔􀀖􀀔􀀙􀀔􀀘􀀔􀀗􀀔􀀔􀀕􀀕􀀖􀀖􀀗􀀗
Ядро можно рассматривать как «скользящее окно», которое сверточный уровень перемещает по одному пикселу слева направо по изображению. Когда ядро достигает правого края, сверточный уровень смещает ядро на один пиксел вниз и повторяет процесс слева направо. Обычно используются размеры ядра 3 × 31, хотя нам встречались ядра 5 × 5 и 7 × 7 для изображений более высокого разрешения. Размер ядра является настраиваемым гиперпараметром.
В исходном состоянии ядро находится в левом верхнем углу исходного изображения — позиция ядра 1 (закрашенный квадрат) на входном уровне на диаграмме со с. 716. Сверточный уровень выполняет математические вычис1
https://www.quora.com/How-can-I-decide-the-kernel-size-output-maps-and-layers-of-CNN.
15.6. Сверточные нейронные сети для распознавания образов 717
ления, используя эти девять признаков для «обучения», после чего выводит один новый признак в позицию 1 выхода уровня. Рассматривая признаки, находящиеся по соседству друг с другом, сеть начинает распознавать такие признаки, как контуры, прямые линии и кривые.
Затем сверточный уровень смещает ядро на один пиксел вправо (величина смещения называется шагом) в позицию 2 входного уровня. Новая позиция перекрывается с двумя из трех столбцов предыдущей позиции, что позволяет сверточному уровню учиться по всем соприкасающимся признакам. Уровень обучается по девяти признакам ядра в позиции 2 и выводит один новый признак в позиции 2 на выходе:
􀉙􀉞􀉪􀉨
􀀙􀀃􀁛􀀃􀀙􀀃􀉞􀉨􀀃􀉫􀉜􀉟􀉪􀉬􀉤􀉢􀀗􀀃􀁛􀀃􀀗􀀃􀉩􀉨􀉫􀉥􀉟􀀃􀉫􀉜􀉟􀉪􀉬􀉤􀉢􀀔􀀗􀀖􀀕􀈼􀉯􀉨􀉞􀀃􀉫􀉜􀉟􀉪􀉬􀉨􀉱􀉧􀉨􀉝􀉨􀀃􀉭􀉪􀉨􀉜􀉧􀉹􀈼􀉵􀉯􀉨􀉞􀀃􀉫􀉜􀉟􀉪􀉬􀉨􀉱􀉧􀉨􀉝􀉨􀀃􀉭􀉪􀉨􀉜􀉧􀉹􀀘􀀛􀀚􀀙􀀜􀀔􀀕􀀔􀀔􀀔􀀓􀀔􀀖􀀔􀀙􀀔􀀘􀀔􀀗􀀔􀀔􀀕􀀕􀀖􀀖􀀗􀀗
Для изображения 6 × 6 и ядра 3 × 3 сверточный уровень повторяет процедуру еще два раза, чтобы получить признаки для позиций 3 и 4 на выходе уровня. Затем сверточный уровень смещает ядро на один пиксел и повторяет процесс слева направо для следующих четырех позиций ядра, формируя выход для позиций 5–8, затем 9–12 и, наконец, 13–16. Полный проход по изображению слева направо и сверху вниз называется фильтром. Для ядра 3 × 3 размеры фильтра (4 × 4 в приведенном примере) на 2 меньше размеров входных данных (6 × 6). Для каждого изображения MNIST 28 × 28 размер фильтра составит 26 × 26. При обработке небольших изображений (таких, как в MNIST) количество фильтров в сверточном уровне обычно равно 32 или 64, и каждый фильтр предоставляет разные результаты. Число фильтров зависит от размеров изображения: изображения с высоким разрешением имеют больше признаков, поэтому им требуется больше фильтров. Если изучить код, который
718 Глава 15. Глубокое обучение
использовался командой Keras для построения заранее обученных сверточных нейронных сетей1, вы увидите, что они используют в своих первых сверточных уровнях 64, 128 и даже 256 фильтров. На основании сверточных нейронных сетей и того факта, что изображения MNIST невелики, мы будем использовать 64 фильтра в первом сверточном уровне. Набор фильтров, производимых сверточным уровнем, называется картой признаков.
Последующие сверточные уровни объединяют признаки из предыдущих карт признаков для распознавания более крупных признаков и т. д. Например, если сеть предназначена для распознавания лиц, то ранние уровни могут распознавать линии, контуры и кривые, а последующие уровни могут объединять их в признаки более высокого уровня — глаза, брови, носы, уши и т. д. После того как сеть изучит некоторый признак, вследствие свертки она сможет распознать его в любом месте изображения. Это — одна из причин использования сверточных нейронных сетей для распознавания объектов в изображениях.
Добавление сверточного уровня
Добавим в модель сверточный уровень Conv2D:
[27]: cnn.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu',
input_shape=(28, 28, 1)))
Уровень Conv2D настраивается следующими аргументами:
ØØ
filters=64 — количество фильтров в итоговой карте признаков;
ØØ
kernel_size=(3, 3) — размер ядра, используемого в каждом фильтре;
ØØ
activation='relu' — для получения вывода уровня используется функция активации 'relu' (Rectified Linear Unit). 'relu' — наиболее часто используемая функция активации в современных сетях глубокого обучения2; она просто вычисляется, что хорошо отражается на быстродействии3. Чаще всего для сверточных уровней рекомендуется использовать именно эту функцию4.
1 https://github.com/keras-team/keras-applications/tree/master/keras_applications.
2 Шолле Франсуа. Глубокое обучение на Python. — СПб.: Питер, 2020. С. 97.
3 https://towardsdatascience.com/exploring-activation-functions-for-neural-networks-73498da59b02.
4 https://www.quora.com/How-should-I-choose-a-proper-activation-function-for-theneural-network.
15.6. Сверточные нейронные сети для распознавания образов 719
Так как это первый уровень модели, мы также передаем аргумент input_shape=(28, 28,1) для определения размерности каждого образца. При этом автоматически создается входной уровень для загрузки образцов и передачи их уровню Conv2D, который является первым скрытым уровнем. В Keras каждый последующий уровень определяет свое значение input_shape по выходным данным предыдущего уровня, что упрощает наложение уровней.
Размерность вывода первого сверточного уровня
На предыдущем сверточном уровне входные образцы имеют формат 28 × 28 × 1, то есть 784 признака для каждого. Мы задали для уровня 64 фильтра и размер ядра 3 × 3, так что вход каждого изображения имеет размеры 26 × 26 × 64, что дает 43 264 признака в карте признаков — размерность существенно возрастает, а число огромно по сравнению с признаками, которые обрабатывались в моделях главы 14. Так как каждый уровень добавляет новые признаки, степень размерности полученных карт признаков значительно увеличивается. Это — одна из причин, по которым исследования в области глубокого обучения часто требуют колоссальных вычислительных мощностей.
Чрезмерная подгонка
Чрезмерная подгонка (см. главу 14) возникает, когда модель слишком сложна по сравнению с тем, что она моделирует. В исключительных случаях модель запоминает свои обучающие данные. Построенный вами прогноз на основании модели с чрезмерной подгонкой будет точным, если новые данные совпадают с обучающими, но модель при этом может работать неэффективно с неизвестными ей данными. Чрезмерная подгонка обычно возникает при глубоком обучении, когда размерность уровней становится слишком большой1,2,3. В результате сеть изучает признаки изображений цифр из обучающего набора, вместо того чтобы изучать общие признаки изображений цифр. Среди методов предотвращения чрезмерной подгонки можно выделить обучение для меньшего количества эпох, приращение данных, прореживание и L1/L2-регуляризацию4,5 (о прореживании см. ниже).
1 https://cs231n.github.io/convolutional-networks/.
2 https://medium.com/@cxu24/why-dimensionality-reduction-is-important-dd60b5611543.
3 https://towardsdatascience.com/preventing-deep-neural-network-from-overfitting-953458db800a.
4 https://towardsdatascience.com/deep-learning-3-more-on-cnns-handling-overfitting-2bd5d99abe5d.
5 https://www.kdnuggets.com/2015/04/preventing-overfitting-neural-networks.html.
720 Глава 15. Глубокое обучение
Более высокая степень размерности увеличивает (иногда значительно) и время вычислений. Если же глубокое обучение выполняется на обычном процессоре (вместо графического или тензорного), то обучение может стать недопустимо медленным.
Добавление объединяющего уровня
Для предотвращения чрезмерной подгонки и сокращения времени вычислений за сверточным уровнем часто следует один или несколько уровней, сокращающих степень размерности выходных данных сверточного уровня. Объединяющий уровень сжимает результаты, отбрасывая признаки, вследствие чего модель становится более общей. Самый распространенный метод объединения — max-объединение; он анализирует квадрат признаков 2 × 2 и оставляет только максимальный признак. Чтобы понять, как работает объединение, вернемся к набору признаков 6 × 6. На следующей диаграмме числовые значения в квадрате 6 × 6 представляют признаки, которые требуется сжать, и квадрат 2 × 2 в позиции 1 представляет исходный пул признаков для анализа:
􀉉􀉭
􀉥􀀙􀀃􀁛􀀃􀀙􀀃􀉞􀉨􀀃􀉩􀉪􀉢􀉦􀉟􀉧􀉟􀉧􀉢􀉹􀀃􀁐􀁄􀁛􀀐􀉨􀉛􀉴􀉟􀉞􀉢􀉧􀉟􀉧􀉢􀉹􀀃􀀕􀀃􀁛􀀃􀀕􀀖􀀃􀁛􀀃􀀖􀀃􀉩􀉨􀉫􀉥􀉟􀀃􀉩􀉪􀉢􀉦􀉟􀉧􀉟􀉧􀉢􀉹􀀃􀁐􀁄􀁛􀀐􀉨􀉛􀉴􀉟􀉞􀉢􀉧􀉟􀉧􀉢􀉹􀀃􀀕􀀃􀁛􀀃􀀕􀀜􀀜􀀚􀈼􀉯􀉨􀉞􀀃􀉨􀉛􀉴􀉟􀉞􀉢􀉧􀉹􀉸􀉳􀉟􀉝􀉨􀀃􀉭􀉪􀉨􀉜􀉧􀉹􀈼􀉵􀉯􀉨􀉞􀀃􀉨􀉛􀉴􀉟􀉞􀉢􀉧􀉹􀉸􀉳􀉟􀉝􀉨􀀃􀉭􀉪􀉨􀉜􀉧􀉹􀀚􀀛􀀜􀀜􀀚􀀚􀀜􀀕􀀗􀀘􀀕􀀖􀀔􀀚􀀗􀀜􀀘􀀖􀀔􀀚􀀖􀀗􀀕􀀗􀀜􀀘􀀚􀀖􀀔􀀙􀀛􀀜􀀔􀀙􀀔􀀖􀀘􀀛􀀕􀀗􀀖􀀚􀀔􀀔􀀕􀀕􀀖􀀖
Уровень max-объединения сначала проверяет пул в позиции 1 на приведенной диаграмме, после чего выводит максимальный признак из этого пула (9) на диаграмме. В отличие от свертки, пулы не перекрываются. Пул смещается на свою ширину — для пула 2 × 2 шаг равен 2. Для второго пула, представленного
15.6. Сверточные нейронные сети для распознавания образов 721
оранжевым квадратом 2 × 2, уровень выводит признак (7). Для третьего пула выводится признак (9). Когда пул достигнет правого края, объединяющий уровень смещает пул вниз на его высоту (2 строки), после чего продолжает смещение слева направо. Так как каждая группа из четырех признаков сокращается до 1, объединение 2 × 2 сжимает количество признаков на 75%. Добавим уровень MaxPooling2D в модель:
[28]: cnn.add(MaxPooling2D(pool_size=(2, 2)))
Выход предыдущего уровня сокращается с 26 × 26 × 64 до 13 × 13 × 641.
Хотя объединение часто применяется для борьбы с чрезмерной подгонкой, авторы некоторых исследований считают, что дополнительные сверточные уровни с большим размером шага ядра могут сократить степень размерности и предотвратить чрезмерную подгонку без потери признаков2.
Добавление еще одного сверточного уровня и объединяющего уровня
Сверточные нейронные сети часто содержат много сверточных и объединяющих уровней. Сверточные сети Keras обычно удваивают количество фильтров в последующих сверточных уровнях, чтобы модель могла извлечь больше связей между признаками3. Добавим второй сверточный уровень со 128 фильтрами, за которым следует второй объединяющий уровень для сокращения степени размерности на 75%:
[29]: cnn.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu'))
[30]: cnn.add(MaxPooling2D(pool_size=(2, 2)))
Входом второго сверточного уровня является выход 13 × 13 × 64 первого объединяющего уровня. Таким образом, выход фрагмента [29] будет иметь размеры 11 × 11 × 128. Для нечетных размеров (например, 11 × 11) объединяющие уровни Keras по умолчанию используют округление вниз (в данном
1 Другой метод сокращения чрезмерной подгонки заключается в добавлении уровней прореживания.
2 Tobias, Jost, Dosovitskiy, Alexey, Brox, Thomas, Riedmiller, and Martin. «Striving for Simplicity: The All Convolutional Net.» 13 апреля 2015 г., https://arxiv.org/abs/1412.6806.
3 https://github.com/keras-team/keras-applications/tree/master/keras_applications.
722 Глава 15. Глубокое обучение
случае до 11 × 11), так что выход этого объединяющего уровня будет иметь размеры 5 × 5 × 128.
Одномерное преобразование результатов
На текущий момент выход предыдущего уровня является трехмерным (5 × 5 × 128), но на выходе модель должна выдавать одномерный массив 10 вероятностей классификации цифр. Для подготовки одномерных прогнозов сначала необходимо преобразовать трехмерный выход предыдущего уровня к одному измерению. Уровень Keras Flatten преобразует свой вход к одному измерению. В данном случае выход уровня Flatten будет иметь размеры 1 × 3200 (то есть 5*5*128):
[31]: cnn.add(Flatten())
Добавление уровня Dense для сокращения количества признаков
Уровни, предшествующие уровню Flatten, изучали признаки цифр. Теперь необходимо взять все эти признаки и изучить отношения между ними, чтобы наша модель могла определить, какую цифру представляет то или иное изображение. Изучение отношений между признаками и проведение классификации достигается в полносвязных уровнях Dense наподобие изображенных на диаграмме нейронной сети ранее в этой главе. Следующий уровень Dense создает 128 нейронов (блоков), обучающихся на 3200 выходных значениях предыдущего уровня:
[32]: cnn.add(Dense(units=128, activation='relu'))
Многие сверточные сети содержат по крайней мере один уровень Dense. Сверточные сети, предназначенные для обработки более сложных графических наборов данных с изображениями более высокого разрешения вроде ImageNet — набора данных, содержащего более 14 миллионов изображений1, — часто содержат несколько уровней Dense, обычно с 4096 нейронами. Такие конфигурации встречаются в некоторых предварительно обученных сверточных нейронных сетях Keras для ImageNet2 (см. раздел 15.11).
1 http://www.image-net.org.
2 https://github.com/keras-team/keras-applications/tree/master/keras_applications.
15.6. Сверточные нейронные сети для распознавания образов 723
Добавление еще одного уровня Dense для получения итогового результата
Последним уровнем нашей сети будет уровень Dense, который классифицирует свои входные данные по нейронам, представляющим классы от 0 до 9. Функция активации softmax преобразует значения 10 нейронов в классификационные вероятности. Нейрон, производящий наибольшую вероятность, представляет прогноз для заданного изображения:
[33]: cnn.add(Dense(units=10, activation='softmax'))
Вывод сводной информации модели
Метод summary модели выводит информацию об уровнях модели. В частности, здесь можно найти интересную информацию о размерах выходных данных разных уровней и количестве параметров. Параметрами являются веса, выведенные сетью в ходе обучения1,2. Сеть относительно невелика, однако ей пришлось изучить почти 500 000 параметров! И это — в случае с крошечными изображениями, занимающими меньше четверти размера значка на домашних экранах большинства современных смартфонов. Но представьте, сколько признаков придется изучить сети для обработки кадров видео 4K или изображений сверхвысокого разрешения, создаваемых современными цифровыми камерами! В графе Output Shape значение None означает лишь то, что модель не знает заранее, сколько обучающих образцов вы предоставите, — это станет известным лишь с началом обучения.
[34]: cnn.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 26, 26, 64) 640
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 13, 13, 64) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 11, 11, 128) 73856
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 5, 5, 128) 0
1 https://hackernoon.com/everything-you-need-to-know-about-neural-networks-8988c3ee4491.
2 https://www.kdnuggets.com/2018/06/deep-learning-best-practices-weight-initialization.html.
724 Глава 15. Глубокое обучение
_________________________________________________________________
flatten_1 (Flatten) (None, 3200) 0
_________________________________________________________________
dense_1 (Dense) (None, 128) 409728
_________________________________________________________________
dense_2 (Dense) (None, 10) 1290
=================================================================
Total params: 485,514
Trainable params: 485,514
Non-trainable params: 0
_________________________________________________________________
Обратите внимание и на отсутствие «необучаемых» (Non-trainable) параметров. По умолчанию Keras проводит обучение по всем параметрам, но обучение можно заблокировать для конкретных уровней; обычно это делается в процессе настройки и оптимизации сетей или при использовании параметров, полученных в ходе обучения другой модели, в новой модели (этот процесс называется переносом обучения1).
Визуализация структуры модели
Чтобы получить наглядное представление о модели, воспользуйтесь функцией plot_model из модуля tensorflow.keras.utils:
[35]: from tensorflow.keras.utils import plot_model
from IPython.display import Image
plot_model(cnn, to_file='convnet.png', show_shapes=True,
show_layer_names=True)
Image(filename='convnet.png')
После сохранения результата в файле convnet.png мы используем класс Image модуля IPython.display для отображения результата в документе Notebook. Keras назначает имена уровней на диаграмме2:
1 https://keras.io/getting-started/faq/#how-can-i-freeze-keras-layers.
2 Узел с большим целочисленным значением 112430057960 в верхней части диаграммы появился из-за ошибки в текущей версии Keras. Узел представляет входной уровень и должен иметь обозначение «InputLayer».
15.6. Сверточные нейронные сети для распознавания образов 725
Компиляция модели
После добавления всех уровней построение модели завершается вызовом метода compile:
[36]: cnn.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
726 Глава 15. Глубокое обучение
Аргументы:
ØØ
optimizer='adam' — оптимизатор, используемый моделью для регулировки весов в нейронной сети в процессе обучения. Отметим, что существует много подходящих оптимизаторов1, в частности, 'adam' показывает неплохие результаты в широком спектре моделей2,3.
ØØ
loss='categorical_crossentropy' — функция потерь, используемая оптимизатором в сетях множественной классификации (таких, как наша сверточная сеть), которая будет прогнозировать 10 классов. В процессе обучения нейронной сети оптимизатор пытается минимизировать значения, возвращаемые функцией потерь. Чем ниже потери, тем лучше справляется нейронная сеть с прогнозированием. Для бинарной классификации (которая будет использоваться позднее в этой главе) Keras предоставляет функцию 'binary_crossentropy', а для регрессии — 'mean_squared_error'. За информацией о других функциях потерь обращайтесь по адресу:
https://keras.io/losses/.
ØØ
metrics=['accuracy'] — список метрик, которые будут производиться сетью, для того чтобы упростить вам оценку модели. Точность — популярная метрика, часто используемая в классификационных моделях. В этом примере мы воспользуемся метрикой точности для проверки процента правильных прогнозов. Список других метрик доступен по адресу:
https://keras.io/metrics/.
15.6.5. Обучение и оценка модели
По аналогии с моделями scikit-learn обучим модель Keras вызовом ее метода fit:
ØØ
Как и в Scikit-learn, в первых двух аргументах передаются обучающие данные и категорийные метки целей.
1 За описаниями других оптимизаторов Keras обращайтесь по адресу https://keras.io/optimizers/.
2 https://medium.com/octavian-ai/which-optimizer-and-learning-rate-should-i-use-for-deep-learning-5acb418f9b2.
3 https://towardsdatascience.com/types-of-optimization-algorithms-used-in-neural-networks-and-ways-to-optimize-gradient-95ae5d39529f.
15.6. Сверточные нейронные сети для распознавания образов 727
ØØ
Аргумент epochs сообщает, сколько раз модель должна обработать весь набор обучающих данных. Напомним, обучение нейронных сетей проходит в итеративном режиме.
ØØ
Аргумент batch_size задает количество образцов, обрабатываемых за один раз в каждой эпохе. Для большинства моделей выбирается степень 2 от 32 до 512. Более высокие значения могут привести к снижению точности модели1. Мы выбрали значение 64. Вы можете опробовать разные значения и определить, как они влияют на эффективность модели.
ØØ
В общем случае некоторые образцы должны использоваться для проверки модели. Если вы укажете проверочные данные, то после каждой эпохи модель использует их для построения прогнозов и вывода проверочных значений потерь и точности. Вы можете изучить эти модели для настройки ваших уровней и гиперпараметров метода fit или, возможно, для изменения структуры уровней модели. В данном случае мы использовали аргумент validation_split для обозначения того, что модель должна зарезервировать последние 10% (0.1) обучающих образцов для проверки2, — в данном случае 6000 образцов будут использованы для проверки. Если у вас имеются отдельные проверочные данные, то аргумент validation_data (см. раздел 15.9) может использоваться для передачи кортежа с массивами образцов и целевых меток. В общем случае лучше использовать случайно выбранные проверочные данные. Для этой цели можно воспользоваться функцией train_test_split библиотеки scikit-learn (как это будет сделано позднее в этой главе), после чего передать случайно выбранные данные в аргументе validation_data.
В следующем выводе точность обучения (acc) и точность проверки (val_acc) выделены жирным шрифтом:
[37]: cnn.fit(X_train, y_train, epochs=5, batch_size=64,
validation_split=0.1)
Train on 54000 samples, validate on 6000 samples
Epoch 1/5
54000/54000 [==============================] - 68s 1ms/step - loss:
1 Keskar, Nitish Shirish, Dheevatsa Mudigere, Jorge Nocedal, Mikhail Smelyanskiy and Ping Tak Peter Tang. «On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima.» CoRR abs/1609.04836 (2016). https://arxiv.org/abs/1609.04836.
2 https://keras.io/getting-started/faq/#how-is-the-validation-split-computed.
728 Глава 15. Глубокое обучение
0.1407 - acc: 0.9580 - val_loss: 0.0452 - val_acc: 0.9867
Epoch 2/5
54000/54000 [==============================] - 64s 1ms/step - loss:
0.0426 - acc: 0.9867 - val_loss: 0.0409 - val_acc: 0.9878
Epoch 3/5
54000/54000 [==============================] - 69s 1ms/step - loss:
0.0299 - acc: 0.9902 - val_loss: 0.0325 - val_acc: 0.9912
Epoch 4/5
54000/54000 [==============================] - 70s 1ms/step - loss:
0.0197 - acc: 0.9935 - val_loss: 0.0335 - val_acc: 0.9903
Epoch 5/5
54000/54000 [==============================] - 63s 1ms/step - loss:
0.0155 - acc: 0.9948 - val_loss: 0.0297 - val_acc: 0.9927
[37]:
В разделе 15.7 рассматривается TensorBoard — инструмент TensorFlow для визуализации данных по моделям глубокого обучения. В частности, мы рассмотрим диаграммы, которые показывают, как точность обучения и проверки и значения потерь изменяются в разных эпохах. В разделе 15.8 будет продемонстрирована программа Андрея Карпати (Andrej Karpathy) ConvnetJS, которая обучает сверточные сети в браузере и динамически строит визуализацию выходов уровней, включая то, что «видит» каждый сверточный уровень в процессе обучения. Апробация моделей MNIST и CIFAR10 поможет вам лучше понять сложные механизмы работы нейронных сетей.
В процессе обучения метод fit выводит различную информацию: прогресс каждой эпохи, длительность выполнения эпохи (в нашем случае каждая занимала 63–70 секунд) и оценочные метрики для текущего прохода. В последней эпохе этой модели точность достигла 99,48% для обучающих образцов (acc) и 99,27% для проверочных образцов (val_acc). Впечатляющие показатели, особенно если учесть, что мы еще не пытались настраивать гиперпараметры или подбирать количество и типы уровней, что может улучшить (или ухудшить) результаты. Как и машинное обучение, глубокое обучение является эмпирической дисциплиной, в которой большое количество экспериментов приносит пользу.
Оценка модели
Теперь точность модели можно проверить на данных, неизвестных модели. Для этого вызовем метод evaluate модели, который выводит продолжитель15.6.
Сверточные нейронные сети для распознавания образов 729
ность обработки тестовых образцов (4 секунды и 366 микросекунд в данном случае):
[38]: loss, accuracy = cnn.evaluate(X_test, y_test)
10000/10000 [==============================] - 4s 366us/step
[39]: loss
[39]: 0.026809450998473768
[40]: accuracy
[40]: 0.9917
Из этого вывода следует, что наша модель сверточных нейронных сетей обеспечивает точность 99,17% при прогнозировании меток для незнакомых данных, хотя мы еще даже не пытались настраивать модель. Поиски в интернете позволяют отыскать модели, способные прогнозировать данные MNIST с почти 100-процентной точностью. Попробуйте поэкспериментировать с разными уровнями, типами уровней и их параметрами, наблюдая за тем, как эти изменения влияют на результаты.
Построение прогнозов
Метод predict модели прогнозирует классы изображений цифр из своего аргумента-массива (X_test):
[41]: predictions = cnn.predict(X_test)
Чтобы проверить, какой цифре соответствует первый образец, достаточно просмотреть y_test[0]:
[42]: y_test[0]
[42]: array([0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], dtype=float32)
Как видим, первый образец представляет цифру 7, потому что в категорийном представлении метки тестового образца в элементе с индексом 7 содержится значение 1.0 (напомним, представление создано прямым унитарным кодированием).
Проверим вероятности, возвращаемые методом predict для первого тестового образца:
730 Глава 15. Глубокое обучение
[43]: for index, probability in enumerate(predictions[0]):
print(f'{index}: {probability:.10%}')
0: 0.0000000201%
1: 0.0000001355%
2: 0.0000186951%
3: 0.0000015494%
4: 0.0000000003%
5: 0.0000000012%
6: 0.0000000000%
7: 99.9999761581%
8: 0.0000005577%
9: 0.0000011416%
Согласно этим результатам, predictions[0] показывает, что по мнению нашей модели образец представляет цифру 7 с почти 100-процентной вероятностью. Не все прогнозы обладают такой достоверностью.
Поиск неправильных прогнозов
На следующем шаге стоит просмотреть несколько неправильно спрогнозированных изображений, чтобы понять, с какими изображениями у нашей модели возникли трудности. Например, если модель всегда ошибается с распознаванием цифры 8, то, возможно, в обучающие данные стоит добавить больше образцов 8.
Прежде чем просматривать ошибочные прогнозы, необходимо их найти. Возьмем приведенную выше строку predictions[0]. Чтобы определить, был ли прогноз правильным, необходимо сравнить индекс наибольшей вероятности в predictions[0] с индексом элемента, содержащего 1.0 в y_test[0]. Если значения индексов совпадают, то прогноз правильный; в противном случае он ошибочен. Функция argmax библиотеки NumPy определяет индекс элемента с наибольшим значением в своем аргументе-массиве. Воспользуемся этой функцией для поиска ошибочных прогнозов. В следующем фрагменте p — массив прогнозируемых значений, а e — массив ожидаемых значений (ожидаемыми значениями являются метки тестовых изображений из набора данных):
[44]: images = X_test.reshape((10000, 28, 28))
incorrect_predictions = []
for i, (p, e) in enumerate(zip(predictions, y_test)):
15.6. Сверточные нейронные сети для распознавания образов 731
predicted, expected = np.argmax(p), np.argmax(e)
if predicted != expected:
incorrect_predictions.append(
(i, images[i], predicted, expected))
В этом фрагменте мы сначала изменим размеры (28, 28, 1), необходимые Keras для обучения, до (28, 28), требуемых Matplotlib для вывода изображений. Затем список incorrect_predictions заполняется в цикле for. Мы упаковываем строки данных, представляющие каждый образец в массивах predictions и y_test, а затем перебираем их для сохранения индексов. Если результаты argmax для p и e различные, то это означает, что прогноз ошибочен, и к списку incorrect_predictions присоединяется кортеж с индексом образца, изображением, прогнозируемым и ожидаемым значением. Следующий фрагмент проверяет общее количество ошибочных прогнозов (из 10 000 изображений тестового набора):
[45]: len(incorrect_predictions)
[45]: 83
Визуализация ошибочных предсказаний
Следующий фрагмент выводит 24 неправильных изображения с указанием индекса каждого изображения (index), прогнозируемого значения (p) и ожидаемого значения (e):
[46]: figure, axes = plt.subplots(nrows=4, ncols=6, figsize=(16, 12))
for axes, item in zip(axes.ravel(), incorrect_predictions):
index, image, predicted, expected = item
axes.imshow(image, cmap=plt.cm.gray_r)
axes.set_xticks([]) # remove x-axis tick marks
axes.set_yticks([]) # remove y-axis tick marks
axes.set_title(
f'index: {index}\np: {predicted}; e: {expected}')
plt.tight_layout()
Прежде чем просматривать ожидаемые значения, взгляните на каждое изображение и запишите, какой цифре, на ваш взгляд, оно соответствует — это важная составляющая изучения данных:
732 Глава 15. Глубокое обучение
Вывод вероятностей для нескольких ошибочных прогнозов
Просмотрим вероятности нескольких ошибочных прогнозов. Следующая функция выводит вероятности заданного массива прогнозов:
[47]: def display_probabilities(prediction):
for index, probability in enumerate(prediction):
print(f'{index}: {probability:.10%}')
Хотя изображение 8 (с индексом 495) в первой строке вывода похоже на 8, у нашей модели возникли с ней затруднения. Как видно из следующего вывода, модель спрогнозировала это значение как 0, но также полагала, что с 16-процентной вероятностью это может быть 6, а с 23-процентной вероятностью — 8:
[48]: display_probabilities(predictions[495])
0: 59.7235262394%
1: 0.0000015465%
2: 0.8047289215%
3: 0.0001740813%
4: 0.0016636326%
5: 0.0030567855%
6: 16.1390662193%
7: 0.0000001781%
8: 23.3022540808%
9: 0.0255270657%
15.6. Сверточные нейронные сети для распознавания образов 733
Изображение 2 (с индексом 583) в первой строке спрогнозировано как 7 с вероятностью 62,7%, но модель также считала, что с 36,4-процентной вероятностью это может быть цифра 2:
[49]: display_probabilities(predictions[583])
0: 0.0000003016%
1: 0.0000005715%
2: 36.4056706429%
3: 0.0176281916%
4: 0.0000561930%
5: 0.0000000003%
6: 0.0000000019%
7: 62.7455413342%
8: 0.8310816251%
9: 0.0000114385%
Изображение 6 (с индексом 625) в начале второй строки было спрогнозировано как 4, хотя этот прогноз был далек от полной уверенности. В данном случае вероятность 4 (51,6%) была лишь немного выше вероятности 6 (48,38%):
[50]: display_probabilities(predictions[625])
0: 0.0008245181%
1: 0.0000041209%
2: 0.0012774357%
3: 0.0000000009%
4: 51.6223073006%
5: 0.0000001779%
6: 48.3754962683%
7: 0.0000000085%
8: 0.0000048182%
9: 0.0000785786%
15.6.6. Сохранение и загрузка модели
Обучение моделей нейронных сетей может потребовать значительного времени. После того как вы спроектируете и протестируете подходящую модель, можно сохранить ее состояние. Это позволит вам загрузить ее в будущем для построения новых прогнозов. Иногда модели загружаются и проходят дальнейшее обучение для новых задач. Например, уровни нашей модели уже умеют распознавать такие признаки, как линии и кривые, которые также могут пригодиться для распознавания рукописных символов (как в наборе данных EMNIST). Таким образом, теоретически вы можете загрузить существующую модель и использовать ее как основу для построения более мощной модели.
734 Глава 15. Глубокое обучение
Этот процесс называется переносом обучения1,2 — знания существующей модели переносятся в новую модель. Метод save моделей Keras сохраняет архитектуру модели и информацию состояния в формате HDF5 (Hierarchical Data Format). Такие файлы по умолчанию используют расширение .h5:
[51]: cnn.save('mnist_cnn.h5')
Сохраненную модель можно загрузить функцией load_model из модуля tensorflow.keras.models:
from tensorflow.keras.models import load_model
cnn = load_model('mnist_cnn.h5')
После этого вы сможете вызывать методы модели. Например, при появлении дополнительных данных можно вызвать метод predict для построения новых прогнозов для новых данных или же вызвать fit, чтобы начать обучение с дополнительными данными.
Keras предоставляет ряд дополнительных функций для сохранения и загрузки отдельных аспектов ваших моделей. За подробной информацией обращайтесь по адресу:
https://keras.io/getting-started/faq/#how-can-i-save-a-keras-model
15.7. Визуализация процесса обучения нейронной сети в TensorBoard
Сети глубокого обучения невероятно сложны, а их внутренняя работа в основном остается скрытой, и разработчику трудно понять все происходящее. Это создает проблемы с тестированием, отладкой и обновлением моделей и алгоритмов. Глубокое обучение выявляет признаки, число которых может быть колоссальным и которые могут быть вам совершенно не очевидны.
Компания Google предоставляет TensorBoard3,4 — инструмент для визуализации нейронных сетей, реализованный с использованием TensorFlow и Keras.
1 https://towardsdatascience.com/transfer-learning-from-pre-trained-models-f2393f124751.
2 https://medium.com/nanonets/nanonets-how-to-use-deep-learning-when-you-have-lim-ited-data-f68c0b512cab.
3 https://github.com/tensorflow/tensorboard/blob/master/README.md.
4 https://www.tensorflow.org/guide/summaries_and_tensorboard.
15.7. Визуализация процесса обучения нейронной сети в TensorBoard 735
Подобно тому как на приборной панели автомобиля отображаются данные с датчиков (скорость, температура двигателя, количество оставшегося бензина), на панели TensorBoard отображаются данные модели глубокого обучения, дающие представление о том, как проходит обучение модели. Эти данные, возможно, помогут и в настройке ее гиперпараметров.
Запуск TensorBoard
TensorBoard отслеживает каталог в вашей системе и ищет в нем файлы с данными, которые будут отображаться в браузере. Создадим эту папку, запустим сервер TensorBoard и обратимся к нему из браузера. Выполните следующие действия:
1.
Перейдите в каталог ch15 в терминале, командной оболочке или приглашении Anaconda.
2.
Активируйте нестандартную среду Anaconda tf_env:
conda activate tf_env
3.
Создайте подкаталог с именем logs, в который модели глубокого обучения запишут информацию для визуализации средствами TensorBoard:
mkdir logs
4.
Запустите TensorBoard:
tensorboard --logdir=logs
5.
Теперь к TensorBoard можно обратиться в браузере по адресу:
http://localhost:6006
Если подключиться к TensorBoard перед выполнением какой-либо модели, будет выведена страница с сообщением об отсутствии активных панелей для текущего набора данных1.
Панель TensorBoard
TensorBoard отслеживает содержимое заданного каталога и файлы, выводимые моделью во время обучения. Обнаружив обновления, TensorBoard загружает данные на панель:
1 В настоящее время TensorBoard не работает с браузером Microsoft Edge.
736 Глава 15. Глубокое обучение
Данные можно просматривать как в процессе обучения, так и после его завершения. На панели, изображенной выше, показана вкладка TensorBoard SCALARS с диаграммами отдельных значений, изменяющихся во времени; в первой строке выводится точность обучения (acc) и потери обучения (loss), во второй — точность проверки (val_acc) и потери проверки (val_loss). На диаграммах представлена визуализация серии из 10 эпох для нашей сверточной нейронной сети MNIST, представленной в документе Notebook MNIST_CNN_TensorBoard.ipynb. Эпохи выводятся по осям x, начиная с 0 для первой эпохи. Значения точности и потерь выводятся по осям y. По виду графиков точностей обучения и проверки заметно, что результаты первых пяти эпох сходны с результатами серии из пяти эпох в предыдущем разделе.
Для серии из 10 эпох точность обучения продолжала улучшаться до девятой эпохи, а затем слегка снизилась. Возможно, в этой точке началось влияние чрезмерной подгонки модели, но чтобы быть уверенным в этом, необходимо продолжить обучение. Что касается точности проверки, то мы видим, что она сначала быстро возросла, а затем оставалась относительно неизменной на протяжении пяти эпох, после чего вновь выросла и уменьшилась. Потери обучения быстро падали, а затем непрерывно уменьшались до девятой эпохи с последующим незначительным ростом. Потери проверки быстро снижались, а затем попеременно то росли, то вновь снижались. Эту модель можно выпол15.7.
Визуализация процесса обучения нейронной сети в TensorBoard 737
нить с большим количеством эпох, чтобы узнать, улучшит ли это результаты, но по виду диаграмм похоже, что в шестой эпохе достигается хорошее сочетание точности обучения и проверки при минимальных потерях проверки.
Обычно такие диаграммы выстраиваются по вертикали на панели TensorBoard. Мы использовали поле поиска (над диаграммами) для вывода всех каталогов, имя которых содержит «mnist», — вскоре мы настроим этот аспект. TensorBoard может загрузить данные нескольких моделей одновременно, чтобы вы выбрали, какая модель должна визуализироваться. Это позволяет легко сравнить несколько разных моделей или несколько результатов выполнения одной и той же модели.
Копирование документа Notebook для сверточной сети MNIST
Чтобы создать новый документ Notebook в данном примере:
1.
Щелкните правой кнопкой мыши на файле MNIST_CNN.ipynb на вкладке File Browser в JupyterLab и выберите команду Duplicate, чтобы создать копию документа.
2.
Щелкните правой кнопкой мыши на новом документе с именем MNIST_CNN-Copy1.ipynb, выберите команду Rename, введите имя MNIST_CNN_TensorBoard.ipynb и нажмите Enter.
Откройте документ Notebook, сделав двойной щелчок на его имени.
Настройка Keras для записи журнальных файлов TensorBoard
Чтобы использовать TensorBoard, перед подгонкой модели следует настроить объект TensorBoard (модуль tensorflow.keras.callbacks), используемый моделью для записи данных в каталог, отслеживаемый TensorBoard. Этот объект называется в Keras объектом обратного вызова (callback). В документе Notebook щелкните слева от фрагмента, в котором вызывается метод fit модели, и нажмите клавишу «a» для добавления новой кодовой ячейки над текущей (клавишу «b» — для добавления ячейки ниже текущей). В новой ячейке введите следующий код для создания объекта TensorBoard:
from tensorflow.keras.callbacks import TensorBoard
import time
tensorboard_callback = TensorBoard(log_dir=f'./logs/mnist{time.time()}',
histogram_freq=1, write_graph=True)
738 Глава 15. Глубокое обучение
Аргументы:
ØØ
log_dir — имя каталога, в который будут записываться журнальные файлы модели. Запись './logs/' означает, что новый каталог создается внутри текущего; далее следует имя 'mnist' и текущее время. Такая схема выбора имени гарантирует, что при каждом новом выполнении документа Notebook будет создаваться отдельный каталог и вы сможете сравнить результаты нескольких выполнений в TensorBoard.
ØØ
histogram_freq — частота в эпохах, с которой Keras будет выводить данные в журнальные файлы модели. В данном случае данные будут записываться в журналы каждую эпоху.
ØØ
write_graph — при истинном значении этого аргумента будет выводиться граф модели. Его можно посмотреть на вкладке GRAPHS в TensorBoard.
Обновление вызова fit
Наконец, необходимо изменить исходный вызов метода fit во фрагменте 37. Для данного примера назначается количество эпох 10, и мы добавляем аргумент callbacks со списком объектов обратного вызова1:
cnn.fit(X_train, y_train, epochs=10, batch_size=64,
validation_split=0.1, callbacks=[tensorboard_callback])
Теперь вы можете повторно выполнить документ Notebook командой KernelRestart Kernel and Run All Cells в JupyterLab. После завершения первой эпохи в TensorBoard начнут появляться данные.
15.8. ConvnetJS: глубокое обучение и визуализация в браузере
В этом разделе рассматривается инструмент ConvnetJS на базе JavaScript, разработанный Андреем Карпати (Andrej Karpathy) и предназначенный для обучения и визуализации сверточных нейронных сетей в браузере2:
https://cs.stanford.edu/people/karpathy/convnetjs/
1 Другие объекты обратного вызова Keras можно просмотреть по адресу https://keras.io/callbacks/.
2 ConvnetJS также можно загрузить из репозитория GitHub по адресу https://github.com/karpathy/convnetjs.
15.8. ConvnetJS: глубокое обучение и визуализация в браузере 739
Вы можете запускать готовые примеры сверточных нейронных сетей ConvnetJS или создавать собственные. Мы использовали ConvnetJS в разных браузерах для настольных компьютеров, планшетов и телефонов. Демонстрационное приложение ConvnetJS обучает сверточную нейронную сеть по набору данных MNIST из раздела 15.6. В нем используется панель с поддержкой прокрутки, которая динамически обновляется в процессе обучения модели и состоит из нескольких разделов.
Training Stats (статистика обучения)
Кнопка Pause позволяет приостановить процесс обучения и «зафиксировать» текущие визуализации на панели. Когда вы приостанавливаете демонстрационное приложение, надпись на кнопке заменяется текстом Resume. Повторный щелчок на кнопке продолжает обучение. В этом разделе выводится статистика обучения, включая точность обучения и проверки, а также график потерь обучения.
Instantiate a Network and Trainer (создание сети и обучающего кода)
В этом разделе находится код JavaScript, который создает сверточную нейронную сеть. По умолчанию сеть состоит примерно из тех же уровней, что и сверточная нейронная сеть из раздела 15.6. В документации ConvnetJS1 описаны поддерживаемые типы уровней и возможности их настройки. Вы можете поэкспериментировать с разными конфигурациями уровней при помощи текстового поля и начать обучение обновленной сети, щелкнув на кнопке Change Network.
Network Visualization (визуализация сети)
В этом ключевом разделе выводится одно обучающее изображение и информация о том, как сеть обрабатывает это изображение на каждом уровне. Щелкните на кнопке Pause, чтобы просмотреть выход всех уровней для заданной цифры, — это поможет получить представление о том, какую информацию «видит» сеть в процессе обучения. Последний уровень сети выдает вероятностные классификации. Для него отображаются 10 квадратов — 9 черных и 1 белый, обозначающие прогнозируемый класс текущего изображения цифры.
1 https://cs.stanford.edu/people/karpathy/convnetjs/docs.html.
740 Глава 15. Глубокое обучение
Example Predictions on Test Set (примеры прогнозов для тестового набора)
В последнем разделе приводится случайная выборка изображений из тестового набора и три возможных класса с максимальными вероятностями для каждой цифры. Прогноз с наибольшей вероятностью выводится на зеленой полосе, а два других — на красных полосах. Длина каждой полосы является визуальным признаком вероятности этого класса.
15.9. Рекуррентные нейронные сети для последовательностей; анализ эмоциональной окраски с набором данных IMDb
В сверточной нейронной сети MNIST мы сосредоточились на последовательном наложении уровней сети. Также возможны модели со структурой, которая не является последовательной, как будет показано в этом разделе на примере рекуррентных нейронных сетей. В этом разделе набор данных с отзывами о фильмах IMDb (Internet Movie Database), входящий в поставку Keras1, используется для выполнения бинарной классификации, то есть прогнозирования того, является эмоциональная окраска заданного отзыва положительной или отрицательной.
Мы будем использовать рекуррентную нейронную сеть (RNN), обрабатывающую последовательности данных, например временные ряды или текст в предложениях. Термин «рекуррентный» возник как реакция на наличие в нейронной сети циклов, в которых выход заданного уровня становится входом для того же уровня на следующем временном шаге. Во временных рядах временной шаг определяет следующую точку во времени. В текстовой последовательности «временным шагом» является следующее слово в последовательности слов. Наличие циклов в рекуррентных нейронных сетях позволяет им выявлять и запоминать отношения между данными в последовательностях. Для примера возьмем следующие предложения, которые использовались в главе 11. Предложение
The food is not good.
1 Maas, Andrew L. and Daly, Raymond E. and Pham, Peter T. and Huang, Dan and Ng, Andrew Y. and Potts, Christopher, “Learning Word Vectors for Sentiment Analysis,” Proceedings of the 49th Annual Meeting of the Association for Computational Linguistics: Human Language Technologies, июнь 2011 г. — Портленд (Орегон), США. Association for Computational Linguistics, с. 142–150. http://www.aclweb.org/anthology/P11-1015.
15.9. Рекуррентные нейронные сети для последовательностей 741
очевидно обладает отрицательной эмоциональной окраской. Аналогичным образом предложение
The movie was good.
обладает положительной эмоциональной окраской, хотя и не настолько положительной, как предложение
The movie was excellent!
В первом предложении слово «good» само по себе обладает положительной эмоциональной окраской. Однако если ему в предложении предшествует слово «not», эмоциональная окраска становится отрицательной. Рекуррентные сети учитывают отношения между более ранними и более поздними частями последовательности. В предыдущем примере слова, определяющие эмоциональную окраску, стоят в соседних позициях. Тем не менее при определении смысла слова иногда приходится учитывать контекст соседних с ним слов, которые могут быть разделены произвольным количеством других слов. В этом разделе мы используем уровень долгой краткосрочной памяти (LSTM), который делает нейронную сеть рекуррентной и оптимизируется для обучения на последовательностях, сходных с описанными выше. Рекуррентные нейронные сети применялись для решения многих задач, включая следующие1,2,3:
ØØ
прогнозируемый ввод текста — вывод следующих возможных слов во время ввода;
ØØ
анализ эмоциональной окраски;
ØØ
ответы на вопросы с прогнозируемыми лучшими ответами на базе корпуса текста;
ØØ
перевод на другие языки;
ØØ
автоматизированное генерирование субтитров в видео.
15.9.1. Загрузка набора данных IMDb
Набор данных с отзывами на фильмы IMDb, поставляемый с Keras, содержит 25 000 обучающих наборов и 25 000 тестовых образцов, каждый из которых помечен эмоциональной окраской: положительной (1) или отрицательной
1 https://www.analyticsindiamag.com/overview-of-recurrent-neural-networks-and-their-applications/.
2 https://en.wikipedia.org/wiki/Recurrent_neural_network#Applications.
3 http://karpathy.github.io/2015/05/21/rnn-effectiveness/.
742 Глава 15. Глубокое обучение
(0). Импортируем модуль tensorflow.keras.datasets.imdb, чтобы загрузить набор данных:
[1]: from tensorflow.keras.datasets import imdb
Функция load_data модуля imdb возвращает обучающий и тестовый наборы IMDb. Набор данных содержит более 88 000 уникальных слов. Функция load_data позволяет задать количество уникальных слов, импортируемых в составе обучающих и тестовых данных. В данном случае были загружены только 10 000 наиболее часто встречающихся слов из-за ограниченного объема памяти в нашей системе и того факта, что мы (намеренно) выполняем обучение на основном процессоре вместо графического процессора (потому что для большинства читателей системы с GPU и TPU недоступны). Чем больше данных вы загрузите, тем больше времени займет обучение, но больший объем данных поможет построить лучшие модели:
[2]: number_of_words = 10000
[3]: (X_train, y_train), (X_test, y_test) = imdb.load_data(
num_words=number_of_words)
Функция load_data возвращает кортеж из двух элементов, содержащих обучающий и тестовый наборы. Каждый элемент представляет собой кортеж, содержащий образцы и метки соответственно. В каждом отдельном отзыве load_data заменяет все слова, кроме 10 000 наиболее часто употребляемых в отзывах, заполнителем (см. ниже).
15.9.2. Исследование данных
Проверим размерность образцов обучающего набора (X_train), меток обучающего набора (y_train), образцов тестового набора (X_test) и меток тестового набора (y_test):
[4]: X_train.shape
[4]: (25000,)
[5]: y_train.shape
[5]: (25000,)
[6]: X_test.shape
[6]: (25000,)
[7]: y_test.shape
[7]: (25000,)
15.9. Рекуррентные нейронные сети для последовательностей 743
Одномерные массивы y_train и y_test содержат значения 1 и 0, показывающие, является каждый отзыв положительным или отрицательным. На основании предшествующего вывода X_train и X_test также кажутся одномерными. Тем не менее их элементы в действительности представляют собой списки целых чисел, каждый из которых представляет содержимое одного отзыва, как показывает фрагмент [9]1:
[8]: %pprint
[8]: Pretty printing has been turned OFF
[9]: X_train[123]
[9]: [1, 307, 5, 1301, 20, 1026, 2511, 87, 2775, 52, 116, 5, 31, 7, 4,
91, 1220, 102, 13, 28, 110, 11, 6, 137, 13, 115, 219, 141, 35, 221, 956,
54, 13, 16, 11, 2714, 61, 322, 423, 12, 38, 76, 59, 1803, 72, 8, 2, 23,
5, 967, 12, 38, 85, 62, 358, 99]
Модели глубокого обучения Keras требуют числовых данных, поэтому команда Keras заранее обработала набор данных IMDb.
Кодирование отзывов о фильмах
Так как отзывы о фильмах кодируются в числовом виде, для просмотра их исходного текста необходимо знать, какому слову соответствует каждое число. Набор данных IMDb в Keras предоставляет словарь, связывающий слова с их индексами. Значение, соответствующее каждому слову, представляет частоту его вхождения среди всех слов во всем наборе отзывов. Таким образом, слово с частотой 1 является наиболее частым (что было вычислено командой Keras на основании набора данных), слово с частотой 2 — вторым по частоте, и т. д.
Хотя значения в словаре начинаются с 1 (как наиболее часто используемого слова), в кодированных отзывах (таких, как показанное выше значение X_train[123]) индексы смещаются на 3. Таким образом, в любом отзыве, содержащем самое частое слово, все его вхождения слова заменяются значением 4. Keras резервирует значения 0, 1 и 2 в каждом закодированном отзыве для следующих целей:
ØØ
Значение 0 в отзывах представляет дополнение. Алгоритмы глубокого обучения Keras ожидают, что все обучающие образцы имеют одинако1
Здесь мы используем магическую команду %pprint для отключения «красивой печати», чтобы вывод следующего фрагмента отображался горизонтально, а не вертикально для экономии места. Режим «красивой печати» можно снова включить повторным выполнением магической команды %pprint.
744 Глава 15. Глубокое обучение
вые размеры, поэтому некоторые отзывы иногда приходится расширять до нужной длины, а другие — укорачивать. Отзывы, которые необходимо расширить, дополняются нулями.
ØØ
Значение 1 представляет маркер, который используется во внутренней работе Keras для обозначения начала текстовой последовательности для целей обучения.
ØØ
Значение 2 в отзыве представляет неизвестное слово — обычно слово, которое не было загружено, потому что функция load_data была вызвана с аргументом num_words. В этом случае в любом отзыве, содержащем слова с частотным показателем выше num_words, числовые значения этих слов заменяются на 2. Все это Keras делает автоматически при загрузке данных.
Так как числовые значения во всех отзывах смещены на 3, нам придется учитывать это обстоятельство при декодировании отзыва.
Декодирование отзывов о фильмах
Попробуем декодировать отзыв. Сначала получим словарь, связывающий слова с индексами, вызовом функции get_word_index из модуля tensorflow.keras.datasets.imdb:
[10]: word_to_index = imdb.get_word_index()
Слово 'great' может присутствовать в положительных отзывах; посмотрим, присутствует ли оно в словаре:
[11]: word_to_index['great']
[11]: 84
Следовательно, 'great' является 84-м по частоте словом в наборе данных. При попытке поиска по слову, отсутствующему в словаре, происходит исключение.
Чтобы преобразовать частотные показатели в слова, сначала инвертируем словарь word_to_index для поиска слов по их частотным показателям. Следующая трансформация словаря создает словарь с обратным направлением ассоциаций:
[12]: index_to_word = \
{index: word for (word, index) in word_to_index.items()}
15.9. Рекуррентные нейронные сети для последовательностей 745
Напомним, метод items словаря используется для перебора кортежей пар «ключ-значение». Каждый кортеж распаковывается в переменные word и index, после чего в новом словаре создается новый элемент с использованием синтаксиса index: word.
Следующая трансформация списка получает 50 самых частых слов из нового словаря — напомним, что самому частому слову соответствует значение 1:
[13]: [index_to_word[i] for i in range(1, 51)]
[13]: ['the', 'and', 'a', 'of', 'to', 'is', 'br', 'in', 'it', 'i',
'this', 'that', 'was', 'as', 'for', 'with', 'movie', 'but', 'film', 'on',
'not', 'you', 'are', 'his', 'have', 'he', 'be', 'one', 'all', 'at', 'by',
'an', 'they', 'who', 'so', 'from', 'like', 'her', 'or', 'just', 'about',
"it's", 'out', 'has', 'if', 'some', 'there', 'what', 'good', 'more']
Обратите внимание: большинство слов в списке относится к категории игнорируемых. Игнорируемые слова можно оставить или удалить — все зависит от конкретного приложения. Например, если вы создаете приложение для прогнозируемого ввода текста, которое предлагает следующее слово в вводимой пользователем серии, то игнорируемые слова стоит оставить, чтобы они выводились среди прогнозируемых слов.
Теперь можно перейти к декодированию отзыва. Для получения значения, связанного с ключом, используется метод get с двумя аргументами словаря index_to_word вместо оператора []. Если значение отсутствует в словаре, то метод get возвращает второй аргумент вместо выдачи исключения. Аргумент i-3 учитывает существующее смещение в закодированных отзывах частотных показателей каждого отзыва. Когда в отзыве встречаются зарезервированные значения Keras 0–2, get возвращает '?'; в остальных случаях get возвращает слово с ключом i-3 в словаре index_to_word:
[14]: ' '.join([index_to_word.get(i - 3, '?') for i in X_train[123]])
[14]: '? beautiful and touching movie rich colors great settings good
acting and one of the most charming movies i have seen in a while i
never saw such an interesting setting when i was in china my wife
liked it so much she asked me to ? on and rate it so other would
enjoy too'
Из массива y_train видно, что отзыв классифицируется как положительный:
[15]: y_train[123]
[15]: 1
746 Глава 15. Глубокое обучение
15.9.3. Подготовка данных
Количество слов в отзывах непостоянно, а Keras требует, чтобы все образцы имели одинаковые размеры. Следовательно, данные необходимо подготовить. В данном случае необходимо ограничить каждый отзыв постоянным количеством слов. Одни обзоры приходится дополнять неинформативными данными, другие нуждаются в усечении. Вспомогательная функция pad_sequences (модуль tensorflow.keras.preprocessing.sequence) изменяет размеры образцов X_train (то есть строк данных) по количеству признаков, заданному аргументом maxlen (200), и возвращает двумерный массив:
[16]: words_per_review = 200
[17]: from tensorflow.keras.preprocessing.sequence import pad_sequences
[18]: X_train = pad_sequences(X_train, maxlen=words_per_review)
Если образец содержит больше признаков, то pad_sequences усекает его по заданной длине. Если образец содержит меньше признаков, то pad_sequences добавляет 0 в начало последовательности до заданной длины. Проверим новые размеры X_train:
[19]: X_train.shape
[19]: (25000, 200)
Также необходимо изменить размеры X_test для оценки модели в будущем:
[20]: X_test = pad_sequences(X_test, maxlen=words_per_review)
[21]: X_test.shape
[21]: (25000, 200)
Разбиение тестовых данных на проверочные
и тестовые данные
В нашей сверточной нейронной сети аргумент validation_split метода fit используется для обозначения того, что 10% обучающих данных должны быть зарезервированы для проверки модели в процессе обучения. В нашем примере 25 000 тестовых образцов будут вручную разбиты на 20 000 тестовых образцов и 5000 проверочных образцов. Затем 5000 проверочных образцов передаются методу fit модели в аргументе validation_data. Для разбиения тестового на15.9.
Рекуррентные нейронные сети для последовательностей 747
бора мы воспользуемся функцией train_test_split библиотеки scikit-learn, упоминавшейся в предыдущей главе:
[22]: from sklearn.model_selection import train_test_split
X_test, X_val, y_test, y_val = train_test_split(
X_test, y_test, random_state=11, test_size=0.20)
Теперь проверим разбиение по размерам X_test и X_val:
[23]: X_test.shape
[23]: (20000, 200)
[24]: X_val.shape
[24]: (5000, 200)
15.9.4. Создание нейронной сети
Перейдем к настройке рекуррентной нейронной сети. Вновь начнем с модели Sequential, в которую будут добавляться уровни, образующие сеть:
[25]: from tensorflow.keras.models import Sequential
[26]: rnn = Sequential()
Импортируем уровни, которые будут использоваться в модели:
[27]: from tensorflow.keras.layers import Dense, LSTM
[28]: from tensorflow.keras.layers.embeddings import Embedding
Добавление уровня векторного представления
Ранее прямое унитарное кодирование использовалось для преобразования целочисленных меток набора данных MNIST в категорийные данные. Результатом для каждой метки будет вектор, в котором все элементы, кроме одного, равны нулю. То же можно сделать со значениями индексов, представляющими слова. Однако в нашем примере обрабатываются 10 000 слов; это означает, что для представления всех слов понадобится массив 10 000 × 10 000. Получается, что массив содержит 100 000 000 элементов, из которых почти все равны нулю. Такой способ кодирования данных вряд ли можно назвать эффективным. А для обработки всех 88 000+ уникальных слов в наборе данных потребуется массив почти из 8 миллиардов элементов!
748 Глава 15. Глубокое обучение
Для сокращения степени размерности рекуррентная нейронная сеть, обрабатывающая текстовые последовательности, обычно начинается с кодирующего уровня, который преобразует каждое слово в более компактное представление плотного вектора. Векторы, производимые уровнем векторного представления, также сохраняют контекст слова, то есть отражают, как конкретное слово связано с соседними словами. Таким образом, кодирующий уровень позволяет рекуррентной сети изучать отношения между словами в обучающих данных.
Существуют и предварительно определенные векторные представления, например Word2Vec и GloVe. Вы можете загрузить их в нейронные сети для экономии времени обучения. Иногда они используются и для включения в модель информации об отношениях между словами при недостаточных объемах обучающих данных. Это может повысить точность модели, позволяя ей пользоваться ранее изученными отношениями между словами, вместо того чтобы пытаться изучать эти отношения при недостаточных объема данных.
Создадим уровень векторного представления (модуль tensorflow.keras.layers):
[29]: rnn.add(Embedding(input_dim=number_of_words, output_dim=128,
input_length=words_per_review))
Аргументы:
ØØ
input_dim — количество уникальных слов;
ØØ
output_dim — размер векторного представления каждого слова. Если вы загружаете готовые векторные представления1 (такие, как Word2Vec и GloVe), этому аргументу следует присвоить размер загружаемых векторных представлений слов;
ØØ
input_length=words_per_review — количество слов в каждом входном образце.
Добавление уровня LSTM
Затем добавим уровень долгой краткосрочной памяти (LSTM):
[30]: rnn.add(LSTM(units=128, dropout=0.2, recurrent_dropout=0.2))
1 https://blog.keras.io/using-pre-trained-word-embeddings-in-a-keras-model.html.
15.9. Рекуррентные нейронные сети для последовательностей 749
Аргументы:
ØØ
units — количество нейронов на уровне. Чем больше нейронов, тем больше может запомнить сеть. Простое эмпирическое правило: начните со значения между длиной обрабатываемых последовательностей (200 в данном примере) и количеством классов, которые вы пытаетесь прогнозировать (2 в данном примере1).
ØØ
dropout — процент нейронов, случайным образом блокируемых при обработке входа и выхода уровня. Прореживание, как и объединяющие уровни в сверточных нейронных сетях, — проверенный метод2,3 для предотвращения чрезмерной подгонки. В Keras существует уровень прореживания Dropout, который вы можете добавлять в свои модели.
ØØ
recurrent_dropout — процент нейронов, случайным образом блокируемых при передаче выхода уровня обратно на уровень, чтобы сеть могла обучаться на известных ей данных.
Механика того, как уровень LSTM выполняет свою задачу, выходит за рамки этой книги. Шолле по этому поводу замечает: «Вам не обязательно понимать все о конкретной архитектуре ячейки LSTM; вы — человек, и это не ваша задача. Просто помните, для чего предназначена ячейка LSTM: предоставить возможность повторного внедрения прошлой информации в будущем»4.
Добавление уровня уплотненного вывода
Наконец, необходимо взять вывод уровня LSTM и сократить его до одного результата — признака эмоциональной окраски отзыва (положительная или отрицательная); отсюда значение 1 аргумента units. Здесь используется функция активации 'sigmoid', которая считается предпочтительной для бинарной
1 https://towardsdatascience.com/choosing-the-right-hyperparameters-for-a-simple-lstm-using-keras-f8e9ed76f046.
2 Yarin, Ghahramani, and Zoubin. «A Theoretically Grounded Application of Dropout in Recurrent Neural Networks.» 05 октября 2016 г. https://arxiv.org/abs/1512.05287.
3 Srivastava, Nitish, Geoffrey Hinton, Alex Krizhevsky, Ilya Sutskever, and Ruslan Salakhutdinov. «Dropout: A Simple Way to Prevent Neural Networks from Overfitting.» Journal of Machine Learning Research 15 (14 июня 2014 г.): 1929–1958. http://jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf.
4 Шолле Франсуа. Глубокое обучение на Python. — СПб.: Питер, 2020. С. 238.
750 Глава 15. Глубокое обучение
классификации1. Она сводит произвольные значения до диапазона 0,0–1,0 с получением вероятности:
[31]: rnn.add(Dense(units=1, activation='sigmoid'))
Компиляция модели и вывод итоги
Затем модель нужно откомпилировать. В данном случае есть всего два возможных вывода, поэтому используется функция потерь binary_crossentropy:
[32]: rnn.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
Ниже приведено сводное описание модели. Хотя рекуррентная нейронная сеть содержит меньше уровней, чем наша сверточная нейронная сеть, она имеет почти втрое больше обучаемых параметров (весов сети), а рост количества параметров означает рост продолжительности обучения. Большое количество параметров возникает прежде всего от умножения количества слов в словаре (мы загрузили 10 000) на количество нейронов в выходе уровня векторного представления (128):
[33]: rnn.summary()
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_1 (Embedding) (None, 200, 128) 1280000
_________________________________________________________________
lstm_1 (LSTM) (None, 128) 131584
_________________________________________________________________
dense_1 (Dense) (None, 1) 129
=================================================================
Total params: 1,411,713
Trainable params: 1,411,713
Non-trainable params: 0
15.9.5. Обучение и оценка модели
Проведем обучение модели2. Обратите внимание: для каждой следующей эпохи обучение модели занимает намного больше времени. Отчасти это обу1
Шолле Франсуа. Глубокое обучение на Python. — СПб.: Питер, 2020. С. 144.
2 На момент написания книги TensorFlow выводит предупреждение при выполнении этой команды. Это известный дефект TensorFlow; из публикаций на форумах следует, что на предупреждение можно не обращать внимания.
15.9. Рекуррентные нейронные сети для последовательностей 751
словлено большим количеством параметров (weights), на которых должна обучаться модель RNN. Мы выделили жирным шрифтом значения точности (acc) и точности проверки (val_acc) для удобочитаемости — они представляют процент обучающих образцов и процент образцов validation_data, правильно спрогнозированных моделью.
[34]: rnn.fit(X_train, y_train, epochs=10, batch_size=32,
validation_data=(X_test, y_test))
Train on 25000 samples, validate on 5000 samples
Epoch 1/5
25000/25000 [==============================] - 299s 12ms/step - loss:
0.6574 - acc: 0.5868 - val_loss: 0.5582 - val_acc: 0.6964
Epoch 2/5
25000/25000 [==============================] - 298s 12ms/step - loss:
0.4577 - acc: 0.7786 - val_loss: 0.3546 - val_acc: 0.8448
Epoch 3/5
25000/25000 [==============================] - 296s 12ms/step - loss:
0.3277 - acc: 0.8594 - val_loss: 0.3207 - val_acc: 0.8614
Epoch 4/5
25000/25000 [==============================] - 307s 12ms/step - loss:
0.2675 - acc: 0.8864 - val_loss: 0.3056 - val_acc: 0.8700
Epoch 5/5
25000/25000 [==============================] - 310s 12ms/step - loss:
0.2217 - acc: 0.9083 - val_loss: 0.3264 - val_acc: 0.8704
[34]:
Наконец, мы можем оценить результаты по тестовым данным. Функция evaluate возвращает значения потерь и точности. В данном случае точность модели составила 85,99%:
[35]: results = rnn.evaluate(X_test, y_test)
20000/20000 [==============================] - 42s 2ms/step
[36]: results
[36]: [0.3415240607559681, 0.8599]
Заметим, что точность модели кажется низкой по сравнению с результатами сверточной сети MNIST, но ведь и задача перед ней стояла намного сложнее. Поискав в интернете данные других исследований бинарной классификации эмоциональной окраски, вы найдете множество результатов менее 90%. Следовательно, наша маленькая рекуррентная нейронная сеть, состоящая всего из трех уровней, показала вполне неплохие результаты. Тем не менее попробуйте изучить модели в интернете и построить более эффективную модель.
752 Глава 15. Глубокое обучение
15.10. Настройка моделей глубокого обучения
В разделе 15.9.5 в выводе метода fit как точность тестирования (85,99%), так и точность проверки (87,04%) были значительно ниже точности обучения 90,83%. Обычно такие расхождения происходят от чрезмерной подгонки, так что в нашей модели остается достаточно возможностей для усовершенствования1,2. Взглянув на вывод каждой эпохи, вы заметите, что точность как обучения, так и проверки продолжает возрастать. Напомним, что обучение на слишком большом количестве эпох может привести к чрезмерной подгонке, но, возможно, в нашем случае обучение все еще было недостаточным. Одной из возможных настроек гиперпараметра для этой модели могло бы стать повышение количества эпох.
Назовем некоторые переменные, влияющие на эффективность модели:
ØØ
больший или меньший объем данных для обучения;
ØØ
больший или меньший объем данных для тестирования;
ØØ
больший или меньший объем данных для проверки;
ØØ
большее или меньшее количество уровней;
ØØ
типы используемых уровней;
ØØ
порядок уровней.
В нашем примере рекуррентной нейронной сети IMDb можно было попытаться настроить следующие параметры:
ØØ
разные объемы обучающих данных — мы использовали только 10 000 наиболее часто используемых (в отзывах о фильмах) слов;
ØØ
разное количество слов в одном отзыве — мы использовали только 200;
ØØ
разное количество нейронов в уровнях;
ØØ
большее количество уровней;
ØØ
предварительная загрузка заранее обученных векторов вместо информации, которую уровень Embedded сможет извлечь «с нуля».
Время вычислений, необходимое для многократного обучения моделей, значительно, поэтому в глубоком обучении обычно вы не настраиваете ги1
https://towardsdatascience.com/deep-learning-overfitting-846bf5b35e24.
2 https://hackernoon.com/memorizing-is-not-learning-6-tricks-to-prevent-overfitting-in-machine-learning-820b091dc42.
15.11. Модели сверточных нейронных сетей с предварительным обучением 753
перпараметры такими методами, как k-проходная перекрестная проверка или сеточный поиск1. Существует много разных методов оптимизации2,3,4,5, но одной из самых перспективных областей является автоматизированное машинное обучение (AutoML). Например, библиотека AutoKeras6 предназначена для автоматизации выбора лучших конфигураций моделей Keras. Среди множества других проектов в области автоматизированного машинного обучения можно выделить Google Cloud AutoML и Baidu EZDL.
15.11. Модели сверточных нейронных сетей с предварительным обучением на ImageNet
При глубоком обучении (вместо того чтобы начинать затратное обучение, проверку и тестирование заново для каждого проекта) вы можете использовать предварительно обученные модели глубокого обучения для:
ØØ
построения новых прогнозов;
ØØ
продолжения обучения на новых данных;
ØØ
переноса весов, полученных моделью в ходе обучения для аналогичной задачи, в новую модель — это называется переносом обучения.
Предварительно обученные модели сверточных нейронных сетей Keras
Keras поставляется со следующими предварительно обученными моделями сверточных сетей7, прошедшими обучение на ImageNet8 — растущем наборе данных из 14+ миллионов изображений:
1 https://www.quora.com/Is-cross-validation-heavily-used-in-deep-learning-or-is-it-too-expensive-to-be-used.
2 https://towardsdatascience.com/what-are-hyperparameters-and-how-to-tune-the-hyperparameters-in-a-deep-neural-network-d0604917584a.
3 https://medium.com/machine-learning-bites/deeplearning-series-deep-neural-networks-tuning-and-optimization-39250ff7786d.
4 https://flyyufelix.github.io/2016/10/03/fine-tuning-in-keras-part1.html и https://flyyufelix.github.io/2016/10/08/fine-tuning-in-keras-part2.html.
5 https://towardsdatascience.com/a-comprehensive-guide-on-how-to-fine-tune-deep-neural-networks-using-keras-on-google-colab-free-daaaa0aced8f.
6 https://autokeras.com/.
7 https://keras.io/applications/.
8 http://www.image-net.org.
754 Глава 15. Глубокое обучение
ØØ
Xception
ØØ
VGG16
ØØ
VGG19
ØØ
ResNet50
ØØ
Inception v3
ØØ
Inception-ResNet v2
ØØ
MobileNet v1
ØØ
DenseNet
ØØ
NASNet
ØØ
MobileNet v2
Повторное использование предварительно
обученных моделей
Набор ImageNet слишком велик для эффективного обучения на большинстве компьютеров, поэтому многие разработчики предпочли бы начать с одной из меньших предварительно обученных моделей. Вы можете повторно использовать архитектуру каждой модели и обучить ее на новых данных или же повторно использовать предварительно обученные веса. Несколько простых примеров доступны по адресу:
https://keras.io/applications/
ImageNet Challenge
В завершающих проектах этой главы исследуются и используются некоторые из этих моделей, входящих в поставку Keras. Также будет рассмотрен конкурс ImageNet Large Scale Visual Recognition Challenge по оценке обнаружения объектов и моделей распознавания изображений1. Этот конкурс проходил с 2010 по 2017 год. В настоящее время ImageNet проводит на сайте Kaggle постоянный конкурс, который называется ImageNet Object Localization Challenge2. Задача
1 http://www.image-net.org/challenges/LSVRC/.
2 https://www.kaggle.com/c/imagenet-object-localization-challenge.
15.12. Итоги 755
заключается в выявлении «всех объектов в пределах изображения для их классификации и разметки». ImageNet публикует текущий рейтинг лидеров раз в квартал.
Многое из того, что вы видели в главах, посвященных машинному обучению и глубокому обучению, составляет суть конкурса, представленного на сайте Kaggle. Не существует очевидного оптимального решения для многих задач машинного и глубокого обучения. На самом деле единственным ограничением является творческий потенциал разработчиков. На сайте Kaggle компании и организации финансируют конкурсы, в которых разработчики со всего мира ищут более эффективные решения задач, важных для их отрасли или организации. Иногда компании предоставляют призовой фонд, который достигал 1 000 000 долларов в знаменитом конкурсе Netflix. Компания Netflix хотела добиться 10% или более высокого прироста качества в своей модели определения того, понравился ли зрителям фильм, на основании их предшествующих оценок1. Результаты использовались для повышения качества рекомендаций. Даже если вы не победите в конкурсе Kaggle, участие в нем будет очень полезно — вы сможете получить практический опыт в работе над актуальными задачами.
15.12. Итоги
Итак, мы заглянули в будущее искусственного интеллекта. Глубокое обучение захватило воображение сообществ компьютерных технологий и data science. Возможно, это была самая важная глава, посвященная искусственному интеллекту.
Мы упомянули ключевые платформы глубокого обучения и выделили среди них Google TensorFlow как наиболее широко используемую. Вы узнали, почему библиотека Keras, предоставляющая удобный интерфейс к TensorFlow, стала настолько популярной.
Затем мы настроили нестандартную среду Anaconda для TensorFlow, Keras и JupyterLab, после чего воспользовались средой для реализации примеров Keras.
1 https://netflixprize.com/rules.html.
756 Глава 15. Глубокое обучение
Вы узнали, что такое тензоры и почему они играют такую важную роль в глубоком обучении. Были рассмотрены основные концепции нейронов и многоуровневых нейронных сетей для построения моделей глубокого обучения Keras, а также часто используемые разновидности уровней и возможности их упорядочения.
Далее были представлены сверточные нейронные сети, особенно хорошо подходящие для приложений распознавания изображений. Затем мы построили, обучили, проверили на корректность и протестировали сверточную сеть по базе данных изображений рукописных цифр MNIST, для которых была достигнута точность прогнозирования 99,17%. Это выдающийся результат, особенно если учесть, что он был достигнут с использованием базовой модели и без настройки гиперпараметров. Вы можете опробовать более сложные модели и настроить гиперпараметры для улучшения эффективности. В этом разделе были перечислены различные интересные задачи из области распознавания изображений.
Далее мы представили TensorBoard — инструмент визуализации процессов обучения и проверки нейронных сетей Keras и TensorFlow. Также был описан ConvnetJS — инструмент обучения и визуализации сверточных сетей на базе браузера, позволяющий заглянуть «за кулисы» процесса обучения.
После этого мы представили рекуррентные нейронные сети (RNN) для обработки последовательностей данных, таких как временные ряды или текст в предложениях. Мы использовали RNN с набором данных IMDb, содержащим отзывы о фильмах, для выполнения бинарной классификации эмоциональной окраски (то есть прогнозирования того, является каждый отзыв положительным или отрицательным). Была рассмотрена настройка моделей глубокого обучения и то, как высокопроизводительное оборудование (например, графические процессоры NVIDIA или тензорные процессоры Google) позволяет более широкому кругу разработчиков браться за серьезные исследования в области глубокого обучения.
С учетом того, насколько дорогостоящей и продолжительной оказывается процедура обучения моделей глубокого обучения, мы объяснили стратегию использования предварительно обученных моделей. Мы привели список различных моделей распознавания изображений на базе сверточных сетей Keras, которые были обучены на гигантском наборе данных ImageNet, и рассказали, как перенос обучения позволяет быстро и эффективно использовать эти модели для создания новых моделей. Поскольку глубокое обучение — большая и сложная тема, в этой главе мы сосредоточились на его основах.
15.12. Итоги 757
В следующей главе будет представлена инфраструктура больших данных, поддерживающая различные технологии AI, рассмотренные в главах с 12-й по 15-ю. Будут рассмотрены платформы Hadoop и Spark для пакетной обработки больших данных, а также приложения потоковой передачи данных в реальном времени. Мы представим реляционные базы данных и язык SQL для обработки запросов — эти технологии многие годы занимали ведущее положение в области баз данных. Мы поговорим о проблемах, которые возникают из-за больших данных и плохо решаются реляционными базами данных, и познакомимся с базами данных NoSQL, которые проектировались для решения этих проблем. Книга завершается обсуждением концепции «интернета вещей» (IoT), который наверняка станет крупнейшим мировым источником больших данных и предоставит предпринимателям много возможностей для создания качественно новых видов коммерческой деятельности, способных оказать сильное влияние на человеческую жизнь.
16
Большие данные: Hadoop,
Spark, NoSQL и IoT
В этой главе:
•• Концепция больших данных и темпы роста.
•• Работа с реляционной базой данных SQLite на языке SQL (Structured Query
Language).
•• Четыре основные разновидности баз данных NoSQL.
•• Сохранение твитов в документной базе данных MongoDB и их визуализа-
ция на карте Folium.
•• Технология Аpache Hadoop и ее применение в приложениях пакетной об-
работки больших данных.
•• Построение MapReduce-приложения на базе Hadoop в облачном сервисе
Microsoft Azure HDInsight.
•• Применение Apache Spark в высокопроизводительных приложениях, рабо-
тающих с большими данными в реальном времени.
•• Использование потоковой передачи Spark для обработки данных в формате
мини-пакетов.
•• «Интернет вещей» (IoT) и модель публикации/подписки.
•• Публикация сообщений с моделируемого устройства, подключенного к ин-
тернету, и их визуализация на информационной панели.
•• Подписка на «живой» Twitter PubNub и IoT-потоки, и визуализация данных.
16.1. Введение 759
16.1. Введение
В разделе 1.7 была представлена концепция больших данных. В этой главе будут рассмотрены популярные аппаратные и программные инфраструктуры для работы с большими данными. Кроме того, мы разработаем полноценные приложения на нескольких настольных и облачных платформах больших данных.
Базы данных
Базы данных (далее — БД, не путать с большими данными) формируют важнейшую инфраструктуру больших данных для хранения и обработки больших объемов создаваемых данных. Они также играют важную роль для безопасного и конфиденциального сопровождения этих данных, особенно в контексте еще более жестких законов защиты данных, таких как Закон об ответственности и переносе данных о страховании здоровья граждан (HIPAA, Health Insurance Portability and Accountability Act) в США и Общий регламент защиты данных (GDPR, General Data Protection Regulation) в Евросоюзе.
Начнем с изучения реляционных БД, хранящих структурированные данные в таблицах. Каждая строка данных в такой таблице состоит из определенного количества столбцов фиксированного размера. Для работы с реляционными БД используется язык структурированных запросов SQL (Structured Query Language).
Большая часть данных, производимых в наши дни, относится к неструктурной категории (например, содержимое постов Facebook, твитов Twitter) или полуструктурированных данных (например, документов JSON или XML). Скажем, Twitter обрабатывает содержимое каждого твита в полуструктурированный документ JSON, содержащий большое количество метаданных (см. главу 12). Реляционные БД не предназначены для неструктурированных и полуструктурированных данных в приложениях больших данных. По мере развития больших данных создавались новые разновидности БД для эффективной обработки таких данных. Мы рассмотрим четыре основные разновидности БД NoSQL: ключ-значение, документные, столбцовые и графовые. Кроме того, будут описаны БД NewSQL, сочетающие преимущества реляционных баз данных и баз данных NoSQL. Многие разработчики баз данных NoSQL и NewSQL упрощают освоение своих продуктов за счет предоставления бесплатных уровней и пробных версий, чаще всего в облачных средах, требующих минимальной установки и настройки. Это позволяет получить опыт работы с большими данными, перед тем как серьезно браться за дело.
760 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
Apache Hadoop
В наши дни данные нередко настолько велики, что не помещаются в одной системе. С ростом больших данных возникла необходимость в распределенном хранении данных и средствах параллельной обработки для повышения эффективности работы с ними. Это привело к появлению сложных технологий распределенной обработки и массового параллелизма между кластерами компьютеров, в которых система автоматически и корректно реализует все технические подробности, таких как Apache Hadoop. Мы обсудим ниже технологию Hadoop, ее архитектуру и способы применения в приложениях больших данных. Будет описан процесс настройки многоузлового кластера Hadoop с использованием облачного сервиса Microsoft Azure HDInsigh. Затем мы воспользуемся им для выполнения MapReduce-задания, реализованного на Python. Хотя сервис HDInsight не бесплатен, компания Microsoft предоставляет щедрый кредит для новых пользователей, что позволит вам выполнить примеры кода этой главы без лишних затрат.
Apache Spark
С ростом потребностей в обработке больших данных сообщество информационных технологий постоянно искало возможности повышения эффективности. Hadoop выполняет задачи, разбивая их на блоки, выполняющие большой объем операций ввода/вывода между многими компьютерами. Технология Spark была разработана для выполнения некоторых операций больших данных в памяти для улучшения быстродействия.
В этой главе будет рассмотрена система Apache Spark, ее архитектура и возможность применения в высокопроизводительных приложениях больших данных в реальном времени. Мы реализуем приложение Spark с использованием средств программирования в функциональном стиле «фильтр/отображение/свертка». Сначала приложение будет построено на базе стека Jupyter Docker, выполняемого локально на вашем настольном компьютере, а затем оно будет реализовано на базе многоузлового кластера Spark в облачном сервисе Microsoft Azure HDInsight. Далее будет представлен механизм потоковой передачи данных Spark для обработки потоковых данных в мини-пакетах. Потоковая передача Spark собирает данные в течение короткого интервала времени, заданного вами, а затем предоставляет собранный пакет данных для обработки. Мы реализуем потоковое приложение Spark для обработки твитов. В этом примере мы используем Spark SQL для запроса данных, хранящихся в коллекции Spark DataFrame; в отличие от коллекций DataFrame библиотеки
16.1. Введение 761
Pandas, они могут содержать данные, распределенные по многим компьютерам в кластере.
Интернет вещей
Глава завершается введением в «интернет вещей» (IoT) — это миллиарды устройств, постоянно производящих данные по всему миру. Будет описана модель публикации/подписки, которая используется IoT и другими типами приложений для связывания пользователей данных с поставщиками данных. Сначала без написания кода мы построим информационную панель на базе браузера с использованием Freeboard.io и прямой потоковой передачи от сервиса обмена сообщениями PubNub. Затем мы смоделируем подключенный к интернету термостат, публикующий сообщения в бесплатном сервисе обмена сообщениями Dweet.io, с использованием модуля Python Dweepy, а затем создадим визуализацию данных при помощи Freeboard.io. Наконец, мы построим клиент Python, который подписывается на живой поток данных от сервиса PubNub и строит динамическую визуализацию потока средствами Seaborn и FuncAnimation библиотеки Matplotlib.
Облачные сервисы и настольные программы для работы с большими данными
Разработчики облачных сервисов ставят на первый план сервисно-ориентированную архитектуру (SOA), в которой они предоставляют функциональность «как сервис», к которому подключаются приложения и используются в облаке. Вот некоторые типичные сервисы, предоставляемые разработчиками облачных платформ1:
Сокращения «как сервис» (обратите внимание на некоторые совпадения)
Большие данные как сервис (BDaaS)
Платформа как сервис (PaaS)
Hadoop как сервис (HaaS)
Программное обеспечение как сервис (SaaS)
Оборудование как сервис (HaaS)
Пространство для хранения данных как сервис (SaaS)
Инфраструктура как сервис (IaaS)
Spark как сервис (SaaS)
1 Другие сокращения «как сервис» перечислены в статьях https://en.wikipedia.org/wiki/Cloud_computing и https://en.wikipedia.org/wiki/As_a_service.
762 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
Поэкспериментируем в этой главе с несколькими облачными инструментами. В примерах будут задействованы следующие платформы:
ØØ
Бесплатный облачный кластер MongoDB Atlas.
ØØ
Многоузловой кластер Hadoop, работающий в облачном сервисе Microsoft Azure HDInsight, — для этого вы можете воспользоваться кредитом, который предоставляется для новой учетной записи Azure.
ØØ
Бесплатный одноузловой «кластер» Spark, работающий на вашем настольном компьютере с использованием контейнера в технологическом стеке Jupyter Docker.
ØØ
Многоузловой кластер Spark, также работающий в Microsoft Azure HDInsight, — для этого вы продолжите пользоваться своим кредитом новой учетной записи Azure.
Существует и много других вариантов, включая облачные сервисы от Amazon Web Services, Google Cloud и IBM Watson, бесплатные настольные версии платформ Hortonworks и Cloudera (которые также существуют в облачных платных версиях). Кроме того вы можете опробовать одноузловой кластер Spark, работающий на бесплатной облачной платформе Databricks Community Edition. Создатели Spark были основателями Databricks.
Во всех случаях проверяйте новейшие условия использования каждого задействованного сервиса. Некоторые сервисы требуют включения расчета по кредитной карте для использования своих кластеров. Предупреждение: после того как вы выделите ресурсы кластеров Microsoft Azure HDInsight (или кластеров других разработчиков), вы начинаете нести расходы. Завершив работу с такими сервисами, как Microsoft Azure, обязательно удалите свой кластер(-ы) и другие ресурсы (например, дисковое пространство). Это продлит срок действия кредита новой учетной записи Azure.
Процедуры установки и настройки зависят от конкретной платформы и изменяются со временем. Всегда следуйте новейшему описанию от разработчика. Если у вас появятся вопросы, то лучшим источником информации станет техническая поддержка разработчика и форумы. Также проверяйте такие сайты, как stackoverflow.com, — возможно, другие люди задавали вопросы о похожих проблемах и уже получили на них ответы от сообщества разработчиков.
16.1. Введение 763
Алгоритмы и данные
Алгоритмы и данные занимают центральное место в программировании Python. Начальные главы этой книги в основном были посвящены алгоритмам. Мы описали управляющие команды и обсуждали разработку алгоритмов. Данные были небольшими — преимущественно целые числа, числа с плавающей точкой и строки.
В главах 5–9 основное внимание уделялось структурированию данных в списках, кортежах, словарях, множествах, массивах и файлах.
Смысл данных
Но как насчет смысла данных? Можно ли воспользоваться данными для извлечения информации, которая повысит эффективность диагностики рака? Спасения жизней? Улучшения качества жизни пациентов? Борьбы с загрязнением окружающей среды? Экономии воды? Повышения урожайности? Снижения ущерба от опустошительных бурь и пожаров? Создания рабочих мест? Повышения прибыльности работы компании?
Во всех практических примерах data science из глав 11–15 центральное место занимал искусственный интеллект. В этой главе мы сосредоточимся на инфраструктуре больших данных, которая лежит в основе AI-решений. Так как объем данных, используемых с этими технологиями, продолжает экспоненциально расти, мы хотим обучаться на этих данных, причем делать это очень быстро. Для достижения этих целей используется сочетание сложных алгоритмов, оборудования, программного обеспечения и сетевых структур. Мы представили различные методы машинного обучения и убедились в том, что из данных действительно можно извлечь очень ценную информацию. При большем объеме данных, и особенно с большими данными, машинное обучение может стать еще более эффективным.
Источники больших данных
В следующих статьях и на сайтах содержатся ссылки на сотни бесплатных источников больших данных:
764 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
ИСТОЧНИКИ БОЛЬШИХ ДАННЫХ
«Awesome-Public-Datasets», GitHub.com, https://github.com/caesar0301/awesome-public-datasets.
«AWS Public Datasets», https://aws.amazon.com/public-datasets/.
«Big Data And AI: 30 Amazing (And Free) Public Data Sources For 2018», by B. Marr, https://www.forbes.com/sites/bernardmarr/2018/02/26/big-data-and-ai-30-amazing-and-free-public-data-sources-for-2018/.
«Datasets for Data Mining and Data Science», http://www.kdnuggets.com/datasets/index.html.
«Exploring Open Data Sets», https://datascience.berkeley.edu/open-data-sets/.
«Free Big Data Sources», Datamics, http://datamics.com/free-big-data-sources/.
Hadoop Illuminated, глава 16. Publicly Available Big Data Sets, http://hadoopilluminated.com/hadoop_illuminated/Public_Bigdata_Sets.html.
«List of Public Data Sources Fit for Machine Learning», https://blog.bigml.com/list-of-public-data-sources-fit-for-machine-learning/.
«Open Data», Wikipedia, https://en.wikipedia.org/wiki/Open_data.
«Open Data 500 Companies», http://www.opendata500.com/us/list/.
«Other Interesting Resources/Big Data and Analytics Educational Resources and Research», B. Marr, http://computing.derby.ac.uk/bigdatares/?page_id=223.
«6 Amazing Sources of Practice Data Sets», https://www.jigsawacademy.com/6-amazing-sources-of-practice-data-sets/.
«20 Big Data Repositories You Should Check Out», M. Krivanek, http://www.datasciencecentral.com/profiles/blogs/20-free-big-data-sources-everyone-should-check-out.
«70+ Websites to Get Large Data Repositories for Free», http://bigdata-madesimple.com/70-websites-to-get-large-data-repositories-for-free/.
«Ten Sources of Free Big Data on Internet», A. Brown, https://www.linkedin.com/pulse/ten-sources-free-big-data-internet-alan-brown.
«Top 20 Open Data Sources», https://www.linkedin.com/pulse/top-20-open-data-sources-zygimantas-jacikevicius.
«We’re Setting Data, Code and APIs Free», NASA, https://open.nasa.gov/open-data/.
«Where Can I Find Large Datasets Open to the Public?» Quora, https://www.quora.com/Where-can-I-find-large-datasets-open-to-the-public.
16.2. Реляционные базы данных и язык структурированных запросов (SQL) 765
16.2. Реляционные базы данных и язык структурированных запросов (SQL)
Базы данных играют важную роль, особенно при работе с большими данными. В главе 9 была продемонстрирована последовательная обработка текстовых файлов, в том числе при работе с данными из файлов CSV и работе с JSON.
Обе возможности чрезвычайно важны при обработке данных файла полностью или частично. С другой стороны, обработка транзакций требует быстрого поиска и, если потребуется. быстрого обновления отдельных элементов данных.
База данных представляет собой интегрированную коллекцию данных. Система управления базами данных (СУБД) предоставляет механизмы хранения и упорядочения данных способом, соответствующим формату БД. СУБД обеспечивает удобный доступ к данным и их хранение, при этом разработчику не приходится отвлекаться на внутреннее представление баз данных.
Реляционные системы управления базами данных (РСУБД) хранят данные в таблицах и определяют отношения между таблицами. Язык структурированных запросов (SQL) почти повсеместно используется с РСУБД для работы с данными и выполнения запросов, извлекающих информацию по заданному критерию. Среди популярных РСУБД с открытым кодом выделим SQLite, PostgreSQL, MariaDB и MySQL. Любой желающий может загрузить эти продукты и свободно пользоваться ими. Для перечисленных РСУБД существует поддержка Python. Мы будем использовать РСУБД SQLite, входящую в поставку Python. В число популярных коммерческих РСУБД входят Microsoft SQL Server, Oracle, Sybase и IBM Db2.
Таблицы, строки и столбцы
Реляционная БД — логическое табличное представление данных, которое позволяет обращаться к данным без учета их физической структуры. Таблицы состоят из строк, каждая из которых описывает отдельный объект. На следующей диаграмме изображена таблица Employee, которая может использоваться в отделе кадров:
766 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
23603
2456834589357614713278321JonesKerwinLarsonMyersNeumannStephensNumber ­€ ƒ„…†‡ˆƒ‰Š‰ ­‹†‡ˆ„ŒŽName413413642611413611Department110020001800140090008500SalaryNew JerseyNew JerseyLos AngelesOrlandoNew JerseyOrlandoLocation
Таблица предназначена для хранения атрибутов работников — каждая ее строка представляет одного работника. Строки состоят из столбцов, содержащих значения атрибутов. Каждый столбец представляет отдельный атрибут данных.
Эта таблица состоит из шести строк. Столбец Number представляет первичный ключ — столбец (группу столбцов) со значением, уникальным для каждой строки (см. также ниже). Это гарантирует, что каждая строка однозначно идентифицируется своим первичным ключом. Примеры первичных ключей — номера социального страхования, табельные номера работников и номера деталей в системе складского учета. Значения каждого из этих атрибутов заведомо уникальны. В данном случае строки перечисляются по возрастанию уникального ключа, но они могут перечисляться и по убыванию или вообще без какого-либо определенного порядка. Итак, строки таблицы уникальны (по значению первичного ключа), но значения обычного столбца могут повторяться в разных строках. Например, три разные строки столбца Department таблицы Employee содержат число 413.
Выборка подмножества данных
Разных пользователей баз данных интересуют разные данные и разные отношения между данными. Многим пользователям достаточно небольшого подмножества строк и столбцов. Запросы указывают, какие подмножества данных должны выбираться из таблицы. Для определения запросов используется язык SQL, который вскоре будет описан более подробно. Например, вы можете выбрать данные из таблицы Employee для получения информации о местонахождении филиалов с сортировкой данных в порядке возрастания номеров отделов:
16.2. Реляционные базы данных и язык структурированных запросов (SQL) 767
Department Location
413 New Jersey
611 Orlando
642 Los Angeles
SQLite
В примерах кода из оставшейся части раздела 16.2 используется СУБД с открытым кодом SQLite, входящая в поставку Python, но в большинстве популярных СУБД реализована поддержка Python. Каждая СУБД обычно предоставляет модуль с поддержкой программного интерфейса Python Database Application Programming Interface (DB-API), определяющего общие имена объектов и методов для работы с любой БД.
16.2.1. База данных books
В этом разделе представлена БД books, содержащая информацию о нескольких книгах. Мы создадим эту БД в SQLite с использованием модуля sqlite3 стандартной библиотеки Python при помощи сценария, находящегося в подкаталоге sql каталога примеров ch16, перейдя затем к описанию таблиц БД. Эта БД будет использована в сеансе IPython для представления различных концепций баз данных, включая операции создания, чтения, обновления и удаления данных (так называемые операции CRUD). При описании таблиц мы воспользуемся SQL и коллекциями DataFrame библиотеки Pandas для вывода содержимого каждой таблицы. Затем в нескольких ближайших разделах будут рассмотрены другие возможности SQL.
Создание базы данных books
В приглашении Anaconda, терминале или командной оболочке перейдите в подкаталог sql каталога примеров ch16. Следующая команда sqlite3 создает БД SQLite с именем books.db и выполняет сценарий SQL books.sql, который определяет таблицы БД и заполняет их:
sqlite3 books.db < books.sql
Синтаксис < указывает, что содержимое books.sql передается на вход команды sqlite3. После завершения команды БД готова к использованию. Создайте новый сеанс IPython.
768 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
Подключение к базе данных Python из Python
Для работы с БД из Python сначала вызовите функцию connect модуля sqlite3, чтобы подключиться к БД и подключить объект Connection:
In [1]: import sqlite3
In [2]: connection = sqlite3.connect('books.db')
Таблица authors
База данных состоит из трех таблиц — authors, author_ISBN и titles. Таблица authors, содержащая все данные авторов, состоит из трех столбцов:
ØØ
id — уникальный идентификатор автора. Этот целочисленный столбец определяется как автоматически увеличиваемый — для каждой строки, вставляемой в таблицу, SQLite увеличивает значение id на 1, чтобы каждая строка гарантированно имела уникальное значение этого столбца. Этот столбец является первичным ключом таблицы;
ØØ
first — имя автора (строка);
ØØ
last — фамилия автора (строка).
Просмотр содержимого таблицы authors
Используем запрос SQL с pandas для просмотра содержимого таблицы authors:
In [3]: import pandas as pd
In [4]: pd.options.display.max_columns = 10
In [5]: pd.read_sql('SELECT * FROM authors', connection,
...: index_col=['id'])
...:
Out[5]:
first last
id
1 Paul Deitel
2 Harvey Deitel
3 Abbey Deitel
4 Dan Quirk
5 Alexander Wald
Функция Pandas read_sql выполняет запрос SQL и возвращает коллекцию DataFrame с результатами запроса. Аргументы функции:
16.2. Реляционные базы данных и язык структурированных запросов (SQL) 769
ØØ
строка, представляющая выполняемый запрос SQL;
ØØ
объект Connection базы данных SQLite;
ØØ
ключевой аргумент index_col, указывающий, какой столбец должен использоваться в качестве индекса строк DataFrame (столбец id в данном случае).
Как вы вскоре увидите, если аргумент index_col не указан, то слева от строк DataFrame выводятся значения индексов, начинающиеся с 0.
Запрос SQL SELECT получает строки и столбцы из одной и более таблиц в БД. В запросе:
SELECT * FROM authors
звездочка (*) представляет собой универсальный символ, показывающий, что запрос должен получить все столбцы из таблицы authors (о запросах SELECT см. ниже).
Таблица titles
Таблица titles содержит данные всех книг. Она состоит из четырех столбцов:
ØØ
isbn — код ISBN книги (строка) является первичным ключом таблицы. ISBN — сокращение от «International Standard Book Number», то есть «международный стандартный номер книги» — схема нумерации, которая позволяет издателю присвоить каждой книге уникальный идентификационный номер;
ØØ
title — название книги (строка);
ØØ
edition — номер издания книги (целое число);
ØØ
copyright — год регистрации авторского права книги (строка).
Воспользуемся SQL и pandas для просмотра содержимого таблицы titles:
In [6]: pd.read_sql('SELECT * FROM titles', connection)
Out[6]:
isbn title edition copyright
0 0135404673 Intro to Python for CS and DS 1 2020
1 0132151006 Internet & WWW How to Program 5 2012
2 0134743350 Java How to Program 11 2018
3 0133976890 C How to Program 8 2016
4 0133406954 Visual Basic 2012 How to Program 6 2014
770 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
5 0134601548 Visual C# How to Program 6 2017
6 0136151574 Visual C++ How to Program 2 2008
7 0134448235 C++ How to Program 10 2017
8 0134444302 Android How to Program 3 2017
9 0134289366 Android 6 for Programmers 3 2016
Таблица author_ISBN
Таблица author_ISBN использует следующие столбцы для связывания авторов из таблицы authors с книгами из таблицы titles:
ØØ
id — идентификатор автора (целое число).
ØØ
isbn — код ISBN книги (строка).
Столбец id является внешним ключом — столбцом таблицы, который совпадает со столбцом первичного ключа другой таблицы, а именно столбцом id таблицы authors. Столбец isbn тоже является внешним ключом — он совпадает со столбцом первичного ключа isbn таблицы titles. База данных может содержать много таблиц. При проектировании БД проектировщик стремится минимизировать дублирование данных между таблицами. Для этого каждая таблица должна иметь конкретное наполнение, а внешние ключи — использоваться для связывания данных в нескольких таблицах. Первичные и внешние ключи назначаются при создании таблиц БД (в нашем случае в сценарии books.sql).
Комбинация столбцов id и isbn таблицы образует составной первичный ключ. Каждая ее строка однозначно связывает одного автора с кодом ISBN одной книги. Таблица содержит много записей, поэтому воспользуемся SQL и pandas для просмотра первых пяти строк:
In [7]: df = pd.read_sql('SELECT * FROM author_ISBN', connection)
In [8]: df.head()
Out[8]:
id isbn
0 1 0134289366
1 2 0134289366
2 5 0134289366
3 1 0135404673
4 2 0135404673
Каждое значение внешнего ключа должно присутствовать в строке другой таблицы как значение первичного ключа, чтобы СУБД могла проверить действительность значения внешнего ключа — это называется правилом ссылочной целостности. В частности, СУБД проверяет действительность значения
16.2. Реляционные базы данных и язык структурированных запросов (SQL) 771
id конкретной строки author_ISBN, убеждаясь в том, что в таблице authors существует строка с таким значением первичного ключа.
Внешние ключи также позволяют выбирать взаимосвязанные данные из нескольких таблиц и объединять их. Между первичным ключом и соответствующим внешним ключом существует отношение «один ко многим» — один автор может написать много книг, хотя одна книга может быть написана несколькими авторами. Таким образом, внешний ключ может встречаться в своей таблице многократно, но только один раз (как первичный ключ) в другой таблице. Например, в БД books код ISBN 0134289366 встречается в нескольких строках таблицы author_ISBN, потому что книга имеет несколько авторов, но в titles встречается только один раз в качестве первичного ключа.
Диаграмма сущностей и связей (ER)
На следующей диаграмме сущностей и связей (ER-диаграмма, Entity-Relationship) БД books показаны таблицы базы данных и отношения между ними:
1
1titlescopyrighteditiontitleisbnauthor_ISBNisbnidauthorslastfirstid
В первом разделе каждого блока указано имя таблицы, в остальных — имена ее столбцов. Курсивом выделены первичные ключи. Первичный ключ таблицы однозначно идентифицирует каждую строку таблицы. Каждая строка должна иметь определенное значение первичного ключа, и это значение должно быть уникальным в таблице — в этом заключается правило ссылочной целостности. И снова для таблицы author_ISBN первичный ключ образуется комбинацией обоих столбцов (составной первичный ключ).
Линии, соединяющие таблицы, представляют отношения между таблицами. Возьмем линию между таблицами authors и author_ISBN. На стороне authors стоит обозначение 1, а на стороне author_ISBN — знак бесконечности (∞). Так обозначаются отношения «один ко многим». Для каждого автора из таблицы authors может существовать произвольное количество кодов ISBN для книг, написанных этим автором, в таблице author_ISBN, то есть автор может написать
772 Глава 16. Большие данные: Hadoop, Spark, NoSQL и IoT
любое количество книг, а значение id автора может встречаться в нескольких строках таблицы author_ISBN. Линия отношения связывает столбец id в таблице authors (для которой id является первичным ключом) со столбцом id таблицы author_ISBN (для которой id является внешним ключом). Линия между таблицами соединяет первичный ключ с соответствующим внешним ключом.
Линия между таблицами titles и author_ISBN представляет отношение «один ко многим» — одна книга может быть написана многими авторами. Линия связывает первичный ключ isbn в таблице titles с соответствующим внешним ключом в таблице author_ISBN. Отношения на диаграмме сущностей и связей демонстрируют, что единственным предназначением таблицы author_ISBN является формирование отношения «многие ко многим» между таблицами authors и titles — автор может написать много книг, а книга может иметь много авторов.
Ключевые слова SQL
В следующем подразделе продолжится ваше знакомство с SQL в контексте БД books. Запросы SQL и команды, использующие ключевые слова SQL, описаны в табл. 16.1. Другие ключевые слова SQL выходят за рамки настоящего описания.
Таблица 16.1. Запросы SQL и команды, использующие ключевые слова SQL
Ключевое слово SQL
Описание
SELECT
Выбирает данные из одной или нескольких таблиц
FROM
Таблицы, задействованные в запросе (должно присутствовать в каждой команде SELECT)
WHERE
Критерий выбора, определяющий строки данных для операции выборки, удаления или обновления (может отсутствовать в команде SQL)
GROUP BY
Критерий группировки строк (может отсутствовать в команде SQL)
ORDER BY
Критерий упорядочения строк (может отсутствовать в команде SQL)
INNER JOIN
Слияние строк из нескольких таблиц
INSERT
Вставка строк в заданную таблицу
UPDATE
Обновление строк в заданной таблице
DELETE
Удаление строк из заданной таблицы
16.2. Реляционные базы данных и язык структурированных запросов (SQL) 773
16.2.2. Запросы SELECT
Предыдущий раздел использует команды SELECT и универсальный символ * для получения всех столбцов из таблицы. Обычно программиста интересует только подмножество столбцов, особенно в больших данных, которые могут содержать десятки, сотни, тысячи и более столбцов. Чтобы извлечь отдельные столбцы, укажите список имен столбцов, разделенных запятыми. Допустим, вы хотите извлечь из таблицы authors только столбцы first и last:
In [9]: pd.read_sql('SELECT first, last FROM authors', connection)
Out[9]:
first last
0 Paul Deitel
1 Harvey Deitel
2 Abbey Deitel
3 Dan Quirk
4 Alexander Wald
16.2.3. Секция WHERE
Нередко из БД выбирается часть строк данных, удовлетворяющих определенным критериям, особенно в области больших данных, в которых БД может содержать миллионы и даже миллиарды строк. Выбираются только строки, удовлетворяющие критерию выбора (который формально называется предикатом). Условие WHERE определяет критерий выбора. Выберем поля title, edition и copyright для всех книг, у которых год регистрации авторского права (copyright) больше 2016. Строковые значения в запросах SQL заключаются в одинарные апострофы (') — например, '2016':
In [10]: pd.read_sql("""SELECT title, edition, copyright
...: FROM titles
...: WHERE copyright > '2016'""", connection)
Out[10]:
title edition copyright
0 Intro to Python for CS and DS 1 2020
1 Java How to Program 11 2018
2 Visual C# How to Program 6 2017
3 C++ How to Program 10 2017
4 Android How to Program 3 2017
Поиск по шаблону: нуль и более символов
Условие WHERE может содержать операторы <, >, <=, >=, =, <> (не равно) и LIKE. Оператор LIKE используется для поиска по шаблону — поиска строк, удовлет774
Download 0,77 Mb.

Do'stlaringiz bilan baham:
1   ...   12   13   14   15   16   17   18   19   20




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish