Market Basket Analysis with SQL Server ML Services

接續 GLM(General Linear Model)與預防性維修,本篇要來介紹西元2000年最讓人津津樂道的購物籃分析(啤酒與尿布)關聯規則(APRIORI)演算法,這是一個要學產品推薦的建議起手式,尤其是在電商百家爭鳴的時代。此次的環境還是用到了Azure上的VM template,其版本為 SQL Server 2017(R3.3.3)

APRIORI 是一個發展的比較久的演算法,它的好處是不用很巨量的資料也能算,它有三個主要的 hyper-parameter(超參數),定義如下:
Support(支持度):在所有事件發生的狀況下,同時發生A、B事件的機率=P(B∩A)。換句話說,我們可以透過某個規則或關聯性在資料集中出現的頻率,來評估其代表母體的支持性是夠高?
Confidence(信心水準):在A事件發生的狀況下,同時發生A、B事件的機率=條件機率 = P(B∣A)A。換句話說,我們可以透過觀察這個數值,來評估其因果的關聯性是否夠高?
Lift(增益值):A、B事件的因果關係 Confidence / Expected Confidence。當Lift值>1,則A與B間有正向關係;當Lift值<1,則A與B間為負向關係;當Lift值=1,則A與B間沒有關係
上述科學的定義可能很難消化,我們來舉一個生活的例子。假設某超級市場有100個客戶,其中10個買了牛奶,8個買奶油;再其中有6個是同時二個都買。
很明顯地這二個產品被購買的行為是有關聯的,若我們從先買牛奶再買奶油的探討這件事(反方向也可以算喔!端看你要從什麼角度來運算)
Support = 同時買牛奶與奶油的機率 = 6/100 = 0.06
Confidence = 若發生買牛奶的事件這二個產品同時被買的機率 = Support除以買奶油的機率 = 0.06/0.08 = 0.75
Lift = 買牛奶與買奶油的因果關係 = Confindence除以買牛奶的機率 = 0.75/0.10 = 7.5 (大於1就表示正相關)

至於結果分析的,除了會將這三個超參數的機率列在後面,還會將產品以LHS(left hand side)RHS(right hand side)的方式來呈現。舉例,相對於左手買了可口可樂,右手會隨著買樂事洋芋片。實務上你就可以透過某個商品在LHS或RHS,來了解買某個商品之後會接著買什麼?來了解買某個商品之前會先買什麼?


以下是此次的訓練資料集,裡面是大賣場的交易記錄,經過特徵工程,我只留下了三個欄位,包括:訂單號碼、客戶編號、商品名稱
至於什麼是特徵工程?就跟做BI很像,為了不要garbage in garbage out,你需要篩選欄位。或是收斂結果你把牛、馬、羊…等動物歸納為草食動物,甚至做一些減少欄位的降維dimension reduction動作…等

**若你對於 R的指令操作還不熟,建議你先安插一篇之前介紹GLM的文章,以免跟不上。

由於 R是基礎於開源的環境,不管是架構上、使用上會跟以往被微軟服務的好好的情況不太一樣。在開始之前先要去了解一些相依性,在RGUI上方的Help按鈕叫出來問(或是下達指令help.start())。果然,在
線上指南馬上告訴我們,Apriori函式(演算法)需要在 R3.4.0以上的版本才能用…
其實升級是有分Package函式庫與RGUI的升級,從RGUI上面Package做升級只能滿足前者,需要將「installr」函式庫加進來,你就能透過UI或是指令來升級

# installing/loading the package:
if(!require(installr)) { install.packages("installr"); require(installr)} 
#load / install+load installr

#=========  step by step  ============== 

check.for.updates.R() 
#tells you if there is a new version of R or not.
install.R() 
#download and run the latest R installer
copy.packages.between.libraries() 
#copy your packages to the newest R installation

