日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【实用算法教学】——Apriori算法,教你使用亲和性分析方法推荐电影

發(fā)布時(shí)間:2024/1/8 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【实用算法教学】——Apriori算法,教你使用亲和性分析方法推荐电影 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文學(xué)習(xí)如何用親和性分析方法找出在什么情況下兩個(gè)對(duì)象經(jīng)常一起出現(xiàn)。通俗來講,這也 叫“購物籃分析”,因?yàn)樵腥擞盟页瞿男┥唐方?jīng)常一起出售。 前一篇文章關(guān)注的對(duì)象為球隊(duì),并用特征描述球隊(duì)。本文所用到的電影評(píng)分?jǐn)?shù)據(jù)有所不同,我們 所關(guān)注的對(duì)象(電影)埋在數(shù)據(jù)中。本章數(shù)據(jù)挖掘任務(wù)的目標(biāo)是找出對(duì)象同時(shí)出現(xiàn)的情況,也就 是尋找用戶同時(shí)喜歡幾部電影的情況。 本文主要涉及以下幾個(gè)概念。 ? 親和性分析 ? Apriori 算法挖掘關(guān)聯(lián)特征 ? 電影推薦 ? 數(shù)據(jù)稀疏問題


一 親和性分析

親和性分析用來找出兩個(gè)對(duì)象共同出現(xiàn)的情況。而前文,我們關(guān)注的是同種對(duì)象之間的相似度。親和性分析所用的數(shù)據(jù)通常為類似于交易信息的數(shù)據(jù)。從直觀上來看,這些數(shù)據(jù)就像是商店的交易數(shù)據(jù)—— 從中能看出哪些商品是顧客一起購買的。 然而,親和性分析方法的應(yīng)用場(chǎng)景有很多,比如: ? 欺詐檢測(cè) ? 顧客區(qū)分 ? 軟件優(yōu)化 ? 產(chǎn)品推薦 親和性分析比分類更具探索性,因?yàn)橥ǔN覀儫o法拿到像在很多分類任務(wù)中所用的那樣完整 的數(shù)據(jù)集。例如,在電影推薦任務(wù)中,我們拿到的是不同用戶對(duì)不同電影的評(píng)價(jià)。但是,每個(gè)用 戶不可能評(píng)價(jià)過所有電影,這就給親和性分析帶來一個(gè)不容忽視的大難題。如果用戶沒有評(píng)價(jià)過 一部電影,是因?yàn)樗麄儾幌矚g這部電影(據(jù)此就不推薦給他們),還是因?yàn)樗麄兂鲇趧e的原因還 沒有評(píng)價(jià)? 本文不對(duì)上述問題做出解答,但是我們要思考數(shù)據(jù)集中類似這樣的潛在問題該怎么解決。這 些思考有助于提升推薦算法的準(zhǔn)確性。

二 親和性分析算法

