推薦算法——Surprise

Surprise入門使用

官網:https://yiyibooks.cn/sorakunnn/surprisesurprise-v1.0.5/surprise-v1.0.5/index.html

1. 使用movielens數據集

from surprise import SVD, KNNWithMeans, Reader
import os
from surprise import Dataset
from surprise.model_selection import cross_validate
# 默認載入movielens數據集
# data = Dataset.load_builtin('ml-100k')

# 載入自己數據集的方法
# 把path中包含的"~"和"~user"轉換成用戶目錄
filepah = os.path.expanduser('~/.surprise_data/ml-100k/ml-100k/u.data')
reader = Reader(line_format='user item rating timestamp', sep='\t')
data = Dataset.load_from_file(file_path=filepah, reader=reader)

# 試一把SVD矩陣分解
algo = SVD()
# 也可以試試別的算法
# algo = KNNWithMeans()
# 在數據集上測試一下效果並打印, 3折交叉驗證
cross_validate(algo, data, measures=['RMSE', 'MAE'], cv=3, verbose=True)


在這裏插入圖片描述

2. 算法調參(讓推薦系統有更好的效果)

這裏實現的算法用到的算法無外乎也是SGD等,因此也有一些超參數會影響最後的結果,我們同樣可以用sklearn中常用到的網格搜索交叉驗證(GridSearchCV)來選擇最優的參數。簡單的例子如下所示:

from surprise import Dataset, SVD
from surprise.model_selection import GridSearchCV

# 定義好需要優選的參數網格:輪次,學習率,正則化程度
param_grid = {'n_epochs': [5, 10], 'lr_all': [0.002, 0.005],
              'reg_all': [0.4, 0.6]}
# 使用網格搜索交叉驗證
grid_search = GridSearchCV(SVD, param_grid, measures=['rmse', 'mae', 'fcp'], cv=3)
data = Dataset.load_builtin('ml-100k')
# 在數據集上找到最好的參數
grid_search.fit(data)
# 輸出調優的參數組

# 輸出最好的RMSE結果
print(grid_search.best_score['rmse'])
# 輸出對應最好的RMSE結果的參數
print(grid_search.best_params['rmse'])

# 輸出最好的MAE結果
print(grid_search.best_score['mae'])
# 輸出對應最好的MAE結果的參數
print(grid_search.best_params['mae'])

print(grid_search.best_score['fcp'])
print(grid_search.best_params['fcp'])

在這裏插入圖片描述

2. 在數據集上訓練模型

1.用協同過濾構建模型並進行預測

movielens的例子,以下的程序段告訴大家如何在協同過濾算法建模以後,根據一個item取回相似度最高的item,主要是用到algo.get_neighbors()這個函數

import io
import os

from surprise import Dataset
from surprise import KNNBaseline

def read_item_names():
    """
    獲取電影名到電影id 和 電影id到電影名的映射
    構建映射字典
    :return:
    """
    filename = (os.path.expanduser('~/.surprise_data/ml-100k/ml-100k/u.item'))
    rid_to_name = {}
    name_to_rid = {}
    with io.open(filename, 'r', encoding='ISO-8859-1') as f:
        for line in f:
            line = line.split('|')
            rid_to_name[line[0]] = line[1]
            name_to_rid[line[1]] = line[0]
    return rid_to_name, name_to_rid

# 首先,用算法計算相互間的相似度
data = Dataset.load_builtin('ml-100k')
# 使用協同過濾必須有這行,將我們的算法運用於整個數據集,而不進行交叉驗證,構建了新的矩陣
trainset = data.build_full_trainset()
# 度量準則:pearson距離,協同過濾:基於item
sim_options = {'name': 'pearson_baseline', 'user_based': False}

algo = KNNBaseline(sim_options=sim_options)
algo.fit(trainset=trainset)

rid_to_name, name_to_rid = read_item_names()

# 拿出來Toy Story這部電影對應的item id
toy_story_raw_id = name_to_rid['Toy Story (1995)']
# 轉換爲內部id
toy_story_inner_id = algo.trainset.to_inner_iid(toy_story_raw_id)

# 根據內部id找到最近的10個鄰居
toy_story_neighbors = algo.get_neighbors(toy_story_inner_id, k=10)

# 將10個鄰居的內部id轉換爲item id也就是raw
toy_story_neighbors_rids = (algo.trainset.to_raw_iid(inner_id) for inner_id in toy_story_neighbors)
# 將10個鄰居的item id 轉爲name
toy_story_neighbors_names = (rid_to_name[raw_id] for raw_id in toy_story_neighbors_rids)
# 打印結果
print('----------The 10 nearest neighbors of Toy Story---------------')
for movie in toy_story_neighbors_names:
    print(movie)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章