上面介紹了二種指令,在=======分隔線以上的是只做 R平台的升級;以下是先做 R平台的升級,再做函式庫的升級它會跳出一個網頁,列出更新了哪些項目、修復了哪些Bug…我們需要再回到剛才的彈出視窗,繼續下載與安裝動作

不管你選擇下達一步到位或是分解動作的指令,反正就是完成升級動作。
關閉RGUI再重開,雖然平台與函式庫已經升級至 3.6.1,但是Apriori是歸屬於之前還沒有安裝的函式庫,所以還需要手動安裝它…
從RGUI上方的Package找到Install選項package(s)...
先選下載點
再選什麼套件?
接著就可以執行以下指令

library (arules)
library(arulesViz)
library(tidyr)
library(dplyr)

dataset1<-read.csv(file="C:/Users/christian/Documents/TRAIN-ARULES.csv",header=TRUE,sep=",");
aggdata<-split(dataset1$product_name,dataset1$order_id)
tr<-as(aggdata,"transactions")
rules <- apriori(tr, parameter = list(supp = 0.01, conf = 0.8,target="rules"))
rules <- sort(rules, by="lift", decreasing=TRUE)

plot(rules)
plot(rules, method = "graph", control = list(verbose = TRUE))

首先是載入函式庫至記憶體,然後把Training data讀取至 data frame。
請注意在R語言中,路徑符號跟Windows不太一樣,若你是從檔案總管直接複製,要幫它換邊喔!從"\"換成"/"
接著再做一些資料轉換,並且把 Class變成Transcations,就能呼叫apriori函式產生關聯規則。並且依據Lift做遞減排序

在上圖中,可以發現系統在近13000筆資料,找出了34組規則。
觀察一下這34個規則或關係,可以發現幾個最佳配角(買有些產品會順便搭配)還不少…例如Dark Chocolate Minis, Organic Pink Lemonade Fruit Snacks, Peach-Pear Sparking Water
以下的指令就是,當我們想分析客戶在買了迷你黑巧克力棒,接下來會買什麼?以及買迷你黑巧克力棒之前,會想買什麼?
rules <- apriori (data=tr, parameter=list (supp=0.01,conf = 0.8), appearance = list (default="rhs",lhs="Dark Chocolate Minis"), control = list (verbose=F))
rules <- apriori (data=tr, parameter=list (supp=0.01,conf = 0.8), appearance = list (default="lhs",rhs="Dark Chocolate Minis"), control = list (verbose=F))

請注意,由於指令只是設定參數值跟顯示無關,所以呈現的方式還是維持先show出 LHS接著才是 RHS
但是基於信心水準與支持度的參數值,並非一定能算出你預期的結果。例如在這近13000筆資料中,可以找出買迷你黑巧克力棒之前,會先買什麼?但是反向,之後會買什麼卻沒有幾筆記錄,所以算不出來
再用 plot函數來畫散佈圖

High level是呈現規則與信心水準的分佈,Details是呈現規則是包含哪些品項?
補充一下,當你想要分析sample data除了用 Excel看,也可以用 summary指令來分析。來觀察其最小值、最大值、中位數、平均數…

a<-intersect(itemLabels(rules),Itembasket)
rulesMatchLHS <- subset(rules,lhs%ain% a)

if (nrow(rulesMatchLHS@quality)==0)
{
  OutputClient =data.frame(  lhs = c('The product does not match other item baskets'),                       
                             rhs = c('No recommendations available'))
} else if (nrow(rulesMatchLHS@quality)>0)
{
OutputClient =data.frame(  lhs = labels(lhs(rulesMatchLHS))$elements,                       
                             rhs = labels(rhs(rulesMatchLHS))$elements,
                             rulesMatchLHS@quality)
}

可惜這個資料集只有三個欄位下面有一些有些很典型的圖例這次畫不出來,只好先上網抓一下。找一天我把資料集換一個多一點欄位的,重做一次

李秉錡 Christian Lee
Once worked at Microsoft Taiwan