基礎(chǔ)的親和性分析算法,嘗試了所有可能的規(guī)則組合,計(jì)算了每條規(guī)則的置信度和支持度,并根據(jù)這兩個(gè)標(biāo)準(zhǔn)進(jìn)行排序,選取最佳規(guī)則。 然而,這個(gè)方法效率不高。即使是再不起眼的小賣鋪出售的商品也達(dá)上百種之多,網(wǎng)店更是有成千上萬種 商品(甚至幾百萬種!)。如果規(guī)則生成方法 過于簡(jiǎn)單,計(jì)算這些規(guī)則所需要的時(shí)間復(fù)雜度將呈指數(shù)級(jí)增長(zhǎng)。隨著商品數(shù)量的增加,計(jì)算所有規(guī)則所需的時(shí)間增長(zhǎng)得很快。 。數(shù)據(jù)集有 5 個(gè)特征,可能的規(guī)則就有 31 條;有 10 個(gè)特征,可能的規(guī)則就有1023 條;僅僅有 100 個(gè)特征,規(guī)則數(shù)就能達(dá)到 30 位數(shù)字。即使計(jì)算能力大幅提升也未必能趕上在線商品的增長(zhǎng)速度。因此,與其跟計(jì)算機(jī)過不去,不如尋找更加聰明的算法。 Apriori 算法可以說是經(jīng)典的親和性分析算法。它只從數(shù)據(jù)集中頻繁出現(xiàn)的商品中選取共同出現(xiàn)的商品組成頻繁項(xiàng)集 frequent itemset ),避免了上述復(fù)雜度呈指數(shù)級(jí)增長(zhǎng)的問題。一旦找到頻繁項(xiàng)集,生成關(guān)聯(lián)規(guī)則就很容易了。 Apriori 算法背后的原理簡(jiǎn)潔卻不失巧妙。首先,確保了規(guī)則在數(shù)據(jù)集中有足夠的 支持度 。 Apriori算法的一個(gè)重要參數(shù)就是最小支持度。比如,要生成包含商品 A B 的頻繁項(xiàng)集( A, B ),要求支持度至少為30 ,那么 A B 都必須至少在數(shù)據(jù)集中出現(xiàn) 30 次。更大的頻繁項(xiàng)集也要遵守該項(xiàng)約定,比如要生成頻繁項(xiàng)集(A, B, C, D ),那么子集 (A, B, C) 必須是頻繁項(xiàng)集(當(dāng)然 D 自己也 要滿足最小支持度標(biāo)準(zhǔn))。 生成 頻繁項(xiàng)集 后,將不再考慮其他可能的卻不夠頻繁的項(xiàng)集(這樣的集合有很多),從而大 大減少測(cè)試新規(guī)則所需的時(shí)間。 其他親和性分析算法有 Eclat 頻繁項(xiàng)集挖掘算法 FP-growth )。從數(shù)據(jù)挖掘角度看,這些 算法比起基礎(chǔ)的 Apriori 算法有很多改進(jìn),性能也有進(jìn)一步提升。接下來,先來看一下最基礎(chǔ)的 Apriori 算法。

三 選擇參數(shù)

挖掘親和性分析所用的關(guān)聯(lián)規(guī)則之前,我們先用Apriori算法生成頻繁項(xiàng)集。接著,通過檢測(cè)頻繁項(xiàng)集中前提和結(jié)論的組合,生成關(guān)聯(lián)規(guī)則(例如,如果用戶喜歡電影X,那么他很可能喜歡電影Y)。

第一個(gè)階段,需要為 Apriori 算法指定一個(gè)項(xiàng)集要成為頻繁項(xiàng)集所需的最小支持度。任何小于最小支持度的項(xiàng)集將不再考慮。如果最小支持度值過小,Apriori 算法要檢測(cè)大量的項(xiàng)集,會(huì)拖慢的運(yùn)行速度;最小支持度值過大的話,則只有很少的頻繁項(xiàng)集。 找出頻繁項(xiàng)集后,在第二個(gè)階段,根據(jù)置信度選取關(guān)聯(lián)規(guī)則。可以設(shè)定最小置信度,返回一 部分規(guī)則,或者返回所有規(guī)則,讓用戶自己選。 本文,我們?cè)O(shè)定最小置信度,只返回高于它的規(guī)則。置信度過低將會(huì)導(dǎo)致規(guī)則支持度高,正確率低;置信度過高,導(dǎo)致正確率高,但是返回的規(guī)則少。

四 電影推薦問題

產(chǎn)品推薦技術(shù)是門大生意。網(wǎng)店經(jīng)常用它向潛在用戶推薦他們可能購買的產(chǎn)品。好的推薦算法能帶來更高的銷售業(yè)績(jī)。每年有幾百萬乃至幾千萬用戶進(jìn)行網(wǎng)購,向他們推薦更多的商品,潛在收益著實(shí)可觀。 產(chǎn)品推薦問題被人們研究了多年,但它一直不溫不火,直到 2007 年到 2009 年間, Netflix 公司推出數(shù)據(jù)建模大賽,并設(shè)立Netflix Prize 獎(jiǎng)項(xiàng)之后,才得到迅猛發(fā)展。該競(jìng)賽意在尋找比 Netflix公司所使用的預(yù)測(cè)用戶為電影打分的系統(tǒng)更準(zhǔn)確的解決方案。最后獲獎(jiǎng)隊(duì)伍以比現(xiàn)有系統(tǒng)高10個(gè)百分點(diǎn)的優(yōu)勢(shì)勝出。雖然這個(gè)改進(jìn)看起來不是很大,但是Netflix 公司卻能借助它實(shí)現(xiàn)更精準(zhǔn)的電影推薦服務(wù),從而多賺上百萬美元。

