sklearn OPTICS和预计算余弦矩阵不产生簇

时间:2019-09-10 11:51:43

标签: python scikit-learn dbscan optics-algorithm

我正在尝试使用 sklearn.cluster.OPTICS 对已计算的相似度(距离)矩阵进行聚类,并填充归一化余弦距离(0.0到1.0)

但是但是,无论我给 max_eps eps 做什么,我都不会出现任何集群。

稍后,我将需要在超过129'000 x 129'000项的相似性矩阵上运行OPTICS,希望依靠Dask来保持较低的内存占用。

我正在提取少量单词的快速文本向量(每个向量300个维),并使用dask距离从向量创建相似矩阵。

结果是一个矩阵,如下所示:

import { Component, ChangeDetectorRef } from '@angular/core';

constructor(..,  private cdr: ChangeDetectorRef){}

this.myValueSubscription = this.myService.getValue().subscribe(value => {
    this.myValue = value;
    alert("myValue : " + this.myValue);

    this.cdr.detectChanges(); // <= ADDED
})

例如,我可以使用0.8的阈值进行聚类

function transferArchive() {

//TAB 1
//Target Range - Tab 1, Range 1
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ss = sss.getSheetByName('Front Sheet');
var range = ss.getRange('B4:E');
var data = range.getValues();

//Destination Range - Tab 1, Range 1
var tss = SpreadsheetApp.getActiveSpreadsheet();
var ts = tss.getSheetByName('Printed POs');
ts.getRange(lastRow(ts, 1), 2, data.length, data[0].length).setValues(data);
}

function lastRow(sheet, colNum) {
var v = sheet.getRange(1, colNum, sheet.getLastRow()).getValues(),
    l = v.length,
    r;
while (l > 0) {
    if (v[l] && v[l][0].toString().length > 0) {
        r = (l + 2);
        break;
    } else {
        l--;
    }
}
return r ? r : 1;

}

可打印

sim == [[0.         0.56742118 0.42776633 0.42344265 0.84878847 0.87984235
  0.87468601 0.95224451 0.89341788 0.80922083]
 [0.56742118 0.         0.59779273 0.62900345 0.83004028 0.87549904
  0.887784   0.8591598  0.80752158 0.80960947]
 [0.42776633 0.59779273 0.         0.45120935 0.79292425 0.78556189
  0.82378645 0.93107747 0.83290157 0.85349163]
 [0.42344265 0.62900345 0.45120935 0.         0.81379353 0.83985011
  0.8441614  0.89824009 0.77074847 0.81297649]
 [0.84878847 0.83004028 0.79292425 0.81379353 0.         0.15328565
  0.36656755 0.79393195 0.76615941 0.83415538]
 [0.87984235 0.87549904 0.78556189 0.83985011 0.15328565 0.
  0.36000894 0.7792588  0.77379052 0.83737352]
 [0.87468601 0.887784   0.82378645 0.8441614  0.36656755 0.36000894
  0.         0.82404421 0.86144969 0.87628284]
 [0.95224451 0.8591598  0.93107747 0.89824009 0.79393195 0.7792588
  0.82404421 0.         0.521453   0.5784272 ]
 [0.89341788 0.80752158 0.83290157 0.77074847 0.76615941 0.77379052
  0.86144969 0.521453   0.         0.629014  ]
 [0.80922083 0.80960947 0.85349163 0.81297649 0.83415538 0.83737352
  0.87628284 0.5784272  0.629014   0.        ]]

但是我期望会有几个集群。

我为OPTICS中所有受支持的参数尝试了许多不同的值,但没有能够产生任何可用的甚至比一个集群更多的集群。

我正在使用以下版本:

from dask import array as da
import dask_distance
import logging
import numpy as np
from sklearn.cluster import OPTICS
from collections import defaultdict

log = logging.warning
np.set_printoptions(suppress=True)


if __name__ == "__main__":
    array = np.load("vectors.npy")
    vectors = da.from_array(array)

    sim = dask_distance.cosine(vectors, vectors)

    sim = sim.clip(0.0, 1.0)

    m = np.max(sim)

    c = OPTICS(eps=-1, cluster_method="dbscan", metric="precomputed", algorithm="brute")
    clusters = c.fit(sim)

    words = [
        "icecream",
        "cake",
        "cream",
        "ice",
        "dog",
        "cat",
        "animal",
        "car",
        "truck",
        "bus",
    ]
    cs = defaultdict(list)
    for index, c in enumerate(clusters.labels_):
        cs[c].append(words[index])
    for v in cs.values():
        log(v)
    log(clusters.labels_)

这是使用sklearn DBSCAN的外观

['icecream', 'cake', 'cream', 'ice', 'dog', 'cat', 'animal', 'car', 'truck', 'bus']
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]

收益

python -V
Python 3.7.3

sklearn.__version__
'0.21.3'

dask.__version__
'2.3.0'

numpy.__version__
'1.17.0'

这是非常正确的,但是具有更大的内存占用空间(OPTICS显然只需要计算矩阵的一半)

1 个答案:

答案 0 :(得分:1)

您是否尝试估计129000x129000矩阵需要多少内存-计算和使用该内存需要多长时间?!?我强烈怀疑,在此方面,dask在此方面是否会有所帮助。首先,您需要使用某种索引方法来避免任何O(n²)成本。用k个节点将O(n²)切成k的倍数,只会使您无法扩展到足够的规模。

使用"precomputed"时,您已经计算了完整距离矩阵。现在,无论是OPTICS还是DBSCAN都不会再次对其进行计算(也不是DBSCAN的下半部分),它们只会在这个巨大的巨大矩阵上进行迭代,因为它们无法对此做出任何假设:甚至不是对称的。

您为什么认为eps=-1是正确的? min_samples与OPTICS怎么样?如果您没有选择相同的参数,那么您当然不会获得类似的OPTICS和DBSCAN结果。

OPTICS使用您的参数找到的结果是正确的。在eps=-1上,没有点是邻居,并且在min_samples=5下没有簇,所有点都应标记为-1。