제12장 협동 필터 추천 알고리즘 프로그램 실현
1. 데이터베이스에 연결하여 원시 데이터를 얻는다
import pandas as pd
import pymysql
conn = pymysql.connect(host='localhost', user='root', password='password', port=3306, db='liuyan', charset='utf8')
cur = conn.cursor() #
cursor = cur.execute('select * from all_gzdata') # sql
data = cur.fetchall() #
from pandas import DataFrame
df = DataFrame(list(data), columns=['realIP', 'realAreacode', 'userAgent', 'userOS',
'userID', 'clientID', 'timestamp', 'timestamp_format',
'pagePath', 'ymd', 'fullURL', 'fullURLId', 'hostname',
'pageTitle', 'pageTitleCategoryId', 'pageTitleCategoryName',
'pageTitleKw', 'fullReferrer', 'fullReferrerURL', 'organicKeyword',
'source'])
cur.close()
conn.close()
2. 데이터 탐색 분석
탐색 분석은 데이터 분석을 하는 첫걸음이자 우리가 실제 데이터의 상황을 대체적으로 이해하고 그 내재된 규칙을 얻을 수 있도록 하는 것이다.
2.1 웹 유형 분석(웹 유형은'웹 주소 유형'의 상위 3자리 숫자를 가리킨다)
# ( “ ” 3 )
df['urlcat'] = df['fullURLId'].str.extract('(\d{3})')
counts3 = df.groupby('urlcat').size().sort_values(ascending=False)
counts3 = counts3.reset_index()
counts3.columns = ['index', 'num']
counts3['prec'] = counts3['num'] / counts3['num'].sum() * 100
#
counts_101 = df[df['urlcat'] == '101'].groupby('fullURLId').size().sort_values(ascending=False)
counts_101 = counts_101.reset_index()
counts_101.columns = ['index', 'num']
counts_101['prec'] = counts_101['num'] / counts_101['num'].sum() * 100
#
# 107
def count107(i):
j = i[['fullURL']][i['fullURLId'].str.contains('107')].copy() # 107
j['type'] = None #
j['type'][j['fullURL'].str.contains('info/.+?/')] = u' '
j['type'][j['fullURL'].str.contains('info/.+?/.+?')] = u' '
j['type'][j['fullURL'].str.contains('/\d+?_*\d+?\.html')] = u' '
return j['type'].value_counts()
counts_107 = count107(df)
counts_107 = counts_107.reset_index()
counts_107.columns = ['index', 'num']
counts_107['prec'] = counts_107['num'] / counts_107['num'].sum() * 100
#
df['baohan'] = 0
df['baohan'][df['fullURL'].str.contains('\?{0}')] = 0
df['baohan'][df['fullURL'].str.contains('\?')] = 1
df['baohan'].value_counts()
counts_bh = df[df['baohan'] == 1].groupby(df['fullURLId']).size()
counts_bh = counts_bh.reset_index()
counts_bh.columns = ['index', 'num']
#
df['xiaguang'] = 0
df['xiaguang'][df['fullURL'].str.contains('http.*?/$')] = 1
df['xiaguang'].value_counts()
counts_xg = df[df['xiaguang'] == 1].groupby(df['urlcat']).size()
counts_xg = counts_xg.reset_index()
counts_xg.columns = ['index', 'num']
counts_xg['prec'] = counts_xg['num'] / counts_xg['num'].sum() * 100
2.2 클릭 횟수 분석
#
df['dj'] = 1
dianji = df['dj'].groupby(df['realIP']).size() # IP
dianji = dianji.reset_index()
dianji.columns = ['realIP', 'num']
dianjicishu = dianji.groupby('num').size() # ‘ ’
dianjicishu = dianjicishu.reset_index()
dianjicishu.columns = ['cishu', 'renshu']
dianjicishu['prec'] = dianjicishu['renshu'] / dianjicishu['renshu'].sum() * 100 #
dianjicishu['jilu_prec'] = dianjicishu['renshu'] / df['dj'].sum() * 100 #
# 7
qici = dianjicishu[dianjicishu['cishu'] > 7]
del qici['prec']
del qici['jilu_prec']
import numpy as np
qici2 = DataFrame([['8-50', 0], ['50-100', 0], ['100 ', 0]], columns=[' ', ' '])
qici2[' '][0] = qici[(7 < qici['cishu']) & (qici['cishu'] < 50)]['renshu'].sum()
qici2[' '][1] = qici[(qici['cishu'] > 50) & (qici['cishu'] < 100)]['renshu'].sum()
qici2[' '][2] = qici[qici['cishu'] > 100]['renshu'].sum()
#
dianji_one = df.groupby(['realIP', 'fullURLId']).size()
dianji_one = dianji_one.reset_index()
dianji_one.columns = ['realIP', 'fullURLId', 'num']
dianji_one = dianji_one[dianji_one['num'] == 1]
dianji_one2 = dianji_one.groupby('fullURLId').size()
dianji_one2 = dianji_one2.reset_index()
dianji_one2.columns = ['fullURLId', 'num']
dianji_one2['prec'] = dianji_one2['num'] / dianji_one2['num'].sum() * 100
dianji_one2 = dianji_one2.sort_values('prec', ascending=False)
#
dianji_one_web = df.groupby(['fullURL', 'realIP']).size()
dianji_one_web = dianji_one_web.reset_index()
dianji_one_web.columns = ['fullURL', 'realIP', 'num']
dianji_one_web = dianji_one_web[dianji_one_web['num'] == 1]
dianji_one_web2 = dianji_one_web.groupby('fullURL').size()
dianji_one_web2 = dianji_one_web2.reset_index()
dianji_one_web2.columns = ['fullURL', 'num']
2.3 웹 페이지 순위
#
dianji_web = df.groupby('fullURL').size()
dianji_web = dianji_web.reset_index()
dianji_web.columns = ['fullURL', 'num']
dianji_web = dianji_web.sort_values('num', ascending=False)
#
dianji2 = df.groupby(['urlcat', 'realIP']).size()
dianji2 = dianji2.reset_index()
dianji2.columns = ['urlcat', 'realIP', 'num']
dianji2['counts'] = 1
leixingdianji = DataFrame([[' ( )', 0, 0, 0.0],
[' ', 0, 0, 0.0]], columns=['html ',' ', ' ', ' '])
leixingdianji[' '][0] = dianji2[dianji2['urlcat'] == '107']['num'].sum()
leixingdianji[' '][1] = dianji2[dianji2['urlcat'] == '101']['num'].sum()
leixingdianji[' '][0] = dianji2[dianji2['urlcat'] == '107']['counts'].sum()
leixingdianji[' '][1] = dianji2[dianji2['urlcat'] == '101']['counts'].sum()
leixingdianji[' '][0] = leixingdianji[' '][0] / leixingdianji[' '][0]
leixingdianji[' '][1] = leixingdianji[' '][1] / leixingdianji[' '][1]
3. 데이터 사전 처리
원시 데이터의 탐색 분석을 토대로 분석과 무관하거나 모델이 처리해야 할 데이터를 발견하고 이런 데이터에 대해 처리한다.이때의 데이터 예처리는 데이터 세척, 데이터 변환, 속성 규약을 포함한다.
3.1 데이터 세척(상관없는 기록 및 중복된 기록 삭제)
# ( midques_ )
data1= df[~df['fullURL'].str.contains('midques_')] # 2989
count1 = df[df['fullURL'].str.contains('midques_')]['fullURL'].count() # =7
df['fullURL'].count() # =2996
# ( - )
count2 = data1[data1['pageTitle'] == ' - ']['pageTitle'].count() # =76
data2 = data1[~(data1['pageTitle'] == ' - ')] # 2913
#
count3 = data2[data2['pageTitle'] == ' ']['pageTitle'].count() # =14
data3 = data2[~(data2['pageTitle'] == ' ')] # 2899
# , ask,info,fagui,lawyer
data4 = data3[((data3['fullURL'].str.contains('ask')) | (data3['fullURL'].str.contains('info')) |
(data3['fullURL'].str.contains('fagui')) | (data3['fullURL'].str.contains('lawyer')))] # 2667
count4 = data3[~((data3['fullURL'].str.contains('ask')) | (data3['fullURL'].str.contains('info')) |
(data3['fullURL'].str.contains('fagui')) | (data3['fullURL'].str.contains('lawyer')))]['fullURL'].count() # =232
#
count5 = data4[((data4['pageTitle'].str.contains(' ')) | (data4['pageTitle'].str.contains(' ')))]['pageTitle'].count() # =38
data5 = data4[~((data4['pageTitle'].str.contains(' ')) | (data4['pageTitle'].str.contains(' ')))] # 2629
# ? ( 199)
data6 = data5[~((data5['fullURL'].str.contains('\?')) & (data5['fullURLId'].str.contains('199')))] # 2627
count6 = data5[(data5['fullURL'].str.contains('\?')) & (data5['fullURLId'].str.contains('199'))]['fullURL'].count() # =2
# .html
count7 = data6[~data6['fullURL'].str.contains('html')]['fullURL'].count() # =107
data7 = data6[data6['fullURL'].str.contains('html')] # 2520
#
data7[data7.duplicated(['realIP', 'timestamp', 'fullURL'])][['realIP', 'timestamp', 'fullURL']].sort_values(
['realIP', 'timestamp']) # df.duplicated() Series,
data8 = data7.drop_duplicates() # 1583
3.2 데이터 변환
data8_2=data8.copy()
data8_2['fullURL']=data8_2['fullURL'].str.replace('_\d.html','.html')
#data8_2[data8_2['fullURL'].str.contains('_\d\.html')] #
data8_2=data8_2.drop_duplicates() #
del data8_2['urlcat']
#
#### Navicat Premium gzdata # :`` , 。
# , ,
python list , :
( : )
def insertNews(data):
for index in range(len(data)):
newsobj = data.iloc[index]
newsobjs = [newsobj.get('realIP'), newsobj.get('realAreacode'),newsobj.get('userAgent'),newsobj.get('userOS'),
newsobj.get('userID'), newsobj.get('clientID'),newsobj.get('timestamp'),newsobj.get('timestamp_format'),
newsobj.get('pagePath'), newsobj.get('ymd'),newsobj.get('fullURL'), newsobj.get('fullURLId'),
newsobj.get('hostname'),newsobj.get('pageTitle'),newsobj.get('pageTitleCategoryId'),
newsobj.get('pageTitleCategoryName'),newsobj.get('pageTitleKw'),
newsobj.get('fullReferrer'), newsobj.get('fullReferrerURL'),newsobj.get('organicKeyword'), newsobj.get('source')]
conn = pymysql.connect(host='localhost', user='root', password='password', port=3306, db='liuyan',charset='gbk')
cur = conn.cursor()
cur.execute("insert into gzdata(realIP,realAreacode,userAgent,userOS,userID,clientID,timestamp,timestamp_format,pagePath,ymd,fullURL,fullURLId,hostname,pageTitle,pageTitleCategoryId,pageTitleCategoryName,pageTitleKw,fullReferrer,fullReferrerURL,organicKeyword,source)"
"VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')" %tuple(newsobjs))
# ,
conn.commit()
#
cur.close()
#
conn.close()
insertNews(data8_2)
#
import pymysql
from pandas import DataFrame
conn2=pymysql.connect(host='localhost',user='root',password='password',port=3306,db='liuyan',charset='utf8')
cur2=conn2.cursor()
cursor2=cur2.execute('select * from gzdata')
data2=cur2.fetchall()
df2=DataFrame(list(data2),columns=['realIP', 'realAreacode', 'userAgent',
'userOS','userID', 'clientID', 'timestamp',
'timestamp_format','pagePath', 'ymd',
'fullURL', 'fullURLId', 'hostname',
'pageTitle', 'pageTitleCategoryId',
'pageTitleCategoryName','pageTitleKw',
'fullReferrer', 'fullReferrerURL',
'organicKeyword','source'])
df2['type']='weizhi'
df2['urlcat'] = df2['fullURLId'].str.extract('(\d{3})')
df2.loc[df2['urlcat']=='101','type']='zixun'
df2.loc[df2['urlcat']=='107','type']=u'zhishi'
# (199) ,
df2.loc[((df2['fullURL'].str.contains('ask'))|(df2['fullURL'].str.contains('askzt'))),'type']='zixun' # ‘ask’ 'askzt'
df2.loc[((df2['fullURL'].str.contains('zhishi'))|(df2['fullURL'].str.contains('faguizt'))),'type']='zhishi' # ‘zhishi’ ‘faguizt’
df2.groupby('type').size() #df2[df2.type=='weizhi'][['fullURL','fullURLId','urlcat','type']] 'weizhi'
#
df2['type2']='weizhi2'
df2.loc[((df2['type']=='zhishi')&(df2['fullURL'].str.contains('info'))),'type2']=df2['fullURL'].str.extract('info\/(.*?)\/',expand=False)
df2['type3']='weizhi3'
df2.loc[((df2['type']=='zhishi')&(df2['fullURL'].str.contains('info'))),'type3']=df2['fullURL'].str.extract('info\/.*?\/(.*?)\/',expand=False)
#
hunyin_count=df2[((df2['type']=='zhishi')&(df2['type2']=='hunyin'))].groupby('fullURL').size()
hunyin_count=hunyin_count.reset_index()
hunyin_count.columns=['fullURL','num']
hunyin_count2=hunyin_count.groupby('num').size()
hunyin_count2=hunyin_count2.reset_index()
hunyin_count2.columns=[' ',' ']
hunyin_count.groupby('num').sum()
3.3 속성 규약
추천 시스템 모델의 입력 데이터가 필요하기 때문에 처리된 데이터에 대해 속성 규약을 하고 모델이 필요로 하는 속성을 추출해야 한다.본 사례에서 모델에 필요한 데이터 속성은 사용자와 사용자가 방문한 웹 페이지이다.
import numpy as np
a=df2['fullURL'].unique() # , a 。
b=sorted(a.tolist()) # 'fullURL' , sorted(set(df2['fullURL']))
goods_matrix=DataFrame(np.arange(len(df2['realIP'][:1000])*len(b[:200])).reshape(len(df2['realIP'][:1000]),len(b[:200])),
index=df2['realIP'][:1000],columns=b[:200]) # IP , dataframe, IP1000 , 200 。
주: 본인의 컴퓨터 설정이 너무 낮아서 1000명의 사용자의 정보를 골라 계속 분석했기 때문에 다음 결과는 좋지 않습니다.
4. 모델 구성
협동 필터 추천 알고리즘은 사용자 기반과 물품 기반으로 나뉘는데 본 사례는 물품 기반의 협동 필터 알고리즘을 선택한다. 즉,'어떤 물품을 사용자 B에게 추천합니까?'라고 대답한다.
4.1 사용자가 아이템에 대한 관심 매트릭스 생성
# goods_matrix ( ) , 0-1 。
import time
start=time.clock()
for i in range(goods_matrix.index.size):
for j in range(goods_matrix.columns.size):
if df2.loc[i,'fullURL']==goods_matrix.columns[j]:
goods_matrix.iloc[i, j]=1 # df2.loc[i,'fullURL'] goods_matrix j , 1, 0
else:
goods_matrix.iloc[i, j]=0
end=time.clock()
print(end-start,"seconds process time")
4.2 훈련집과 테스트집 획득
# goods_matrix , 10% , 90% 。
import random
#random.shuffle(goods_matrix) # :random.shuffle(list) None, , , 。
all_matrix=np.random.permutation(goods_matrix) # :random.permutation(list) , , 。all_matrix 。
all_matrix2=DataFrame(all_matrix,index=df2['realIP'][:1000],columns=b[:200]) # dataframe
#
train=all_matrix2.iloc[:int(len(all_matrix)*0.9),:]
test=all_matrix2.iloc[int(len(all_matrix)*0.9):,:]
train2=train.as_matrix() #
test2=test.as_matrix() #
4.3 협동 필터 알고리즘 구축
import numpy as np
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): # , , x (0-1 )
self.sim = self.similarity(x, distance)
def recommend(self,a): #
return np.dot(self.sim,a)*(1-a)
4.4 테스트 집합에서의 사용자 행동 예측
# , , 。
train3=train2.T # , , 。
test3=test2.T
r=Recommender()
sim=r.fit(train3) #
result=r.recommend(test3) #
sim2=DataFrame(sim)
result2=DataFrame(result) # dataframe,
result2.index=test.columns
result2.columns=test.index
4.5 IP당 K개 웹 사이트 추천
이곳의 추천 함수는 블로그를 클릭하여 링크를 여는 방법을 참고한 것이다.
4
from pandas import Series
def tuijian_result(K,recomMatrix):
recomMatrix.fillna(0,inplace=True)
xietong = ['xietong' + str(K) for K in range(1, K + 1)]
tuijian = DataFrame([], index=recomMatrix.columns, columns=xietong)
for i in range(len(recomMatrix.columns)):
temp = result2.sort_values(by=recomMatrix.columns[i], ascending=False)
k = 0
while k < K:
tuijian.iloc[i, k] = temp.index[k]
if temp.iloc[k, i] == 0:
tuijian.iloc[i, k:K] = np.nan
break
k = k + 1
return tuijian
start1=time.clock()
final_result=tuijian_result(3,result2)
end1=time.clock()
이로써 본고는 하나의 추천 알고리즘만 제시했고 다른 추천 모델을 고려할 수 있으며 각 모델이 서로 다른 추천 값에 대한 평가 지표 값을 비교하고 각 모델에 있는 F1 지표를 계산할 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.