我写了代码,
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()
Run Code Online (Sandbox Code Playgroud)
我想除以data使用 KShape 的聚类。现在显示了图,但我找不到每个 3 聚类中的数据。
数据是 A,B,C,D 的顺序。所以我想显示标签来绘制或聚类的结果。我搜索了 KShape 的文档(http://tslearn.readthedocs.io/en/latest/ auto_examples/plot_kshape.html),但我找不到做我理想中的事情的信息。我应该怎么做?
K-Shape 随机工作,如果没有为每次迭代设置种子,您可能会得到不同的集群和质心。如果给定的类完全由给定的质心描述,则没有确定性的方法来知道先验,但是您可以以离线方式以模糊方式进行,通过检查给定类主要归类到哪个质心。
A例如,任何给定的类都可能包含属于您正在考虑的特征空间中的两个集群的元素。
假设您有 3 个类,但您的数据集最好由 4 个集群来描述(例如通过最大平均密度):您肯定会有至少一个类的一些点进入第 4 个集群。
或者,假设您的类不与您正在考虑的距离度量生成的质心重叠:考虑一个明显的例子:您有 3 个类,数字从 0 到 100,从 100 到 1000,从 1000 到 1100,但是您的数据集包含从 0 到 150 和从 950 到 1100 的数字:聚类算法会在 2 个聚类中找到最佳值,并将 A 类的点放在两者之一中。
例如,一旦您确定 classA主要转到 cluster 1, classB到 cluster2等......您可以继续将该集群分配给给定的类。
我们将通过将最适合的类分配给包含其大部分点的集群来继续确定集群类:
对于此示例,我们使用tslearn.datasets. 此代码部分取自tslearn 上的此 K-Shape 示例。
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
Run Code Online (Sandbox Code Playgroud)
我们设置种子,以实现代码可重复性:
seed = 0
np.random.seed(seed)
Run Code Online (Sandbox Code Playgroud)
首先我们准备数据集,选择第一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]
Run Code Online (Sandbox Code Playgroud)
现在我们找到集群,有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)
Run Code Online (Sandbox Code Playgroud)
我们现在继续计算分配给每个集群的每个类的元素,并为没有给定类的元素分配给给定集群的地方添加 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]))]
Run Code Online (Sandbox Code Playgroud)
添加填充:
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]])
Run Code Online (Sandbox Code Playgroud)
对得到的矩阵进行归一化:
normalized_data = padded_data / np.sum(padded_data, axis=-1)[:, np.newaxis]
>>> array([[0., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
Run Code Online (Sandbox Code Playgroud)
我们可以使用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)
Run Code Online (Sandbox Code Playgroud)
获得:
在这种最优情况下,每个集群只包含一个类,所以我们得到绝对精度:
classes_clusters = np.argmax(normalized_data, axis=1)
>>> array([2, 0, 1])
Run Code Online (Sandbox Code Playgroud)
为简单起见,为了模拟不与集群完全重叠的类,我只是将部分标签打乱,但有很多示例:大多数聚类问题最终都与不完全重合的类簇。
tmp = y_train[:20]
np.random.shuffle(tmp)
y_train[:20] = tmp
Run Code Online (Sandbox Code Playgroud)
现在,当我们再次执行脚本时,我们会得到一个完全不同的矩阵:
但是我们仍然能够确定类集群:
classes_clusters = np.argmax(normalized_data, axis=1)
>>> array([2, 0, 1])
Run Code Online (Sandbox Code Playgroud)
假设我们认为数据集中存在 4 个类:我们会在使用不同值运行后发现当前数据集中k的最佳集群数:我们将k=3如何继续将类分配给集群?哪个班级可以扔掉?
我们通过将第四个类任意分配给我们的标签来模拟这种情况:
y_train[:20] = 4
Run Code Online (Sandbox Code Playgroud)
再次运行我们的脚本,我们将获得:
很明显,第四节课已经开始了。我们可以对平均方差进行阈值处理:
threshold = np.mean(np.var(normalized_data, axis=1))
result = np.argmax(normalized_data[np.var(normalized_data, axis=1)>threshold], axis=1)
Run Code Online (Sandbox Code Playgroud)
我们再次获得:
array([2, 0, 1])
Run Code Online (Sandbox Code Playgroud)
我希望这个解释已经解决了你的大部分疑惑!
| 归档时间: |
|
| 查看次数: |
2028 次 |
| 最近记录: |