F= {1}, {2}, {3}, {6}, {1,2}, {2,6}
10. Подсчёт достоверности (см. Таблицу 18): Таблица 18. Составление ассоциативных правил
№ Правило Достоверность, % А Если покупатель взял мясо, то он купит хлеб.
75 А Если покупатель взял хлеб, то он купит спички.
60 А Если покупатель взял хлеб, то он купит мясо.
60 А Если покупатель взял спички, то он купит хлеб.
100 Данные в графе достоверность мы подсчитали следующим образом
𝑐𝑜𝑛𝑓(𝐴1) =
sup({1,2})
sup({1})
=
3 4
= 75%
𝑐𝑜𝑛𝑓(𝐴2) =
sup({2,6})
sup({2})
=
3 5
= 60% И для пар, образованных обратным образом
𝑐𝑜𝑛𝑓(𝐴3) =
sup({2,1})
sup({2})
=
3 5
= 60%
184
𝑐𝑜𝑛𝑓(𝐴4) =
sup({6,2})
sup({6})
=
3 100
= 100% Примечание. Изданной выборки следовало, что покупатель всегда берёт хлеб, если он купил спички, что не будет действовать на выборках с большим количеством входящих данных. Чем больше транзакций и товаров рассматривается, тем результат надёжней. Это именно тот случай, когда алгоритм ведёт себя иначе на маленьких выборках. Задача № 5. Пример с частично автоматизированным решением доступен в свободном доступе вместе с дополнительными данными и примером решений по ссылке https://www.techlyc.ru/Apriori или Там же
находятся примеры кейсов с заданиями, из которых предлагается выбрать область исследования. Задача №6. Лавка моих друзей Данная задача похожа на Задачу
№4, однако решается с помощью Python. Друзья решили открыть свою лавку фермерских продуктов на рынке, и им нужно проследить, на какие полки положить товары, чтобы быстрее получить доходи расшириться. Вы согласились помочь им, сказав, что знаете подходящий инструмент для анализа и уже имеете достаточный опыт. Их ассортимент довольно прост хлеб, булочки, домашняя колбаса и котлеты, масло и молоко, сметана и перец, а ещё — дальневосточная икра. Вам дали неполный список транзакций – только за первый день. Что ж, вы понимаете, что этого мало, но друзья вас просят вывести правила (см. Таблица 19).
185 Таблица 19. Список покупок за первый день Клиент Купил
1 хлеб, колбаса, масло, икра
2 булочка, масло, сметана, икра
3 хлеб, колбаса, котлета
4 перец, молоко, котлета
5 масло, молоко, булочка
6 хлеб, колбаса, масло, молоко, котлета
7 котлета, перец, икра
8 булочка, масло
9 икра, масло, хлеб Содержимое исходной таблицы с транзакциями хлеб, колбаса, масло, молоко, котлета, сметана, булочка, перец хлеб, колбаса, масло, икра булочка, масло, сметана, икра хлеб, колбаса, котлета перец, молоко, котлета масло, молоко, булочка хлеб, колбаса, масло, молоко, котлета котлета, перец, икра булочка, масло икра, масло, хлеб Приведем наше решение import numpy as np
186 import pandas as pd from apyori import apriori Импорт таблицы сданными без заголовка trans_set = pd.read_csv('prod.csv', header=0) Список с множеством транзакций list_trans_set = [] for i in range(0, len(trans_set)): list_trans_set.append([str(trans_set.values[i,j]) for j in range(0, int(trans_set.size/len(trans_set)))])
# Обучение модели apriori_results
= list(apriori(list_trans_set, min_support=0.3, min_confidence=0.05, min_length=3))
# Вывод результатов на экран print("==============Н=А=Ч=А=Л=О===Р=А=Б=О=Т=Ы======") number=1 for item in range(0, len(apriori_results)): current=str(apriori_results[item]).split('=') if not "nan" in current[1]: Набор
№
{number}
=============================="[:50]) Набор)
187 Поддержка) if (current[1].count("'"))==2: Достоверность) if(current[1].count("'"))==4: Достоверность прямого правила) Достоверность обратного правила) if (current[1].count("'"))==6: Достоверность для двух последних к первому) Достоверность первых двух к последнему) Достоверность двух крайних к среднему) number=number+1
188 print("=============================================") print("===========К=О=Н=Е=Ц===Р=А=Б=О=Т=Ы===========") Результат выполнения
==============Н=А=Ч=А=Л=О===Р=А=Б=О=Т=Ы=========== Набор № 1 ==========================
|Набор:'булочка' Поддержка Достоверность
================================================== Набор № 2 ==========================
|Набор:'икра' Поддержка Достоверность
================================================== Набор № 3 ==========================
|Набор:'колбаса' Поддержка Достоверность
================================================== Набор № 4 ==========================
|Набор:'котлета' Поддержка Достоверность
================================================== Набор № 5 ==========================
|Набор:'масло' Поддержка
189 Достоверность
================================================== Набор № 6 ==========================
|Набор:'молоко' Поддержка Достоверность
================================================== Набор № 7 ==========================
|Набор:'хлеб' Поддержка Достоверность
================================================== Набор № 8 ==========================
|Набор:'булочка', 'масло' Поддержка Достоверность прямого правила Достоверность обратного правила
================================================== Набор № 9 ==========================
|Набор:'икра', 'масло' Поддержка Достоверность прямого правила Достоверность обратного правила
================================================== Набор № 10 =========================
|Набор:'колбаса', 'хлеб' Поддержка Достоверность прямого правила Достоверность обратного правила
190
================================================== Набор № 11 =========================
|Набор:'хлеб', 'масло' Поддержка Достоверность прямого правила Достоверность обратного правила
==================================================
===========К=О=Н=Е=Ц===Р=А=Б=О=Т=Ы================ Следующая задача намного сложнее, поскольку будет рассматривать не только частный случай (ранее выводились только трёхэлементные множества и правила для них. Задача № 7. Жильё на Манхеттене. Обратимся к ресурсу с большими данными, например, Kaggle за свободным сетом с выборкой с описанием отелей Нью-Йорка и качества обслуживания в них Требуется исследовать, какие апартаменты, судя по отзывами где снимают гости в Нью-Йорке. Работа производится с файлом
AB_NYC_2019.csv. Используйте изданных только часть столбцов, а именно neighbourhood_group – округ, neighbourhood – район, room_type – тип апартаментов. Пример решения import numpy as np import pandas as pd from apyori from apyori import apriori data
= pd.read_csv('AB_NYC_2019.csv', header=0, usecols=['neighbourhood_group',
'neighbourhood','room_type'])
191 list_trans_set = [] for i in range(0, len(data)): list_trans_set.append([str(data.values[i,j]) for j in range(0, int(data.size/len(data)))]) apriori_results
= list(apriori(list_trans_set, min_support=0.3, min_confidence=0.05, min_length=3))
# Добавление фильтров для поиска neighbourhood_group = Какая часть города вас интересует - ") room_type = Какой тип комнат учитывать - ") Вывод результатов на экран result = False for item in range(0, len(apriori_results)): current = str(apriori_results[item]) if
((current.find(neighbourhood_group)!=(-
1))&(current.find(room_type)!=(-1))): print(current.find(current)) result = True if result==False: Записей не найдено)
192 В случае, если результат не найден, например, при поиске гостевого дома в Бруклине, можно проверить, существует ли в принципе подобная зависимость (правило) в данных. Для этого потребуется код for item in range(0, len(apriori_results)): current = str(apriori_results[item]) print(current+'\n') На этот запрос система даст следующий ответ
RelationRecord(items=frozenset({'Brooklyn'}), support=0.41116678596993556, ordered_statistics=[OrderedStatistic(items_base=frozen set(), items_add=frozenset({'Brooklyn'}), confidence=0.41116678596993556, lift=1.0)])
RelationRecord(items=frozenset({'Entire home/apt'}), support=0.5196645873811229, ordered_statistics=[OrderedStatistic(items_base=frozen set(), items_add=frozenset({'Entire home/apt'}), confidence=0.5196645873811229, lift=1.0)])
RelationRecord(items=frozenset({'Manhattan'}), support=0.4430105327743123, ordered_statistics=[OrderedStatistic(items_base=frozen set(), items_add=frozenset({'Manhattan'}), confidence=0.4430105327743123, lift=1.0)])
193
RelationRecord(items=frozenset({'Private room'}), support=0.45661110543000305, ordered_statistics=[OrderedStatistic(items_base=frozen set(), items_add=frozenset({'Private room'}), confidence=0.45661110543000305, lift=1.0)]) Результат значит, что нет зависимостей между типом помещения и районом города. Чаще всего люди снимают жильё в Бруклине или на
Манхеттене, ноне любят снимать там с кем-то, арендуя весь дом или квартиру, либо же запирающуюся комнату без соседей. В качестве дополнительного задания предлагается изменить фильтры, чтобы извлечь полезные знания для турагентства. В качестве дополнительных материалов по теме были подготовлены описания ситуаций в формате кейсов, которые обучающиеся должны решить любым из известных им способов на выбор. РЕГРЕССИЯ Следующий блок задач посвящён линейной регрессии. Здесь помимо работы со встроенными функциями табличных процессоров и построение линии тренда на графике как частных случаев регрессии (т.к. используются статические данные, а не потоковые в практикуме пример не приводится, предлагается более сложная задача. Приведём пример с пошаговым решением задачи на Python. Задача № 8. Регрессия может быть использована для прогнозирования будущих результатов или восстановления утерянных данных. Попробуйте изучить зависимость таких непрерывных значений как рост и вес живых существ. Они изменяются непрерывно и обычно между собой связаны. Обратитесь к ресурсу с большими данными, выложенными
194 в открытый доступ, Kaggle. Нам понадобится база данных под названием
Fish, которую можно найти по адресу https://www.kaggle.com/aungpyaeap/fish-market
. В этой базе данных содержится информация о проданном в рыбном магазинчике товаре. У каждой рыбы описаны её вид, несколько измерений и вес. Требуется выяснить характеристики зависимости (и её наличие) между двумя свойствами — весом рыбы и её длиной. Решение. С помощью линейной регрессии мы проанализируем данные, чтобы подтвердить или опровергнуть сформулированную статистическую гипотезу. Гипотеза 0 (Н "Вес никак не влияет на размер рыбы, то есть зависимость между этими свойствами статистически незначима с уровнем значимости alpha". Следовательно, противоположная Гипотеза 1 (Н звучит как "Вес влияет на размер рыбы с уровнем значимости alpha". Для удобства уровень значимости возьмём классическое для статистики значение alpha = 0,05. Подключим необходимые библиотеки import pandas as pd Для работы с фреймами данных import numpy as np Для работы с массивами import researchpy as rp Чтобы узнать общую сводку по исходным данных import matplotlib.pyplot as plt Для построения графиков import statsmodels.formula.api as smf Для реализации модели линейной регрессии
195 import scipy Для статистических инструментов и работы с выборкой Также нам понадобится ещё несколько модулей первый из них мы применим для тасовки данных в выборке, а второй для предсказания разброса значений, неуказанных пока в выборке, но описываемых будущей регрессией. Далее нам потребуется несколько статистических инструментов, включая проверку нормального распределения объектов выборки. from sklearn.utils import shuffle Для перемешивания данных в выборке from statsmodels.sandbox.regression.predstd import wls_prediction_std Для прогнозирования ошибок from scipy.stats import normaltest Для проверки на нормальное распределение Следующим шагом необходимо загрузить таблицу сданными. Сразу же проверим первые строки, чтобы понять, правильно ли произошёл импорт data = pd.read_csv("Fish.csv", header=0) data.head() Выберем из всего ассортимента информацию о конкретном виде рыб, чтобы выявить зависимость. Допустим, мы хотим исследовать веси размер окуней (Perch). Для этого мы выделим изданных только те строки, где значение свойства вид (Species) сравнимо с окунем. data=data.loc[data['Species'] == 'Perch'] В качестве исследуемых свойств каждой рыбы выберем её веси длину в сантиметрах (Length1). В качестве независимой переменной выступает веса как зависимую мы рассматриваем длину.
196 data
=data[['Weight','Length1']] Несмотря на то, что мы импортировали таблицу из специализированного ресурса, данные необходимо подготовить для анализа.
Сначала нам надо проверить, похожи ли данные на правдивые. Это достаточно легко сделать по графику. В качестве
x выберем столбец с весома в качестве зависимой переменной
y — длину рыб. Также подпишем оси (см. Рисунок 23). fig
= plt.figure() Продаваемые окуни) x
=data.Weight y
=data.Length1 plt.plot(x,y) Вес, г) Длина, см) plt.show()
197 Рис. 23. Зависимость между размером и весом окуней Визуально данные похожи на правду. Проверим нормальность распределения объектов исходной выборки с помощью специального инструмента из пакета scipy.stats. К сожалению, он обрабатывает только массивы типа numpy, поэтому нам придётся произвести дополнительное преобразование. В качестве уровня значимости alpha выбираем привычное значение 0.05. Если найденные значения вероятности распределения меньше alpha, будем считать объекты не распределённым нормально. alpha = 0.05 statistic, pvalue = scipy.stats.normaltest(data.to_numpy()) if(pvalue.all() < alpha): print (Объекты не распределены нормально) else:
198 Нормальное распределение) Распределение было нормальным. Удостоверившись, что данные подходят для дальнейшей работы, произведём ряд дополнительных действий. В данной выборке они не являются обязательными, но демонстрируют возможности пакета. Хотя мы говорили, что регрессия позволяет восстановить пропущенные значения, мы всё же должны убрать их из обучающей выборки (строки, где встречается NaN): data=data.dropna() Проверим типы данных в колонках print(data.dtypes) На экране получим
Weight float64
Length1 float64 dtype: object Здесь данные заведомо приведены к одному типу. Иногда требуется использование функции to_numeric(), когда числовые на первый взгляд столбцы сохранены как символьные. Для удобства переименуем Length1 вне трогая остальную таблицу data=data.rename(columns={"Length1":
"Length"}, inplace = False) Для эксперимента нам потребуется разбить данные на две выборки обучающую (на которой будет тренироваться модель) и тестовую, с результатами которой мы будем сравнивать прогнозирование. Вы, наверное, уже заметили, что данные отсортированы повесу рыб. Есть два способа разделить выборку на две части оставить чётные записи в обучающей, а в тестовую вынести записи с нечётными индексами, второй
199 же способ заключается в создании случайного списка. Давайте перемешаем записи data
= shuffle(data) Переназначим красиво индексы, которые встряхнулись вместе с остальными данными, так как являются на самом деле нулевым столбцом таблицы, и посмотрим, как теперь выглядят данные (обратите внимание, что смешивание происходит случайным образом, ваш вывод может незначительно отличаться data=data.reset_index(drop=True) print(data) Всего есть 56 значений. Это число делится пополам, и мы можем взять первые 28 записей в обучающую выборку. Сразу приведём её к красивому виду, отсортировав по значениям веса и затем упорядочив индексы. data_train=data[:28] data_train=data_train.sort_values(by=['Weight']) data_train=data_train.reset_index(drop=True) print(data_train) Оставшиеся значения внесём в тестовую выборку. Поступаем аналогичным образом data_test=data[28:] data_test=data_test.sort_values(by=['Weight']) data_test=data_test.reset_index(drop=True) print(data_test) Инструмент ResearchPy
позволяет делать общие сводки поданным, куда сразу включается встречаемость разных значений. rp.summary_cat(data_train[['Weight','Length']])
200 При запуске сданной случайной выборкой у нас было целых 3 окуня длиной 20 см и 2 окуня по 19 см, а также по 2 рыбы весом по 1,1 кг и 1 кг и пос весами 820, 700 г и по 2 маленьких рыбки пои г. Выборка была достаточно маленькой, поэтому результаты не так интересны. Напоминаем, что выборка может несколько отличаться. Воспользуемся инструментом под названием ols — Ordinary least
squares
regression, регрессия с применением простого метода наименьших квадратов (МНК). Эту функцию мы находим в инструментарии пакета statsmodels. На вход в качестве параметров необходимо подать названия свойств, зависимость между которыми мы изучаем, а также указать источник данных. В нашем случае мы проверяем зависимость WeightLength на обучающей выборке model = smf.ols("WeightLength", data= data_train) model_results=model.fit() Чтобы узнать результаты и различные метрики, нам понадобится вывести на экран отчёт (см. Рис. 24): model_results.summary()
201 Рис. 24. Результаты работы модели Внимательно изучите показатель
R-squared. Первым идёт коэффициент детерминации R2. Напомним, что он принимает значение от 0 дои полученное значение 0.939 говорит нам явной зависимости между рассматриваемыми свойствами.
202 В данном примере
F-statistic имеет очень большое значение. Значение намного больше критического значения критерия Фишера, которое вы можете найти по специальной таблице как 4,22. Значит, гипотеза Н отвергается и принимается гипотеза Н. На практике обычно проверяют не само значение теста Фишера, а уровень значимости — вероятность p(F) того, что случайная величина сданным распределением Фишера превысит данное значение статистики. Если p(F) меньше уровня значимости alpha, то нулевая гипотеза Н отвергается. if model_results.f_pvalue < 0.05: Гипотеза Н отвергается. Зависимость значима с уровнем значимости alpha, гипотеза Н принимается) else: Зависимость не значима, гипотеза Н подтверждена) Гипотеза Н отвергается. Зависимость значима с уровнем значимости alpha, гипотеза Н принимается.
Перейдём к визуализации работы полученной модели. Сначала подготовим значения
x и
y для объектов обучающей, затем — тестовой выборки. Для удобства построения отсортируем данные по необходимым нам колонкам вес — для
y, длина — для
x. data_train