在 python 中的 sklearn 中绘制 DBSCAN 中的特定点

Posted

技术标签:

【中文标题】在 python 中的 sklearn 中绘制 DBSCAN 中的特定点【英文标题】:Plot specific points in DBSCAN in sklearn in python 【发布时间】:2018-02-26 04:40:03 【问题描述】:

我有一组文档,并从中创建了一个特征矩阵。然后我计算文档之间的余弦相似度。我将该余弦距离矩阵输入到 DBSCAN 算法。我的代码如下。

import pandas as pd
import numpy as np
from sklearn.metrics import pairwise_distances
from scipy.spatial.distance import cosine
from sklearn.cluster import DBSCAN

# Initialize some documents
doc1 = 'Science':0.8, 'History':0.05, 'Politics':0.15, 'Sports':0.1
doc2 = 'News':0.2, 'Art':0.8, 'Politics':0.1, 'Sports':0.1
doc3 = 'Science':0.8, 'History':0.1, 'Politics':0.05, 'News':0.1
doc4 = 'Science':0.1, 'Weather':0.2, 'Art':0.7, 'Sports':0.1
doc5 = 'Science':0.2, 'Weather':0.7, 'Art':0.8, 'Sports':0.9
doc6 = 'Science':0.2, 'Weather':0.8, 'Art':0.8, 'Sports':1.0
collection = [doc1, doc2, doc3, doc4, doc5, doc6]
df = pd.DataFrame(collection)
# Fill missing values with zeros
df.fillna(0, inplace=True)
# Get Feature Vectors
feature_matrix = df.as_matrix()
print(feature_matrix.tolist())

# Get cosine distance between pairs
sims = pairwise_distances(feature_matrix, metric='cosine')

# Fit DBSCAN
db = DBSCAN(min_samples=1, metric='precomputed').fit(sims)

现在,如 sklearn 的 DBSCAN demo 所示,我绘制了集群。也就是说,我插入了sims,而不是X,这是我的余弦距离矩阵。

labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print('Estimated number of clusters: %d' % n_clusters_)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
#print(labels)