六 獲取數(shù)據(jù)集

自打 Netflix Prize 獎(jiǎng)項(xiàng)設(shè)立以來,美國(guó)明尼蘇達(dá)大學(xué)的 Grouplens 研究團(tuán)隊(duì)公開了一系列用于 測(cè)試推薦算法的數(shù)據(jù)集。其中,就包括幾個(gè)大小不同的電影評(píng)分?jǐn)?shù)據(jù)集,分別有 10 萬、 100 萬和 1000 萬條電影評(píng)分?jǐn)?shù)據(jù)。 數(shù)據(jù)集下載地址為 http://grouplens.org/datasets/movielens/ 。本文將使用包含 100 萬條數(shù)據(jù)的 MovieLens 數(shù)據(jù)集。下載數(shù)據(jù)集,解壓到你的 Data 文件夾。啟動(dòng) IPython Notebook 筆記本,輸入以 下代碼。 import os import pandas as pd data_folder = os.path.join(os.path.expanduser("~"), "Data", "ml-100k") ratings_filename = os.path.join(data_folder, "u.data") 確保 ratings_filename 指向解壓后得到的文件夾中的 u.data 文件。

七 用?pandas 加載數(shù)據(jù)

MovieLens數(shù)據(jù)集非常規(guī)整,但是有幾點(diǎn)跟pandas.read_csv方法的默認(rèn)設(shè)置有出入,所以要調(diào)整參數(shù)設(shè)置。第一個(gè)問題是數(shù)據(jù)集每行的幾個(gè)數(shù)據(jù)之間用制表符而不是逗號(hào)分隔。其次,沒有表頭,這表示數(shù)據(jù)集的第一行就是數(shù)據(jù)部分,我們需要手動(dòng)為各列添加名稱。

加載數(shù)據(jù)集時(shí),把分隔符設(shè)置為制表符,告訴 pandas 不要把第一行作為表頭( header=None ), 設(shè)置好各列的名稱。代碼如下: all_ratings = pd.read_csv(ratings_filename, delimiter="\t", header=None, names = ["UserID", "MovieID", "Rating", "Datetime"]) 雖然本文用不到,還是稍微提一下,你可以用下面的代碼解析時(shí)間戳數(shù)據(jù)。 all_ratings["Datetime"] = pd.to_datetime(all_ratings['Datetime'], unit='s') 運(yùn)行下面的代碼,看一下前五條記錄。 all_ratings[:5] 輸出結(jié)果如下

?八?稀疏數(shù)據(jù)格式

這是一個(gè)稀疏數(shù)據(jù)集,我們可以將每一行想象成巨大特征矩陣的一個(gè)格子,在這個(gè)矩陣中,每一行表示一個(gè)用戶,每一列為一部電影。第一列為每一個(gè)用戶給第一部電影打的分?jǐn)?shù),第二列為每一個(gè)用戶給第二部電影打的分?jǐn)?shù),以此類推。

數(shù)據(jù)集中有 1000 名用戶和 1700 部電影,這就意味著整個(gè)矩陣很大。將矩陣讀到內(nèi)存中及在它 基礎(chǔ)上進(jìn)行計(jì)算可能存在難度。然而,這個(gè)矩陣的很多格子都是空的,也就是對(duì)大部分用戶來說, 他們只給少數(shù)幾部電影打過分。比如用戶 #213 沒有為電影 #675 打過分,大部分用戶沒有為大部分 電影打過分。 用上述圖表中的格式也能表示矩陣,且更為緊湊。序號(hào)為 0 的那一行表示,用戶 #196 1997 12 4 日為電影 #242 打了 3 分(滿分是 5 分)。 任何沒有出現(xiàn)在數(shù)據(jù)集中的用戶和電影組合表示它們實(shí)際上是不存在的。這比起在內(nèi)存中保 存大量的 0 ,節(jié)省了很多空間。這種格式叫作 稀疏矩陣 sparse matrix )。根據(jù)經(jīng)驗(yàn)來說,如果數(shù) 據(jù)集中 60% 或以上的數(shù)據(jù)為 0 ,就應(yīng)該考慮使用稀疏矩陣,從而節(jié)省不少空間。 在對(duì)稀疏矩陣進(jìn)行計(jì)算時(shí),我們關(guān)注的通常不是那些不存在的數(shù)據(jù),不會(huì)去比較眾多的 0 值, 相反我們關(guān)注的是現(xiàn)有數(shù)據(jù),并對(duì)它們進(jìn)行比較。


