2016-03-10 3 views
0

Я использую ELKI для кластеризации своих данных. Я использовал KMeansLloyd<NumberVector>with k=3 каждый раз, когда запускаю свой код Java. Я получаю совершенно разные результаты кластеров, это нормально или есть что я должен сделать, чтобы сделать мой результат почти стабильным? вот мой код, который я получил от Елки учебниковЯ получаю разные результаты каждый раз, когда запускаю свой код

DatabaseConnection dbc = new ArrayAdapterDatabaseConnection(a); 
    // Create a database (which may contain multiple relations!) 
    Database db = new StaticArrayDatabase(dbc, null); 
    // Load the data into the database (do NOT forget to initialize...) 
    db.initialize(); 
    // Relation containing the number vectors: 
    Relation<NumberVector> rel = db.getRelation(TypeUtil.NUMBER_VECTOR_FIELD); 
    // We know that the ids must be a continuous range: 
    DBIDRange ids = (DBIDRange) rel.getDBIDs(); 

    // K-means should be used with squared Euclidean (least squares): 
    //SquaredEuclideanDistanceFunction dist = SquaredEuclideanDistanceFunction.STATIC; 
    CosineDistanceFunction dist= CosineDistanceFunction.STATIC; 

    // Default initialization, using global random: 
    // To fix the random seed, use: new RandomFactory(seed); 
    RandomlyGeneratedInitialMeans init = new RandomlyGeneratedInitialMeans(RandomFactory.DEFAULT); 

    // Textbook k-means clustering: 
    KMeansLloyd<NumberVector> km = new KMeansLloyd<>(dist, // 
    3 /* k - number of partitions */, // 
    0 /* maximum number of iterations: no limit */, init); 

    // K-means will automatically choose a numerical relation from the data set: 
    // But we could make it explicit (if there were more than one numeric 
    // relation!): km.run(db, rel); 
    Clustering<KMeansModel> c = km.run(db); 

    // Output all clusters: 
    int i = 0; 
    for(Cluster<KMeansModel> clu : c.getAllClusters()) { 
     // K-means will name all clusters "Cluster" in lack of noise support: 
     System.out.println("#" + i + ": " + clu.getNameAutomatic()); 
     System.out.println("Size: " + clu.size()); 
     System.out.println("Center: " + clu.getModel().getPrototype().toString()); 
     // Iterate over objects: 
     System.out.print("Objects: "); 

     for(DBIDIter it = clu.getIDs().iter(); it.valid(); it.advance()) { 
     // To get the vector use: 
     NumberVector v = rel.get(it); 

     // Offset within our DBID range: "line number" 
     final int offset = ids.getOffset(it); 
     System.out.print(v+" " + offset); 
     // Do NOT rely on using "internalGetIndex()" directly! 
     } 
     System.out.println(); 
     ++i; 
    } 
+0

** Прочитайте комментарии в исходном коде ** ... Они это не просто украшение. –

ответ

5

Я хотел бы сказать, так как вы используете RandomlyGeneratedInitialMeans:

Инициализировать K-средства, генерируя случайных векторов (в пределах диапазона наборов данных значений) ,

RandomlyGeneratedInitialMeans init = new RandomlyGeneratedInitialMeans(RandomFactory.DEFAULT); 

Да, это нормально.

+0

очень приятно ... так что я должен заменить его на другой init или что-то !! * _ * –

+0

Вы не хотите, чтобы это было случайным ??? – Idos

+0

Нет Я хочу стабильный результат (так как я хочу сгруппировать набор резюме) –

0

Это слишком долго для комментария. Как заявил @Idos, вы произвольно инициализируете свои данные; поэтому вы получаете случайные результаты. Теперь вопрос в том, как вы гарантируете, что результаты надежны? Попробуйте следующее:

Запустить алгоритм N раз. Каждый раз записывайте членство в кластере для каждого наблюдения. Когда вы закончите, классифицируйте наблюдение в кластере, который содержал его чаще всего. Например, предположим, что у вас есть 3 наблюдения, 3-х классов, а также запустить алгоритма 3 раза:

obs R1 R2 R3 
1 A A B 
2 B B B 
3 C B B 

Затем следует классифицировать obs1, как A, так как это наиболее часто классифицируется как A. Классифицируйте obs2 как B, так как он всегда классифицировался как B. И классифицируйте obs3 как B, поскольку он был наиболее часто классифицирован по алгоритму B. Результаты должны становиться все более стабильными, чем больше вы запускаете алгоритм.

+0

его было бы здорово наблюдать за моими данными, так как у меня есть большой набор данных о возобновлении, я знал, что выход очень разный каждый раз от количества элементов в каждом кластере –

+0

Возможно, вам повезло на «CrossValidated "- http://stats.stackexchange.com/ –

+0

ok Я попробую там :))))) thanx @Austin –

2

K-Means is Предполагается, что будет инициализирован случайным образом. Это желательно, чтобы получить разные результаты при запуске его несколько раз.

Если вы не хотите этого, используйте фиксированное случайное семя.

Из кода вы скопировать и вставить:

// To fix the random seed, use: new RandomFactory(seed); 

То есть именно то, что вы должны сделать ...

long seed = 0; 
RandomlyGeneratedInitialMeans init = new RandomlyGeneratedInitialMeans(
    new RandomFactory(seed)); 
Смежные вопросы