Surprise에서 미리 정의 된 접기에서 데이터를로드 할 때 전체 trainset을 구축하는 방법은 무엇입니까?

user2529589

다양한 추천 시스템 알고리즘을 평가하기 위해 Surprise사용하고 있습니다. 가능한 모든 사용자 및 항목 순열에 대한 예측 및 예측 범위를 계산하고 싶습니다. 내 데이터는 미리 정의 된 분할에서로드됩니다.

예측 범위를 계산하는 내 전략은

  1. 완전한 trainset 및 적합 구축
  2. 모든 사용자 및 항목 목록 가져 오기
  3. 목록을 반복하고 예측합니다.
  4. 예측이 예측 범위를 계산할 수없는 예외를 계산합니다.

호출을 시도 data.build_full_trainset())하면 다음 오류가 발생합니다.

AttributeError: 'DatasetUserFolds' object has no attribute 'build_full_trainset'

미리 정의 된 접기에서 데이터를로드 할 때 전체 학습 세트를 빌드하는 방법이 있습니까?

또는 Surprise의 외부 데이터를 데이터 프레임으로 결합하고 프로세스를 다시 실행 해 보겠습니다. 아니면 더 나은 접근 방식이 있습니까?

감사합니다.

# %% #https://surprise.readthedocs.io/en/stable/getting_started.html#basic-usage

import random
import pickle
import numpy as np
import pandas as pd

# from survey.data_cleaning import long_ratings
from surprise import NormalPredictor
from surprise import Dataset
from surprise import Reader
from surprise.model_selection import cross_validate
from surprise.model_selection import GridSearchCV
# from surprise.model_selection import LeaveOneOut, KFold
from surprise.model_selection import PredefinedKFold

#set random seed for reproducibility
my_seed = 0
random.seed(my_seed)
np.random.seed(my_seed)

path = 'data/recommenders/'

def load_splits():
    """
    Loads splits from files load data from splits created by colab code and stored to files. used in surprise_recommenders.py

    returns splits as dataset
    """
    # path to dataset folder
    files_dir = 'data/recommenders/splits/'
    # This time, we'll use the built-in reader.
    reader = Reader(line_format='user item rating', sep=' ', skip_lines=0, rating_scale=(1, 5))

    # folds_files is a list of tuples containing file paths:
    # [(u1.base, u1.test), (u2.base, u2.test), ... (u5.base, u5.test)]
    train_file = files_dir + 'u%d.base'
    test_file = files_dir + 'u%d.test'
    folds_files = [(train_file % i, test_file % i) for i in (1, 2, 3, 4, 5)]

    data = Dataset.load_from_folds(folds_files, reader=reader)
    return data

data = load_splits()

pkf = PredefinedKFold()

algos = {
  'NormalPredictor': {'constructor': NormalPredictor,
                      'param_grid': {}
   }}

key = "stratified_5_fold"
cv_results={}
print(f"Performing {key} cross validation.")
for algo_name, v in algos.items():
    print("Working on algorithm: ", algo_name)
    gs = GridSearchCV(v['constructor'], v['param_grid'], measures=['rmse', 'mae'], cv=pkf)

    gs.fit(data)
    # best RMSE score
    print(gs.best_score['rmse'])
    
    # combination of parameters that gave the best RMSE score
    print(gs.best_params['rmse'])

    # Predict on full dataset
    # Use the weights that yields the best rmse:
    algo = gs.best_estimator['rmse']
    algo.fit(data.build_full_trainset())     #predefined folds breaks it.


    cv_results[algo_name] = pd.DataFrame.from_dict(gs.cv_results)
user2529589

TLDR; Surprise model_selection 문서는 전체 trainset에 데이터를 맞추는 " refit "방법을 나타내지 만 사전 정의 된 폴드에서는 명시 적으로 작동하지 않습니다.

