|
|
|
|
# https://github.com/GISerWang/Spatio-temporal-Clustering.git
|
|
|
|
|
import os
|
|
|
|
|
import numpy as np
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
|
from scipy.spatial.distance import pdist
|
|
|
|
|
from scipy.spatial.distance import squareform
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def DBSCAN(data_, eps, minPts):
|
|
|
|
|
# 获得距离矩阵
|
|
|
|
|
disMat = squareform(pdist(data_, metric='euclidean'))
|
|
|
|
|
# 获得数据的行和列(一共有n条数据)
|
|
|
|
|
n, m = data_.shape
|
|
|
|
|
# 将矩阵的中小于eps的数赋予1, 大于eps的数置0, 按行求和, 求核心点坐标的索引
|
|
|
|
|
core_points_index = np.where(np.sum(np.where(disMat <= eps, 1, 0), axis=1) >= minPts)[0]
|
|
|
|
|
# 初始化类别,-1代表未分类。
|
|
|
|
|
labels = np.full((n,), -1)
|
|
|
|
|
clusterId = 0
|
|
|
|
|
# 遍历所有的核心点
|
|
|
|
|
for pointId in core_points_index:
|
|
|
|
|
# 如果核心点未被分类,将其作为的种子点,开始寻找相应簇集
|
|
|
|
|
if labels[pointId] == -1:
|
|
|
|
|
# 首先将点pointId标记为当前类别(即标识为已操作)
|
|
|
|
|
labels[pointId] = clusterId
|
|
|
|
|
# 然后寻找种子点的eps邻域且没有被分类的点,将其放入种子集合
|
|
|
|
|
neighbour = np.where((disMat[:, pointId] <= eps) & (labels == -1))[0]
|
|
|
|
|
seeds = set(neighbour)
|
|
|
|
|
# 通过种子点,开始生长,寻找密度可达的数据点,一直到种子集合为空,一个簇集寻找完毕
|
|
|
|
|
while len(seeds) > 0:
|
|
|
|
|
# 弹出一个新种子点
|
|
|
|
|
newPoint = seeds.pop()
|
|
|
|
|
# 将newPoint标记为当前类
|
|
|
|
|
labels[newPoint] = clusterId
|
|
|
|
|
# 寻找newPoint种子点eps邻域(包含自己)
|
|
|
|
|
queryResults = np.where(disMat[:, newPoint] <= eps)[0]
|
|
|
|
|
# 如果newPoint属于核心点,那么newPoint是可以扩展的,即密度是可以通过newPoint继续密度可达的
|
|
|
|
|
if len(queryResults) >= minPts:
|
|
|
|
|
# 将邻域内且没有被分类的点压入种子集合
|
|
|
|
|
for resultPoint in queryResults:
|
|
|
|
|
if labels[resultPoint] == -1:
|
|
|
|
|
seeds.add(resultPoint)
|
|
|
|
|
# 簇集生长完毕,寻找到一个类别
|
|
|
|
|
clusterId = clusterId + 1
|
|
|
|
|
return labels
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def plotFeature(md_keys_, data_, labels_, output_path_):
|
|
|
|
|
clusterNum = len(set(labels_))
|
|
|
|
|
fig = plt.figure()
|
|
|
|
|
scatterColors = ['black', 'blue', 'green', 'yellow', 'red', 'purple', 'orange', 'brown']
|
|
|
|
|
ax = fig.add_subplot(111, projection='3d')
|
|
|
|
|
for i in range(-1, clusterNum):
|
|
|
|
|
colorStyle = scatterColors[i % len(scatterColors)]
|
|
|
|
|
subCluster = data_[np.where(labels_ == i)]
|
|
|
|
|
ax.scatter(subCluster[:, 0], subCluster[:, 1], subCluster[:, 2], c=colorStyle, s=12)
|
|
|
|
|
ax.set_xlabel(md_keys_[0], rotation=0) # 设置标签角度
|
|
|
|
|
ax.set_ylabel(md_keys_[1], rotation=-45)
|
|
|
|
|
ax.set_zlabel(md_keys_[2], rotation=0)
|
|
|
|
|
plt.title(output_path_.split('\\')[-1].split('.')[0])
|
|
|
|
|
plt.savefig(output_path_, dpi=500)
|
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
outcome_path = r'E:\Data\Research\Outcome'
|
|
|
|
|
config_dir = r'\Magellan+Smac+roberta-large-nli-stsb-mean-tokens+inter-0.5'
|
|
|
|
|
dataset_name_list = [f.name for f in os.scandir(outcome_path) if f.is_dir()]
|
|
|
|
|
for dataset_name in dataset_name_list:
|
|
|
|
|
absolute_path = outcome_path + rf'\{dataset_name}' + config_dir + r'\mds.txt'
|
|
|
|
|
md_keys = []
|
|
|
|
|
with open(absolute_path, 'r') as f:
|
|
|
|
|
# 读取每一行的md,加入该文件的md列表
|
|
|
|
|
data = []
|
|
|
|
|
for line in f.readlines():
|
|
|
|
|
md_metadata = line.strip().split('\t')
|
|
|
|
|
md_tuple = eval(md_metadata[1])
|
|
|
|
|
md_keys = list(md_tuple[0].keys())[1:4]
|
|
|
|
|
md_values = list(md_tuple[0].values())
|
|
|
|
|
data.append(md_values[1:4])
|
|
|
|
|
if len(data) == 10000:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
data = np.array(data, dtype=np.float32)
|
|
|
|
|
labels = DBSCAN(data, 0.5, 30)
|
|
|
|
|
output_path = outcome_path + rf'\{dataset_name}.png'
|
|
|
|
|
plotFeature(md_keys, data, labels, output_path)
|