九 Apriori 算法的實(shí)現(xiàn)

本章數(shù)據(jù)挖掘的目標(biāo)是生成如下形式的規(guī)則: 如果用戶喜歡某些電影,那么他們也會(huì)喜歡這 部電影 。作為對(duì)上述規(guī)則的擴(kuò)展,我們還將討論喜歡某幾部電影的用戶,是否喜歡另一部電影。 要解決以上問題,首先要確定用戶是不是喜歡某一部電影。為此創(chuàng)建新特征 Favorable ,若 用戶喜歡該電影,值為 True all_ratings["Favorable"] = all_ratings["Rating"] > 3 我們?cè)跀?shù)據(jù)集中看一下這個(gè)新特征。 all_ratings[10:15]

?從數(shù)據(jù)集中選取一部分?jǐn)?shù)據(jù)用作訓(xùn)練集,這能有效減少搜索空間,提升Apriori算法的速度。 我們?nèi)∏?00名用戶的打分?jǐn)?shù)據(jù)。

ratings = all_ratings[all_ratings['UserID'].isin(range(200))] 接下來,新建一個(gè)數(shù)據(jù)集,只包括用戶喜歡某部電影的數(shù)據(jù)行。 favorable_ratings = ratings[ratings["Favorable"]] 在生成項(xiàng)集時(shí),需要搜索用戶喜歡的電影。因此,接下來,我們需要知道每個(gè)用戶各喜歡哪 些電影,按照 User ID 進(jìn)行分組,并遍歷每個(gè)用戶看過的每一部電影。 favorable_reviews_by_users = dict((k, frozenset(v.values)) for k, v in favorable_ratings groupby("UserID")["MovieID"]) 上面的代碼把 v.values 存儲(chǔ)為 frozenset,便于快速判斷用戶是否為某部電影打過分。對(duì)于這種操作,集合比列表速度快。 最后,創(chuàng)建一個(gè)數(shù)據(jù)框,以便了解每部電影的影迷數(shù)量。 num_favorable_by_movie = ratings[["MovieID", "Favorable"]]. groupby("MovieID").sum() 用以下代碼查看最受歡迎的五部電影。 num_favorable_by_movie.sort("Favorable", ascending=False)[:5] 輸出結(jié)果如下:

十 Apriori 算法

Apriori 算法是親和性分析的一部分,專門用于查找數(shù)據(jù)集中的頻繁項(xiàng)集。基本流程是從前一步找到的頻繁項(xiàng)集中找到新的備選集合,接著檢測(cè)備選集合的頻繁程度是否夠高,然后算法像下面這樣進(jìn)行迭代。 (1) 把各項(xiàng)目放到只包含自己的項(xiàng)集中,生成最初的頻繁項(xiàng)集。只使用達(dá)到最小支持度的項(xiàng)目。 (2) 查找現(xiàn)有頻繁項(xiàng)集的超集,發(fā)現(xiàn)新的頻繁項(xiàng)集,并用其生成新的備選項(xiàng)集。 (3) 測(cè)試新生成的備選項(xiàng)集的頻繁程度,如果不夠頻繁,則舍棄。如果沒有新的頻繁項(xiàng)集, 就跳到最后一步。 (4) 存儲(chǔ)新發(fā)現(xiàn)的頻繁項(xiàng)集,跳到步驟 (2) (5) 返回發(fā)現(xiàn)的所有頻繁項(xiàng)集。 整個(gè)過程表示如下。

十一 實(shí)現(xiàn)

Apriori算法第一次迭代時(shí),新發(fā)現(xiàn)的項(xiàng)集長(zhǎng)度為2,它們是步驟(1)中創(chuàng)建的項(xiàng)集的超集。第二次迭代(經(jīng)過步驟(4))中,新發(fā)現(xiàn)的項(xiàng)集長(zhǎng)度為3。這有助于我們快速識(shí)別步驟(2)所需的項(xiàng)集。

我們把發(fā)現(xiàn)的頻繁項(xiàng)集保存到以項(xiàng)集長(zhǎng)度為鍵的字典中,便于根據(jù)長(zhǎng)度查找,這樣就可以找到最新發(fā)現(xiàn)的頻繁項(xiàng)集。下面的代碼初始化一個(gè)字典。

frequent_itemsets = {} 我們還需要確定項(xiàng)集要成為頻繁項(xiàng)集所需的最小支持度。這個(gè)值需要根據(jù)數(shù)據(jù)集的具體情況 來設(shè)定,可自行嘗試其他值,建議每次只改動(dòng) 10 個(gè)百分點(diǎn),即使這樣你可能也會(huì)發(fā)現(xiàn)算法運(yùn)行時(shí) 間變動(dòng)很大!下面,設(shè)置最小支持度。 min_support = 50 我們先來實(shí)現(xiàn) Apriori 算法的第一步,為每一部電影生成只包含它自己的項(xiàng)集,檢測(cè)它是否夠 頻繁。電影編號(hào)使用 frozenset ,后面要用到集合操作。此外,它們也可以用作字典的鍵(普通 集合不可以)。代碼如下: frequent_itemsets[1] = dict((frozenset((movie_id,)), row["Favorable"]) for movie_id, row in num_favorable_ by_movie.iterrows() if row["Favorable"] > min_support) 接著,用一個(gè)函數(shù)來實(shí)現(xiàn)步驟 (2) (3) ,它接收新發(fā)現(xiàn)的頻繁項(xiàng)集,創(chuàng)建超集,檢測(cè)頻繁程 度。下面為函數(shù)聲明及字典初始化代碼。 from collections import defaultdict def find_frequent_itemsets(favorable_reviews_by_users, k_1_itemsets, min_support): counts = defaultdict(int)

經(jīng)驗(yàn)告訴我們,要盡量減少遍歷數(shù)據(jù)的次數(shù),所以每次調(diào)用函數(shù)時(shí),再遍歷數(shù)據(jù)。這樣做效果不是很明顯(因?yàn)閿?shù)據(jù)集相對(duì)較小),但是數(shù)據(jù)集更大的情況下,就很有必要。我們來遍歷所有用戶和他們的打分?jǐn)?shù)據(jù)。

for user, reviews in favorable_reviews_by_users.items(): 接著,遍歷前面找出的項(xiàng)集,判斷它們是否是當(dāng)前評(píng)分項(xiàng)集的子集。如果是,表明用戶已經(jīng) 為子集中的電影打過分。代碼如下: for itemset in k_1_itemsets: if itemset.issubset(reviews): 接下來,遍歷用戶打過分卻沒有出現(xiàn)在項(xiàng)集里的電影,用它生成超集,更新該項(xiàng)集的計(jì)數(shù)。 代碼如下: for other_reviewed_movie in reviews - itemset: current_superset = itemset | frozenset((other_ reviewed_movie,)) counts[current_superset] += 1 函數(shù)最后檢測(cè)達(dá)到支持度要求的項(xiàng)集,看它的頻繁程度夠不夠,并返回其中的頻繁項(xiàng)集。 return dict([(itemset, frequency) for itemset, frequency in counts.items() if frequency >= min_support]) 創(chuàng)建循環(huán),運(yùn)行 Apriori 算法,存儲(chǔ)算法運(yùn)行過程中發(fā)現(xiàn)的新項(xiàng)集。循環(huán)體中, k 表示即將發(fā) 現(xiàn)的頻繁項(xiàng)集的長(zhǎng)度,用鍵 k ? 1 可以從 frequent_itemsets 字典中獲取剛發(fā)現(xiàn)的頻繁項(xiàng)集。新 發(fā)現(xiàn)的頻繁項(xiàng)集以長(zhǎng)度為鍵,將其保存到字典中。代碼如下: for k in range(2, 20): cur_frequent_itemsets = find_frequent_itemsets(favorable_reviews_by_users, frequent_itemsets[k-1], min_support) frequent_itemsets[k] = cur_frequent_itemsets 如果在上述循環(huán)中沒能找到任何新的頻繁項(xiàng)集,就跳出循環(huán)(輸出信息,告知我們沒能找到 長(zhǎng)度為 k 的頻繁項(xiàng)集) if len(cur_frequent_itemsets) == 0: print("Did not find any frequent itemsets of length {}". format(k)) sys.stdout.flush() break 如果確實(shí)找到了頻繁項(xiàng)集,我們也讓程序輸出信息,告知我們它會(huì)再次運(yùn)行。因?yàn)樗惴ㄟ\(yùn)行 時(shí)間很長(zhǎng),所以每隔一段時(shí)間輸出一下狀態(tài)是很有必要的!代碼如下: else: print("I found {} frequent itemsets of length {}".format(len(cur_frequent_itemsets), k)) sys.stdout.flush() 最后,循環(huán)結(jié)束,我們對(duì)只有一個(gè)元素的項(xiàng)集不再感興趣 —— 它們對(duì)生成關(guān)聯(lián)規(guī)則沒有用 —— 生成關(guān)聯(lián)規(guī)則至少需要兩個(gè)項(xiàng)目。刪除長(zhǎng)度為 1 的項(xiàng)集。代碼如下: del frequent_itemsets[1] 上面這些代碼要好幾分鐘才能運(yùn)行完,老機(jī)器需要的時(shí)間更長(zhǎng)。如果你在本地運(yùn)行代碼有問 題,可以考慮使用云主機(jī)提升速度。 上述代碼返回了不同長(zhǎng)度的 1718 個(gè)頻繁項(xiàng)集。你也許會(huì)發(fā)現(xiàn)隨著項(xiàng)集長(zhǎng)度的增加,項(xiàng)集數(shù)隨 著可用規(guī)則的增加而增長(zhǎng)一段時(shí)間后才開始變少,減少是因?yàn)轫?xiàng)集達(dá)不到最低支持度要求。項(xiàng)集 的減少是 Apriori 算法的優(yōu)點(diǎn)之一。如果我們搜索所有可能的項(xiàng)集(不只是頻繁項(xiàng)集的超集),判 斷多余項(xiàng)集的頻繁程度需要成千上萬次查詢。

十二 抽取關(guān)聯(lián)規(guī)則

Apriori算法結(jié)束后,我們得到了一系列頻繁項(xiàng)集,這還不算是真正意義上的關(guān)聯(lián)規(guī)則,但是很接近了。頻繁項(xiàng)集是一組達(dá)到最小支持度的項(xiàng)目,而關(guān)聯(lián)規(guī)則由前提和結(jié)論組成。 我們可以從頻繁項(xiàng)集中抽取出關(guān)聯(lián)規(guī)則,把其中幾部電影作為前提,另一部電影作為結(jié)論組成如下形式的規(guī)則:

如果用戶喜歡前提中的所有電影,那么他們也會(huì)喜歡結(jié)論中的電影。

每一個(gè)項(xiàng)集都可用這種方式生成一條規(guī)則。 下面的代碼通過遍歷不同長(zhǎng)度的頻繁項(xiàng)集,為每個(gè)項(xiàng)集生成規(guī)則。 candidate_rules = [] for itemset_length, itemset_counts in frequent_itemsets.items(): for itemset in itemset_counts.keys(): 然后,遍歷項(xiàng)集中的每一部電影,把它作為結(jié)論。項(xiàng)集中的其他電影作為前提,用前提和結(jié) 論組成備選規(guī)則。 for conclusion in itemset: premise = itemset - set((conclusion,)) candidate_rules.append((premise, conclusion)) 這樣就能得到大量備選規(guī)則。通過以下代碼查看前五條規(guī)則。 print(candidate_rules[:5]) 輸出結(jié)果如下: [(frozenset({79}), 258), (frozenset({258}), 79), (frozenset({50}), 64), (frozenset({64}), 50), (frozenset({127}), 181)] 在上述這些 規(guī)則 中,第一部分( frozenset )是作為規(guī)則前提的電影編號(hào),后面的數(shù)字表示 作為結(jié)論的電影編號(hào)。第一組數(shù)據(jù)表示如果用戶喜歡電影 79 ,他很可能喜歡電影 258 接下來,計(jì)算每條規(guī)則的置信度,計(jì)算方法跟第 1 章類似,只不過要根據(jù)這里新的數(shù)據(jù)格式 做些改動(dòng)。 我們需要先創(chuàng)建兩個(gè)字典,用來存儲(chǔ)規(guī)則應(yīng)驗(yàn)( 正例 )和規(guī)則不適用( 反例 )的次數(shù)。代碼 如下: correct_counts = defaultdict(int) incorrect_counts = defaultdict(int) 遍歷所有用戶及其喜歡的電影數(shù)據(jù),在這個(gè)過程中遍歷每條關(guān)聯(lián)規(guī)則。 for user, reviews in favorable_reviews_by_users.items(): for candidate_rule in candidate_rules: premise, conclusion = candidate_rule

測(cè)試每條規(guī)則的前提對(duì)用戶是否適用。換句話說,用戶是否喜歡前提中的所有電影。代碼如下:

if premise.issubset(reviews): 如果前提符合,看一下用戶是否喜歡結(jié)論中的電影。如果是的話,規(guī)則適用,反之,規(guī)則不 適用。 if premise.issubset(reviews): if conclusion in reviews: correct_counts[candidate_rule] += 1 else: incorrect_counts[candidate_rule] += 1 用規(guī)則應(yīng)驗(yàn)的次數(shù)除以前提條件出現(xiàn)的總次數(shù),計(jì)算每條規(guī)則的置信度。 rule_confidence = {candidate_rule: correct_counts[candidate_rule] / float(correct_counts[candidate_rule] + incorrect_counts[candidate_rule]) for candidate_rule in candidate_rules} 對(duì)置信度字典進(jìn)行排序后,輸出置信度最高的前五條規(guī)則。 結(jié)果如下: Rule #1 Rule: If a person recommends frozenset({64, 56, 98, 50, 7}) they will also recommend 174 - Confidence: 1.000 Rule #2 Rule: If a person recommends frozenset({98, 100, 172, 79, 50, 56}) they will also recommend 7 - Confidence: 1.000 Rule #3 Rule: If a person recommends frozenset({98, 172, 181, 174, 7}) they will also recommend 50 - Confidence: 1.000 Rule #4 Rule: If a person recommends frozenset({64, 98, 100, 7, 172, 50}) they will also recommend 174 - Confidence: 1.000 Rule #5 Rule: If a person recommends frozenset({64, 1, 7, 172, 79, 50}) they will also recommend 181 - Confidence: 1.000

輸出結(jié)果中只顯示電影編號(hào),而沒有顯示電影名字,很不友好。我們下載的數(shù)據(jù)集中的u.items文件里存儲(chǔ)了電影名稱和編號(hào)(還有體裁等信息)。

用pandasu.items文件加載電影名稱信息。關(guān)于該文件和類別的更多信息請(qǐng)見數(shù)據(jù)集中的 README文件u.items文件為CSV格式,但是用豎線分隔數(shù)據(jù)。讀取時(shí)需要指定分隔符,設(shè)置表 頭和編碼格式。每一列的名稱是從README文件中找到的。

