直播系統,利用關聯規則實現推薦演算法
關聯規則是以規則的方式呈現直播系統之間的相關性:關聯規則(Association Rules)是反映一個事物與其他事物之間的相互依存性和關聯性,是資料探勘的一個重要技術,用於從大量資料中挖掘出有價值的資料項之間的相關關係。
關聯規則的經典例子是透過發現顧客放入其購物籃中的不同商品之間的聯絡,可分析顧客在直播系統中的購買習慣。透過了解哪些商品頻繁地被顧客同時購買,可以幫助零售商制定營銷策略。
Apriori Algorithm(先驗)
它是一種購物車的分析方法,用於揭示產品之間的關聯關係。
他有三個簡單的公式:
Support(X, Y) = Freq(X, Y) / N :它表示 X 和 Y 一起出現的機率。它是 X 和 Y 一起出現的頻率除以 N。
Confidence(X, Y) = Freq(X, Y) / Freq(X) :表示購買產品X時購買產品Y的機率。X 和 Y 一起出現的頻率除以 X 出現的頻率。
Lift = Support(X, Y) / (Support(x) * Support (Y)) :當購買X時,購買Y的機率增加了lift的倍數。X 和 Y 一起出現的機率是 X 和 Y 分別出現的機率的乘積。它陳述了一個表示式,例如當我們購買一種產品時,購買另一種產品的機率會增加多少倍。
下面我們將使用Apriori Algorithm向使用者推薦相應的產品
資料預處理
這裡我們使用的資料集是online retail II dataset
!pip install mlxtend import pandas as pd pd.set_option('display.max_columns', None) pd.set_option('display.max_rows', None) pd.set_option('display.width', 500) # It ensures that the output is on one line. pd.set_option('display.expand_frame_repr', False) from mlxtend.frequent_patterns import apriori, association_rules df_ = pd.read_excel("datasets/online_retail_II.xlsx", sheet_name = "Year 2010-2011") df = df_.copy() df.info() # Column Non-Null Count Dtype # --- ------ -------------- ----- # 0 Invoice 541910 non-null object # 1 StockCode 541910 non-null object # 2 Description 540456 non-null object # 3 Quantity 541910 non-null int64 # 4 InvoiceDate 541910 non-null datetime64[ns] # 5 Price 541910 non-null float64 # 6 Customer ID 406830 non-null float64 # 7 Country 541910 non-null objectdf.head() # Invoice StockCode Description Quantity InvoiceDate Price Customer ID Country # 0 536365 85123A WHITE HANGING HEART T-LIGHT HOLDER 6 2010-12-01 08:26:00 2.55 17850.0 United Kingdom # 1 536365 71053 WHITE METAL LANTERN 6 2010-12-01 08:26:00 3.39 17850.0 United Kingdom # 2 536365 84406B CREAM CUPID HEARTS COAT HANGER 8 2010-12-01 08:26:00 2.75 17850.0 United Kingdom # 3 536365 84029G KNITTED UNION FLAG HOT WATER BOTTLE 6 2010-12-01 08:26:00 3.39 17850.0 United Kingdom # 4 536365 84029E RED WOOLLY HOTTIE WHITE HEART. 6 2010-12-01 08:26:00 3.39 17850.0 United Kingdom
我們使用這個函式來確定資料的閾值。
def outlier_thresholds(dataframe, variable): quartile1 = dataframe[variable].quantile(0.01) quartile3 = dataframe[variable].quantile(0.99) interquantile_range = quartile3 - quartile1 up_limit = quartile3 + 1.5 * interquantile_range low_limit = quartile1 - 1.5 * interquantile_range return low_limit, up_limit
下面這個函用閾值替換了異常值。
def replace_with_thresholds(dataframe, variable): low_limit, up_limit = outlier_thresholds(dataframe, variable) dataframe.loc[(dataframe[variable] < low_limit), variable] = low_limit dataframe.loc[(dataframe[variable] > up_limit), variable] = up_limit
第三個函式中我們從資料中提取包含“C”的值。“C”表示退回的物品。要計算總價,變數數量和價格必須大於零。在這個函式中還呼叫了 Outlier 和 Threshold 函式。
def retail_data_prep(dataframe): dataframe.dropna(inplace=True) dataframe = dataframe[~dataframe["Invoice"].str.contains("C", na=False)] dataframe = dataframe[dataframe["Quantity"] > 0] dataframe = dataframe[dataframe["Price"] > 0] replace_with_thresholds(dataframe, "Quantity") replace_with_thresholds(dataframe, "Price") return dataframedf = retail_data_prep(df)
準備購買-物品的矩陣
資料集中的收據(Invoice)包含了產品的購買,所以我們先處理這個
df_gr = df[df['Country'] == 'Germany'] df_gr.head() Invoice StockCode Description Quantity InvoiceDate Price Customer ID Country 1109 536527 22809 SET OF 6 T-LIGHTS SANTA 6.0 2010-12-01 13:04:00 2.95 12662.0 Germany 1110 536527 84347 ROTATING SILVER ANGELS T-LIGHT HLDR 6.0 2010-12-01 13:04:00 2.55 12662.0 Germany 1111 536527 84945 MULTI COLOUR SILVER T-LIGHT HOLDER 12.0 2010-12-01 13:04:00 0.85 12662.0 Germany 1112 536527 22242 5 HOOK HANGER MAGIC TOADSTOOL 12.0 2010-12-01 13:04:00 1.65 12662.0 Germany 1113 536527 22244 3 HOOK HANGER MAGIC GARDEN 12.0 2010-12-01 13:04:00 1.95 12662.0 Germany
根據 Invoice 和 Description,我們透過 groupby 計算 Quantities,可以計算產品的數量。
df_gr.groupby(['Invoice', 'Description']).agg({"Quantity": "sum"}).head(20) # Invoice Description # 536527 3 HOOK HANGER MAGIC GARDEN 12.0 # 5 HOOK HANGER MAGIC TOADSTOOL 12.0 # 5 HOOK HANGER RED MAGIC TOADSTOOL 12.0 # ASSORTED COLOUR LIZARD SUCTION HOOK 24.0 # CHILDREN'S CIRCUS PARADE MUG 12.0 # HOMEMADE JAM SCENTED CANDLES 12.0 # HOT WATER BOTTLE BABUSHKA 4.0 # JUMBO BAG OWLS 10.0 # JUMBO BAG WOODLAND ANIMALS 10.0 # MULTI COLOUR SILVER T-LIGHT HOLDER 12.0 # PACK 3 FIRE ENGINE/CAR PATCHES 12.0 # PICTURE DOMINOES 12.0 # POSTAGE 1.0 # ROTATING SILVER ANGELS T-LIGHT HLDR 6.0 # SET OF 6 T-LIGHTS SANTA 6.0 # 536840 6 RIBBONS RUSTIC CHARM 12.0 # 60 CAKE CASES VINTAGE CHRISTMAS 24.0 # 60 TEATIME FAIRY CAKE CASES 24.0 # CAKE STAND WHITE TWO TIER LACE 2.0 # JAM JAR WITH GREEN LID 12.0
我們使用 unstack 來避免重複的索引,使用 iloc 來顯示前 5 個觀察結果。如果產品不在收據中,則 使用NA 表示。
df_gr.groupby(['Invoice', 'Description']).agg({"Quantity": "sum"}).unstack().iloc[0:5, 0:5] # Description 50'S CHRISTMAS GIFT BAG LARGE DOLLY GIRL BEAKER I LOVE LONDON MINI BACKPACK RED SPOT GIFT BAG LARGE SET 2 TEA TOWELS I LOVE LONDON # Invoice # 536527 NaN NaN NaN NaN NaN # 536840 NaN NaN NaN NaN NaN # 536861 NaN NaN NaN NaN NaN # 536967 NaN NaN NaN NaN NaN # 536983 NaN NaN NaN NaN NaN
進行獨熱編碼。把 NA 的地方寫 0。
df_gr.groupby(['Invoice', 'Description']).agg({"Quantity": "sum"}).unstack().fillna(0).iloc[0:5, 0:5] # Description 50'S CHRISTMAS GIFT BAG LARGE DOLLY GIRL BEAKER I LOVE LONDON MINI BACKPACK RED SPOT GIFT BAG LARGE SET 2 TEA TOWELS I LOVE LONDON # Invoice # 536527 0.0 0.0 0.0 0.0 0.0 # 536840 0.0 0.0 0.0 0.0 0.0 # 536861 0.0 0.0 0.0 0.0 0.0 # 536967 0.0 0.0 0.0 0.0 0.0 # 536983 0.0 0.0 0.0 0.0 0.0
如果發票中的產品數量大於0,我們就寫1,如果小於0或0,我們就寫0。用apply對行或列進行操作。這裡將透過應用 applymap 並執行操作來遍歷所有單元格。
df_gr.groupby(['Invoice', 'Description']).agg({"Quantity": "sum"}).unstack().fillna(0).applymap(lambda x: 1 if x > 0 else 0).iloc[0:5, 0:5] # Description 50'S CHRISTMAS GIFT BAG LARGE DOLLY GIRL BEAKER I LOVE LONDON MINI BACKPACK RED SPOT GIFT BAG LARGE SET 2 TEA TOWELS I LOVE LONDON # Invoice # 536527 0 0 0 0 0 # 536840 0 0 0 0 0 # 536861 0 0 0 0 0 # 536967 0 0 0 0 0 # 536983 0 0 0 0 0
我們建立了一個名為 create_invoice_df 的函式。如果想根據id變數搜尋並得到結果,它會根據stockcode進行與上述相同的操作。如果我們輸入的id為False,它會根據Description執行上面的操作。
def create_invoice_product_df(dataframe, id=False): if id: return dataframe.groupby(['Invoice', "StockCode"])['Quantity'].sum().unstack().fillna(0). \ applymap(lambda x: 1 if x > 0 else 0) else: return dataframe.groupby(['Invoice', 'Description'])['Quantity'].sum().unstack().fillna(0). \ applymap(lambda x: 1 if x > 0 else 0) gr_inv_pro_df = create_invoice_product_df(df_gr) gr_inv_pro_df.head(20) gr_inv_pro_df = create_invoice_product_df(df_gr, id=True) gr_inv_pro_df.head() def check_id(dataframe, stock_code): product_name = dataframe[dataframe["StockCode"] == stock_code][["Description"]].values[0].tolist() print(product_name) check_id(df_gr, 16016) # ['LARGE CHINESE STYLE SCISSOR']
所有可能的產品組合
frequent_itemsets = apriori(gr_inv_pro_df, min_support=0.01, use_colnames=True) frequent_itemsets.sort_values("support", ascending=False).head() # support itemsets # 538 0.818381 (POST) # 189 0.245077 (22326) # 1864 0.225383 (POST, 22326) # 191 0.157549 (22328) # 1931 0.150985 (22328, POST) check_id(df_gr, 22328) #['ROUND SNACK BOXES SET OF 4 FRUITS ']
透過將我們用 Apriori 找到的Support插入到 association_rules 函式中,找到一些其他的統計資料,例如置信度和提升度。
rules = association_rules(frequent_itemsets, metric="support", min_threshold=0.01) rules.sort_values("support", ascending=False).head()
POST產品和編號為22326的產品同時出現的機率為0.225383。被一起買的機率是0.275401。同時購買這兩種產品的機率增加為1.123735。
# antecedents consequents antecedent support consequent support support confidence lift leverage conviction # 2650 (POST) (22326) 0.818381 0.245077 0.225383 0.275401 1.123735 0.024817 1.041850 # 2651 (22326) (POST) 0.245077 0.818381 0.225383 0.919643 1.123735 0.024817 2.260151 # 2784 (22328) (POST) 0.157549 0.818381 0.150985 0.958333 1.171012 0.022049 4.358862 # 2785 (POST) (22328) 0.818381 0.157549 0.150985 0.184492 1.171012 0.022049 1.033038 # 2414 (22328) (22326) 0.157549 0.245077 0.131291 0.833333 3.400298 0.092679 4.529540
以上就是直播系統,利用關聯規則實現推薦演算法, 更多內容歡迎關注之後的文章