또 다른 주요 문제 : 이 문제에 대한 oyyablokov의 의견 은 NaN이있는 데이터로 모델을 적합수 없음을 시사합니다 . 따라서 전체 trainset이 있더라도 평가가 있거나없는 모든 사용자 및 항목 조합이 필요한 예측 범위와 같은 것을 계산하기 위해 전체 예측 행렬을 어떻게 생성합니까?

내 해결 방법은 3 개의 Surprise 데이터 세트를 만드는 것이 었습니다.

  1. best_params를 계산하기위한 사전 정의 된 접기의 데이터 세트
  2. 평가의 전체 데이터 세트 (Surprise 외부의 모든 접기 결합)
  3. 사용자 및 항목의 가능한 모든 조합을 포함하는 전체 예측 매트릭스 데이터 세트 (평가 유무에 관계없이).

그리드 검색 교차 유효성 검사로 최상의 매개 변수를 찾은 후 다음과 같이 예측 및 적용 범위를 찾을 수 있습니다.

import pandas as pd
from surprise import Dataset, Reader

def get_pred_coverage(data_matrix, algo_constructor, best_params, verbose=False):
    """
    Calculates coverage
    inputs:
        data_matrix: Numpy Matrix with 0, 1, 2 columns as user, service, rating
        algo_constructor: the Surprise algorithm constructor to pass the best params into
        best_params: Surprise gs.best_params to pass into algo.

    returns: coverage & full predictions
    """
    reader=Reader(rating_scale=(1,5))

    full_predictions = [] #list to store prediction results
    
    df = pd.DataFrame(data_matrix)
    if verbose: print(df.info())
    df_no_nan = df.dropna(subset=[2])
    if verbose: print(df_no_nan.head())
    no_nan_dataset = Dataset.load_from_df(df_no_nan[[0,1,2]], reader)
    full_dataset = Dataset.load_from_df(df[[0, 1, 2]], reader)
    #Predict on full dataset
    # Use the weights that yields the best rmse:
    algo = algo_constructor(**best_params) # Pass the dictionary as double star keyword arguments to the algorithm constructor

    #Create a no-nan trainset to fit on 
    no_nan_trainset = no_nan_dataset.build_full_trainset()
    algo.fit(no_nan_trainset)
    if verbose: print('Number of trainset users: ', no_nan_trainset.n_users, '\n')
    if verbose: print('Number of trainset items: ', no_nan_trainset.n_items, '\n')

    pred_set = full_dataset.build_full_trainset()
    if verbose: print('Number of users: ', pred_set.n_users, '\n')
    if verbose: print('Number of items: ', pred_set.n_items, '\n')
    
    #get all item ids
    pred_set_iids = list(pred_set.all_items())
    # print(f'pred_set iids are {pred_set_iids}')
    iid_converter = lambda x: pred_set.to_raw_iid(x)
    pred_set_raw_iids = list(map(iid_converter, pred_set_iids))
    
    #get all user ids
    pred_set_uids = list(pred_set.all_users())
    uid_converter = lambda x: pred_set.to_raw_uid(x)
    pred_set_raw_uids = list(map(uid_converter, pred_set_uids))
    # print(f'pred_set uids are {pred_set_uids}')

    for user in pred_set_raw_uids:
        for item in pred_set_raw_iids:
            r_ui = float(df[2].loc[(df[0] == user) & (df[1]== item)])  #find the rating, by user and value
            # print(f"r_ui is type {type(r_ui)} and value {r_ui}")
            
            prediction = algo.predict(uid = user, iid = item, r_ui=r_ui)
            # print(prediction)
            full_predictions.append(prediction)
    #access a tuple 
    #5th element, dicitonary item "was_impossible"
    impossible_count = 0
    for prediction in full_predictions:
        impossible_count += prediction[4]['was_impossible']

    if verbose: print(f"for algo {algo}, impossible_count is {impossible_count} ")

    prediction_coverage = (pred_set.n_users*pred_set.n_items - impossible_count)/(pred_set.n_users*pred_set.n_items)
    print(f"prediction_coverage is {prediction_coverage}")

    return prediction_coverage, full_predictions

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관