Уровень алгоритма

Участник:Demon smd/Нечеткий алгоритм С средних: различия между версиями

Материал из Алговики
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
Строка 1: Строка 1:
{{Assignment}}
{{algorithm
{{algorithm
| name              = Нечеткий алгоритм C средних (Fuzzy C-means)
| name              = Нечеткий алгоритм C средних (Fuzzy C-means)

Версия от 17:47, 14 октября 2016

Файл:Symbol wait.svgЭта работа ждет рассмотрения преподавателем
Дата последней правки страницы:
14.10.2016
Авторы этой статьи считают, что задание выполнено.



Нечеткий алгоритм C средних (Fuzzy C-means)
Последовательный алгоритм
Последовательная сложность [math]\displaystyle{ O(C^2*N*D*IterNumber) }[/math]
Объём входных данных [math]\displaystyle{ |X|*C }[/math]
Объём выходных данных [math]\displaystyle{ |X|*C }[/math]
Параллельный алгоритм
Высота ярусно-параллельной формы [math]\displaystyle{ O(\log_{2}C^4*|X|^3) * IterNumber }[/math]
Ширина ярусно-параллельной формы [math]\displaystyle{ O(C^2*|X|) }[/math]


Авторы описания алгоритма: Д.А.Гуськов М.А.Абраменкова

Свойства и структура алгоритма

Общее описание алгоритма

Нечёткий алгоритм кластеризации С-средних был разработан (для случая m=2) J.C. Dunn в 1973 г. [1] и усовершенствован (для случая m>1) J.C. Bezdek в 1981 г. [2] . В отличие от алгоритма c-means данный метод кластеризации предполагает, что входные данные могут принадлежать более, чем одному кластеру одновременно. Алгоритм получает на вход набор кластеризуемых векторов, количество кластеров, коэффициент неопределённости m и коэффициент [math]\displaystyle{ \varepsilon \gt 0 }[/math], определяющий точность алгоритма. На выходе алгоритма получаем матрицу вероятностей принадлежности каждого входного вектора каждому кластеру.

Нечеткий алгоритм С средних заключается в следующем. Изначально для каждого вектора определяется случайным образом вероятность принадлежности вектора к каждому кластеру. Далее запускается итерационный процесс, на каждой итерации которого происходит:

1) расчёт центров кластеров

2) расчёт Евклидова расстояния от каждого вектора до центра каждого кластера

3) расчёт и нормализация коэффициентов принадлежности векторов кластерам

4) расчёт значения решающей функции и сравнение этого значения со значением решающей функции на предшествующей итерации: если разница этих значений меньше установленного значения, то алгоритм прекращает работу (решающая функция возвращает сумму всех Евклидовых расстояний каждого объекта к каждому центру кластера умноженному на коэффициент принадлежности)

Математическое описание алгоритма

Нечеткий алгоритм С средних минимизирует величину:

[math]\displaystyle{ \begin{align} J_{m} = \sum_{i = 1}^{N}\sum_{j = 1}^{C}u_{i,j}^m\left\Vert{x_{i}-c_{j}}\right\|^2 & , & & 1 \le m \le \infty , \\ \end{align} }[/math]

где m - это действительное число не меньше единицы, [math]\displaystyle{ u_{i,j} }[/math] - коэффициент принадлежности вектора [math]\displaystyle{ x_{i} }[/math] к кластеру [math]\displaystyle{ c_{j} }[/math], [math]\displaystyle{ x_{i} }[/math] - [math]\displaystyle{ i }[/math]-ый компонент [math]\displaystyle{ N }[/math]-мерного вектора [math]\displaystyle{ x }[/math], [math]\displaystyle{ c_{j} }[/math] - центр [math]\displaystyle{ j }[/math]-ого кластера, а [math]\displaystyle{ \left\Vert{*}\right\| }[/math] - это любая норма, определяющая расстояние от вектора до центра кластера. Нечёткое разбиение входных данных на кластеры производится итеративной оптимизацией вышеуказанной функции с обновлением коэффициента принадлежности [math]\displaystyle{ u_{i,j} }[/math] и переопределением центра кластера [math]\displaystyle{ c_{j} }[/math] на каждой итерации алгоритма.

Вычисляемые данные на каждой итерации

  • Центры кластеров рассчитываются по следующей формуле: [math]\displaystyle{ c_{j} = {{\sum_{i = 1}^{n}{u_{i,j}^m} * x_{i}} \over {\sum_{i = 1}^{n}{u_{i,j}^m}}} }[/math], где [math]\displaystyle{ u_{i,j} }[/math] — коэффициент принадлежности [math]\displaystyle{ x_{i} }[/math] вектора к кластеру [math]\displaystyle{ c_{j} }[/math].
  • Коэффициент принадлежности рассчитывается по формуле: [math]\displaystyle{ u_{i,j} = {1 \over \sum_{k = 1}^{C}{({\left\Vert{x_{i}-c_{j}}\right\| \over \left\Vert{x_{i}-c_{k}}\right\|})}^{2 \over m-1}} }[/math]
  • Решающая функция рассчитывается по формуле: [math]\displaystyle{ \max_{i,j}(|u_{i,j}^{(k)} - u_{i,j}^{(k-1)}|) }[/math], где [math]\displaystyle{ k }[/math] - номер итерации алгоритма

Вычислительное ядро алгоритма

Ядром алгоритма является:

  • вычисление новых центров кластеров
  • для каждого входного вектора вычисление Евклидова расстояния до центров кластеров, а также коэффициента принадлежности кластерам
  • вычисление решающей функции

Макроструктура алгоритма

В каждой итерации алгоритма происходит 3 основных действия описанных в п. 1.2.1:

  • вычисление центров кластеров
  • вычисление коэффициентов принадлежности
  • вычисление решающей функции

Подробное описание макроструктур в виде кода приведено в пункте 1.5

Схема реализации последовательного алгоритма

Схему реализации последовательного алгоритма можно описать на C++ следующим образом:

FCM (X[], C, m, eps){
    float deside = 0;
    float newDeside = 0;
    generateMembershipDegree();            //заполняет uPrev[][] случайными нормрованными коэффициентами
    while (true){
        newDeside = deside;

        //вычисление центров кластеров
        for (int j=0; j<C; j++){           //для каждого кластера
            float numerator = 0;
            float denumerator = 0;
            for (int i=0; i<X.size(); i++){        //для каждого вектора
                numerator+=pow(u[i][j], m) * x[i];
                denumerator+=pow(u[i][j], m);
            }
            c[j] = numerator / denumerator;
        }

        //вычисление коэффициентов u[][]
        for (int i=0; i<X.size(); i++)    //для каждого вектора
            for (int j=0; j<C; j++){   //для каждого кластера
                sum = 0;
                for (int k=0; k<C; k++)
                    sum+= pow( dist(x[i], c[j]) / dist(x[i], c[k]), 2/(m-1));
                u[i][j] = 1/sum
            }

        //определения максимального различия между u[][] и uPrev[][]
        float max = 0;
        for (int i=0; i<X.size(); i++)    //для каждого вектора
            for (int j=0; j<C; j++){   //для каждого кластера
                if (abs(uPrev[i][j]-u[i][j])>max)
                    max = abs(uPrev[i][j]-u[i][j]);

        if (eps <= max)
            for (int i=0; i<X.size(); i++)    //для каждого вектора
                for (int j=0; j<C; j++){   //для каждого кластера
                    uPrev[i][j]=u[i][j];
        else
            break;
             
    }
    return u;
}

Последовательная сложность алгоритма

Последовательная сложность всего алгоритма складывается из сложности операций на каждой итерации умноженную на количество итераций. Так как в данном алгоритме количество итераций не является фиксированным и зависит от:

  • параметра [math]\displaystyle{ \varepsilon }[/math]
  • набора входных векторов [math]\displaystyle{ x }[/math]
  • выбора начальных коэффициентов [math]\displaystyle{ u }[/math]

то в данном пункте будет приведена сложность одной итерации относительно количества входных векторов. Как видно из предыдущего пункта, для вычисления центров кластеров требуется [math]\displaystyle{ O(2*C*|X|) }[/math] операций, для определения коэффициентов [math]\displaystyle{ u }[/math] - [math]\displaystyle{ O(C^2*|X|) }[/math] операций, а для вычисления решающей функции - [math]\displaystyle{ O(2*C*|X|) }[/math] операций, где [math]\displaystyle{ |X| }[/math] - число входных векторов, а [math]\displaystyle{ C }[/math] - количество кластеров.

Таким образом итоговая сложность одной итерации составляет [math]\displaystyle{ O(C^2*|X|) }[/math].

Информационный граф

Как видно из пункта 1.5, на каждом действии каждой итерации алгоритма все операции, выполняющиеся в цикле, не зависят друг от друга и могут быть распаралелены. Это показано на Рисунке 1.

Рисунок 1. Информационный граф алгоритма. (1)-(7) - это наборы последовательных действий (например, (2) - последовательные операции деления, взятия адреса и присваивания).

Ресурс параллелизма алгоритма

На каждом ярусе ярусно-параллельной формы алгоритма будет располагаться конечное число элементарных операций, например, взятие адреса, сложение или возведение в степень. Информационый граф из п.1.7 изображает свёрнутую ярусно-параллельную форму алгоритма.

Сложность алгоритма будем рассчитывать в предположении, что число вычислительных ядер стремится к бесконечности. Как видно из информационного графа, параллельная сложность вычисления центров кластеров составляет [math]\displaystyle{ O(\log_{2} C*|X|) }[/math], вычисления коэффициентов принадлежности - [math]\displaystyle{ O(\log_{2} C^2*|X|) }[/math], а вычисления решающей функции - не больше чем [math]\displaystyle{ O(\log_{2} C*|X|) }[/math].

Таким образом параллельная сложность итерации алгоритма составляет [math]\displaystyle{ O(\log_{2} C^4*|X|^3) }[/math].

Так как задачи, решаемые в макроструктуре алгоритма могут быть сведены к задачам вычисления суммы элементов массива и максимального элемента массива, то на [math]\displaystyle{ i }[/math]-ом ярусе графа будет находиться [math]\displaystyle{ {N}\over{2^i} }[/math] операции, где N - количество элементов массива.

Входные и выходные данные алгоритма

Входные данные алгоритма

  • [math]\displaystyle{ x_{i} }[/math] - набор входных векторов
  • [math]\displaystyle{ C }[/math] - количество кластеров
  • [math]\displaystyle{ m }[/math] - коэффициент неопределённости
  • [math]\displaystyle{ \varepsilon \gt 0 }[/math] - коэффициент, определяющий точность алгоритма.

Выходные данные алгоритма

  • [math]\displaystyle{ u }[/math] - матрица принадлежности векторов кластерам

Свойства алгоритма

Увеличение скорости работы алгоритма при распараллеливании на бесконечном количестве процессоров составляет [math]\displaystyle{ O({{C^2*|X|}\over{\log_{2} (C^4*|X|^3)}}) }[/math]. Например, для разбиения 1000 элементов на 10 кластеров производительность параллельного алгоритма будет в 2315 раз больше, а на 20 кластеров - уже в 8477 раз.

Программная реализация алгоритма

Особенности реализации последовательного алгоритма

Локальность данных и вычислений

Возможные способы и особенности параллельной реализации алгоритма

Масштабируемость алгоритма и его реализации

Как видно из предыдущих пунктов, масштабируется данный алгоритм хорошо. С увеличением количества процессоров время работы падает, а с увеличением количества входных данных и количества кластеров - растёт. На рисунках показана масштабируемость алгоритма.

Рисунок 2. Масштабируемость алгоритма. Зависимость сложности алгоритма от количества процессоров и входных данных при фиксированном количестве кластеров.
Рисунок 3. Масштабируемость алгоритма. Зависимость сложности алгоритма от количества процессоров и кластеров при фиксированном количестве входных данных.

Динамические характеристики и эффективность реализации алгоритма

Выводы для классов архитектур

Существующие реализации алгоритма

Существует множество реализаций данного алгоритма. Рассмотрим некоторые из них:

- Например, тут: https://habrahabr.ru/post/208496/ [3] приведено краткое описание алгоритма и приведена его реализация на php. В данной статье довольно подробно расписан каждый шаг алгоритма и приведён соответствующий ему фрагмент кода.

- Тут: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html [4] приводится реализация алгоритма для PostgreSQL, а также прилагается скрипт внедрения алгоритма.

Литература

<references \>

  1. ↑ Dunn, J. C. (1973-01-01). "A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters". Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.
  2. ↑ Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.
  3. ↑ Нестер А. "Алгоритм нечёткой кластеризации fuzzy c-means на PHP". [html](https://habrahabr.ru/post/208496/)
  4. ↑ Миниахметов Р.М., Цымблер М.Л. "Интеграция алгоритма кластеризации Fuzzy c-Means в PostgreSQL". [html](http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html)