Я реализовал априорный алгоритм для добычи частых наборов элементов, он отлично работает для образцов данных, но когда я попытался выполнить его для набора данных для розничной торговли, доступного по адресу http://fimi.ua.ac.be/data/retail.dat, что составляет около 3 МБ данных с 88 КБ транзакций и 1600 уникальных элементов, это занимает около 29 часов. Я искал причину снижения производительности и обнаружил, что алгоритм генерации набора элементов-кандидатов занимает много времени. Может ли кто-нибудь помочь мне улучшить производительность или это нормальное поведение алгоритма.

1
user1276005 21 Янв 2014 в 19:56

3 ответа

Лучший ответ

Какой алгоритм вы используете и каковы ваши пороговые значения ?

Если у вас есть n 1-элементных наборов, которые удовлетворяют вашей минимальной поддержке, Apriori (и многие другие) должны рассмотреть n*(n-1)/2 2-элементные наборы. Это, конечно, обходится довольно дорого. В Apriori набор из 2 элементов часто является самым большим и самым дорогим шагом (в зависимости от ваших настроек, наборы из 3 элементов могут быть хуже, но обычно вы не заходите так далеко ...)

В зависимости от характеристик ваших данных Eclat может работать лучше или хуже. FP-рост очень умен, но, кажется, действительно сложно реализовать правильно и эффективно.

Также существует множество вариантов, некоторые из них вероятностные и могут быть значительно быстрее.

Но по сути имеет значение реализация и набор данных / настройки параметров . Один подход может быть лучше другого для одного и того же набора данных; и реализации могут легко иметь 10-кратную разницу в производительности. В частности, для APRIORI, где многие люди не до конца понимают используемые приемы обрезки и в конечном итоге выполняют слишком много работы.

Для вашего примера набора данных (который, к сожалению, совершенно бесполезен без словаря, объясняющего числа), мой APRIORI завершается примерно через 1 минуту на низком уровне процессора Atom с minSupport = 1000. Были найдены 4 набора элементов:

32, 38, 39, 48: 1236
32, 39, 41, 48: 1646
36, 38, 39, 48: 1080
38, 39, 41, 48: 1991
38, 39, 48, 110: 1031
38, 39, 48, 170: 1193

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

При minSupport = 1000:

1-frequentItemsets (56)
2-frequentItemsets (49)
3-frequentItemsets (24)
4-frequentItemsets (6)
APRIORI runtime: 55401 ms

При minSupport = 500:

1-frequentItemsets (185)
2-frequentItemsets (191)
3-frequentItemsets (79)
4-frequentItemsets (13)
5-frequentItemsets (0)
APRIORI runtime: 136594 ms

Как видите, время выполнения увеличилось более чем вдвое. Причина в том, что количество наборов из 1 элемента выросло, и появилось гораздо больше кандидатов из 2 элементов. В наборах из 3 и 4 пунктов разница уже не так велика. Но в целом время работы в 2 минуты на действительно низком процессоре еще неплохо.

Уменьшение минимальной поддержки до 250:

1-frequentItemsets (587)
2-frequentItemsets (640)
3-frequentItemsets (273)
4-frequentItemsets (54)
5-frequentItemsets (4)
APRIORI runtime: 954984 ms

Теперь время выполнения начинает взрываться. Почти 16 минут, чтобы найти наборы из 5 пунктов:

32, 38, 39, 41, 48: 448
36, 38, 39, 41, 48: 334
38, 39, 41, 48, 110: 346
38, 39, 41, 48, 170: 413

Как вы можете видеть, набор из 4 элементов 38, 39, 41, 48 играет ключевую роль в этом наборе данных (но мы уже обнаружили это при первом запуске). Теперь мы также можем дать уверенность для 38, 39, 41, 48 -> 32, которое будет наиболее достоверным правилом, касающимся 5 элементов: примерно 22.5% транзакций с участием первых четырех также включает элемент 32. Но учитывая, что AFAICT значение чисел для этого набора данных неизвестно, мы не знаем, действительно ли это правило интересно на практике или это просто игрушечное упражнение.

При переходе к minSupport = 100 время выполнения увеличивается:

1-frequentItemsets (1857)
2-frequentItemsets (2785)
3-frequentItemsets (1475)
4-frequentItemsets (306)
5-frequentItemsets (28)
6-frequentItemsets (0)
APRIORI runtime: 8256507 ms

То есть более двух часов. Большая часть этого времени тратится на наборы из двух пунктов: 1,7 миллиона кандидатов, из которых 2785 были частыми. Для наборов из 3 пунктов можно приблизительно оценить, что будет всего несколько тысяч кандидатов, но уже не миллионы. У меня есть планы по дальнейшему улучшению реализации путем переключения между двумя кодовыми путями в зависимости от количества кандидатов. ('' 'Обновление:' '' с более простой модификацией я дополнительно сократил время выполнения в 20 раз. Так что да, '' 'реализация имеет значение' '', это может легко сделать коэффициент от 100 до 1000 или более когда обрезка APRIORI реализована не полностью, например)

Если я когда-нибудь найду время, чтобы прочитать алгоритм Eclat и реализовать его заново, я могу обновить его результатами. Я считаю, что здесь будет намного быстрее, как и рост FP.

2
Has QUIT--Anony-Mousse 22 Янв 2014 в 15:37

Это зависит от вашей реализации. При внедрении Apriori можно сделать много оптимизаций.

Во-первых, если вы прочитаете исходную статью Apriori от Agrawal & Srikant, вы заметите, что они предлагают использовать специальное хеш-дерево для эффективного подсчета поддержки кандидатов. Если вы хотите увидеть, как работает эта реализация, существует версия Apriori, реализованная с помощью HashTree в библиотеке интеллектуального анализа данных с открытым исходным кодом SPMF. Он называется AprioriHT.

Другая оптимизация, позволяющая избежать многократного сканирования базы данных, называется AprioriTID. Каждый набор элементов аннотируется набором идентификаторов транзакции (tid set), в которой он содержится. Затем, когда кандидат создается путем объединения двух наборов элементов A и B, чтобы подсчитать поддержку AUB напрямую без сканирования базы данных, вы можете выполнить пересечение наборов tid A и B. Для дальнейшей оптимизации вы можете реализовать наборы tid с битовые векторы. Эта версия APriori называется AprioriTID.

Еще одна оптимизация была предложена в алгоритме Паскаль. Он заключается в использовании понятия генераторов для определения пороговых значений поддержки некоторых наборов элементов без сканирования базы данных с использованием концепции генераторов наборов элементов из Formal Concept Analysis.

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

Есть и другие оптимизации. На сайте FIMI представлены различные реализации с разными оптимизациями.

Если вы хотите взглянуть на оптимизированную версию, вы можете взглянуть на мои реализации в Библиотека интеллектуального анализа данных SPMF на Java. Кроме того, на том же веб-сайте вы получите реализации более быстрых алгоритмов, таких как FPGrowth.

0
Phil 1 Июл 2016 в 02:38