Кластеризация KMeans - ошибка значения: n_samples = 1 должно быть> = n_cluster - PullRequest
0 голосов
/ 22 февраля 2019

Я выполняю эксперимент с тремя наборами данных временных рядов с различными характеристиками для моего эксперимента, формат которого следующий.

    0.086206438,10
    0.086425551,12
    0.089227066,20
    0.089262508,24
    0.089744425,30
    0.090036815,40
    0.090054172,28
    0.090377569,28
    0.090514071,28
    0.090762872,28
    0.090912691,27

Первый столбец - timestamp.По причинам воспроизводимости, я делюсь данными здесь .Из столбца 2 я хотел прочитать текущую строку и сравнить ее со значением предыдущей строки.Если оно больше, я продолжаю сравнивать.Если текущее значение меньше значения предыдущего ряда, я хочу разделить текущее значение (меньше) на предыдущее значение (больше).Соответственно, вот код:

import numpy as np
import matplotlib.pyplot as plt

protocols = {}

types = {"data1": "data1.csv", "data2": "data2.csv", "data3": "data3.csv"}

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T
    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    protocols[protname] = {
        "col_time": col_time,
        "col_window": col_window,
        "quotient_times": quotient_times,
        "quotient": quotient,
    }

    plt.figure(); plt.clf()
    plt.plot(quotient_times,quotient, ".", label=protname, color="blue")
    plt.ylim(0, 1.0001)
    plt.title(protname)
    plt.xlabel("time")
    plt.ylabel("quotient")
    plt.legend()
    plt.show()

И это дает следующие три точки - по одной на каждый набор данных , который я поделился.

enter image description here enter image description here enter image description here

Как видно из точек на графиках, основанных на приведенном выше коде, data1 довольно последовательно, чьезначение около 1, data2 будет иметь два коэффициента (значения которых будут сконцентрированы либо около 0,5 или 0,8), а значения data3 сконцентрированы около двух значений (около 0,5 или 0,7).Таким образом, учитывая новую точку данных (с quotient и quotient_times), я хочу узнать, к какой cluster она принадлежит, создав каждый набор данных, объединяющий эти две преобразованные функции quotient и quotient_times.Я пытаюсь с кластеризацией KMeans следующим образом

from sklearn.cluster import KMeans
k_means = KMeans(n_clusters=3, random_state=0)
k_means.fit(quotient)

Но это дает мне ошибку: ValueError: n_samples=1 should be >= n_clusters=3.Как мы можем исправить эту ошибку?

Обновление: данные samlpe = = 1040 *

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Как есть, ваша quotient переменная теперь один единственный образец;здесь я получаю другое сообщение об ошибке, вероятно, из-за другой версии Python / scikit-learn, но суть та же:

import numpy as np
quotient = np.array([ 0.7 , 0.7 , 0.4973262 , 0.7008547 , 0.71287129, 0.704 , 0.49723757, 0.49723757, 0.70676692, 0.5 , 0.5 , 0.70754717, 0.5 , 0.49723757, 0.70322581, 0.5 , 0.49723757, 0.49723757, 0.5 , 0.49723757])
quotient.shape
# (20,)

from sklearn.cluster import KMeans
k_means = KMeans(n_clusters=3, random_state=0)
k_means.fit(quotient)

Это дает следующую ошибку:

ValueError: Expected 2D array, got 1D array instead:
array=[0.7        0.7        0.4973262  0.7008547  0.71287129 0.704
 0.49723757 0.49723757 0.70676692 0.5        0.5        0.70754717
 0.5        0.49723757 0.70322581 0.5        0.49723757 0.49723757
 0.5        0.49723757].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.

которая, несмотря на другую формулировку, не отличается от вашей - по сути, это говорит о том, что ваши данные выглядят как единая выборка.

Следуя первому совету (т.е. учитывая, что quotient содержит одну особенность (столбец) решает проблему:

k_means.fit(quotient.reshape(-1,1))
# result
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=0, tol=0.0001, verbose=0)
0 голосов
/ 23 февраля 2019

Пожалуйста, попробуйте код ниже.Краткое объяснение того, что я сделал:

Сначала я построил набор данных sample = np.vstack((quotient_times, quotient)).T и стандартизировал его, чтобы его было легче кластеризовать.Затем я применил DBScan с несколькими гиперпараметрами (eps и min_samples), пока не нашел тот, который лучше разделял точки.Наконец, я нанес на график данные с соответствующими метками, поскольку вы работаете с двухмерными данными, легко представить, насколько хороша кластеризация.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler

types = {"data1": "data1.csv", "data2": "data2.csv", "data3": "data3.csv"}

dataset = np.empty((0, 2))

for protname, fname in types.items():
    col_time,col_window = np.loadtxt(fname,delimiter=',').T

    trailing_window = col_window[:-1] # "past" values at a given index
    leading_window  = col_window[1:]  # "current values at a given index
    decreasing_inds = np.where(leading_window < trailing_window)[0]
    quotient = leading_window[decreasing_inds]/trailing_window[decreasing_inds]
    quotient_times = col_time[decreasing_inds]

    sample = np.vstack((quotient_times, quotient)).T
    dataset = np.append(dataset, sample, axis=0)

scaler = StandardScaler()
dataset = scaler.fit_transform(dataset)

k_means = DBSCAN(eps=0.6, min_samples=1)
k_means.fit(dataset)

colors = [i for i in k_means.labels_]

plt.figure();
plt.title('Dataset 1,2,3')
plt.xlabel("time")
plt.ylabel("quotient")
plt.scatter(dataset[:, 0], dataset[:, 1], c=colors)
plt.legend()
plt.show()

enter image description here

...