【知识发现】隐语义模型LFM算法python实现(一)
生活随笔
收集整理的這篇文章主要介紹了
【知识发现】隐语义模型LFM算法python实现(一)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1、隱語義模型:
物品:表示為長度為k的向量q(每個(gè)分量都表示 ?物品具有某個(gè)特征的程度)
用戶興趣:表示為長度為k的向量p(每個(gè)分量都表示 ?用戶對某個(gè)特征的喜好程度)
用戶u對物品i的興趣可以表示為:
其損失函數(shù)定義為:
使用隨機(jī)梯度下降,獲得參數(shù)p,q。
負(fù)樣本生成:對于只有正反饋信息(用戶收藏了,關(guān)注了xxx)的數(shù)據(jù)集,需要生成負(fù)樣本,原則如下
1)生成的負(fù)樣本要和正樣本數(shù)量相當(dāng)
2)物品越熱門(用戶沒有收藏該物品),越有可能是負(fù)樣本
?
2、數(shù)據(jù)集:https://grouplens.org/datasets/movielens/
格式:
?
3、參考代碼:
?
# -*- coding: utf-8 -*- ''' Created on 2017年9月15日@author: Jason.F '''from math import exp import pandas as pd import numpy as np import pickle import time from numpy import rankdef getUserNegativeItem(frame, userID):'''獲取用戶負(fù)反饋物品:熱門但是用戶沒有進(jìn)行過評分 與正反饋數(shù)量相等:param frame: ratings數(shù)據(jù):param userID:用戶ID:return: 負(fù)反饋物品'''userItemlist = list(set(frame[frame['userid'] == userID]['itemid'])) #用戶評分過的物品otherItemList = [item for item in set(frame['itemid'].values) if item not in userItemlist] #用戶沒有評分的物品itemCount = [len(frame[frame['itemid'] == item]['userid']) for item in otherItemList] #物品熱門程度series = pd.Series(itemCount, index=otherItemList)series = series.sort_values(ascending=False)[:len(userItemlist)] #獲取正反饋物品數(shù)量的負(fù)反饋物品negativeItemList = list(series.index)return negativeItemListdef getUserPositiveItem(frame, userID):'''獲取用戶正反饋物品:用戶評分過的物品:param frame: ratings數(shù)據(jù):param userID: 用戶ID:return: 正反饋物品'''series = frame[frame['userid'] == userID]['itemid']positiveItemList = list(series.values)return positiveItemListdef initUserItem(frame, userID=1):'''初始化用戶正負(fù)反饋物品,正反饋標(biāo)簽為1,負(fù)反饋為0:param frame: ratings數(shù)據(jù):param userID: 用戶ID:return: 正負(fù)反饋物品字典'''positiveItem = getUserPositiveItem(frame, userID)negativeItem = getUserNegativeItem(frame, userID)itemDict = {}for item in positiveItem: itemDict[item] = 1for item in negativeItem: itemDict[item] = 0return itemDictdef initUserItemPool(frame,userID):'''初始化目標(biāo)用戶樣本:param userID:目標(biāo)用戶:return:'''userItem = []for id in userID:itemDict = initUserItem(frame, userID=id)userItem.append({id:itemDict})return userItemdef initPara(userID, itemID, classCount):'''初始化參數(shù)q,p矩陣, 隨機(jī):param userCount:用戶ID:param itemCount:物品ID:param classCount: 隱類數(shù)量:return: 參數(shù)p,q'''arrayp = np.random.rand(len(userID), classCount) #構(gòu)造p矩陣,[0,1]內(nèi)隨機(jī)值arrayq = np.random.rand(classCount, len(itemID)) #構(gòu)造q矩陣,[0,1]內(nèi)隨機(jī)值p = pd.DataFrame(arrayp, columns=range(0,classCount), index=userID)q = pd.DataFrame(arrayq, columns=itemID, index=range(0,classCount))return p,qdef initModel(frame, classCount):'''初始化模型:參數(shù)p,q,樣本數(shù)據(jù):param frame: 源數(shù)據(jù):param classCount: 隱類數(shù)量:return:'''userID = list(set(frame['userid'].values))itemID = list(set(frame['itemid'].values))p, q = initPara(userID, itemID, classCount)#初始化p、q矩陣userItem = initUserItemPool(frame,userID)#建立用戶-物品對應(yīng)關(guān)系return p, q, userItemdef latenFactorModel(frame, classCount, iterCount, alpha, lamda):'''隱語義模型計(jì)算參數(shù)p,q:param frame: 源數(shù)據(jù):param classCount: 隱類數(shù)量:param iterCount: 迭代次數(shù):param alpha: 步長:param lamda: 正則化參數(shù):return: 參數(shù)p,q'''p, q, userItem = initModel(frame, classCount)for step in range(0, iterCount):for user in userItem:for userID, samples in user.items():for itemID, rui in samples.items():eui = rui - lfmPredict(p, q, userID, itemID)for f in range(0, classCount):print('step %d user %d class %d' % (step, userID, f))p[f][userID] += alpha * (eui * q[itemID][f] - lamda * p[f][userID])q[itemID][f] += alpha * (eui * p[f][userID] - lamda * q[itemID][f])alpha *= 0.9return p, qdef sigmod(x):'''單位階躍函數(shù),將興趣度限定在[0,1]范圍內(nèi):param x: 興趣度:return: 興趣度'''y = 1.0/(1+exp(-x))return ydef lfmPredict(p, q, userID, itemID):'''利用參數(shù)p,q預(yù)測目標(biāo)用戶對目標(biāo)物品的興趣度:param p: 用戶興趣和隱類的關(guān)系:param q: 隱類和物品的關(guān)系:param userID: 目標(biāo)用戶:param itemID: 目標(biāo)物品:return: 預(yù)測興趣度'''p = np.mat(p.ix[userID].values)q = np.mat(q[itemID].values).Tr = (p * q).sum()r = sigmod(r)return rdef recommend(frame, userID, p, q, TopN=10):'''推薦TopN個(gè)物品給目標(biāo)用戶:param frame: 源數(shù)據(jù):param userID: 目標(biāo)用戶:param p: 用戶興趣和隱類的關(guān)系:param q: 隱類和物品的關(guān)系:param TopN: 推薦數(shù)量:return: 推薦物品'''userItemlist = list(set(frame[frame['userid'] == userID]['itemid']))otherItemList = [item for item in set(frame['itemid'].values) if item not in userItemlist]predictList = [lfmPredict(p, q, userID, itemID) for itemID in otherItemList]series = pd.Series(predictList, index=otherItemList)series = series.sort_values(ascending=False)[:TopN]return seriesdef Recall(df_test,p,q):#召回率hit=0all=0df_userid=df_test['userid']df_userid=df_userid.drop_duplicates()for userid in df_userid:pre_item=recommend(df_test, userid, p, q)df_user_item=df_test.loc[df_test['userid'] == userid]true_item=df_user_item['itemid']for itemid,prob in pre_item.items():if itemid in true_item:hit+=1all+=len(true_item)return hit/(all*1.0)def Precision(df_test,p,q):hit=0all=0df_userid=df_test['userid']df_userid=df_userid.drop_duplicates()for userid in df_userid:pre_item=recommend(df_test, userid, p, q)df_user_item=df_test.loc[df_test['userid'] == userid]true_item=df_user_item['itemid']for itemid,prob in pre_item.items():if itemid in true_item:hit+=1all+=len(pre_item)return hit/(all*1.0)if __name__ == '__main__': start = time.clock() #導(dǎo)入數(shù)據(jù)df_sample = pd.read_csv("D:\\tmp\\ratings.csv",names=['userid','itemid','ratings','time'],header=0) #模型訓(xùn)練p, q = latenFactorModel(df_sample,5, 3, 0.02, 0.01 )#模型評估df_test=df_sample.sample(frac=0.2)#抽20%來測試print (Recall(df_test,p,q))#召回率print (Precision(df_test,p,q))#準(zhǔn)確率 print (Coverage(df_test,p,q))#覆蓋率end = time.clock() print('finish all in %s' % str(end - start))
實(shí)際推薦應(yīng)用中,應(yīng)結(jié)合特征工程開展。
?
?
補(bǔ)充覆蓋率評價(jià)指標(biāo)的函數(shù):
?
def Coverage(df_test,p,q):#覆蓋率df_itemid=df_test['itemid']df_itemid=df_itemid.drop_duplicates()rec_items=set()#推薦的物品總數(shù)df_userid=df_test['userid']df_userid=df_userid.drop_duplicates()for userid in df_userid:pre_item=recommend(df_test, userid, p, q)for itemid,prob in pre_item.items():rec_items.add(itemid)return len(rec_items)/(len(df_itemid)*1.0)?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的【知识发现】隐语义模型LFM算法python实现(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数据挖掘知识点三】大数定理与中心极限定
- 下一篇: 【知识发现】基于用户的协同过滤推荐算法p