Реализация функции расстояния для многомерных и многотипных данных

Я использую ELKI в java для кластеризации текста твита в алгоритме kmeans. Перед кластеризацией я рассчитал сходство текста твита с мерой tf-idf, которую он использовал для кластеризации.

 public void clustering(String file) throws FileNotFoundException {
    //Distance.calSim("after sorting.txt");
    similarity = MainElki.getSimilarity();
    PrintWriter writer = new PrintWriter(new File(file));
    StringBuilder strBuilder = new StringBuilder();

    for (int k = 0; k < numCorpus; k = k + 20) {
        double[][] subArray = new double[20][20];
        subArray = getSubArray(k, k);

        DatabaseConnection dbc = new ArrayAdapterDatabaseConnection(subArray);
        Database db = new StaticArrayDatabase(dbc, null);
        db.initialize();
        SquaredEuclideanDistanceFunction dist = SquaredEuclideanDistanceFunction.STATIC;
        RandomlyGeneratedInitialMeans init = new RandomlyGeneratedInitialMeans(RandomFactory.DEFAULT);

        KMeansLloyd<NumberVector> km = new KMeansLloyd<>(dist, 3, 0, init);
        Clustering<KMeansModel> c = km.run(db);

        Relation<NumberVector> rel = db.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
        DBIDRange ids = (DBIDRange) rel.getDBIDs();
        strBuilder.append("\n******** subArray[" + k + "]" + "[" + k + "]");
        int i = 2;
        for (Cluster<KMeansModel> clu : c.getAllClusters()) {
            // K-means will name all clusters "Cluster" in lack of noise support:
            strBuilder.append("\n    #" + i + ": " + clu.getNameAutomatic() + "\n");
            strBuilder.append("    Size: " + clu.size() + "\n");
            strBuilder.append("    Center: " + clu.getModel().getPrototype().toString() + "\n");

            strBuilder.append("  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);
                strBuilder.append(" " + (offset + k));
                // Do NOT rely on using "internalGetIndex()" directly!
            }
            i++;
        }
    }//end of for subArray
    writer.write(strBuilder.toString());
    writer.close();
}//end of clustering function

Теперь я хотел бы использовать другую функцию твитов в кластеризации (например, хэштеги, количество лайков, количество ретвитов, …). Я знаю, что могу определить пользовательскую функцию расстояния в ELKI, но весь абстрактный класс функции расстояния ELKI находится в одном типе данных (например, AbstractNumberVectorDistanceFunction), но функция твитов отличается: double для istance текста твита, int для количества лайков и ретвитов, Строка для хэштегов.

 public class CustomizedDistance extends AbstractNumberVectorDistanceFunction    {
 @Override
public double distance(NumberVector arg0, NumberVector arg1) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

}

Есть ли способ написать настраиваемую функцию расстояния, которая вычисляет расстояние до текста твита, а затем вычисляет окончательное расстояние, используя другие функции, такие как количество лайков?


person NASRIN    schedule 03.10.2017    source источник


Ответы (2)


KMeans, как следует из названия, должен вычислять среднее значение.

Этот алгоритм можно использовать только для векторов в R^d.

Так что в любом случае, если вы действительно хотите это сделать (kmeans плохо работает с атрибутами разного масштаба!), вам придется преобразовать все ваши атрибуты в числа. . Или используйте другой алгоритм.

person Has QUIT--Anony-Mousse    schedule 03.10.2017
comment
У вас есть пример, с которым я могу работать в elki, поддерживающих атрибуты нескольких типов? - person NASRIN; 04.10.2017
comment
Нет, я использую только числовые данные. Я попытался рассмотреть статистические причины многотипных данных, и они оказались очень слабыми. Так что, кажется, нет надежного способа справиться с этим, только черная магия с результатами не лучше случайных. - person Has QUIT--Anony-Mousse; 04.10.2017
comment
из-за моего исследования мне нужно проверить, может ли использование других функций улучшить результат или нет. Кажется, что использование всех функций твитов может помочь группировать твиты. - person NASRIN; 04.10.2017
comment
Может быть. Я не думаю, что вы можете сгруппировать твиты каким-либо полезным способом. Но если вы хотите использовать метод k-средних, вы должны выполнить требование R^d. Не ждите, что я заставлю k-средние волшебным образом работать с символами, когда вам нужны реальные числа для вычисления средних... - person Has QUIT--Anony-Mousse; 04.10.2017
comment
Нет, мне не нужно использовать kmeans. Я хочу начать с библиотеки, которая имеет лучший алгоритм для кластеризации или определения темы в моем наборе данных. - person NASRIN; 05.10.2017
comment
Рекомендации библиотеки не по теме. - person Has QUIT--Anony-Mousse; 05.10.2017

Метод K-средних может работать только с NumberVectors, и нет способа обойти это.

Для многих других алгоритмов это возможно. Вам нужно будет:

  1. Реализовать новый тип данных YourDataType с несколькими типами данных.
  2. Реализовать парсер для загрузки данных
  3. Реализовать DistanceFunction<YourDataType>

Но, как отмечено в ответе Anony-Mousse, k-means может поддерживать только NumberVector. Он не примет YourDataType. Потому что он не может вычислить среднее значение для этих данных.

Хотелось бы иметь поддержку этого в ELKI, но у меня самой в этом нет необходимости; Я не вижу хорошей функции расстояния для таких данных (есть функция Гауэра, но это не то, что я считаю "хорошим" - чтобы быть полезным, потребуется много ручного масштабирования, взвешивания и подобных модификаций для каждого набора данных снова ), и неясно, как оптимизировать реализации для этого сценария. Так что это слишком низко в моем списке приоритетов, чтобы реализовать себя, но я ценю хорошо продуманные запросы на вытягивание.

person Erich Schubert    schedule 05.10.2017
comment
Спасибо за ваше руководство. Вы предлагаете мне реализовать новый тип данных и использовать другие алгоритмы ELKI или я напишу свой алгоритм? - person NASRIN; 05.10.2017
comment
Даже если вы напишете свой собственный алгоритм, вам сначала придется реализовать тип данных для управления данными. Поэтому я бы сначала сделал это, затем попробовал некоторые существующие алгоритмы, а затем, при необходимости, добавил свой собственный алгоритм. - person Erich Schubert; 10.10.2017