Запуск DBSCAN в ELKI

Я пытаюсь сгруппировать некоторые геопространственные данные и ранее использовал библиотеку WEKA. . Я нашел этот сравнительный анализ и решил попробовать ELKI.

Несмотря на совет не использовать ELKI в качестве библиотеки Java (которая предположительно менее обслуживаема, чем пользовательский интерфейс), я включил ее в свое приложение и могу сказать, что вполне доволен результатами. . Структуры, которые он использует для хранения данных, гораздо более эффективны, чем те, которые использует Weka, и тот факт, что у него есть возможность использовать пространственный индекс, определенно является плюсом.

Однако, когда я сравниваю результаты DBSCAN от Weka с результатами от DBSCAN ELKI, я немного озадачен. Я бы согласился с тем, что разные реализации могут дать немного разные результаты, но эта величина разницы заставляет меня думать, что с алгоритмом что-то не так (возможно, с моим кодом). Количество кластеров и их геометрия сильно различаются в двух алгоритмах.

Для справки, я использую последнюю версию ELKI (0.6.0), и параметры, которые я использовал для своих симуляций, были следующими:

minpts=50 эпсилон=0,008

Я закодировал две функции DBSCAN (для Weka и ELKI), где «точка входа» — это csv с точками, а «выход» для обеих из них также идентичен: функция, вычисляющая вогнутую оболочку набора точек ( по одному на каждый кластер). Поскольку функция, которая считывает файл csv в «базу данных» ELKI, относительно проста, я думаю, что моя проблема может заключаться в следующем:

а) в параметризации алгоритма; б) чтение результатов (наиболее вероятно).

Параметризация DBSCAN не представляет никаких проблем, и я использую два обязательных параметра, которые я ранее тестировал через пользовательский интерфейс:

ListParameterization params2 = new ListParameterization();
params2.addParameter(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.Parameterizer.MINPTS_ID,        minPoints);
params2.addParameter(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.Parameterizer.EPSILON_ID, epsilon);

Чтение результата немного сложнее, так как я не совсем понимаю организацию структуры, в которой хранятся кластеры; Моя идея состоит в том, чтобы перебрать каждый кластер, получить список точек и передать его функции, которая вычисляет вогнутую оболочку, чтобы создать многоугольник.

    ArrayList<Clustering<?>> cs = ResultUtil.filterResults(result, Clustering.class);
    for (Clustering<?> c : cs) {
        System.out.println("clusters: " + c.getAllClusters().size());
      for (de.lmu.ifi.dbs.elki.data.Cluster<?> cluster : c.getAllClusters()) {
              if (!cluster.isNoise()){
                 Coordinate[] ptList=new Coordinate[cluster.size()];
                 int ct=0;
                    for (DBIDIter iter = cluster.getIDs().iter(); iter.valid(); iter.advance()) {
                        ptList[ct]=dataMap.get(DBIDUtil.toString(iter));
                        ++ct;
                    }                   
                //there are no "empty" clusters
                assertTrue(ptList.length>0);

                GeoPolygon poly=getBoundaryFromCoordinates(ptList);
                if (poly.getCoordinates().getGeometryType()==
                        "Polygon"){

                    try {
                        out.write(poly.coordinates.toText()+"\n");
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }           

                }else
                    System.out.println(
                            poly.getCoordinates().getGeometryType());

              }//!noise
      }
    }

Я заметил, что «шум» возник как кластер, поэтому я проигнорировал этот кластер (я не хочу его рисовать). Я не уверен, что это правильный способ чтения кластеров, так как я не нашел много примеров. У меня также есть несколько вопросов, на которые я пока не нашел ответов:

  • В чем разница между getAllClusters() и getTopLevelClusters()?
  • Являются ли кластеры DBSCAN «вложенными», то есть можем ли мы иметь точки, принадлежащие многим кластерам одновременно? Почему?
  • Я где-то читал, что мы не должны использовать идентификаторы базы данных для идентификации точек, так как они предназначены для внутреннего использования ELKI, но как еще можно получить список точек в каждом кластере? Я читал, что вы можете использовать отношение для меток, но я не уверен, как это реализовать...

Любые комментарии, которые могли бы указать мне правильное направление, или любые предложения по коду для повторения набора результатов ELKI DBSCAN будут действительно приветствоваться! Я также использовал ELKI OPTICSxi в своем коде, и у меня есть еще больше вопросов относительно этих результатов, но, думаю, я приберегу их для другого поста.


person doublebyte    schedule 13.05.2014    source источник


Ответы (2)


Доступ к DBIDs ELKI работает, если вы обратите внимание на то, как они назначены.

Для статической базы данных getDBIDs() вернет объект RangeDBIDs, и это может дать вам смещение в базе данных. Это очень надежно. Но если вы всегда перезапускаете свой процесс, DBIDs все равно будет назначено детерминировано (только при использовании MiniGUI они будут отличаться, если вы перезапустите задание!)

Это также будет более эффективно, чем DBIDUtil.toString.

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

Что касается Weka, то она иногда делает автоматическую нормализацию. Тогда значение эпсилон будет искажено. Для географических данных я бы все равно предпочел геодезическое расстояние, евклидово расстояние по широте и долготе не имеет смысла.