# Plot result
import matplotlib.pyplot as plt

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = sims[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)

    xy = sims[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
    我的第一个问题是,将sims 改为X 是否正确,因为X 代表坐标值in the demo of sklearn 而sims 代表余弦距离值? 我的第二个问题是,是否可以将给定的点变成红色?比如我想把feature_matrix中代表[0.8, 0.0, 0.0, 0.0, 0.2, 0.9, 0.7]的点改成红色?

【问题讨论】:

【参考方案1】:

首先是关于术语的评论:

有两种类型的矩阵可以衡量数据集中对象的接近程度:

距离矩阵描述数据集中对象之间的成对距离

相似度矩阵描述数据集中对象之间的成对相似度

一般来说,当两个物体距离很近时,它们的距离很小,但它们的相似度很大。所以距离矩阵和相似度矩阵在某种意义上是相互对立的。例如,对于余弦度量,距离矩阵D 和相似矩阵S 之间的关系可以写成D = 1 - S

由于上述示例中的sims 数组包含成对距离,因此将其称为dists 数组可能更合适。


我的第一个问题是,更改模拟人生而不是 X 是否正确? 因为 X 代表 sklearn 演示中的坐标值,而 sims 代表余弦距离值?

没有。如果您在二维平面上绘制数据,则绘图函数需要一个二维坐标数组作为输入。距离矩阵是不够的。

如果您的数据有两个以上的维度,您可以通过某种降维技术获得它的二维表示。 Sklearn 在sklearn.manifoldsklearn.decomposition 模块中包含许多有用的降维算法。算法的选择通常取决于数据的性质,并且可能需要一些实验。

在 sklearn 中,大多数降维方法都接受特征(或坐标)向量作为输入。有些还接受距离或相似度矩阵(这需要从文档中检查;一个很好的提示是在某处提到了关键字precomputed)。还应注意不要在需要距离矩阵的地方使用相似度矩阵,反之亦然。


我的第二个问题是,是否可以将给定的点变成 红色?例如,我想更改表示 [0.8, 0.0, 0.0, 0.0, 0.2, 0.9, 0.7]的feature_matrix变红了?

问题 2 有点不同,主要涉及matplotlib

我假设人们事先知道哪些点会被涂成红色。下面的代码中有一个名为red_points 的数组,它应该包含红点的索引。因此,例如,如果 doc2doc5 应涂成红色,则将设置为 red_points = [1, 4](索引从零开始)。

对于集群的可视化,降维是通过主成分分析 (PCA) 完成的,这是此类任务最直接的方法之一。请注意,我根本不计算距离矩阵,而是直接在feature_matrix 上应用 DBSCAN 和 PCA。

import pandas as pd
import numpy as np
from sklearn.metrics import pairwise_distances
from scipy.spatial.distance import cosine
from sklearn.cluster import DBSCAN

# Initialize some documents
doc1 = 'Science':0.8, 'History':0.05, 'Politics':0.15, 'Sports':0.1
doc2 = 'News':0.2, 'Art':0.8, 'Politics':0.1, 'Sports':0.1
doc3 = 'Science':0.8, 'History':0.1, 'Politics':0.05, 'News':0.1
doc4 = 'Science':0.1, 'Weather':0.2, 'Art':0.7, 'Sports':0.1
doc5 = 'Science':0.2, 'Weather':0.7, 'Art':0.8, 'Sports':0.9
doc6 = 'Science':0.2, 'Weather':0.8, 'Art':0.8, 'Sports':1.0
collection = [doc1, doc2, doc3, doc4, doc5, doc6]
df = pd.DataFrame(collection)
# Fill missing values with zeros
df.fillna(0, inplace=True)
# Get Feature Vectors
feature_matrix = df.as_matrix()

# Fit DBSCAN
db = DBSCAN(min_samples=1).fit(feature_matrix)

labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print('Estimated number of clusters: %d' % n_clusters_)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True

# Plot result
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

#  Perform dimensional reduction of the feature matrix with PCA
X = PCA(n_components=2).fit_transform(feature_matrix) 

# Select which points will be painted red
red_points = [1, 4]
for i in red_points:
    labels[i] = -2

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]

for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = [0, 0, 0, 1]
    if k == -2:
        # Red for selected points
        col = [1, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)

    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

左图为red_points为空的情况,右图为red_points = [1, 4]

【讨论】:

非常感谢您的出色回答。干得漂亮!之前,我将您的答案标记为正确,我有一个非常小的问题。有没有办法验证绘制的图形是否正确?我正在尝试输入不同类型的数据以查看 PCA 是否能够准确绘制我的图表。但我做不到。有什么建议吗? 你能告诉我为什么你在这个for i in red_points: labels[i] = -2中提到了-2。它到底发生了什么? DBSCAN 根据聚类为点分配数字标签。属于某个集群的“普通”点标有非负数(集群 ID)。异常值(不属于任何集群的点)用 -1 标记。由于每个标签都有自己的颜色,我为那些应该涂成红色的点添加了一个额外的标签 -2。 (但这会覆盖 DBSCAN 结果)。 关于您之前的问题,我认为很难定义什么是正确的图表。当一个人执行降维时,总是会丢失一些信息。结果图并不总是“看起来不错”(这在很大程度上取决于数据和降维算法)。

以上是关于在 python 中的 sklearn 中绘制 DBSCAN 中的特定点的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python 中的 SVM sklearn 数据中绘制决策边界?

在 python 中绘制 sklearn 集群

python:如何在sklearn中使用逻辑回归系数构建决策边界

如何在 python 中的 sklearn 中获取 GridSearchCV 中的选定功能

python基于sklearn编程实现交叉验证的ROC曲线绘制自定义AUC的有效小数位数(sklearn中RocCurveDisplay函数的默认有效位数为2位且不可以修改)

如何在sklearn的python代码中使用SwarmPackagePy进行回归?