python数据分析与挖掘实战(电子商务网站用户行为分析及服务推荐)

目录

一、引言

二、分析方法与过程

2.1 分析步骤与流程

2.2数据抽取

 2.3数据探索分析

1)分析网页类型

2)分析网页点击次数

2.4数据预处理

1)删除不符合规则的网页

2)还原翻页网址

扫描二维码关注公众号,回复: 15650875 查看本文章

3)筛去浏览次数不满足两次的用户。

4)划分数据集

2.5 构建智能推荐模型

1)基于物品的协同过滤算法的基本概念

2)基于物品的协同过滤算法的优缺点

3)模型构建

4)模型评价 


一、引言

       智能推荐服务是提高电子商务网站销售转化率的重要技术手段之一。它与传统的搜索技术有着重要的区别,智能推荐服务能够更加精准地提供信息,节省用户找寻信息的时间,提高找寻信息的准确度。通过建立智能推荐系统提高服务效率,帮助消费者节约时间成本,帮助企业制定有针对性的营销战略方案,促进企业长期、稳定、高速发展。
       本篇文章通过对用户访问的网页日志数据进行分析与处理,采用基于物品的协同过滤算法对处理后的数据进行建模分析,并应用模型实现智能推荐,进行个性化推荐,帮助用户更加便捷地获取信息。

二、分析方法与过程

2.1 分析步骤与流程

为了帮助用户从海量的信息中快速发现感兴趣的网页,本案例主要采用协同过滤算法进行推荐,由于用户访问网站的数据记录较多,需要进行分类处理直接采用协同过滤算法进行推荐。

2.2数据抽取

以用户的访问为条件,选取3个月内(2015/2/1~2015/4/29)用户的访问数据作为原始数据集。采取python读取数据库的操作方式进行数据抽取。

import os
import pandas as pd


# 修改工作路径到指定文件夹
os.chdir("D:/pyhoncode")

# 第一种连接方式
from sqlalchemy import create_engine

engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)

# 第二种连接方式
import pymysql as pm

con = pm.connect(host='localhost',user='root',password='123456',database='test',charset='utf8',port=3306)
data = pd.read_sql('select * from all_gzdata',con=con)
con.close()           #关闭连接

# 保存读取的数据
data.to_csv('./data/all_gzdata.csv', index=False, encoding='utf-8')

 2.3数据探索分析

 原始数据集包括用户号、访问时间、来源网站、访问页面等信息,需要原始数据进行网页类型、点击次数、王爷排名等各个维度的分布分析,了解用户浏览网页的行为及关注内容,获取数据内在的规律。

1)分析网页类型

 对原始数据中用户点击的网页类型进行统计分析。

import pandas as pd
from sqlalchemy import create_engine

engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)
# 分析网页类型
counts = [i['fullURLId'].value_counts() for i in sql] #逐块统计
counts = counts.copy()
counts = pd.concat(counts).groupby(level=0).sum()  # 合并统计结果,把相同的统计项合并(即按index分组并求和)
counts = counts.reset_index()  # 重新设置index,将原来的index作为counts的一列。
counts.columns = ['index', 'num']  # 重新设置列名,主要是第二列,默认为0
counts['type'] = counts['index'].str.extract('(\d{3})')  # 提取前三个数字作为类别id
counts_ = counts[['type', 'num']].groupby('type').sum()  # 按类别合并
counts_.sort_values(by='num', ascending=False, inplace=True)  # 降序排列
counts_['ratio'] = counts_.iloc[:,0] / counts_.iloc[:,0].sum()
print(counts_)

结果如下

因此,点击与咨询相关(网页类型为101)的记录占了49.16%,其他类型(网页类型为199)占比24%左右,知识相关(网页类型为107)占比22%左右。根据统计结果对用户点击的页面类型进行排名,然后进一步对咨询类别内部进行统计分析。

# 因为只有107001一类,但是可以继续细分成三类:知识内容页、知识列表页、知识首页
def count107(i): #自定义统计函数
    j = i[['fullURL']][i['fullURLId'].str.contains('107')].copy()  # 找出类别包含107的网址
    j['type'] = None # 添加空列
    j['type'][j['fullURL'].str.contains('info/.+?/')]= '知识首页'
    j['type'][j['fullURL'].str.contains('info/.+?/.+?')]= '知识列表页'
    j['type'][j['fullURL'].str.contains('/\d+?_*\d+?\.html')]= '知识内容页'
    return j['type'].value_counts()
