Как заставить кластеризацию данных в определенной очевидной модели? - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть большой набор значений «Скорость автомобиля против оборотов двигателя» для автомобиля. Я пытаюсь предсказать время, затраченное транспортным средством на каждую передачу.

Я запустил кластеризацию K-Means на наборе данных и получил следующий результат: Vehicle Speed vs Engine RPM (~86000 points)

Очевидно, что мой алгоритм не смог уловить очевидную картину. Я хочу заставить K-Means (или любой другой алгоритм кластеризации) кластеризовать данные по шести наклонным линиям. Фрагмент соответствующего кода:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.cluster import KMeans

plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')

# Importing the dataset
data = pd.read_csv('speedRpm.csv')
print(data.shape)
data.head()

# Getting the data points
f1 = data['rpm'].values
f2 = data['speed'].values
X = np.array(list(zip(f1, f2)))

# Number of clusters
k = 5

kmeans = KMeans(n_clusters=k)
# Fitting the input data
kmeans = kmeans.fit(X)
# Getting the cluster labels
labels = kmeans.predict(X)
# Centroid values
centroids = kmeans.cluster_centers_

labeled_array = {i: X[np.where(kmeans.labels_ == i)] for i in range(kmeans.n_clusters)}

colors = ['r', 'g', 'b', 'y', 'c']
fig, ax = plt.subplots()
for i in range(k):
        points = np.array([X[j] for j in range(len(X)) if kmeans.labels_[j] == i])
        ax.scatter(points[:, 0], points[:, 1], s=7, c=colors[i])
ax.scatter(centroids[:, 0], centroids[:, 1], marker='*', s=200, c='#050505')

plt.show()

Как мне убедиться, что алгоритм кластеризации фиксирует правильный шаблон, даже если он не самый эффективный?

Спасибо!

EDIT

На этот раз проверял тот же набор точек, используя DBSCAN. Поработав некоторое время со значениями eps и min_samples, получил следующий результат:

enter image description here

Хотя алгоритм все еще не идеален и слишком сильно отличается, алгоритм начинает улавливать линейный тренд.

Код:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.cluster import KMeans
from sklearn.cluster import DBSCAN

plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')

# Importing the dataset
data = pd.read_csv('speedRpm.csv')
print(data.shape)
data.head()

# Getting the values and plotting it
f1 = data['rpm'].values
f2 = data['speed'].values
X = np.array(list(zip(f1, f2)))

# DBSCAN

# Compute DBSCAN
db = DBSCAN(eps=1.1, min_samples=3).fit(X)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

# Number of clusters in labels, ignoring noise if present.
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print "Estimated Number of Clusters", n_clusters_

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)

    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

Ответы [ 3 ]

0 голосов
/ 04 сентября 2018

Высокий уровень

Здесь есть два основных варианта:

  1. Преобразование ваших данных, чтобы алгоритмы кластеризации в стиле k-средних были успешными
  2. Выберите другой алгоритм

Незначительный вариант:

  1. Настройте kmeans, заставив инициализацию быть умнее

Вариант 2

Python имеет хорошее описание нескольких алгоритмов кластеризации здесь . По ссылке, (грубо обрезанный) полезный рисунок:

enter image description here

Этот ряд похож на ваш набор данных; Вы пробовали гауссову модель смеси? A GMM имеет мало известных теоретических свойств, но он работает, назначая вероятности того, что точки принадлежат каждому центру кластера на основе апостериорного значения, рассчитанного по данным. Вы часто можете инициализировать его с помощью kmeans, что делает Sklearn для вас.

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

enter image description here

они предлагают подпись:

DBSCAN может найти нелинейно разделимые кластеры. Этот набор данных не может быть адекватно сгруппированы с K-средних

что, кажется, говорит о ваших проблемах.


Больше о ваших неприятностях

Kmeans - чрезвычайно универсальный алгоритм, но он не является глобально оптимальным и страдает от множества слабых мест. Вот плотное чтение

В дополнение к таким проблемам, как проблема Микки Мауса , kmeans часто пытается минимизировать простое евклидово расстояние до центроидов. Хотя это имеет большой смысл для многих проблем, это не имеет смысла в вашей, где перекос кластеров означает, что это не совсем правильный показатель. Обратите внимание, что другие алгоритмы, такие как агломеративная / иерархическая кластеризация, показанная выше, которые используют аналогичные меры, имеют аналогичные атрибуты.

Я не рассматривал преобразование ваших данных или настройку kmeans, потому что последний фактически требует взлома (или написания вашего собственного) алгоритма кластеризации (я не рекомендую для простой исследовательской задачи, учитывая охват sklearn и подобных пакетов), где первое кажется локальным решением, чувствительным к вашим точным данным. ICA может быть неплохим началом, но есть много вариантов для этой задачи

0 голосов
/ 04 сентября 2018

k-средних (и другие алгоритмы кластеризации, указанные в ответе @ en-knight) предназначены для многомерных данных, которые, как правило, имеют группы точек данных, которые «близки» друг к другу (в терминах евклидова расстояния) , но пространственно разделены.

В вашем случае, если данные рассматриваются в необработанном входном пространстве (об / мин в зависимости от скорости), образующиеся «кластеры» очень вытянуты и в значительной степени перекрываются в области около (0,0), поэтому большинство, если нет все методы, основанные на евклидовом расстоянии, обречены на провал.

Ваши данные на самом деле не являются 6 группами двумерных точек, которые пространственно разделены. На самом деле это смесь из 6 возможных линейных трендов.

Следовательно, группировка должна основываться на x / y (передаточное число). Он одномерный: каждая пара (об / мин, скорость) соответствует одному значению (об / мин / скорость), и вы хотите сгруппировать их.

Я не знаю, может ли k-means (или другие алгоритмы) взять 1-D набор данных, но если это невозможно, вы можете создать новый массив с парами, такими как [0, rpm / vel] и выполнить что через это.

Возможно, вы захотите найти одномерный алгоритм, более эффективный, чем многомерные универсальные.

Это сделает графическую маркировку немного более сложной, поскольку группировка вычисляется на основе производного набора данных, который имеет форму, отличную от формы (1 x выборок), чем исходные данные (2 x выборки), но их отображение не выполняется. т трудно.

0 голосов
/ 04 сентября 2018

Вы можете умножить свои значения y в 10 и более раз, чтобы они распространялись вдоль этой оси. Убедитесь, что вы отслеживаете, работаете ли вы с реальными или умноженными значениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...