我是编程新手,希望有人可以帮助我解决我遇到的特定问题。
我想在两种情况下在100x100二进制numpy ndarray中形成簇:
借助this页上的答案,我制作了一个具有300个零和700个零的ndarray。
> import numpy as np
> N=1000
> K=300
> arr=[0] * K + [1] * (N-K)
> np.random.shuffle(arr)
> arr1=np.resize(arr,(100,100))
然后,我想实现一个聚类算法,该算法允许我指定某种度量聚类密度或聚类大小的方法。
我查看了scipy.ndimage软件包,但似乎找不到任何有用的东西。
编辑:为了使我的问题更清楚,以前我使用的是软件包nlmpy,该软件包使用numpy制作表示虚拟景观的数组。
它是通过生成一个连续数组,其连续值在[0-1]之间,并在像素子集上使用“ 4-邻域”分类来实现的。像素聚类后,它使用插值函数将其余像素分配给一个聚类。
例如,以60%的像素组成簇:
import nlmpy
nRow=100
nCol=100
arr=nlmpy.randomClusterNN(nRow, nCol, 0.60, n='4-neighbourhood', mask=None)
这将为簇提供[0-1]范围内的值:
然后,我使用nlmpy的内置函数将该输出重新分类为二进制ndarray。 例如,50%的像素需要具有值'1'和50%的值'0'。
arrBinair= nlmpy.classifyArray(arr, [0.50, 0.50])
输出:
这里的问题是,并非精确地有50%的值是“ 1”或“ 0”。
print(arrBinair==1).sum()
output: 3023.0
这是因为nlmpy.randomClusterNN
函数首先创建了不同的集群,然后才对集群进行二进制重新分类。
我的问题是,是否可以以更快的方式生成二进制集群格局,而无需先在连续类中集群并且不使用nlmpy包?
我希望这是足够的信息?还是我需要将功能发布到nlmpy软件包的“幕后”?我很犹豫,因为有很多代码。
非常感谢。
答案 0 :(得分:0)
您可以使用sklearn.cluster.DBSCAN
或多或少地获得想要的东西:
from matplotlib import pyplot as plt
import numpy as np
from sklearn.cluster import DBSCAN
def randones(shape, n, dtype=None):
arr = np.zeros(shape, dtype=dtype)
arr.flat[np.random.choice(arr.size, size=n, replace=False)] = 1
return arr
def cluster(arr, *args, **kwargs):
data = np.array(arr.nonzero()).T
c = DBSCAN(*args, **kwargs)
c.fit(data)
return data, c
# generate random data
shape = (100, 100)
n = 300
arr = randones(shape, n)
# perform clustering
data, c = cluster(arr, eps=6, min_samples=4)
# plot the clusters in different colors
colors = [('C%d' % (i%10)) if i > -1 else 'k' for i in c.labels_]
fig = plt.figure(figsize=(8,8))
ax = fig.gca()
ax.scatter(*data.T, c=colors)
输出:
集群中的最小点数由min_samples
参数定义。您可以通过旋转eps
参数(该参数定义
群集中两点之间的最大距离)。例如,您可以通过增加eps
来识别较大,密度较小的群集:
# perform clustering
data, c = cluster(arr, eps=8, min_samples=4)
如果我们以与以前相同的方式绘制此密度较低的聚类,则得出: