本文将介绍三种推荐:基于物品的协同过滤推荐、随机推荐、按照流行度推荐

# 读取数据库数据——模型数据1——婚姻数据(16824条记录)
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/jing?charset=utf8')
data = pd.read_sql('hunyinformodel', engine)# 数据不是很大,不用分块了
data.head()

1 基于物品的协同过滤推荐

1.1 定义协同推荐函数


def Jaccard(a,b): #自定义杰卡德相似系数函数,仅对0-1矩阵有效
    return 1.0*(a*b).sum() /(a+b-a*b).sum()

class Recommender():
    sim = None # 相似度矩阵
    def similarity(self, x, distance): # 计算相似度矩阵的函数
        y = np.ones((len(x), len(x)))
        for i in range(len(x)):
            for j in range(len(x)):
                y[i,j] = distance(x[i], x[j])
        return y
    
    def fit(self, x, distance = Jaccard): # 训练函数
        self.sim = self.similarity(x, distance)
        return self.sim
    
    def recommend(self, a): # 推荐函数
        return np.dot(self.sim, a) * (1-a)
len(data['fullURL'].value_counts()) # 4339
len(data['realIP'].value_counts()) # 10333
# 由题意知  网址数 < 用户数--> 建立基于物品的协同过滤推荐

1.2 将所有数据转成0-1矩阵


# 大概运行时间是40秒左右
import time
start0 = time.clock()
data.sort_values(by=['realIP','fullURL'],ascending=[True,True],inplace=True)
realIP = data['realIP'].value_counts().index
realIP = np.sort(realIP)
fullURL = data['fullURL'].value_counts().index #
fullURL = np.sort(fullURL)
D = DataFrame([], index = realIP, columns = fullURL )

for i in range(len(data)):
    a = data.iloc[i,0] # 用户名
    b = data.iloc[i,1] # 网址
    D.loc[a,b] = 1 
D.fillna(0,inplace = True)
end0 = time.clock()
usetime0 = end0-start0
print '转成0、1矩阵所花费的时间为'+ str(usetime0) +'s!'#34.5123141125s!
# D.shape=10333 rows × 4339 columns
#保存的表名命名格式为“3_1_k此表功能名称”,是本小节生成的第1张表格,功能为zero_one:整个数据集计算得到的0-1矩阵
D.to_csv('3_1_1zero_one.csv')


1.3 交叉验证方法验证推荐

# 步骤:解决采用一次验证的方法,再创建十折交叉验证循环(此处只采用了一次具体十折交叉方法见3_2_10-fold cross-validation.py)
# 由于是基于物品(网址)的推荐,所以测试集需包含所有网址(全集),选择0.9*总用户数个用户记录来进行训练模型
# 注意:将数据随机打乱

# 随机打乱数据
# 注意 每次打乱数据,下面的都会改变
df = D.copy()

simpler = np.random.permutation(len(df)) 
df = df.take(simpler)# 打乱数据

train = df.iloc[:int(len(df)*0.9), :]
test = df.iloc[int(len(df)*0.9):, :]

df = df.as_matrix()

df_train = df[:int(len(df)*0.9), :]# 前90%为训练集len(df_train) = 9299
df_test = df[int(len(df)*0.9):, :]# 后10%为测试集len(df_test) = 103
#由于基于物品的推荐,对于矩阵,根据上面的推荐函数,index为网址,因此需要进行转置
df_train = df_train.T
df_test = df_test.T

print df_train.shape # (4339L, 9299L)
print df_test.shape # (4339L, 1034L)

1.4 建立相似矩阵,训练模型


print df_train.shape # (4339L, 9299L)
import time
start1 = time.clock()
r = Recommender()
sim = r.fit(df_train)# 计算物品的相似度矩阵
end1 = time.clock()

a = DataFrame(sim) # 保存相似度矩阵
usetime1 = end1-start1
print u'建立相似矩阵耗时'+str(usetime1)+'s!'  #1981.60760257s!

print a.shape # (4339L, 9299L)

# 将所有数据保存
a.index = train.columns
a.columns = train.columns

#保存的表名命名格式为“3_1_k此表功能名称”,是本小节生成的第2张表格,功能为similarityMatrix:计算训练集的相似度矩阵
a.to_csv('3_1_2similarityMatrix.csv')
a.head(20)
# 使用测试集进行预测
print df_test.shape # (4339L, 1034L)
start2 = time.clock()
result = r.recommend(df_test)
end2 = time.clock()

result1 = DataFrame(result)
usetime2 = end2-start2
print u'推荐函数耗时'+str(usetime2)+'s!' # 推荐函数耗时2.60267174653s!

result1
# 将推荐结果表格中的对应的网址和用户名对应上
result1.index = test.columns
result1.columns = test.index
#保存的表名命名格式为“3_1_k此表功能名称”,是本小节生成的第3张表格,功能为recommedresult:显示推荐的结果
result1.to_csv('3_1_3recommedresult.csv')
result1

1.5 协同推荐结果展现


# 定义展现具体协同推荐结果的函数,K为推荐的个数,recomMatrix为协同过滤算法算出的推荐矩阵的表格化
# type(K):int, type(recomMatrix):DataFrame

def xietong_result(K, recomMatrix ): 
    recomMatrix.fillna(0.0,inplace=True)# 将表格中的空值用0填充
    n = range(1,K+1)
    recommends = ['xietong'+str(y) for y in n]
    currentemp = DataFrame([],index = recomMatrix.columns, columns = recommends)
    for i in range(len(recomMatrix.columns)):
        temp = recomMatrix.sort_values(by = recomMatrix.columns[i], ascending = False)
        k = 0 
        while k < K:
            currentemp.iloc[i,k] = temp.index[k]
            if temp.iloc[k,i] == 0.0:
                currentemp.iloc[i,k:K] = np.nan
                break
            k = k+1

    return currentemp