movie_name_filename = os.path.join(data_folder, "u.item") movie_name_data = pd.read_csv(movie_name_filename, delimiter="|", header=None, encoding = "mac-roman") movie_name_data.columns = ["MovieID", "Title", "Release Date", "Video Release", "IMDB", "<UNK>", "Action", "Adventure", "Animation", "Children's", "Comedy", "Crime", "Documentary", "Drama", "Fantasy", "Film-Noir", "Horror", "Musical", "Mystery", "Romance", "Sci-Fi", "Thriller", "War", "Western"] 既然電影名稱對(duì)于理解數(shù)據(jù)很重要,我們就來創(chuàng)建一個(gè)用電影編號(hào)獲取名稱的函數(shù),以免去 每次都要人工查找的煩惱。函數(shù)聲明如下: def get_movie_name(movie_id): 在數(shù)據(jù)框 movie_name_data 中查找電影編號(hào),找到后,只返回電影名稱列的數(shù)據(jù)。 title_object = movie_name_data[movie_name_data["MovieID"] == movie_id]["Title"] 我們用 title_object values 屬性獲取電影名稱(不是存儲(chǔ)在 title_object 中的 Series 對(duì)象)。我們只對(duì)第一個(gè)值感興趣 —— 當(dāng)然每個(gè)電影編號(hào)只對(duì)應(yīng)一個(gè)名稱! title = title_object.values[0] 函數(shù)最后返回電影名稱。 return title 調(diào)整之前的代碼,這樣就能在輸出的規(guī)則中顯示電影名稱。請(qǐng)?jiān)?/span> IPython Notebook 筆記本文 件的新格子里輸入以下代碼。 for index in range(5): print("Rule #{0}".format(index + 1)) (premise, conclusion) = sorted_confidence[index][0] premise_names = ", ".join(get_movie_name(idx) for idx in premise) conclusion_name = get_movie_name(conclusion) print("Rule: If a person recommends {0} they will also recommend {1}".format(premise_names, conclusion_name)) print(" - Confidence: {0:.3f}".format(confidence[(premise, conclusion)])) print("") 結(jié)果清楚多了(還有些小問題,暫時(shí)先忽略)。 Rule #1 Rule: If a person recommends Shawshank Redemption, The (1994), Pulp Fiction (1994), Silence of the Lambs, The (1991), Star Wars (1977), Twelve Monkeys (1995) they will also recommend Raiders of the Lost Ark (1981) - Confidence: 1.000 Rule #2 Rule: If a person recommends Silence of the Lambs, The (1991), Fargo (1996), Empire Strikes Back, The (1980), Fugitive, The (1993), Star Wars (1977), Pulp Fiction (1994) they will also recommend Twelve Monkeys (1995) - Confidence: 1.000 Rule #3 Rule: If a person recommends Silence of the Lambs, The (1991), Empire Strikes Back, The (1980), Return of the Jedi (1983), Raiders of the Lost Ark (1981), Twelve Monkeys (1995) they will also recommend Star Wars (1977) - Confidence: 1.000 Rule #4 Rule: If a person recommends Shawshank Redemption, The (1994), Silence of the Lambs, The (1991), Fargo (1996), Twelve Monkeys (1995), Empire Strikes Back, The (1980), Star Wars (1977) they will also recommend Raiders of the Lost Ark (1981) - Confidence: 1.000 Rule #5 Rule: If a person recommends Shawshank Redemption, The (1994), Toy Story (1995), Twelve Monkeys (1995), Empire Strikes Back, The (1980), Fugitive, The (1993), Star Wars (1977) they will also recommend Return of the Jedi (1983) - Confidence: 1.000

十三 小結(jié)

本文把親和性分析用到電影推薦上,從大量電影打分?jǐn)?shù)據(jù)中找到可用于電影推薦的關(guān)聯(lián)規(guī)則。整個(gè)過程分為兩大階段。首先,借助Apriori 算法尋找數(shù)據(jù)中的頻繁項(xiàng)集。然后,根據(jù)找到的頻繁項(xiàng)集,生成關(guān)聯(lián)規(guī)則。 由于數(shù)據(jù)集較大, Apriori 算法就很有必要。我們用一部分?jǐn)?shù)據(jù)作為訓(xùn)練集以發(fā)現(xiàn)關(guān)聯(lián)規(guī)則,在剩余數(shù)據(jù)——測(cè)試集上進(jìn)行測(cè)試。

我們是Greaterwms軟件開發(fā)團(tuán)隊(duì)。

項(xiàng)目介紹:
我們的產(chǎn)品是開源倉儲(chǔ)管理軟件,榮獲gitee最有價(jià)值開源項(xiàng)目獎(jiǎng),評(píng)選為GVP項(xiàng)目

產(chǎn)品支持多倉,波次發(fā)貨,合并揀貨,Milk-Run等業(yè)務(wù)模型。前后端分離為完全開源項(xiàng)目。

軟件著作權(quán)編號(hào):2018SR517685
GitHub地址:github
Gitee地址: ? gitee
視頻教程: ? ?bilibili
Demo地址:DEMO
商務(wù)聯(lián)系:mail@56yhz.com
技術(shù)交流:GreaterWMS-01(加微信進(jìn)群)

總結(jié)

以上是生活随笔為你收集整理的【实用算法教学】——Apriori算法,教你使用亲和性分析方法推荐电影的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。