Шаг 108.
Введение в машинное обучение ... Сравнение работы алгоритмов на наборе изображений лиц. Анализ набора изображений лиц с помошью алгоритма DBSCAN

    На этом шаге мы проведем анализ изображения лиц на основе алгоритма DBSCAN.

    Мы начнем с применения DBSCAN, о котором только что говорили:

[In 71]:
# применяем алгоритм DBSCAN, используя параметры по умолчанию
dbscan = DBSCAN()
labels = dbscan.fit_predict(X_pca)
print("Уникальные метки: {}".format(np.unique(labels)))

Уникальные метки: [-1]

    Мы видим, что все возвращенные метки имеют значение -1, таким образом, согласно алгоритму DBSCAN все данные были помечены как "шум". Здесь у нас есть два инструмента, что исправить эту ситуацию: мы можем увеличить значение eps, чтобы расширить окрестность каждой точки и уменьшить значение min_samples, чтобы рассматривать в качестве кластеров группы с меньшим количеством точек. Давайте сначала попробуем изменить значение min_samples:

[In 72]:
dbscan = DBSCAN(min_samples=3)
labels = dbscan.fit_predict(X_pca)
print("Уникальные метки: {}".format(np.unique(labels)))

Уникальные метки: [-1]

    Даже при количестве точек в группе, равном 3, все точки помечаются как шум. Таким образом, нам нужно увеличить значение eps:

[In 73]:
dbscan = DBSCAN(min_samples=3, eps=15)
labels = dbscan.fit_predict(X_pca)
print("Уникальные метки: {}".format(np.unique(labels)))

Уникальные метки: [-1 0]

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

[In 74]:
# Считаем количество точек в кластерах и шум.
# bincount не допускает отрицательных цифр, поэтому нам нужно добавить 1.
# Первая цифра в выводе соответствует количеству шумовых точек.
print("Количество точек на кластер: {}".format(np.bincount(labels + 1)))

Количество точек на кластер: [  31 2032]

    Шумовых точек оказалось очень мало, около 31, поэтому мы можем все эти точки посмотреть (см. рисунок 1).

[In 75]:
noise = X_people[labels==-1]
fig, axes = plt.subplots(3, 10, subplot_kw={'xticks': (), 'yticks': ()}, 
                         figsize=(12, 4))
for image, ax in zip(noise, axes.ravel()):
    ax.imshow(image.reshape(image_shape), vmin=0, vmax=1)


Рис.1. Примеры из набора изображений лиц, помеченные алгоритмом DBSCAN как шум

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

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

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

[In 76]:
for eps in [1, 3, 5, 7, 9, 11, 13]:
    print("\neps={}".format(eps))
    dbscan = DBSCAN(eps=eps, min_samples=3)
    labels = dbscan.fit_predict(X_pca)
    print("Полученные кластеры: {}".format(np.unique(labels)))
    print("Размеры кластеров: {}".format(np.bincount(labels + 1)))

eps=1
Полученные кластеры: [-1]
Размеры кластеров: [2063]

eps=3
Полученные кластеры: [-1]
Размеры кластеров: [2063]

eps=5
Полученные кластеры: [-1]
Размеры кластеров: [2063]

eps=7
Полученные кластеры: [-1  0  1  2  3  4  5  6  7  8  9 10 11 12]
Размеры кластеров: [2003    4   14    7    4    3    3    4    4    3    3    5    3    3]

eps=9
Полученные кластеры: [-1  0  1  2]
Размеры кластеров: [1306  751    3    3]

eps=11
Полученные кластеры: [-1  0]
Размеры кластеров: [ 413 1650]

eps=13
Полученные кластеры: [-1  0]
Размеры кластеров: [ 120 1943]

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

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

    Результаты для eps=7 выглядят наиболее интересно, здесь мы получаем большое количество маленьких кластеров. Мы можем исследовать результаты этой кластеризации более подробно, визуализировав все точки данных для всех 13 кластеров меньшего размера (рисунок 2):

[In 77]:
dbscan = DBSCAN(min_samples=3, eps=7)
labels = dbscan.fit_predict(X_pca)

for cluster in range(max(labels) + 1):
    mask = labels == cluster
    n_images = np.sum(mask)
    fig, axes = plt.subplots(1, n_images, figsize=(n_images * 1.5, 4),
                             subplot_kw={'xticks': (), 'yticks': ()})
    
    for image, label, ax in zip(X_people[mask], y_people[mask], axes):
        ax.imshow(image.reshape(image_shape), vmin=0, vmax=1)
        ax.set_title(people.target_names[label].split()[-1])


Рис.2. Кластеры, найденные с помощью алгоритма DBSCAN при eps=7

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

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

    Теперь давайте переидем к применению алгоритмов k-средних и агломеративной кластеризации.

    На следующем шаге мы рассмотрим анализ набора изображений лиц с помошью алгоритма k-средних.




Предыдущий шаг Содержание Следующий шаг