Найдите частичное членство с помощью алгоритма кластеризации KMeans

Я могу довольно легко вычислить членство в кластере с помощью 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#. Например, вот некоторая документация по реализации Accord.net для нечетких множеств. Я могу перевести/выполнить пример для F#, но на первый взгляд я не вижу простого способа получить данные из моего запуска Kmeans выше, чтобы они соответствовали формату назначения частичного членства.

Вопросы:

  1. Как бы я использовал среднее/дисперсию членов кластера для расчета частичного членства?

  2. Есть ли простой способ рассчитать частичное членство с KMeans кластеризацией с библиотекой Accord.net?

  3. Алгоритм KMeans в Accord.net прост в реализации; должен ли я потратить некоторое время, пытаясь изучить этот метод кластеризации/членства для решения моей проблемы, вместо того, чтобы пытаться заставить Kmeans кластеризоваться в соответствии с моими потребностями?


person Steven    schedule 20.12.2016    source источник


Ответы (2)


Как упомянул Томас, Accord.NET уже дает вам множество строительных блоков. В частности, вызов clusterModel.Scores дает вам (отрицательные) расстояния до центроидов кластера: 603.cs#L453" rel="nofollow noreferrer">см. исходный код

Из отрицательных расстояний вы можете вычислить приблизительную оценку членства в классе, взяв экспоненты, подобно тому, как вы бы сделали, чтобы вычислить гауссовский 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)
    )

Здесь есть пара предостережений:

  • Стандарт KMeans в Accord использует евклидовы расстояния, что означает, что каждое направление имеет одинаковый вес. В зависимости от характера ваших данных это может не привести к разумным результатам (нарисуйте 2 кластера, каждый из которых имеет форму длинной сигары).
  • Приведенный выше расчет принадлежности к классу также не принимает во внимание кластерную ковариацию. Чтобы быть ближе к истине, вам нужно было бы вычислить расстояние Бхаттачарьи, возвести его в степень, а затем масштабировать с помощью обратной det ковариационной матрицы. Это не удастся для одноэлементных кластеров.

Что касается вашего третьего вопроса: я бы не стал повторно реализовывать. Поначалу это может показаться простым, но обычно возникает множество краеугольных случаев и проблем со стабильностью, с которыми вы сталкиваетесь только через некоторое время.

person Anton Schwaighofer    schedule 29.12.2016

Вы должны иметь возможность использовать Accord.NET для получения "центроидов" кластеров, которые находит алгоритм K-средних. По сути, это центры отдельных кластеров. Затем вы сможете рассчитать расстояние между вашей новой точкой данных и каждым из центроидов, чтобы увидеть, какие из центроидов близки к вашей точке. (Метод Decide возвращает только первый.)

Я не пробовал, но кажется, что KMeans выставляет Clusters, который является KMeansClusterCollection и имеет свойство Centroids (см. документы). Он также предоставляет свойство Distance, которое возвращает функцию для расчета расстояния между точками данных.

Используя их, вы сможете сравнить расстояние вашей точки данных с центроидами всех кластеров и решить, насколько близка точка к отдельным кластерам.

Внедрить метод k-средних с нуля не так сложно (есть хороший пост от Матиаса Брандевиндера по этому поводу), но кажется, что Accord.NET предоставляет всю информацию, которая вам нужна в данном конкретном случае - так что, возможно, это все, что вам нужно (правильное получение всех деталей в пользовательской реализации - это всегда самое сложное...).

person Tomas Petricek    schedule 24.12.2016