Проверьте эту часть кода Wekas: "norm", используемая EuclideanDataObject. Мне действительно кажется, что Wekas ​​DBSCAN применяет нормализацию набора данных! Попробуйте масштабировать ваши данные до [0:1] (я уверен, что в ELKI есть фильтр для этого), если после этого результаты будут идентичными?

Судя по этому фрагменту кода, я бы обвинил Weka. Приведенный выше код также выглядит немного неэффективным для меня. Подход с фильтром, на мой взгляд, имеет больше смысла, чем эта принудительная фильтрация в объектах данных.

person Has QUIT--Anony-Mousse    schedule 13.05.2014
comment
Большое спасибо за ваше глубокое понимание этой проблемы. В первую очередь меня шокирует тот факт, что Weka нормализует набор данных. Имея в виду, что DBSCAN является алгоритмом пространственной кластеризации, и он, вероятно, будет подхватываться приложениями в географическом пространстве, он вносит ненужные искажения. Я также согласен с вашим комментарием относительно использования геодезических координат в евклидовом пространстве. Это не приводит к последовательному решению. Я читал, что Elki учитывает геодезические расстояния, но я не уверен, как это обеспечить (или в Elki расстояния всегда геодезические?) - person doublebyte; 14.05.2014
comment
Подход с фильтрами, на мой взгляд, имеет больше смысла, чем эта принудительная фильтрация в объектах данных Не могли бы вы рассказать об этом немного подробнее? Я не уверен, как получить результаты иначе, и было бы очень полезно для меня, если бы вы могли предоставить мне фрагмент кода! Спасибо - person doublebyte; 14.05.2014
comment
Я решил преобразовать свой комментарий в другой вопрос - person doublebyte; 14.05.2014
comment
карта данных, координаты и GeoPolygon. Кто-нибудь может сказать имя пакета или связанную с ним библиотеку? - person sau; 26.05.2014
comment
Вам не нужно использовать их. Это адаптеры для его внутренних структур данных. Для вычисления выпуклой оболочки лучше использовать классы ELKI, такие как GrahamScanConvexHull2D. Использование dataMap так, как он это делал, крайне неэффективно; поэтому используйте ELKI Relation, когда это возможно. - person Has QUIT--Anony-Mousse; 26.05.2014

В основном это продолжение @Anony-Mousse, который дал довольно полный ответ.

  • getTopLevelClusters() и getAllClusters() делают то же самое для DBSCAN, так как DBSCAN не создает иерархических кластеров.
  • Кластеры DBSCAN не пересекаются. Обработка кластеров с isNoise()==true как одноэлементных объектов, вероятно, является лучшим способом обработки шума. Кластеры, возвращаемые нашей реализацией OPTICSXi, также не пересекаются, но вы должны рассматривать элементы всех дочерних кластеров как часть внешнего кластера. Для выпуклых оболочек эффективный подход состоит в том, чтобы сначала вычислить выпуклую оболочку дочерних кластеров; затем для родителя вычислить выпуклую оболочку дополнительных объектов + точки выпуклой оболочки всех дочерних объектов.
  • Подход RangeDBIDs, упомянутый @Anony-Mousse, довольно чист для статических баз данных. Чистый подход, который также работает с динамическими базами данных, заключается в наличии дополнительного отношения, которое идентифицирует объекты. При использовании CSV-файла в качестве входных данных вместо того, чтобы полагаться на согласованность нумерации строк, вы просто добавляете нечисловой столбец, содержащий метки, например. object123. Это лучший подход с логической точки зрения — если вы хотите иметь возможность идентифицировать объекты, дайте им уникальный идентификатор. ;-)
  • Мы используем ELKI для обучения и очень тщательно проверили его алгоритм DBSCAN (вы можете найти пошаговая демонстрация DBSCAN здесь, и результаты ELKI точно соответствуют этому). Код DBSCAN и OPTICS в Weka был предоставлен студентом давным-давно и никогда не проверялся в той же степени. Судя по быстрой проверке, Weka не выдает правильные результаты в нашем наборе данных о классных упражнениях.
  • Поскольку набор данных для упражнений имеет одинаковое расширение, равное 10, в каждом измерении, мы можем изменить параметр эпсилон на 1/10, и тогда результат Weka будет соответствовать решению; поэтому вывод @Anony-Mousses кажется правильным: реализация Weka обеспечивает масштабирование данных [0; 1].
person Erich Schubert    schedule 14.05.2014
comment
Большое спасибо за ответ. Раньше я замечал искажение результатов Weka по отношению к Elki, но не осознавал, что оно было систематическим и связано с нормализацией. Вот приведены некоторые результаты DBSCAN в Elki и Weka с использованием этого коэффициента масштабирования. вы предложили, и действительно, они в основном накладываются на основной полигон. Что касается DBIDS, я мог бы построить третий столбец в своем CSV, но я не уверен, как я буду читать эти значения из кластеров. Будут ли они встроены в кластерный объект? Не могли бы вы показать мне какой-нибудь код для этого? - person doublebyte; 14.05.2014
comment
Чтобы получить доступ к этим значениям, получите Relation из базы данных. Если у вас есть текстовые метки в CSV-файле, вам нужен тип данных TypeUtil.LABELLIST. Вы также можете добавить отношения с вашими собственными типами данных, чтобы вы могли использовать отношение с целочисленным значением. - person Erich Schubert; 14.05.2014