我写了代码,
import numpy
import matplotlib.pyplot as plt
from tslearn.clustering import KShape
from tslearn.datasets import CachedDatasets
from tslearn.preprocessing import TimeSeriesScalerMeanVariance
ks = KShape(n_clusters=3, n_init=10, verbose=True, random_state=seed)
y_pred = ks.fit_predict(data)
plt.figure(figsize=(16,9))
for yi in range(3):
plt.subplot(3, 1, 1 + yi)
for xx in stack_data[y_pred == yi]:
plt.plot(xx.ravel(), "k-", alpha=.2)
plt.title("Cluster %d" % (yi + 1))
plt.tight_layout()
plt.show()
我想用usigng KShape的聚类除以data
。现在显示了图,但是我找不到每3个聚类中的数据。
数据是A,B,C,D的顺序。因此,我想显示要绘制的标签或聚类的结果。我搜索了KShape的文档(http://tslearn.readthedocs.io/en/latest/auto_examples/plot_kshape.html),但找不到信息来做我理想的事情。我应该怎么做?
答案 0 :(得分:2)
K形随机工作,并且没有为每次迭代设置种子,您可能会得到不同的簇和质心。如果给定类完全由给定质心描述,则没有确定性的方式可以知道先验,但是您可以通过模糊方式检查给定类主要归为哪个质心,从而以脱机方式继续进行模糊处理。>
例如,任何给定的类A
都可以包含属于您正在考虑的特征空间中的两个群集的元素。
假设您有3个类,但最好用4个类来描述您的数据集(例如,按最大平均密度):在第4个类中肯定有至少一个类的某些点。
或者,假设您的类别与正在考虑的距离度量生成的质心不重叠:考虑一个明显的例子:您有3个类别,数字从0到100,从100到1000和从1000到1000。 1100,但是您的数据集包含0到150以及950到1100之间的数字:一种聚类算法会在2个聚类中找到其最佳值,并将A类的点放在两个聚类之一中。
例如,一旦确定类A
主要用于群集1
,类B
专门用于群集2
等,则可以继续进行分配该集群到给定的类。
我们将通过为包含大多数点的聚类分配最佳拟合类来确定聚类类别:
在此示例中,我们使用tslearn.datasets
中的一个。该代码部分取自this K-Shape example on tslearn。
import numpy as np
import matplotlib.pyplot as plt
from tslearn.clustering import KShape
from tslearn.datasets import CachedDatasets
from tslearn.preprocessing import TimeSeriesScalerMeanVariance
from seaborn import heatmap
我们为代码可重复性设置了种子:
seed = 0
np.random.seed(seed)
首先,我们准备数据集,选择第一个classes_number=3
类:
classes_number = 3
X_train, y_train, X_test, y_test = CachedDatasets().load_dataset("Trace")
mask = y_train <= classes_number
X_train, y_train = X_train[mask], y_train[mask] # Keep first 3 classes
X_train = TimeSeriesScalerMeanVariance().fit_transform(X_train) # Keep only 50 time series
sz = X_train.shape[1]
现在我们找到具有clusters_number=3
的簇:
# Euclidean k-means
clusters_number = 3
ks = KShape(n_clusters=clusters_number, verbose=False, random_state=seed)
y_pred = ks.fit_predict(X_train)
我们现在继续计算分配给每个群集的每个类的元素,并为未将给定类的元素分配给给定群集的地方添加0填充(当然会有更多的pythonic的方法,但我还没有找到它):
data = [np.unique(y_pred[y_train==i+1], return_counts=True) for i in range(classes_number)]
>>>[(array([2]), array([26])),
(array([0]), array([21])),
(array([1]), array([22]))]
添加填充:
padded_data = np.array([[
data[j][1][data[j][0] == i][0] if np.any(data[j][0] == i) else 0
for i in range(clusters_number)
] for j in range(classes_number)])
>>> array([[ 0, 0, 26],
[21, 0, 0],
[ 0, 22, 0]])
归一化获得的矩阵:
normalized_data = padded_data / np.sum(padded_data, axis=-1)[:, np.newaxis]
>>> array([[0., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
我们可以使用seaborn.heatmap
可视化获得的矩阵:
xticklabels = ["Cluster n. %s" % (1+i) for i in range(clusters_number)]
yticklabels = ["Class n. %s" % (1+i) for i in range(classes_number)]
heatmap(
normalized_data,
cbar=False,
square=True,
annot=True,
cmap="YlGnBu",
xticklabels=xticklabels,
yticklabels=yticklabels)
plt.yticks(rotation=0)
获取:
在这种最佳情况下,每个聚类仅包含且仅包含一个类,因此我们可以绝对精确地获得:
classes_clusters = np.argmax(normalized_data, axis=1)
>>> array([2, 0, 1])
为简单起见,为了模拟不与集群完全重叠的类,我将仅对部分标签进行混洗,但是有大量示例:大多数集群问题最终都归因于不完全相同的类与簇重合。
tmp = y_train[:20]
np.random.shuffle(tmp)
y_train[:20] = tmp
现在,当我们再次执行脚本时,我们得到了完全不同的矩阵:
但是我们仍然能够确定类的簇:
classes_clusters = np.argmax(normalized_data, axis=1)
>>> array([2, 0, 1])
假设我们被认为是在数据集中存在4个类:在使用不同的k
值运行后,我们会发现在当前数据集中,最佳簇数为k=3
:我们继续将类分配给集群?哪个班可以丢掉?
我们通过向标签任意分配第四类来模拟这种情况:
y_train[:20] = 4
再次运行我们的脚本,我们将获得:
第四节课显然要去了。我们可以对平均方差进行阈值处理:
threshold = np.mean(np.var(normalized_data, axis=1))
result = np.argmax(normalized_data[np.var(normalized_data, axis=1)>threshold], axis=1)
我们又得到了:
array([2, 0, 1])
我希望这种解释消除了您的大部分疑问!