# 注意:获取一次sql对象就需要重新访问一下数据库(!!!)
#engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)

counts2 = [count107(i) for i in sql] # 逐块统计
counts2 = pd.concat(counts2).groupby(level=0).sum()  # 合并统计结果
print(counts2)
#计算各个部分的占比
res107 = pd.DataFrame(counts2)
# res107.reset_index(inplace=True)
res107.index.name= '107类型'
res107.rename(columns={'type':'num'}, inplace=True)
res107['比例'] = res107['num'] / res107['num'].sum()
res107.reset_index(inplace = True)
print(res107)

结果如下

可得,浏览咨询内容页(101003)记录最多,其次是咨询列表页(101002)和咨询首页(101001)。初步分析可得用户都喜欢通过浏览问题方式找到自己需要的信息,而不是以提问的方式或者查看长篇内容的方式寻找信息。对原始数据的网址中带“?”的数据进行统计。

def countquestion(i):  # 自定义统计函数
    j = i[['fullURLId']][i['fullURL'].str.contains('\?')].copy()  # 找出类别包含107的网址
    return j

engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)

counts3 = [countquestion(i)['fullURLId'].value_counts() for i in sql]
counts3 = pd.concat(counts3).groupby(level=0).sum()
print(counts3)

# 求各个类型的占比并保存数据
df1 =  pd.DataFrame(counts3)
df1['perc'] = df1['fullURLId']/df1['fullURLId'].sum()*100
df1.sort_values(by='fullURLId',ascending=False,inplace=True)
print(df1.round(4))

结果如下

可得,网址中带“?”的记录一种有64718条,且不仅仅出现在其他类别中,同时也会出现在咨询内容页和知识内容页中,但在其他类型(1999001)中占比最高,可达98.82%。因此需要进一步分析其类型内部的规律。

def page199(i): #自定义统计函数
    j = i[['fullURL','pageTitle']][(i['fullURLId'].str.contains('199')) & 
         (i['fullURL'].str.contains('\?'))]
    j['pageTitle'].fillna('空',inplace=True)
    j['type'] = '其他' # 添加空列
    j['type'][j['pageTitle'].str.contains('法律快车-律师助手')]= '法律快车-律师助手'
    j['type'][j['pageTitle'].str.contains('咨询发布成功')]= '咨询发布成功'
    j['type'][j['pageTitle'].str.contains('免费发布法律咨询' )] = '免费发布法律咨询'
    j['type'][j['pageTitle'].str.contains('法律快搜')] = '快搜'
    j['type'][j['pageTitle'].str.contains('法律快车法律经验')] = '法律快车法律经验'
    j['type'][j['pageTitle'].str.contains('法律快车法律咨询')] = '法律快车法律咨询'
    j['type'][(j['pageTitle'].str.contains('_法律快车')) | 
            (j['pageTitle'].str.contains('-法律快车'))] = '法律快车'
    j['type'][j['pageTitle'].str.contains('空')] = '空'
    
    return j

# 注意:获取一次sql对象就需要重新访问一下数据库
engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)# 分块读取数据库信息
#sql = pd.read_sql_query('select * from all_gzdata limit 10000', con=engine)

counts4 = [page199(i) for i in sql] # 逐块统计
counts4 = pd.concat(counts4)
d1 = counts4['type'].value_counts()
print(d1)
d2 = counts4[counts4['type']=='其他']
print(d2)
# 求各个部分的占比并保存数据
df1_ =  pd.DataFrame(d1)
df1_['perc'] = df1_['type']/df1_['type'].sum()*100
df1_.sort_values(by='type',ascending=False,inplace=True)
print(df1_)

结果如下

由此可得,在1999001类型中,标题为“快车—律师助手”这类信息占比为77.09%,这类页面是律师的登录页面。访问记录中有一部分用户并没有点击具体的页面,这类网页以“.html”后缀结尾,且大部分时目录网页,这样的用户可以称为“瞎逛”,漫无目的,总共有165654条记录,统计过程如下

def xiaguang(i): #自定义统计函数
    j = i.loc[(i['fullURL'].str.contains('\.html'))==False,
              ['fullURL','fullURLId','pageTitle']]
    return j

