有没有一种特殊的方法可以将 3 维数组转换为 2 维数组以进行聚类?
Is there a particular way to convert 3-d array to 2-d array for clustering?
我有一个 shape=(3, 60000, 10) 的 3 维数组,它需要是二维的,以便在聚类时能够将其可视化。
我正计划实现从 scikit-learn 到 3-d 数组的 k-means 聚类,并且读到它只采用 2-D 形状,我只是想得到一些关于是否有正确方法的建议去做吧 ?我本来打算制作它 (60000,30) ,但在我继续之前想要澄清一下。
(600000 , 30)
可能不是一个好主意。 K-means 聚类使用距离度量来定义聚类,通常是欧氏距离,但是当您增加第二个维度中的变量数量时,您会陷入 curse of dimensionality 聚类结果将不再有意义的状态。
您当然可以尝试 (600000, 30) 并查看它是否有效,但如果无效,您将需要进行降维,例如通过执行 PCA 并使用 principal组件进行聚类。
编辑
我可能会尝试解释我所说的维度及其引起的问题,因为这似乎有些混乱。
大小为 (100, 2) 的二维数组是二维数据,即它是 2 个变量的 100 个观测值。这些点之间的趋势线将是一维对象(线),您可以将其绘制在二维平面上。同样,(100, 3) 数组是 3 维的,趋势线是 2d 平面,您可以在 3d 图表上绘制这些点。
则(100, 100)数组是100维的。趋势是一个 99 维的超平面,即使在原则上你也无法想象。现在让我们看看这会导致什么问题。让我们定义一个计算欧氏距离的简单函数:
def distance(x, y):
return sum((i - j)**2 for i, j in zip(x, y))**0.5
该函数将两个可迭代对象作为参数并计算它们之间的欧氏距离。现在让我们尝试一些简单的事情:
v1 = (1, 1)
v2 = (2, 2)
v3 = (100, 100)
v4 = (120, 120)
>> distance(v1, v2)
Out: 1.4142135623730951
>> distance(v1, v3)
Out: 140.0071426749364
>> distance(v1, v4)
Out: 168.2914139223983
如果我们使这些元组成为 3 维的,并在所有维度上保持相同的值,则距离分别变为:1.73、171.47、206.11。
现在是有趣的部分 - 让我们添加一堆用“1”填充的维度:
v1 = [1, 1, 1] + list(1 for i in range(47))
v2 = [2, 2, 2] + list(1 for i in range(47))
v2 = [100, 100, 100] + list(1 for i in range(47))
v4 = [120, 120, 120] + list(1 for i in range(47))
>>> distance(v1, v2)
171.47302994931886
>>> distance(v1, v3)
175.16278143486988
>>> distance(v1, v4)
206.11404610069638
所以在这里我们增加了维度,但没有添加额外的信息来分离变量,突然间看起来像两个不同的集群不再如此定义,事实上 v1、v2 和 v3 看起来更像是它们属于一起,而 v4 是一个局外人.
这在大多数情况下也会发生,除非更高维度继续前三个的模式,即 (1, 1, 1...), (2, 2, 2,..), (100 , 100, 100...), (120, 120, 120,...)。但在大多数情况下,你会看到距离缩小,簇变得难以区分。
我的理解是,您有 10 个特征,每个特征都由 3d 数据组成。您打算将所有 10 个特征聚类吗?如果这样重塑它,使你有 600000 x 3 个点(假设你想在 space 中分开)。例如这个
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt, numpy as np
# 3x points
data = np.random.rand(100, 3, 10) + np.arange(10) # add arbitrary offset for "difference" in real data
data = np.moveaxis(data, -1, 1).reshape(-1, 3)
n_clus = 10 # cluster in 10 --> fill in with your goal in mind
km = KMeans(n_clusters = n_clus).fit(data)
fig, ax = plt.subplots(subplot_kw = dict(projection = '3d'))
colors = plt.cm.tab20(np.linspace(0, 1, n_clus))
ax.scatter(*data.T, c = colors[km.labels_])
fig.show()
产量
我有一个 shape=(3, 60000, 10) 的 3 维数组,它需要是二维的,以便在聚类时能够将其可视化。
我正计划实现从 scikit-learn 到 3-d 数组的 k-means 聚类,并且读到它只采用 2-D 形状,我只是想得到一些关于是否有正确方法的建议去做吧 ?我本来打算制作它 (60000,30) ,但在我继续之前想要澄清一下。
(600000 , 30)
可能不是一个好主意。 K-means 聚类使用距离度量来定义聚类,通常是欧氏距离,但是当您增加第二个维度中的变量数量时,您会陷入 curse of dimensionality 聚类结果将不再有意义的状态。
您当然可以尝试 (600000, 30) 并查看它是否有效,但如果无效,您将需要进行降维,例如通过执行 PCA 并使用 principal组件进行聚类。
编辑 我可能会尝试解释我所说的维度及其引起的问题,因为这似乎有些混乱。
大小为 (100, 2) 的二维数组是二维数据,即它是 2 个变量的 100 个观测值。这些点之间的趋势线将是一维对象(线),您可以将其绘制在二维平面上。同样,(100, 3) 数组是 3 维的,趋势线是 2d 平面,您可以在 3d 图表上绘制这些点。
则(100, 100)数组是100维的。趋势是一个 99 维的超平面,即使在原则上你也无法想象。现在让我们看看这会导致什么问题。让我们定义一个计算欧氏距离的简单函数:
def distance(x, y):
return sum((i - j)**2 for i, j in zip(x, y))**0.5
该函数将两个可迭代对象作为参数并计算它们之间的欧氏距离。现在让我们尝试一些简单的事情:
v1 = (1, 1)
v2 = (2, 2)
v3 = (100, 100)
v4 = (120, 120)
>> distance(v1, v2)
Out: 1.4142135623730951
>> distance(v1, v3)
Out: 140.0071426749364
>> distance(v1, v4)
Out: 168.2914139223983
如果我们使这些元组成为 3 维的,并在所有维度上保持相同的值,则距离分别变为:1.73、171.47、206.11。
现在是有趣的部分 - 让我们添加一堆用“1”填充的维度:
v1 = [1, 1, 1] + list(1 for i in range(47))
v2 = [2, 2, 2] + list(1 for i in range(47))
v2 = [100, 100, 100] + list(1 for i in range(47))
v4 = [120, 120, 120] + list(1 for i in range(47))
>>> distance(v1, v2)
171.47302994931886
>>> distance(v1, v3)
175.16278143486988
>>> distance(v1, v4)
206.11404610069638
所以在这里我们增加了维度,但没有添加额外的信息来分离变量,突然间看起来像两个不同的集群不再如此定义,事实上 v1、v2 和 v3 看起来更像是它们属于一起,而 v4 是一个局外人.
这在大多数情况下也会发生,除非更高维度继续前三个的模式,即 (1, 1, 1...), (2, 2, 2,..), (100 , 100, 100...), (120, 120, 120,...)。但在大多数情况下,你会看到距离缩小,簇变得难以区分。
我的理解是,您有 10 个特征,每个特征都由 3d 数据组成。您打算将所有 10 个特征聚类吗?如果这样重塑它,使你有 600000 x 3 个点(假设你想在 space 中分开)。例如这个
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt, numpy as np
# 3x points
data = np.random.rand(100, 3, 10) + np.arange(10) # add arbitrary offset for "difference" in real data
data = np.moveaxis(data, -1, 1).reshape(-1, 3)
n_clus = 10 # cluster in 10 --> fill in with your goal in mind
km = KMeans(n_clusters = n_clus).fit(data)
fig, ax = plt.subplots(subplot_kw = dict(projection = '3d'))
colors = plt.cm.tab20(np.linspace(0, 1, n_clus))
ax.scatter(*data.T, c = colors[km.labels_])
fig.show()
产量