1. 程式人生 > >推薦系統(二) —— 利用使用者行為資料 —— 基於領域的演算法

推薦系統(二) —— 利用使用者行為資料 —— 基於領域的演算法

為了讓推薦結果符合使用者口味,我們需要深入瞭解使用者。使用者的行為不是隨機的,而是蘊含著許多模式的。基於使用者行為分析的推薦演算法是個性化推薦系統的重要演算法,僅僅基於使用者行為資料設計的推薦演算法學術上稱作“協同過濾演算法”。協同過濾,就是指使用者可以齊心協力,通過不斷地和網站互動,是自己的推薦列表能夠不斷過濾掉自己不感興趣的物品,從而越來越滿足自己的需求。

系統過濾演算法,包含基於領域的演算法、隱語義模型、基於圖的演算法等。

下面我們先從使用者行為資料的一些特點講起,再詳細講解上述各類演算法。

1、使用者行為資料

1.1簡介

使用者行為資料在網站上最簡單的存放形式就是日誌。網站在執行過程中都會產生大量原始日誌

,很多網際網路業務會把多種原始日誌按照使用者行為彙總成會話日誌,其中每個會話表示一次使用者行為和對應的服務。會話日誌通常儲存在分散式資料倉庫中,如支援離線分析的Hadoop Hive和支援線上分析的Google Dremel。

使用者行為在個性化推薦系統中一般分為兩種:顯性反饋行為,和隱性反饋行為。顯性反饋行為包括使用者明確表示對物品喜惡的行為。隱性反饋行為指的是那些不能明確反映使用者喜惡的行為,但資料量更大。在很多網站中,很多使用者甚至只有隱性反饋資料。

網際網路中的使用者行為有很多種,用一種統一的方式來表示所有行為很困難。一種叫可行的使用者行為的統一表示可以包含以下部分:

user id,item id,behavior type,context(上下文),behavior weight,behavior content。

1.2使用者行為中蘊含的規律

網際網路上的很多資料分佈都滿足Power Law分佈,在網際網路領域也稱作長尾分佈

有意義的是,很多使用者行為資料也蘊含著這種規律,例如:

個物品產生過行為使用者數;

個使用者產生過行為的物品數;

對應物品流行度為的物品總數;

對應使用者活躍度為的使用者總數;

對應使用者活躍度為的所有使用者評過分的物品的平均流行度;

等等。。。。

這些規律並不是只存在於一兩個網站中的特例,而是存在於很多網站中的普遍規律。

2、基於領域的演算法

2.1基於使用者的協同過濾演算法

1、UserCF是推薦系統中最古老的演算法,其誕生標誌著推薦系統的誕生。UserCF演算法主要包含兩個步驟:

(1)找到和目標使用者興趣相似的使用者集合

(2)找到這個集合中的使用者喜歡的,且目標使用者沒有聽說過的物品,並將其推薦給目標使用者。

2、UserCF算中(1)中,使用者之間的興趣相似度可以通過餘弦相似度公式計算


實際上,使用者間對冷門物品採取過同樣的行為更能說明他們興趣的相似度,因此,我們可以通過懲罰使用者間共同興趣列表中熱門物品的影響(通過下式可見是用分子懲罰的),對上述使用者相似度計算式進行改進


3、 UserCF算中(2)中,度量使用者對某物品的感興趣程度可以用:


其中r為使用者v對物品i的興趣指數。

4、UserCF演算法(與改進興趣相似度公式後的User-IIF演算法)的Python實現

### UserCF algorithm ###

def UserSimilarity(train):
	# input trainSet is a dict, for example:
	# train = {'A':{'a':rAa, 'b':rAb, 'd':rAd}, 'B':{...}, ...}
	# build the inverse table for item_users
	item_users_table = dict()
	for user, items in train.items():
		for item in items.keys():
			if item not in item_users_table:
				item_users_table[item] = set()
			item_users_table[item].add(user)
	# calculate co-rated items between users
	# item_users_table = {'a':set('A','B'), 'b':set('A','C'), ...}
	C = dict() # this is the member of W
	N = dict() 
	for item, users in item_users_table.items():
		for uu in users:
			N[uu] += 1
			for vv in users:
				if uu == vv:
					continue
				## simple cosine user similarity
				C[uu][vv] += 1
				## modified cosine user similarity
				C[uu][vv] += 1 / math.log(1.0+len(item))
	# calculate final similarity matrix W
	W = dict() 	
	for uu, related_user in C.items():
		for vv, Cuv in related_user.items():
			W[uu][vv] = Cuv / math.sqrt(N[uu]*N[vv])
	return W

def Recommend(train, user_u, W, K):
	rank = dict()
	uu = user_u
	interacted_items = train[uu]
	# S(u,K) ahead of N(i)
	for vv, Wuv in sorted(W[uu].items, key=itemgetter(1), reverse=True)[0:K]:
		for item, rvi in train[vv].items():
			if item in interacted_items.keys():
				continue
				# filter the items which user interacted before
			rank[item] += Wuv * rvi
	return rank

5、演算法效能分析

(1)UserCF演算法中重要引數K與推薦演算法的精度指標(Recall和Precision)並不成線性增長關係,且精度對K也不是特別敏感。

(2)K越大,參考的人越多,結果就越趨近於全域性熱門物品,因而導致流行度指數越高,即推薦結果的新穎度降低。