# 注意获取一次sql对象就需要重新访问一下数据库
engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)# 分块读取数据库信息

counts5 = [xiaguang(i) for i in sql]
counts5 = pd.concat(counts5)

xg1 = counts5['fullURLId'].value_counts()
print(xg1)
# 求各个部分的占比
xg_ =  pd.DataFrame(xg1)
xg_.reset_index(inplace=True)
xg_.columns= ['index', 'num']
xg_['perc'] = xg_['num']/xg_['num'].sum()*100
xg_.sort_values(by='num',ascending=False,inplace=True)

xg_['type'] = xg_['index'].str.extract('(\d{3})') #提取前三个数字作为类别id    

xgs_ = xg_[['type', 'num']].groupby('type').sum() #按类别合并
xgs_.sort_values(by='num', ascending=False,inplace=True) #降序排列
xgs_['percentage'] = xgs_['num']/xgs_['num'].sum()*100

print(xgs_.round(4))
 

结果如下

可以看出,小部分网页类型是与知识、咨询相关的,大部分网页类型是与地区、律师和事务所相关的,这类用户可能是找律师服务的,也可能是“瞎逛”的。记录这一些与分析目标无关数据的规则,有利于对数据进行清洗。

2)分析网页点击次数

统计原始数据用户浏览网页次数的情况。

# 分析网页点击次数
# 统计点击次数
engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)# 分块读取数据库信息

counts1 = [i['realIP'].value_counts() for i in sql] # 分块统计各个IP的出现次数
counts1 = pd.concat(counts1).groupby(level=0).sum() # 合并统计结果,level=0表示按照index分组
print(counts1)

counts1_ = pd.DataFrame(counts1)
counts1_
counts1['realIP'] = counts1.index.tolist()

counts1_[1]=1  # 添加1列全为1
hit_count = counts1_.groupby('realIP').sum()  # 统计各个“不同点击次数”分别出现的次数
# 也可以使用counts1_['realIP'].value_counts()功能
hit_count.columns=['用户数']
hit_count.index.name = '点击次数'

# 统计1~7次、7次以上的用户人数
hit_count.sort_index(inplace = True)
hit_count_7 = hit_count.iloc[:7,:]
time = hit_count.iloc[7:,0].sum()  # 统计点击次数7次以上的用户数
hit_count_7 = hit_count_7.append([{'用户数':time}], ignore_index=True)
hit_count_7.index = ['1','2','3','4','5','6','7','7次以上']
hit_count_7['用户比例'] = hit_count_7['用户数'] / hit_count_7['用户数'].sum()
print(hit_count_7)

结果如下

 统计结果分析,浏览一次的用户最多,占所有用户的58%左右。进一步分析浏览次数为一次的用户

# 分析浏览一次的用户行为

engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
all_gzdata = pd.read_sql_table('all_gzdata', con = engine)  # 读取all_gzdata数据

#对realIP进行统计
# 提取浏览1次网页的数据
real_count = pd.DataFrame(all_gzdata.groupby("realIP")["realIP"].count())
real_count.columns = ["count"]
real_count["realIP"] = real_count.index.tolist()
user_one = real_count[(real_count["count"] == 1)]  # 提取只登录一次的用户
#user_one.index = user_one.index.droplevel()   #删除index[realIP]
user_one = user_one.drop(labels='realIP', axis=1)  #删除列标签realIP
#print(real_count)
#print(user_one)
# 通过realIP与原始数据合并
real_one = pd.merge(user_one, all_gzdata, left_on="realIP", right_on="realIP")

# 统计浏览一次的网页类型
URL_count = pd.DataFrame(real_one.groupby("fullURLId")["fullURLId"].count())
URL_count.columns = ["count"]
URL_count.sort_values(by='count', ascending=False, inplace=True)  # 降序排列
# 统计排名前4和其他的网页类型
URL_count_4 = URL_count.iloc[:4,:]
time = hit_count.iloc[4:,0].sum()  # 统计其他的
URLindex = URL_count_4.index.values
URL_count_4 = URL_count_4.append([{'count':time}], ignore_index=True)
URL_count_4.index = [URLindex[0], URLindex[1], URLindex[2], URLindex[3], 
                     '其他']
URL_count_4['比例'] = URL_count_4['count'] / URL_count_4['count'].sum()
print(URL_count_4)

