使用KMeans聚类算法查找部分成员资格

时间:2016-12-20 17:34:20

标签: c# f# hierarchical-clustering accord.net

我可以非常轻松地使用KMeans计算群集成员资格:

open System
open System.IO
open Utils
open Accord
open Accord.Math 
open Accord.MachineLearning

let vals = [|
    [|1.0; 2.0; 3.0; 2.0|]
    [|1.1; 1.9; 3.1; 4.0|]
    [|2.0; 3.0; 4.0; 4.0|]    
    [|3.0; 3.1; 2.0; 3.0|]
    [|2.0; 4.0; 3.0; 6.0|]
    [|1.0; 5.0; 5.0; 7.0|]
    [|4.0; 3.0; 6.0; 8.0|]
    [|5.0; 4.0; 3.0; 6.0|]
    [|6.0; 4.0; 8.0; 7.0|]
    [|5.0; 6.0; 5.0; 9.0|]
    [|4.0; 2.0; 7.0; 8.0|]
    [|8.0; 9.0; 3.1; 2.2|]
    [|8.0; 9.0; 2.0; 2.0|]
    [|10.0; 2.0; 3.0; 2.0|]
    [|10.1; 1.9; 3.1; 4.0|]
    [|20.0; 3.0; 4.0; 4.0|]
    [|22.0; 7.0; 2.0; 3.0|]
    [|21.0; 4.0; 3.0; 6.0|]
|]

let kmeans = new KMeans 5
let clusterModel = kmeans.Learn vals
let clusters = clusterModel.Decide vals

我可以使用标准KMeans算法计算部分成员资格吗?同事建议使用集群成员的均值和方差来确定比例成员资格,今天我一直在研究模糊集及其F#的实现。例如,here is some documentation for the Accord.net implementation for fuzzy sets.我可以翻译/运行F#的示例,但乍看之下,我看不到从上面的Kmeans运行中获取数据的简便方法适合分配部分成员资格的格式。

问题:

  1. 我如何使用群集成员的均值/方差来计算部分成员资格?

  2. 使用Accord.net库进行KMeans聚类是否可以轻松计算部分成员资格?

  3. Accord.net中的KMeans算法易于实现;我应该花些时间尝试学习这种聚类/成员资格的方法来解决我的问题,而不是试图强迫Kmeans聚类以满足我的需求吗?

2 个答案:

答案 0 :(得分:3)

你应该能够使用Accord.NET获得" centroids" K-means算法找到的簇的数量。这些基本上是各个集群的中心。然后,您应该能够计算新数据点与每个质心之间的距离,以查看哪个质心接近您的点。 (Decide方法只返回第一个。)

我没有试过这个,但似乎KMeans公开了Clusters,这是KMeansClusterCollection并且具有Centroids属性(请参阅the docs) 。它还公开Distance属性,该属性返回用于计算数据点之间距离的函数。

使用这些,您应该能够比较数据点与所有聚类的质心的距离,并确定该点与各个聚类的接近程度。

从头开始实现k-means并不是那么难(这里有nice post from Mathias Brandewinder),但似乎Accord.NET在这种特殊情况下暴露了你需要的所有信息 - 所以也许&#39 ;所有你需要的(在自定义实现中获得所有细节总是最困难的部分......)。

答案 1 :(得分:3)

正如Tomas所说,Accord.NET已经为您提供了许多构建模块。特别是,调用clusterModel.Scores会为您提供到群集质心的(负)距离,see source code

从负距离,您可以通过取指数计算近似的类成员分数,类似于计算高斯PDF的方法。在F#中,这看起来像:

// Scores returns the negative distances between each point
// and the cluster centroid
let negDistances = clusterModel.Scores vals
// Compute an estimated cluster assigment score
let clusterMembership =
    negDistances
    |> Array.map (fun distances ->
        // Take the Exponential of the (negative) distances,
        // as in computing a Gaussian pdf
        let expDist = distances |> Array.map Math.Exp
        let total = Array.sum expDist
        expDist
        |> Array.map (fun d -> d/total)
    )

这里有几点需要注意:

  • Accord中的标准KMeans使用欧几里德距离,这意味着每个方向都具有相同的权重。根据您的数据的性质,这可能不会产生合理的结果(图片2簇,每个形状像长雪茄)
  • 上述类成员资格计算也未将集群协方差考虑在内。为了更接近真理,你必须计算Bhattacharyya距离,取幂,然后通过协方差矩阵的逆det进行缩放。单例群集将失败。

关于你的第三个问题:我不会重新实施。最初看起来似乎很容易,但通常会有很多极端情况和稳定性问题,这些问题只会在一段时间后发生。