start3 = time.clock()
xietong_result = xietong_result(3, result1)
end3 = time.clock()
print '按照协同过滤推荐方法为用户推荐3个未浏览过的网址耗时为' + str(end3 - start3)+'s!' #29.4996622053s!

#保存的表名命名格式为“3_1_k此表功能名称”,是本小节生成的第4张表格,功能为xietong_result:显示协同过滤推荐的结果
xietong_result.to_csv('3_1_4xietong_result.csv')

xietong_result # 结果中出现了全空的行,这是冷启动现象



数据协同架构_Python数据分析与挖掘实战


2 随机推荐

# test = df.iloc[int(len(df)*0.9):, :] # 所有测试数据df此时是矩阵,这样不能用
randata = 1 - df_test # df_test是用户浏览过的网页的矩阵形式,randata则表示是用户未浏览过的网页的矩阵形式
randmatrix = DataFrame(randata, index = test.columns,columns=test.index)#这是用户未浏览过(待推荐)的网页的表格形式

2.1 定义随机推荐函数

# 定义展现具体Random随机推荐结果的函数,K为推荐的个数,recomMatrix为用户未浏览过的网页的表格形式


# type(K):int, type(recomMatrix):DataFrame


def rand_recommd(K, recomMatrix):# 
    import random # 注意:这个random是random模块,
    import numpy as np
    
    recomMatrix.fillna(0.0,inplace=True) # 此处必须先填充空值
    recommends = ['recommed'+str(y) for y in range(1,K+1)]
    currentemp = DataFrame([],index = recomMatrix.columns, columns = recommends)
    
    for i in range(len(recomMatrix.columns)): #len(res.columns)1
        curentcol = recomMatrix.columns[i]
        temp = recomMatrix[curentcol][recomMatrix[curentcol]!=0]
    #     = temp.index[random.randint(0,len(temp))]
        if len(temp) == 0:
            currentemp.iloc[i,:] = np.nan
        elif len(temp) < K:
            r = temp.index.take(np.random.permutation(len(temp))) #注意:这个random是numpy模块的下属模块
            currentemp.iloc[i,:len(r)] = r
        else:
            r = random.sample(temp.index, K)
            currentemp.iloc[i,:] =  r
    return currentemp

start4 = time.clock()
random_result = rand_recommd(3, randmatrix) # 调用随机推荐函数
end4 = time.clock()
print '随机为用户推荐3个未浏览过的网址耗时为' + str(end4 - start4)+'s!' # 2.1900423292s!

#保存的表名命名格式为“3_1_k此表功能名称”,是本小节生成的第5张表格,功能为random_result:显示随机推荐的结果
random_result.to_csv('random_result.csv')

random_result # 结果中出现了全空的行,这是冷启动现象



数据协同架构_数据_02


3 按照流行度推荐

3.1 定义按照流行度推荐函数


# 定义展现具体Popular随机推荐结果的函数,K为推荐的个数,recomMatrix为用户未浏览过的网页的表格形式
# type(K):int, type(recomMatrix):DataFrame

def popular_recommed(K, recomMatrix):
    recomMatrix.fillna(0.0,inplace=True)
    import numpy as np
    recommends = ['recommed'+str(y) for y in range(1,K+1)]
    currentemp = DataFrame([],index = recomMatrix.columns, columns = recommends)

    for i in range(len(recomMatrix.columns)):
        curentcol = recomMatrix.columns[i]
        temp = recomMatrix[curentcol][recomMatrix[curentcol]!=0]
        if len(temp) == 0:
            currentemp.iloc[i,:] = np.nan
        elif len(temp) < K:
            r = temp.index #注意:这个random是numpy模块的下属模块
            currentemp.iloc[i,:len(r)] = r
        else:
            r = temp.index[:K]
            currentemp.iloc[i,:] =  r

    return currentemp
# 确定用户未浏览的网页(可推荐的)的数据表格
TEST = 1-df_test
test2 = DataFrame(TEST, index = test.columns, columns=test.index)
print test2.head()
print test2.shape 

# 确定网页浏览热度排名:
hotPopular = data['fullURL'].value_counts()
hotPopular = pd.DataFrame(hotPopular)
print hotPopular.head()
print hotPopular.shape 

# 按照流行度对可推荐的所有网址排序
test3 = test2.reset_index()
list_custom = list(hotPopular.index)
test3['index'] = test3['index'].astype('category')
test3['index'].cat.reorder_categories(list_custom, inplace=True)
test3.sort_values('index',inplace = True)
test3.set_index ('index', inplace = True)
print test3.head()
print test3.shape 


# 按照流行度为用户推荐3个未浏览过的网址
recomMatrix = test3
start5 = time.clock()
popular_result = popular_recommed(3, recomMatrix)
end5 = time.clock()
print '按照流行度为用户推荐3个未浏览过的网址耗时为' + str(end5 - start5)+'s!'#7.70043007471s!

#保存的表名命名格式为“3_1_k此表功能名称”,是本小节生成的第6张表格,功能为popular_result:显示按流行度推荐的结果
popular_result.to_csv('3_1_6popular_result.csv')

popular_result



数据协同架构_Python数据分析与挖掘实战_03


至此,本章所有内容分享完毕