разбиение массива с плавающей запятой на аналогичные сегменты (кластеризация)

У меня есть такой массив поплавков:

[1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200]

Теперь я хочу разбить массив следующим образом:

[[1.91, 2.87, 3.61] , [10.91, 11.91, 12.82] , [100.73, 100.71, 101.89] , [200]]

// [200] будет рассматриваться как выброс из-за меньшей поддержки кластера

Мне нужно найти такой сегмент для нескольких массивов, и я не знаю, какой должен быть размер раздела. Я попытался сделать это с помощью иерархической кластеризации (агломеративной), и это дало мне удовлетворительные результаты. Однако проблема в том, что мне предложили не использовать алгоритмы кластеризации для одномерной задачи, поскольку для этого нет теоретического обоснования (как для многомерных данных).

Я потратил много времени, чтобы найти решение. Однако предложения кажутся совершенно разными, например: ://stackoverflow.com/questions/11513484/1d-number-array-clustering">это VS. это и это и это.

Я нашел другое предложение вместо кластеризации, то есть оптимизация естественных разрывов. Однако для этого также необходимо объявить номер раздела, например K-means (правильно?).

Это довольно запутанно (особенно потому, что я должен выполнять такую ​​​​сегментацию на нескольких массивах, и невозможно узнать оптимальный номер раздела).

Существуют ли какие-либо способы нахождения разделов (таким образом, мы можем уменьшить дисперсию внутри разделов и максимизировать дисперсию между разделами) с некоторым теоретическим обоснованием?

Любые ссылки на статьи/документы (при наличии реализации на C/C++/Java) с некоторым теоретическим обоснованием будут для меня очень полезны.


person alessandro    schedule 05.07.2013    source источник
comment
Мне любопытно, почему кластеризация не подходит для одномерных данных - что, если вы каким-то образом увеличите размерность, например, добавите sqrt (n) в качестве измерения, что немного похоже на то, что происходит в SVM?   -  person zw324    schedule 05.07.2013
comment
@ZiyaoWei, почему кластеризация не подходит для одномерных данных - я действительно не знаю. В классе мне сказали, что использовать кластеризацию в одномерных данных — это сумасшествие. но я не нашел статьи о том, почему я не могу (или могу).   -  person alessandro    schedule 05.07.2013
comment
Увеличение размера @ZiyaoWei без причины не кажется хорошим решением.   -  person alessandro    schedule 05.07.2013
comment
Нет, это не так, просто думаю, что нет реальной разницы между одномерными и многомерными данными. Или они?   -  person zw324    schedule 05.07.2013
comment
... уменьшить дисперсию внутри разделов и максимизировать дисперсию между разделами... Если вы объясните нам, что именно вы имеете в виду, возможно, мы сможем помочь. Вы имеете в виду минимизировать ((средняя дисперсия внутри раздела) - (средняя дисперсия между разделами)) или что?   -  person Beta    schedule 05.07.2013
comment
@Beta, минимизируйте среднее отклонение каждого класса от среднего класса, максимально увеличивая отклонение каждого класса от средних значений других групп, как при оптимизации естественных разрывов (en.wikipedia.org/wiki/).   -  person alessandro    schedule 05.07.2013
comment
@ZiyaoWei одномерные данные упорядочены. 2-х мерных данных нет. Есть существенная разница, оказывающая огромное влияние на алгоритмическую сложность.   -  person Has QUIT--Anony-Mousse    schedule 05.07.2013
comment
@ Anony-Mousse 2-мерные данные определенно можно заказать, если вы хотите - сначала ось Y, затем X, например. Но, возможно, вы правы.   -  person zw324    schedule 05.07.2013


Ответы (2)


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

Изменить: Быстрый демонстрационный код на С++:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <numeric>
#include <functional>

int main() {
    std::vector<double> data{ 
        1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200 
    };

    // sort the input data
    std::sort(data.begin(), data.end());

    // find the difference between each number and its predecessor
    std::vector<double> diffs;
    std::adjacent_difference(data.begin(), data.end(), std::back_inserter(diffs));

    // convert differences to percentage changes
    std::transform(diffs.begin(), diffs.end(), data.begin(), diffs.begin(),
        std::divides<double>());

    // print out the results
    for (int i = 0; i < data.size(); i++) {

        // if a difference exceeds 40%, start a new group:
        if (diffs[i] > 0.4)
            std::cout << "\n";

        // print out an item:
        std::cout << data[i] << "\t";
    }

    return 0;
}

Результат:

1.91    2.87    3.61
10.91   11.91   12.82
100.71  100.73  101.89
200
person Jerry Coffin    schedule 05.07.2013
comment
не могли бы вы уточнить это? Я не могу его получить (может быть, в псевдокоде, если это возможно)? - person alessandro; 05.07.2013
comment
Я пробовал с большей выборкой. Похоже, это не работает [78, 89, 74, 42, 89, 22, 48, 26, 28, 92, 100, 96, 35, 5, 70, 76, 11, 70, 12, 91, 7, 38, 19, 68, 58, 2, 89, 20, 30, 81, 95, 11, 97, 81, 86, 43, 52, 48, 71, 91, 4, 64, 94, 41, 82, 16, 35, 13, 57, 50] - person deep_rugs; 20.07.2019
comment
@deep_rugs: я думаю, вы неправильно поняли намерение. Когда ваши данные отсортированы, есть только один разрыв, потому что в ваших данных нет места, где есть разница более чем на 40% между одним числом и другим. Если вам нужны изменения данных в исходном порядке, удалите строку std::sort и замените if (diffs[i] > 0.4) на if (std::abs(diff[i]) > 0.4). - person Jerry Coffin; 20.07.2019

Кластеризация обычно предполагает многомерные данные.

Если у вас есть одномерные данные, отсортируйте их, а затем используйте либо оценку плотности ядра, либо просто просмотрите самые большие пробелы.

В 1 измерении задача существенно упрощается, потому что данные можно сортировать. Если вы используете алгоритм кластеризации, он, к сожалению, не использует это, поэтому вместо этого используйте одномерный метод!

Попробуйте найти самый большой разрыв в одномерных данных. Это тривиально: отсортируйте (n log n, но на практике так быстро, как это возможно), затем посмотрите на два соседних значения для наибольшей разницы.

Теперь попробуйте определить «самый большой разрыв» в двух измерениях и эффективный алгоритм для его обнаружения...

person Has QUIT--Anony-Mousse    schedule 05.07.2013