结果如下

 由结果可得,问题咨询页占比为64.9%,知识页占比为12.3%,这些记录均是通过搜索引擎进入的。由此可得两种可能性:

1、用户为流失用户,在问题咨询与知识页面上没有找到相关的需要。

2、用户找到其需要的信息,因此直接退出。

综合这些情况,将点击一次的用户行为定义为网页的跳出率。为了降低网页的跳出率,就需要对这些网页进行针对用户的个性化推荐,以帮助用户发现其感兴趣的网页或者需要的网页。统计浏览次数为一次的用户浏览的网页的总浏览次数。

# 在浏览1次的前提下, 得到的网页被浏览的总次数
fullURL_count = pd.DataFrame(real_one.groupby("fullURL")["fullURL"].count())
fullURL_count.columns = ["count"]
fullURL_count["fullURL"] = fullURL_count.index.tolist()
fullURL_count.sort_values(by='count', ascending=False, inplace=True)  # 降序排列

 所以,排名靠前的都是知识与咨询页面,由此猜测出大量用户的关注点在知识或者咨询方面上。

2.4数据预处理

 在本次数据探索中发现知识类网页的浏览次数在全部类型的网页中占比最高。当对原始数据进行探索分析时,发现存在与分析目标无关的数据和不符合建模输入要求的数据,即构建模型需要预处理的数据,需要对此类数据进行数据清洗、去重等操作,以此让数据满足构建推荐系统模型的输入要求

1)删除不符合规则的网页

通过分析原始数据发现,不符合规则的网页包括中间页面的网址、咨询发布成功页面、律师登录助手页面等,需要对其进行删除处理。

import os
import re
import pandas as pd
import pymysql as pm
from random import sample
from sqlalchemy import create_engine

# 修改工作路径到指定文件夹
os.chdir("D:/pyhoncode")

# 读取数据
con = pm.connect(host='localhost',user='root',password='123456',database='test',charset='utf8',port=3306)
data = pd.read_sql('select * from all_gzdata',con=con)
con.close()  # 关闭连接

#engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
#data = pd.read_sql('all_gzdata', engine, chunksize = 10000)


#data = pd.read_csv('./data/all_gzdata.csv')
#print(data.loc[:,'fullURLId'])

# 取出107类型数据
index107 = [re.search('107',str(i))!=None for i in data.loc[:,'fullURLId']]
data_107 = data.loc[index107,:]

# 在107类型中筛选出婚姻类数据
index = [re.search('hunyin',str(i))!=None for i in data_107.loc[:,'fullURL']]
data_hunyin = data_107.loc[index,:]

# 提取所需字段(realIP、fullURL)
info = data_hunyin.loc[:,['realIP','fullURL']]

# 去除网址中“?”及其后面内容
da = [re.sub('\?.*','',str(i)) for i in info.loc[:,'fullURL']]
info.loc[:,'fullURL'] = da     # 将info中‘fullURL’那列换成da
# 去除无html网址
index = [re.search('\.html',str(i))!=None for i in info.loc[:,'fullURL']]
index.count(True)   # True 或者 1 , False 或者 0
info1 = info.loc[index,:]

清洗后数据依然存在大量的目录网页,这类网页不但对构建推荐系统没有作用,反而会影响推荐结果的准确性,同样需要处理。

2)还原翻页网址

处理翻页情况最直接的方式是将翻页的网址删除,但是用户是通过搜索引擎进入网站的,访问入口不一定是原始页面,采取删除方法会损失大量有效数据,影响推荐结果。因此需要对翻页网址进行还原,再针对每个用户访问的页面进行去重操作。

# 找出翻页和非翻页网址
index = [re.search('/\d+_\d+\.html',i)!=None for i in info1.loc[:,'fullURL']]
index1 = [i==False for i in index]
info1_1 = info1.loc[index,:]   # 带翻页网址
info1_2 = info1.loc[index1,:]  # 无翻页网址
# 将翻页网址还原
da = [re.sub('_\d+\.html','.html',str(i)) for i in info1_1.loc[:,'fullURL']]
info1_1.loc[:,'fullURL'] = da
# 翻页与非翻页网址合并
frames = [info1_1,info1_2]
info2 = pd.concat(frames)
# 或者
info2 = pd.concat([info1_1,info1_2],axis = 0)   # 默认为0,即行合并
# 去重(realIP和fullURL两列相同)
info3 = info2.drop_duplicates()
# 将IP转换成字符型数据
info3.iloc[:,0] = [str(index) for index in info3.iloc[:,0]]
info3.iloc[:,1] = [str(index) for index in info3.iloc[:,1]]
len(info3)

3)筛去浏览次数不满足两次的用户。

数据中存在大量仅浏览一次就跳出的用户,浏览次数在两次及以上的用户的浏览记录更适合推荐,而浏览次数仅一次的用户的浏览记录会进入推荐模型会影响推荐模型的效果,因此需要筛去浏览次数不满两次的用户。

# 筛选满足一定浏览次数的IP
IP_count = info3['realIP'].value_counts()
# 找出IP集合
IP = list(IP_count.index)
count = list(IP_count.values)
# 统计每个IP的浏览次数,并存放进IP_count数据框中,第一列为IP,第二列为浏览次数
IP_count = pd.DataFrame({'IP':IP,'count':count})
# 3.3筛选出浏览网址在n次以上的IP集合
n = 2
index = IP_count.loc[:,'count']>n
IP_index = IP_count.loc[index,'IP']

4)划分数据集

将数据集按8:2的比例划分为训练集和测试集。

# 划分IP集合为训练集和测试集
index_tr = sample(range(0,len(IP_index)),int(len(IP_index)*0.8))  # 或者np.random.sample
index_te = [i for i in range(0,len(IP_index)) if i not in index_tr]
IP_tr = IP_index[index_tr]
IP_te = IP_index[index_te]
# 将对应数据集划分为训练集和测试集
index_tr = [i in list(IP_tr) for i in info3.loc[:,'realIP']]
index_te = [i in list(IP_te) for i in info3.loc[:,'realIP']]
data_tr = info3.loc[index_tr,:]
data_te = info3.loc[index_te,:]
print(len(data_tr))
IP_tr = data_tr.iloc[:,0]  # 训练集IP
url_tr = data_tr.iloc[:,1]  # 训练集网址
IP_tr = list(set(IP_tr))  # 去重处理
url_tr = list(set(url_tr))  # 去重处理
len(url_tr)

2.5 构建智能推荐模型

推荐系统是解决信息过载的有效手段,也是电子商务服务提供商提供个性化服务的重要信息工具。

1)基于物品的协同过滤算法的基本概念

基于物品的协同过滤系统的一般处理过程,分析用户与物品的数据集,通过用户对物品的浏览与否(喜好)找到相似的物品,然后根据用户的历史喜好,推荐相似的物品给目标用户。在建立推荐系统时,模型的数据量越大越能消除数据中的随机性,得到的推荐结果越好。其弊端在于数据量越大模型建立以及模型计算耗时越久。

2)基于物品的协同过滤算法的优缺点

1、优点:可以离线完成相似步骤,降低了在线计算量,提高了推荐效率;并利用用户的历史行为给用户做推荐解释,结果容易让客户信服。

2、缺点:现在的协同算法没有充分利用到用户间的差别,使计算得到的相似度不够准确,导致影响了推荐精度;此外,用户的兴趣是随着时间不断变化的,算法可能对用户新点击兴趣的敏感性较低,缺少一定的实时推荐,从而影响推荐质量。同时,基于物品的协同过滤适用于物品数明显小于用户数的情形,如果物品数很多,会导致计算物品相似度矩阵代价巨大。

3)模型构建

将数据集中的数据转换成0-1二元型数据,使用ItemCF算法对数据进行模型,并给出预测推荐结果。

import pandas as pd
# 利用训练集数据构建模型
UI_matrix_tr = pd.DataFrame(0,index=IP_tr,columns=url_tr)
# 求用户-物品矩阵
for i in data_tr.index:
    UI_matrix_tr.loc[data_tr.loc[i,'realIP'],data_tr.loc[i,'fullURL']] = 1
sum(UI_matrix_tr.sum(axis=1))

# 求物品相似度矩阵(因计算量较大,需要耗费的时间较久)
Item_matrix_tr = pd.DataFrame(0,index=url_tr,columns=url_tr)
for i in Item_matrix_tr.index:
    for j in Item_matrix_tr.index:
        a = sum(UI_matrix_tr.loc[:,[i,j]].sum(axis=1)==2)
        b = sum(UI_matrix_tr.loc[:,[i,j]].sum(axis=1)!=0)
        Item_matrix_tr.loc[i,j] = a/b

# 将物品相似度矩阵对角线处理为零
for i in Item_matrix_tr.index:
    Item_matrix_tr.loc[i,i]=0

# 利用测试集数据对模型评价
IP_te = data_te.iloc[:,0]
url_te = data_te.iloc[:,1]
IP_te = list(set(IP_te))
url_te = list(set(url_te))

# 测试集数据用户物品矩阵
UI_matrix_te = pd.DataFrame(0,index=IP_te,columns=url_te)
for i in data_te.index:
    UI_matrix_te.loc[data_te.loc[i,'realIP'],data_te.loc[i,'fullURL']] = 1

# 对测试集IP进行推荐
Res = pd.DataFrame('NaN',index=data_te.index,
                   columns=['IP','已浏览网址','推荐网址','T/F'])
Res.loc[:,'IP']=list(data_te.iloc[:,0])
Res.loc[:,'已浏览网址']=list(data_te.iloc[:,1])

# 开始推荐
for i in Res.index:
    if Res.loc[i,'已浏览网址'] in list(Item_matrix_tr.index):
        Res.loc[i,'推荐网址'] = Item_matrix_tr.loc[Res.loc[i,'已浏览网址'],
                :].argmax()
        if Res.loc[i,'推荐网址'] in url_te:
            Res.loc[i,'T/F']=UI_matrix_te.loc[Res.loc[i,'IP'],
                    Res.loc[i,'推荐网址']]==1
        else:
            Res.loc[i,'T/F'] = False

# 保存推荐结果
Res.to_csv('./data/Res.csv',index=False,encoding='utf8')

通过基于协同过滤算法构建的推荐系统,婚姻知识网址得到了针对每个用户的推荐。

4)模型评价 

推荐系统的评价一般可以从以下几个方面整体进行考虑。

1)用户、物品提供者、提供推荐系统网站。

2)好的推荐系统能够满足用户的需求,推荐其感兴趣的物品。并且在推荐的物品中,能全部都是热门物品,同时也需要用户反馈意见以帮助完善其推荐系统。

       因此、好的推荐系统不仅能预测用户的行为,而且能帮助用户发现可能会感兴趣但却不易被发现的物品;同时,推荐系统还应该帮助商家将长尾中的好商品发掘出来,推荐给可能会对它们感兴趣的用户。

       在实际应用中,评测推荐系统对三方的影响是必不可少的。其评测指标主要来源于如下3种评测推荐效果的实验方法,即离线测试、用户调查和在线实验。

(1)离线测试

离线测试是通过从实际系统中提取数据集,然后采用各种推荐算法对其进行测试,以获取各个算法的评测指标。这种实验方法的好处是不需要真实用户参与。

       注意:离线测试的指标和实际商业指标存在差距,比如预测准确率和用户满意度之间就存在很大差别,高预测准确率不等于高用户满意度。所以当推荐系统投人实际应用之前,需要利用测试的推荐系统进行用户调查。

(2)用户调查

用户调查是利用测试的推荐系统调查真实用户,观察并记录他们的行为,并让他们回答一些相关的问题。通过分析用户的行为和他们反馈的结果,判断测试推荐系统的好坏。

(3)在线测试

在线测试,顾名思义就是直接将系统投入到实际应用中,通过不同的评测指标比较不同的推荐算法的结果,比如点击率、跳出率等。

计算推荐结果的准确率、召回率和F1指标

import pandas as pd
# 读取保存的推荐结果
Res = pd.read_csv('./data/Res.csv',keep_default_na=False, encoding='utf8')

# 计算推荐准确率
Pre = round(sum(Res.loc[:,'T/F']=='True') / (len(Res.index)-sum(Res.loc[:,'T/F']=='NaN')), 3)

print(Pre)

# 计算推荐召回率
Rec = round(sum(Res.loc[:,'T/F']=='True') / (sum(Res.loc[:,'T/F']=='True')+sum(Res.loc[:,'T/F']=='NaN')), 3)

print(Rec)

# 计算F1指标
F1 = round(2*Pre*Rec/(Pre+Rec),3)
print(F1)

采用最基本的协同过滤算法进行建模,因此得到的模型结果也是一个初步结果,在实际引用中的过程中要结合业务进行分析,对模型进一步改造。

猜你喜欢

转载自blog.csdn.net/m0_61463713/article/details/129941556