前天将1000个用户对1000首音乐的打分数据存入PostgreSQL数据库的musicdata表中。
今天实现使用Python读取表中数据,然后使用基于物品的协同过滤算法计算推荐结果,算法使用了最简单的,也没有优化,先这样,后续有时间再优化吧,要熄灯了今天。
1 # -*- coding: utf-8 -*- 2 import psycopg2 3 import math 4 5 def aftersong_i(song_i,song_p): 6 if len(song_i)<len(song_p): 7 return True 8 elif len(song_i)==len(song_p): 9 if song_i<song_p: 10 return True 11 else: 12 return False 13 else: 14 return False 15 16 #读取数据库中用户打分数据存入musicdata 17 conn = psycopg2.connect(database = 'mytest', user = 'postgres', password = 'piao123', host = 'localhost',port='5432') 18 cur = conn.cursor() 19 cur.execute("SELECT * FROM musicdata2;") 20 data=cur.fetchall() 21 musicdata={user[0]:user[1:] for user in data} 22 cur.close() 23 conn.close() 24 print'read database OK' 25 26 #将每首音乐的打分分别存为字典形式 27 musicScores=[] 28 n=len(musicdata) 29 m=len(musicdata['user1']) 30 31 #listenedsongs=set() 32 listened={} 33 unlistened={} 34 for i in range(m): 35 musicScores.append({}) 36 for j in range(n): 37 if not unlistened.get('user'+str(j+1)): 38 unlistened['user'+str(j+1)]=[] 39 if not listened.get('user'+str(j+1)): 40 listened['user'+str(j+1)]=[] 41 if musicdata['user'+str(j+1)][i]!=0: 42 musicScores[i]['user'+str(j+1)]=musicdata['user'+str(j+1)][i] 43 #listenedsongs.add('song'+str(i+1)) 44 listened['user'+str(j+1)].append('song'+str(i+1)) 45 else: 46 unlistened['user'+str(j+1)].append('song'+str(i+1)) 47 musicdata='' 48 print 'musicScores is OK' 49 #计算机song_i和song_j的相似度 50 sim={} 51 for i in range(m): 52 print 'sim',i 53 for j in range(m): 54 if j>i: 55 muiltSum=0 56 leftSquareSum=0 57 rightSquareSum=0 58 for user in range(n): 59 if musicScores[i].get('user'+str(user+1)) and musicScores[j].get('user'+str(user+1)): 60 muiltSum+=musicScores[i]['user'+str(user+1)]*musicScores[j]['user'+str(user+1)] 61 leftSquareSum+=musicScores[i]['user'+str(user+1)]*musicScores[i]['user'+str(user+1)] 62 rightSquareSum+=musicScores[j]['user'+str(user+1)]*musicScores[j]['user'+str(user+1)] 63 sim[('song'+str(i+1),'song'+str(j+1))]=muiltSum/(math.sqrt(leftSquareSum)*math.sqrt(rightSquareSum)) 64 65 print 'sim is OK' 66 pred={} 67 for user in range(n): 68 SumSim=0 69 SumUsim=0 70 for song_p in unlistened['user'+str(user+1)]: 71 for song_i in listened['user'+str(user+1)]: 72 if aftersong_i(song_i,song_p): 73 SumSim += sim[(song_i,song_p)] 74 SumUsim += musicScores[int(song_i[4:])-1]['user'+str(user+1)]*sim[(song_i,song_p)] 75 else: 76 SumSim += sim[(song_p,song_i)] 77 SumUsim += musicScores[int(song_i[4:])-1]['user'+str(user+1)]*sim[(song_p,song_i)] 78 if SumSim!=0: 79 pred[(user+1,song_p)]=SumUsim/SumSim 80 print 'pred is OK' 81 82 83 ''' 84 Created on 2014年4月21日 85 86 @author: Administrator 87 '''
表中打分数据的表示:喜欢——3,收听完无表示——2,不喜欢——1,未听过——0。
预测的速度有点慢,虽然基于物品的推荐本来的计算量就比较大。一个感想是,在一个不合适的数据结构的基础上继续完成一项任务会让人受尽折磨而浑身难受。所以,早期做好计划十分有必要。