2016-12-13 27 views
4

Я выполняю кластерную работу с Accord.net library. В конечном счете, я пытаюсь найти оптимальное количество кластеров для использования с the elbow method, что требует некоторых относительно простых вычислений. Тем не менее, мне трудно получить нужные мне значения, чтобы определить наилучшее количество K, которое будет использоваться в моем KMeans моделировании.Получите расстояние от точки передачи данных до ее центра тяжести с помощью Accord.net

У меня есть пример данных/код:

open Accord 
open Accord.Math 
open Accord.MachineLearning 
open Accord.Statistics 
open Accord.Statistics.Analysis 

let x = [| 
    [|4.0; 1.0; 1.0; 2.0|]; 
    [|2.0; 4.0; 1.0; 2.0|]; 
    [|2.0; 3.0; 1.0; 1.0|]; 
    [|3.0; 6.0; 2.0; 1.0|]; 
    [|4.0; 4.0; 1.0; 1.0|]; 
    [|5.0; 10.0; 1.0; 2.0|]; 
    [|7.0; 8.0; 1.0; 2.0|]; 
    [|6.0; 5.0; 1.0; 1.0|]; 
    [|7.0; 7.0; 2.0; 1.0|]; 
    [|5.0; 8.0; 1.0; 1.0|]; 
    [|4.0; 1.0; 1.0; 2.0|]; 
    [|3.0; 5.0; 0.0; 3.0|]; 
    [|1.0; 2.0; 0.0; 0.0|]; 
    [|4.0; 7.0; 1.0; 2.0|]; 
    [|5.0; 3.0; 2.0; 0.0|]; 
    [|4.0; 11.0; 0.0; 3.0|]; 
    [|8.0; 7.0; 2.0; 1.0|]; 
    [|5.0; 6.0; 0.0; 2.0|]; 
    [|8.0; 6.0; 3.0; 0.0|]; 
    [|4.0; 9.0; 0.0; 2.0|] 
    |] 

и я могу генерировать кластеры легко достаточно с

let kmeans = new KMeans 5 

let kmeansMod = kmeans.Learn x 
let clusters = kmeansMod.Decide x 

, но как я могу вычислить расстояние от любой заданной точки x данных, это назначенный кластер? Я ничего не вижу в KMeans Cluster Collection class documentation, что предполагает, что уже существует метод, реализованный для этой проблемы.

Кажется, должно быть относительно простым рассчитать это расстояние, но я в недоумении. Будет ли это быть так же просто, как сделать что-то вроде

let dataAndClusters = Array.zip clusters x 

let getCentroid (m: KMeansClusterCollection) (i: int) = 
    m.Centroids.[i] 

dataAndClusters 
|> Array.map (fun (c, d) -> (c, (getCentroid kmeansMod c) 
           |> Array.map2 (-) d 
           |> Array.sum)) 

который возвращает

val it : (int * float) [] = 
    [|(1, 0.8); (0, -1.5); (1, -0.2); (0, 1.5); (0, -0.5); (4, 0.0); (2, 1.4); 
    (2, -3.6); (2, 0.4); (3, 0.75); (1, 0.8); (0, 0.5); (1, -4.2); (3, -0.25); 
    (1, 2.8); (4, 0.0); (2, 1.4); (3, -1.25); (2, 0.4); (3, 0.75)|] 

ли я вычисляя расстояние правильно? Я подозреваю, что нет.

Как я уже говорил, я ищу, чтобы определить правильное количество K для использования в KMeans кластеризации. Я просто подумал, что воспользуюсь простым алгоритмом, изложенным в the second paragraph of this Stats.StackExchange.com answer. Обратите внимание, что я не против использования «Статистики промахов», связанной с нижней частью верхнего ответа.

+0

Вы должны иметь возможность вычислить расстояние до ближайшего кластера, используя метод Scores() вместо Decide(). – Cesar

ответ

0

Оказывается, что я не был правильно рассчитывал расстояния, но я был близок.

Проделав еще какое-то копание, я увидел this similar question, but for the R language и сломал процесс, описанный в этом принятом ответе на моей собственной сессии R.

шаги кажутся довольно просто:

1. From each data value, subtract the centroid values 
2. Sum the differences for a given data/centroid pair 
3. Square the differences 
4. Find the square root of the differences. 

Для моего примера данных выше, это нарушило бы к этому:

let distances = 
    dataAndClusters 
    |> Array.map (fun (c, d) -> (c, ((getCentroid kmeansMod c) 
            |> Array.map2 (-) d 
            |> Array.sum 
            |> float) ** 2.0 
            |> sqrt)) 

Обратите внимание на добавление двух линий,

|> float) ** 2.0 преобразует значение в поплавок, чтобы он мог быть квадратным (то есть x**y)

и

|> sqrt), который находит квадратный корень из значения.

Для этого может быть встроенный метод, но я еще не нашел его. Пока это работает для меня.