使用自定义数据集:
Surprise有一些内置数据集,但您当然可以使用自定义数据集。评分数据可以从文件(如csv文件)或pandas 的Dataframe 来加载。无论哪种方法,都需要定义一个Reader对象来解析文件或Dataframe。
1. 从一个文件中上传数据集(例如csv文件),你需要 load_from_file()函数。
from surprise import BaselineOnly
from surprise import Dataset
from surprise.model_selection import cross_validate
from surprise import Reader
import os
file_path = os.path.expanduser(r'C:\Users\60191\.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, reader=reader)
cross_validate(BaselineOnly(),data,verbose=True)
关于readers的更多细节和使用方法,请查阅Reader class文档。
2. 从pandas 的Dataframe 中获取数据,你需要load_from_df()函数。你还需要一个Reader对象,只需要设定参数rating_scale
参数即可。dataframe必须包括三列,分别按顺序对应用户id,物品id以及评分。
import pandas as pd
from surprise import NormalPredictor
from surprise import Dataset
from surprise.model_selection import cross_validate
from surprise import Reader
ratings_dic = {'itemid':[1, 1, 1, 2, 2],
'userid':[9, 32, 2, 45, 'user_foo'],
'rating':[2, 2, 4, 3, 1]}
df = pd.DataFrame(ratings_dic)
reader = Reader(rating_scale=(1,5))
data = Dataset.load_from_df(df[['userid','itemid','rating']], reader)
cross_validate(NormalPredictor(),data,cv=2,verbose=True)
结果:
Evaluating RMSE, MAE of algorithm NormalPredictor on 2 split(s).
Fold 1 Fold 2 Mean Std
RMSE (testset) 2.0250 1.8865 1.9558 0.0693
MAE (testset) 1.6772 1.6113 1.6442 0.0330
Fit time 0.00 0.00 0.00 0.00
Test time 0.00 0.00 0.00 0.00
使用交叉验证迭代器:
我么可以使用cross_validate()
函数做所有对我们来说困难的工作。但是为了更好的控制,我们实例化一个交叉验证迭代器,并使用迭代器的split()
函数和test()函数在每一个split上做出预测。
如下,这是一个将数据集分为3折的经典K-折交叉验证实例。
from surprise import SVD
from surprise import Dataset
from surprise.model_selection import KFold
from surprise import accuracy
data = Dataset.load_builtin('ml-100k')
kf = KFold(n_splits=3)
algo = SVD()
for trainset,testset in kf.split(data):
algo.fit(trainset)
predictions = algo.test(testset)
accuracy.rmse(predictions, verbose=True)
其结果是:
RMSE: 0.9427
RMSE: 0.9443
RMSE: 0.9471
其他验证器,例如留一法等交叉验证器也可使用,可以在这里查看所有的交叉验证器。
我们有时会遇到数据集已经被预划分为几个文件,例如 movielens-100k就分别提供了5个训练集和测试集。Surprise可以使用surprise.model_selection.split.PredefinedKFold
对象来处理这种问题。(情况较少,没有进行翻译与测试,具体查看官方文档)
使用GridSearchCV调整算法参数:
cross_validate()函数可以对一组给定参数的交叉验程序进行准确性测评。如果你想知道哪些参数组合能够产生最好的结果,那么这个 GridSearchCV类就可以帮助你。给定一个参数dic
,它会测试所有的参数组合,并报告对所有评测指标的最佳参数。这个想法受到scikit-learn的GridSearchCV的启发。
下面这个实例,我们测试了SVD算法的参数 n_epochs
, lr_all
和 reg_all
的不同值。
from surprise import SVD
from surprise import Dataset
from surprise.model_selection import GridSearchCV
data = Dataset.load_builtin('ml-100k')
para_grid = {'n_epochs':[5,10],
'lr_all':[0.002,0.005],
'reg_all':[0.4,0.6]}
gs = GridSearchCV(SVD, para_grid, measures=['rmse','mae'],cv=3)
gs.fit(data)
#获得rmse最好得分
print(gs.best_score['rmse'])
#获得使rmse最好得分的参数
print(gs.best_params['rmse'])
其结果:
0.9641795296927803
{'n_epochs': 10, 'lr_all': 0.005, 'reg_all': 0.4}
这里我们测试3折交叉验证过程的平均RMSE和MAE,但也可以使用任何交叉验证迭代器。
一旦fit()
被调用,best_estimator
会使我们得到参数被优化过的算法实例,我们可以这样使用:
algo = gs.best_estimator['rmse']
algo.fit(data.build_full_trainset())
注意:字典参数,例如bsl_options
与sim_options
需特殊对待。请参考以下例子:
param_grid = {'k': [10, 20],
'sim_options': {'name': ['msd', 'cosine'],
'min_support': [1, 5],
'user_based': [False]}
}
当然,两者可以结合,例如 KNNBaseline :
param_grid = {'bsl_options': {'method': ['als', 'sgd'],
'reg': [1, 2]},
'k': [2, 3],
'sim_options': {'name': ['msd', 'cosine'],
'min_support': [1, 5],
'user_based': [False]}
}
进一步分析,cv_results
包括所有的信息而且可以被导入到一个pandas的dataframe。
results_df = pd.DataFrame.from_dict(gs.cv_results)
在我们的例子中,cv_results
看起来像这样(float格式):
'split0_test_rmse' : [ 1.0 , 1.0 , 0.97 , 0.98 , 0.98 , 0.99 , 0.96 , 0.97 ]
'split1_test_rmse' : [ 1.0 , 1.0 , 0.97 , 0.98 , 0.98 , 0.99 , 0.96 , 0.97 ]
'split2_test_rmse' : [ 1.0 , 1.0 , 0.97 , 0.98 , 0.98 , 0.99 , 0.96 , 0.97 ]
'mean_test_rmse' : [ 1.0 , 1.0 , 0.97 , 0.98 , 0.98 , 0.99 , 0.96 , 0.97 ]
'std_test_rmse' : [ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ]
'rank_test_rmse' : [ 7 8 3 5 4 6 1 2 ]
'split0_test_mae' : [ 0.81 , 0.82 , 0.78 , 0.79 , 0.79 , 0.8 , 0.77 , 0.79 ]
'split1_test_mae' : [ 0.8 , 0.81 , 0.78 , 0.79 , 0.78 , 0.79 , 0.77 , 0.78 ]
'split2_test_mae' : [ 0.81 , 0.81 , 0.78 , 0.79 , 0.78 , 0.8 , 0.77 , 0.78 ]
'mean_test_mae' : [ 0.81 , 0.81 , 0.78 , 0.79 , 0.79 , 0.8 , 0.77 , 0.78 ]
'std_test_mae' : [ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ]
'rank_test_mae' : [ 7 8 2 5 4 6 1 3 ]
'mean_fit_time' : [ 1.53 , 1.52 , 1.53 , 1.53 , 3.04 , 3.05 , 3.06 , 3.02 ]
'std_fit_time' : [ 0.03 , 0.04 , 0.0 , 0.01 , 0.04 , 0.01 , 0.06 , 0.01 ]
'mean_test_time' : [ 0.46 , 0.45 , 0.44 , 0.44 , 0.47 , 0.49 , 0.46 , 0.34 ]
'std_test_time' : [ 0.0 , 0.01 , 0.01 , 0.0 , 0.03 , 0.06 , 0.01 , 0.08 ]
'PARAMS' : [{ 'n_epochs' : 5 , 'lr_all' : 0.002 , 'reg_all' : 0.4 }, { 'n_epochs' : 5 , 'lr_all' : 0.002 , 'reg_all' : 0.6 }, {'n_epochs' : 5 , 'lr_all' : 0.005 , 'reg_all' : 0.4 }, { 'n_epochs' : 5 , 'lr_all' : 0.005 , 'reg_all' : 0.6 }, { 'n_epochs' : 10 , 'lr_all' : 0.002 , 'reg_all' : 0.4 }, { 'n_epochs' : 10 , 'lr_all' : 0.002 , 'reg_all' : 0。6 }, {'n_epochs' : 10 , 'lr_all' : 0.005 , 'reg_all' : 0.4 }, { 'n_epochs' : 10 , 'lr_all' : 0.4 ,0.6 ,0.4 ,0.6 ]0.005, 'reg_all': 0.6}]
'param_n_epochs': [5, 5, 5, 5, 10, 10, 10, 10]
'param_lr_all': [0.0, 0.0, 0.01, 0.01, 0.0, 0.0, 0.01, 0.01]
'param_reg_all': [0.4, 0.6, 0.4, 0.6,
你可以发现,每个列表具有相同大小的参数组合数,它对应下面的表格(参见官方文档)。