多维尺度分析(MDS)和非度量多维尺度分析(NMDS)是数据科学中常用的技术,用于在低维空间中表示高维数据。这些方法可以帮助理解数据的内在结构,并通过可视化手段揭示数据点之间的关系。在本文中,将通过Python代码示例来探讨这两种方法的应用。
多维尺度分析是一种用于数据降维的技术,它试图在低维空间中保持数据点之间的相对距离。这种方法特别适用于那些数据点之间的距离可以量化的情况。在Python中,可以使用scikit-learn
库中的manifold.MDS
类来实现MDS。
首先,需要导入必要的库,并生成一些模拟数据。然后,计算数据点之间的欧几里得距离,并将这些距离作为MDS算法的输入。在本例中,添加了一些随机噪声到距离矩阵中,以模拟真实世界数据的不确定性。
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
from sklearn import manifold
from sklearn.decomposition import PCA
from sklearn.metrics import euclidean_distances
# 设置随机数种子以确保结果的可重复性
np.random.seed(3)
# 生成模拟数据
n_samples = 20
X_true = np.random.randint(0, 20, 2 * n_samples).astype(float)
X_true = X_true.reshape((n_samples, 2))
# 计算数据点之间的欧几里得距离
similarities = euclidean_distances(X_true)
# 添加随机噪声到距离矩阵中
noise = np.random.rand(n_samples, n_samples)
noise = noise + noise.T
np.fill_diagonal(noise, 0)
similarities += noise
接下来,使用MDS算法来找到数据点在二维空间中的新位置。设置算法的最大迭代次数为3000,并使用预定义的距离矩阵作为输入。
mds = manifold.MDS(n_components=2, max_iter=3000, eps=1e-9, random_state=np.random.RandomState(seed=3), dissimilarity="precomputed")
pos = mds.fit(similarities).embedding_
为了使结果更容易理解,对数据进行了归一化和旋转处理。这有助于更直观地比较MDS和NMDS的结果。
非度量多维尺度分析是一种更为灵活的方法,它不要求数据点之间的距离是可量化的。这种方法适用于那些距离度量不明确或不适用的情况。在Python中,同样可以使用scikit-learn
库中的manifold.MDS
类来实现NMDS,只需将metric
参数设置为False
即可。
在本例中,使用与MDS相同的数据和距离矩阵,但将metric
参数设置为False
。这允许算法在不考虑距离度量的情况下寻找数据点在低维空间中的新位置。
nmds = manifold.MDS(n_components=2, metric=False, max_iter=3000, eps=1e-12, dissimilarity="precomputed", random_state=np.random.RandomState(seed=3), n_init=1)
npos = nmds.fit_transform(similarities, init=pos)
与MDS类似,对NMDS的结果进行了归一化和旋转处理,以便于比较。
为了直观地展示MDS和NMDS的结果,使用matplotlib
库来绘制数据点在二维空间中的位置。使用不同的颜色来区分真实位置、MDS结果和NMDS结果,并添加了图例以便于识别。
此外,还绘制了数据点之间的连线,以展示它们之间的相似性。连线的粗细和颜色表示相似性的强度,这有助于理解数据点之间的关系。
plt.figure(1)
ax = plt.axes([0.0, 0.0, 1.0, 1.0])
s = 100
plt.scatter(X_true[:, 0], X_true[:, 1], color="navy", s=s, lw=0, label="真实位置")
plt.scatter(pos[:, 0], pos[:, 1], color="turquoise", s=s, lw=0, label="MDS")
plt.scatter(npos[:, 0], npos[:, 1], color="darkorange", s=s, lw=0, label="NMDS")
plt.legend(scatterpoints=1, loc="best", shadow=False)
# 绘制数据点之间的连线
segments = [[X_true[i, :], X_true[j, :]] for i in range(len(pos)) for j in range(len(pos))]
values = np.abs(similarities)
lc = LineCollection(segments, zorder=0, cmap=plt.cm.Blues, norm=plt.Normalize(0, values.max()))
lc.set_array(similarities.flatten())
lc.set_linewidths(np.full(len(segments), 0.5))
ax.add_collection(lc)
plt.show()
通过上述代码,可以清楚地看到MDS和NMDS在数据可视化方面的差异。MDS方法在保持数据点之间距离的同时,可能会产生一些重叠;而NMDS方法则允许数据点之间的距离发生更大的变化,以避免重叠。这两种方法各有优缺点,适用于不同的应用场景。