圖書推薦系統


  • 實驗介紹

通過在阿里雲天池上獲取關於圖書書本的數據集,核心是圍繞協同過濾算法進行推薦,主要是完成以下目標:

查詢功能:基於圖書名實現模糊查詢和准確查詢,基於評分和作者名進行准確查詢。

統計功能:基於圖書的平均評分、讀者對於某書的平均評分和用戶評論數作為依據,進行相關統計。

推薦功能:基於mapreduce和協同過濾算法,對某用戶進行圖書推薦。

  • 實驗框架
    •  

  • 流程設計
    • 查詢功能
    •  

    • 統計功能
    •  

    • 推薦功能
    •  

       

  • 關鍵代碼
    • 查詢功能:主要是基於hive來進行查詢,主要是用sql語句來進行查詢功能,如模糊查詢書名;

      先連接hive,然后編寫sql語句進行相關查詢,最后用impala庫中自帶的as_pandas函數進行相關展示。

    • 1.    if st.sidebar.button("模糊查詢圖書"):  
      2.        sizee=0  
      3.        if bookn=="":  
      4.            st.info('請輸入查詢書名!')  
      5.        else:  
      6.            sql='''''select * from book1 where name like '''+'\''+str(bookn)+'%'+'\''+' limit 10'  
      7.            cursor.execute(sql)  
      8.            a=as_pandas(cursor)  
      9.              
      10.            b=np.mat(a)  
      11.            result=b.tolist()  
      12.            if len(result)==0:  
      13.                st.info('抱歉,未查詢到對應書目。')  
      14.            else:  
      15.                  
      16.                st.dataframe(a)  

       

    • 統計功能:這塊主要是用mysql進行查詢,然后用pyecharts畫相關表進行展示。
    • 1.    if st.sidebar.button("用戶活躍度"):  
      2.      
      3.        sql = '''''select userid ,count(*) from rate1 group by userid order by count(*) desc limit 10'''  
      4.        sqlcursor.execute(sql)  
      5.        users = sqlcursor.fetchall()  
      6.        users  
      7.        user=[]  
      8.        num=[]  
      9.        for u in users:  
      10.            user.append(u[0])  
      11.            num.append(u[1])  
      12.        bar=Bar()  
      13.        bar.add_xaxis(user)  
      14.        bar.add_yaxis('用戶活躍度', num)  
      15.          
      16.        streamlit_echarts.st_pyecharts(bar)  

       

    • 推薦功能:

      本實驗中的圖書推薦系統是基於用戶的協同過濾算法實現的:主要分為3個Mapreduce步驟:

      第一步:根據用戶評分數據集得到用戶-評分矩陣:

      Map操作:key=user_id;values=[書名, 評分]

      Reduce操作:key=user_id;values=[閱讀量,總評分,[書名, 評分],[ 書名, 評分]]

    • 1.    class Step1(MRJob):  
      2.        def map_user(self, key, line):  
      3.            user_id, item_name, rating = line.split('^')    # 將原數據划分  
      4.            yield user_id, (item_name, float(rating))       # map結果 user_id, [書名, 評分]  
      5.      
      6.        def reduce_item(self, user_id, values):  
      7.            item_count = 0      # 用戶讀過的圖書總數 后續計算用戶相似度需要  
      8.            item_sum = 0        # 所有評分總和  
      9.            final = []  
      10.            for item_name, rating in values:  
      11.                item_count += 1  
      12.                item_sum += rating  
      13.                final.append((item_name, rating))       # reduce書名和評分  
      14.            yield user_id, (item_count, item_sum, final)        # user_id, [count, sum, ratings]  
      15.      
      16.        def steps(self):  
      17.            return [MRStep(mapper=self.map_user,  
      18.                           reducer=self.reduce_item),]  

      第二步:以第一步得到的用戶-評分矩陣作為輸入,尋找讀過某圖書的用戶列表;考慮到數據節點的性能,為了便於計算,將上一步的結果篩選,使用閱讀量在[300, 500]的用戶數據;

      Map操作:key=圖書名;values=[user_id,閱讀量]

      Reduce操作:key=圖書名;values=[[user_id1,閱讀量1]…… [user_idn,閱讀量n]]。

    • 1.    class Step2(MRJob):  
      2.        # map輸出的key:圖書名, value:用戶,閱讀量  
      3.        def map_item(self, id, line):  
      4.            strr = line.split('\t', 1)      # 划分一次  
      5.            user_id = eval(strr[0])  
      6.            values = eval(strr[1])  
      7.            item_count, item_sum, ratings = values  
      8.            for item in ratings:  
      9.                yield item[0], (user_id, item_count)  
      10.      
      11.        # 得到book user_list  
      12.        def reduce_user(self, item, values):  
      13.            user_list = []  
      14.            for user in values:  
      15.                user_list.append(user)  
      16.            yield item, (user_list)  
      17.      
      18.        def steps(self):  
      19.            return [MRStep(mapper=self.map_item,  
      20.                           reducer=self.reduce_user), ]  

      第三步:以上一步得到的圖書用戶列表作為輸入文件,計算用戶之間的相似度;

      Map操作:key=[用戶id1,用戶id2];values=[id1閱讀量,id2閱讀量]

      Reduce操作:key=[用戶id1,用戶id2];values=[相似度,共同圖書閱讀量]

    • 1.    class Step3(MRJob):  
      2.        def pair_users(self, user_id, line):  
      3.            values = eval(line.split('\t')[1])  
      4.            for user1, user2 in combinations(values, 2):  
      5.                yield (user1[0], user2[0]), (user1[1], user2[1])  
      6.                # user1[0]是用戶名,user1[1]是用戶閱讀量  
      7.      
      8.        def cal_similarity(self, users, counts):  
      9.            num = 0     # num表示兩人共同讀過的圖書數量  
      10.            user_pair, count = users, counts    # count是用戶1和用戶2的閱讀量  
      11.            user1, user2 = user_pair  
      12.            cnt1 = 0  
      13.            cnt2 = 0  
      14.            for c1, c2 in count:  
      15.                num += 1        # 當兩個key相同時,num++,表示共同圖書加一  
      16.                cnt1 = c1  
      17.                cnt2 = c2  
      18.            fenmu = cnt1 + cnt2 -num  
      19.            similarity = float(num / fenmu)  
      20.            yield (user1, user2), (similarity, num)  

       

  • 結果展示
    • 查詢功能:根據書名進行模糊查詢和准確查詢;查詢評分、查詢作者。

    •  

    • 統計功能:用戶活躍度、最受歡迎圖書等
    •  


       

    • 推薦功能:

      考慮到有的用戶讀的書本很少,相比之下無法進行准確推薦,對於這部分用戶進行推薦查詢時會提醒用戶去查看相關榜單;

    •  

  • 該圖書推薦系統的關鍵在於
    • 推薦算法的實現,使用了基於用戶的協同過濾算法,利用三次mapreduce操作實現算法;
    • 將數據存放至hdfs,使用Hadoop分布式平台。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM