Я получаю разные результаты каждый раз, когда запускаю свой код

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

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;
    } 

person Abeer zaroor    schedule 10.03.2016    source источник
comment
Прочитайте комментарии в исходном коде... Они не просто украшение.   -  person Has QUIT--Anony-Mousse    schedule 10.03.2016


Ответы (3)


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

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

RandomlyGeneratedInitialMeans init = new RandomlyGeneratedInitialMeans(RandomFactory.DEFAULT);

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

person Idos    schedule 10.03.2016
comment
очень приятно... так что я должен заменить его другим init или что-то в этом роде!! _ - person Abeer zaroor; 10.03.2016
comment
Нет, мне нужен стабильный результат (поскольку я хочу сгруппировать набор резюме) - person Abeer zaroor; 10.03.2016
comment
Возможно, вы захотите изучить другие методы кластеризации подпространств. Поиск в Google надежной кластеризации подпространств дает многообещающие результаты. - person Austin D; 10.03.2016
comment
@Abeerzaroor У меня действительно нет большого опыта / знаний об этой библиотеке, но я уверен, что вы можете поискать в Интернете и в документации, чтобы найти то, что вам нужно, если оно существует. - person Idos; 10.03.2016
comment
@AustinD Я погуглил и обнаружил, что elki предоставляет CLIQUE: автоматическую кластеризацию подпространств многомерных данных для приложений интеллектуального анализа данных, поэтому должен ли я использовать это вместо kmean? нет никакого способа сделать его более sable вместо предоставления случайного результата? например изменение типа инициализации!! или это не имеет смысла? - person Abeer zaroor; 10.03.2016
comment
@Idos хорошо, спасибо большое за ответ, я благодарен :))) - person Abeer zaroor; 10.03.2016
comment
Я попытался найти тип инициализации и конструктор, который использует инициализацию для KMeansLloyd<NumberVector>, но не смог найти ничего значимого (я не могу проверить этот код сам, не устанавливая много всего). Извините, я не могу это решить, может быть, открыть другой вопрос, посвященный этой конкретной проблеме, даст результат :) - person Idos; 10.03.2016
comment
вы ответили на мой вопрос (причина, по которой я получил случайный вывод), теперь моя очередь искать другое решение, спасибо большое :))) - person Abeer zaroor; 10.03.2016

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

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

Из кода, который вы копируете и вставляете:

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

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

long seed = 0;
RandomlyGeneratedInitialMeans init = new RandomlyGeneratedInitialMeans(
  new RandomFactory(seed));
person Erich Schubert    schedule 10.03.2016

Это было слишком долго для комментария. Как заявил @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. Результаты должны становиться все более стабильными, чем больше раз вы запускаете алгоритм.

person Austin D    schedule 10.03.2016
comment
Было бы неплохо иметь возможность наблюдать за моими данными, так как у меня есть большой набор данных резюме, я знал, что вывод каждый раз сильно отличается от количества элементов в каждом кластере. - person Abeer zaroor; 10.03.2016
comment
последний вопрос в коде есть // Итерация по объектам// здесь объекты относятся к данным, т.е. вектору для каждого документа\?? - person Abeer zaroor; 10.03.2016
comment
Классы нестабильны и будут меняться местами. Таким образом, в среднем каждый объект будет одинаково часто встречаться в каждом классе. - person Has QUIT--Anony-Mousse; 10.03.2016