(3)隨著K增大,推薦物品的流行度增加,演算法將傾向於推薦熱門物品,從而對長尾物品挖掘能力變差,造成演算法覆蓋率降低。

(4)UserCF演算法固有缺點在於:一則,隨著網站的使用者數目增多,計算使用者興趣相似度矩陣W將越來越困難,其運算時間複雜度和空間複雜度的增長與使用者數的增長近似成平方關係。二來,UserCF演算法難以對其推薦的結果作出解釋,不太適用於商品推薦、視訊推薦等場景。


2.2基於物品的協同過濾演算法

1、ItemCF演算法是目前業界應用最多的演算法。ItemCFB演算法並不是利用物品的內容屬性計算物品之間的相似度,而是通過分析大量使用者的行為來記錄並計算物品之間的相似性,因此可以利用使用者的歷史行為給推薦結果提供推薦。ItemCF演算法主要分為兩步:

(1)計算物品之間的相似度

(2)根據物品的相似度以及使用者的歷史行為給使用者生成推薦列表

2、ItemCF演算法(1)中,在前提“每個使用者的興趣都侷限在某幾個方面”下,可以用下式計算


當上式還存在一個問題,由於每個使用者的興趣列表都會對物品的相似度產生貢獻,但活躍使用者的興趣顯然沒有非活躍使用者的興趣那麼集中,應該使活躍使用者對物品相似度的貢獻低於不活躍使用者才合理,因此可以引進IUF,即使用者活躍度對數的倒數的引數,對上式進行改進:


實際上,IUF只是對活躍使用者做了一種軟性懲罰,實際計算中,往往直接把過於活躍的使用者的興趣列表忽略掉,完全不將其納入相似度計算中,同時避免了相似度矩陣過於稠密。

3、 ItemCF演算法(2)中,度量使用者對某物品的感興趣程度可以用:


4、ItemCF演算法(與改進興趣相似度公式後的Item-IUF演算法)的Python實現

### ItemCF algorithm ###

def ItemSimilarity(train):
	# calculate co-rated users between items
	C = dict()
	N = dict()
	for user, items in train.items():
		for ii in items:
			N[ii] += 1
			for jj in items:
				if ii == jj:
					continue
				## the simple cosine item similarity
				C[ii][jj] += 1
				## the modified cosine item similarity
				C[ii][jj] += 1 / math.log(1.0+len(user))
	# calculate final similarity matrix W
	W = dict() 	
	for ii, related_items in C.items():
		for jj, Cij in related_items.items():
			W[ii][jj] = Cij / math.sqrt(N[ii]*N[jj])
	return W

def Recommend(train, user_u, W, K):
	rank = dict()
	uu = user_u
	interacted_items = train[uu]
	# N(u) ahead of S(j,K)
	for item, rui in interacted_items.items():
		for jj, Wij in sorted(W[item].items, key = itemgetter(1), reverse = True)[0:K]:
			if jj in interacted_items.keys():
				continue
				# filter the items which user interacted before
			rank[jj].weight += Wij * rui
			rank[jj].reason[item] = Wij * rui
			# give the reason of recommendation
	return rank

5、演算法效能分析

(1)同樣,ItemCF演算法中引數K也不與結果精度呈正相關或者負相關。

(2)區別於UserCF,引數K對ItemCF結果的流行度並不是完全正相關的,隨著K增大,流行度逐漸提高但最終會緩慢下降。

(3)同UserCF,K的增加會降低系統的覆蓋率。

(4)注意,通過將ItemCF的相似度矩陣按列最大值歸一化,可以提高系統的準確率、覆蓋率和多樣性,即

(5)ItemCF演算法的覆蓋率和新穎度都不高,是由於熱門物品在相似度矩陣計算中造成了太大的影響,一般可以在wij的分母上對N(i)取指數1-alpha,N(j)取指數alpha,通過調整使熱門物品的alpha大於0.5,甚至更大,對其作出懲罰,可以一定程度上犧牲精度而顯著提高覆蓋率和新穎性。但此方法依然效果一般,即在不同領域的最熱門物品之間往往具有較高的相似度情況下,僅僅靠使用者行為資料很難解決上述問題。此時,只能依靠引入物品的內容資料解決此問題,比如對不用領域的物品降低權重等,當然這些暫時不是協同過濾的討論範疇。

2.3UerCFItemCF 比較

1、從二者的推薦原理來看,UserCF的推薦結果著重於反應和使用者興趣相似的小群體的熱點,而ItemCF的推薦結果著重於維繫使用者的歷史興趣,即,前者的推薦更社會化,反映了使用者所在的小型興趣群體中物品的熱門程度,而後者更加個性化,反映了使用者自己的興趣傳承。 2、從技術角度來看,UserCF需要維護一個使用者相似度矩陣,而ItemCF需要維護一個物品相似度矩陣。 3、從這兩點,大致能看出為什麼文章分享網站Digg使用前者,而亞馬遜使用了後者。 4、這從另一方面又啟示我們,離線實驗的效能並不是選擇推薦演算法的決定性要素,反而應該按照以下順序來選取:(1)應該滿足產品的需求,例如是否需要提供推薦解釋(2)需要看實現代價,也就是使用者更多還是物品更多(3)離線指標和點選率等線上指標不一定成正比,即使離線指標不太好也沒關係,何況經過各種優化改進,一般都不會太差。 5、來份優缺點對錶表: