ホームページ >バックエンド開発 >Python チュートリアル >レコメンダー システムとは何か、またその使用方法
レコメンダー システム、またはレコメンデーション システムは、情報をフィルタリングするために使用されるアルゴリズムです。情報を収集すると、特定のユーザーに最も関連性の高い提案が提供されます。これは、膨大な量の情報があるプラットフォームを選択する必要がある場合に役立ちます。
協調フィルタリングは、特定の製品の過去の視聴や評価などのユーザーの過去の決定と、他のユーザーの同様の行動を使用してモデルを構築し、ユーザーが何を楽しむかを予測します。ユーザー評価マトリックスを使用しており、人口統計や評価以外のその他の情報などの他のユーザー情報は必要ありません。これは、協調フィルタリングの大きな強みです。なぜなら、協調フィルタリングは最小限の情報に依存し、内容を理解せずにアイテムを推奨できるからです。
Last.fm は、ユーザーが定期的に聴いているバンドや個々のトラックを観察し、それらを他のユーザーの聴取行動と比較することによって曲を推奨します。 Last.fm は、ユーザーのライブラリには表示されないが、同様の興味を持つ他のユーザーによってよく再生されるトラックを再生します。このアプローチはユーザーの行動を活用するため、協調フィルタリング手法の一例となります。 Last.fm では正確な推奨を行うために、ユーザーに関する多くの情報が必要です。これは、協調フィルタリング システムで一般的なコールド スタート問題の例です。 (出典: WiKipedia、https://en.wikipedia.org/wiki/Recommender_system)
協調フィルタリングは、過去に同意した人々が将来も同意すると仮定します。現在のユーザーと同様の履歴を持つ別のユーザーを識別し、この近傍を使用して予測を生成します。これらの方法は、メモリベースおよびモデルベースのアプローチとみなされます。
協調フィルタリング アルゴリズムに干渉する可能性のある問題には、コールド スタート、スケーラビリティ、スパース性などがあります。 コールド スタート とは、正確な推奨事項を作成するためのデータが不足していることを指します。また、推奨事項を計算するために大量の計算能力も必要となるため、アルゴリズムのスケーラビリティが低くなります。また、インターネット上には膨大な量の製品やアイテムがあるため、評価はかなりまばらです。
トップブランドと化粧品のレビューを含むデータセットを使用します。このデータセットは、Kaggle Web サイトで見つけることができます: https://www.kaggle.com/datasets/jithinanievarghese/cosmetics-and-beauty-products-reviews-top-brands
rating_list = pd.read_csv('top_brands_cosmetics_product_reviews.csv', sep=',', usecols=['author', 'product_title', 'product_rating', 'review_date']) items = pd.read_csv('top_brands_cosmetics_product_reviews.csv', usecols=['product_title', 'product_url', 'brand_name'], encoding='latin-1') print(f'Number of ratings: {rating_list.author.nunique()} | Number of items: {items.product_title.nunique()}')
ユーザー項目マトリックスを使用してトレーニングをピボットします。
X_train, X_test, y_train, y_test = train_test_split(rating_list, rating_list.product_rating, test_size=0.1, random_state=42) ratings = X_train.pivot_table(index=['author'], columns=['product_title'], values='product_rating').fillna(0) mean_ratings = ratings.mean(axis=1) print(f'Number of users: {ratings.shape[0]} | Number of items: {ratings.shape[1]}')
類似度を計算します。
def get_all_recommendations(user_id, model, use_means=True): distance, knn = model.kneighbors(ratings.fillna(0)) # nearest neighbors knn = pd.DataFrame(knn + 1, index=ratings.index) sim = pd.DataFrame(1 - distance, index=ratings.index) # invert the distance neighbors = knn.loc[user_id, 1:] similarities = sim.loc[user_id, 1:] similarities.index = ratings.loc[neighbors].index if use_means: return pd.Series(mean_ratings.loc[user_id] + ratings.loc[neighbors].subtract(mean_ratings.loc[neighbors], axis='index').mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation') else: return pd.Series(ratings.loc[neighbors].mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation')
特定のユーザー、製品、モデルに対する単一の推奨事項を計算します
def get_recommendations (user_id, product_id, model, use_means=True): if product_id not in ratings.columns: return 2.5 recommendations = get_all_recommendations(user_id, model, use_means=use_means) return recommendations.loc[product_id]
二乗平均平方根誤差 (RMSE) を計算して評価し、データセット内のすべてのユーザーのすべての製品の評価を予測します。次に、予測された評価をテスト セット内の実際の評価と並べて、RMSE.7 を計算します。
model = NearestNeighbors(n_neighbors=40, metric='cosine') model.fit(ratings.fillna(0)) def get_RMSE(X_test, model, use_means=True): group = X_test[['product_title', 'product_rating']].groupby(X_test.author) mse = [] i = 0 for key in group.groups: if key not in rating_list['author']: continue # Skip users not in the dataset predictions = get_all_recommendations(key, model=model, use_means=use_means) rated_products = group.get_group(key).set_index('product_title') df = rated_products.join(predictions).dropna().reset_index() mse.append(df) if i % 100 == 0: score = np.sqrt(mean_squared_error(df.product_rating, df.recommendation)) print(f'{i}/{X_test.author.nunique()} - RMSE: {score:.4f}') i += 1 mse = pd.concat(mse).reset_index(drop=True) score = np.sqrt(mean_squared_error(mse.product_rating, mse.recommendation)) print(f'{X_test.author.nunique()}/{X_test.author.nunique()} - RMSE: {score:.4f}') get_RMSE(X_test, model)
ratings_dict = { "item": [1, 2, 1, 2, 1, 2, 1, 2, 1], "user": ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D', 'E'], "rating": [1, 2, 2, 4, 2.5, 4, 4.5, 5, 3], } df = pd.DataFrame(ratings_dict) reader = Reader(rating_scale=(1, 5)) data = Dataset.load_from_df(df[["user", "item", "rating"]], reader) movielens = Dataset.load_builtin('ml-100k') trainingSet = movielens.build_full_trainset() algo.fit(trainingSet)
def get_recommendation(id_user, id_movie, ratings): #cosine similarity of the ratings similarity_matrix = cosine_similarity(ratings.fillna(0), ratings.fillna(0)) similarity_matrix_df = pd.DataFrame(similarity_matrix, index=ratings.index, columns=ratings.index) cosine_scores = similarity_matrix_df[id_user] ratings_scores = ratings[id_movie] ratings_scores.dropna().dot(cosine_scores[~ratings_scores.isna()]) / cosine_scores[~ratings_scores.isna()].sum() return np.dot(ratings_scores.dropna(), cosine_scores[~ratings_scores.isna()]) / cosine_scores[ ~ratings_scores.isna()].sum() get_recommendation(196, 8, ratings) # get recommandations for user 196 for movie 8
コンテンツベースのフィルタリングアプローチは、アイテムの事前にタグ付けされた一連の個別の特性を利用して、同様のプロパティを持つ追加のアイテムを推奨します。アイテム機能を使用して、ユーザーが探しているものに関連するアイテムを選択して返します。一部のコンテンツベースの推奨アルゴリズムは、実際のコンテンツではなく説明に従ってアイテムを照合します。
Pandora は、曲またはアーティストのプロパティを使用して、同様のプロパティを持つ音楽を再生するキューをシードします。ユーザーのフィードバックはステーションの結果を調整するために使用され、ユーザーが特定の曲を「嫌い」の場合は特定の属性を強調しなくなり、ユーザーが曲を「好き」の場合は他の属性を強調します。これはコンテンツベースのアプローチの一例です。 Pandora が開始するのに必要な情報はほとんどなく、範囲がはるかに制限されています (たとえば、元のシードに類似した推奨事項のみを作成できます)。 (出典: ウィキペディア、https://en.wikipedia.org/wiki/Recommender_system)
この方法は製品の説明とユーザーのプロフィールを使用するため、アイテムに関する既知のデータはあるがユーザーに関するデータは存在しない状況に適しています。コンテンツベースのレコメンダーは、レコメンデーションをユーザー固有の分類問題として扱い、アイテムの特徴に基づいてユーザーの好き嫌いの分類子を学習します。キーワードはアイテムを説明するために使用され、ユーザーの好き嫌いをリストするためにユーザー プロファイルが構築されます。さまざまな候補アイテムを、ユーザーが以前に評価したアイテムと比較し、最も適合するアイテムをレコメンドします。広く使用されているアルゴリズムは TF-IDF 表現です。ユーザーがアイテムを気に入る確率を推定するには、ベイジアン分類器、クラスター分析、デシジョン ツリー、人工ニューラル ネットワークなどの機械学習技術があります。
しかし、コンテンツベースのフィルタリングでは、ユーザーがすでに気に入っているものとよく似たアイテムが提案されることが多く、多様性が制限され、新しいものを発見することが難しくなります。これにより、ユーザーが特定の種類のコンテンツのみを閲覧する「バブル」が発生する可能性があります。また、アイテムのラベル付けや説明がどの程度適切に行われているかにも依存します。情報が不十分な場合や、ユーザーが初心者でまだ多くのコンテンツを操作していない場合には、問題が発生する可能性があります。
rating_list = pd.read_csv('top_brands_cosmetics_product_reviews.csv', sep=',', usecols=['author', 'product_title', 'product_rating', 'review_date']) items = pd.read_csv('top_brands_cosmetics_product_reviews.csv', usecols=['product_title', 'product_url', 'brand_name'], encoding='latin-1') print(f'Number of ratings: {rating_list.author.nunique()} | Number of items: {items.product_title.nunique()}')
数値機械学習アルゴリズムを適用できるように、プロットの要約をベクトル表現に変換します。
X_train, X_test, y_train, y_test = train_test_split(rating_list, rating_list.product_rating, test_size=0.1, random_state=42) ratings = X_train.pivot_table(index=['author'], columns=['product_title'], values='product_rating').fillna(0) mean_ratings = ratings.mean(axis=1) print(f'Number of users: {ratings.shape[0]} | Number of items: {ratings.shape[1]}')
各プロットの概要は、高次元の意味空間 (ここでは TF-IDF モデルが使用されています) を指す一連の単語に変換されます。これは、文書内で単語が出現する回数をカウントし、文書内での単語の重要性を判断します。
print(f'行列には {tfidf_model.shape[0]} 行と {tfidf_model.shape[1]} 列が含まれています')
BOW (Bag of Words) モデルは、文書内に単語が出現する回数をカウントします (スパース、ベクトル内のほとんどのエントリは 0 です)
TF-IDF (Term Frequency — Inverse Document Frequency) モデルは、文書内で単語が出現する回数をカウントしますが、その単語がすべての文書内で出現する頻度も考慮します。文書全体で頻繁に出現する単語の重み付けを下げ、めったに出現しない単語よりも情報量を減らします。すべてのプロット サマリーは、長さがすべてのプロット サマリーの語彙のサイズに等しい単一のベクトルとしてエンコードされ、TD-IDF はプロット サマリーを行列に変換します。レビューの 80% 以上に含まれる単語と 2 件未満に含まれる単語を無視します → ノイズが軽減されます。
一般的なメイクアップ語彙を使用して TF-IDF モデルを検査します。
def get_all_recommendations(user_id, model, use_means=True): distance, knn = model.kneighbors(ratings.fillna(0)) # nearest neighbors knn = pd.DataFrame(knn + 1, index=ratings.index) sim = pd.DataFrame(1 - distance, index=ratings.index) # invert the distance neighbors = knn.loc[user_id, 1:] similarities = sim.loc[user_id, 1:] similarities.index = ratings.loc[neighbors].index if use_means: return pd.Series(mean_ratings.loc[user_id] + ratings.loc[neighbors].subtract(mean_ratings.loc[neighbors], axis='index').mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation') else: return pd.Series(ratings.loc[neighbors].mul(similarities, axis='index').sum(axis='index') / similarities.sum(), name='recommendation')
プロットの概要用語の出現頻度の特徴に基づいて、異なる製品間のコサイン類似度を適用します。
def get_recommendations (user_id, product_id, model, use_means=True): if product_id not in ratings.columns: return 2.5 recommendations = get_all_recommendations(user_id, model, use_means=use_means) return recommendations.loc[product_id]
データセット内の任意の製品に関数を適用します。
model = NearestNeighbors(n_neighbors=40, metric='cosine') model.fit(ratings.fillna(0)) def get_RMSE(X_test, model, use_means=True): group = X_test[['product_title', 'product_rating']].groupby(X_test.author) mse = [] i = 0 for key in group.groups: if key not in rating_list['author']: continue # Skip users not in the dataset predictions = get_all_recommendations(key, model=model, use_means=use_means) rated_products = group.get_group(key).set_index('product_title') df = rated_products.join(predictions).dropna().reset_index() mse.append(df) if i % 100 == 0: score = np.sqrt(mean_squared_error(df.product_rating, df.recommendation)) print(f'{i}/{X_test.author.nunique()} - RMSE: {score:.4f}') i += 1 mse = pd.concat(mse).reset_index(drop=True) score = np.sqrt(mean_squared_error(mse.product_rating, mse.recommendation)) print(f'{X_test.author.nunique()}/{X_test.author.nunique()} - RMSE: {score:.4f}') get_RMSE(X_test, model)
2 つのアルゴリズムを組み合わせて、より洗練された推奨事項を提供することもできます。レコメンダー システムは、ユーザーが他の方法では見つけられなかったアイテムを発見するのに役立ちます。レコメンダー システムは、非従来型データのインデックスを作成する検索エンジンを使用して実装されることがよくあります。
結論として、レコメンダー システムは、パーソナライズされた提案を提供することで、ユーザーが関連するコンテンツや製品を発見できるようにする上で重要な役割を果たします。興味のあるものを見つけるのに必要な時間と労力を削減することで、エクスペリエンスを向上させます。
** GitHub で完全なコードを確認してください: https://github.com/alexiacismaru/recommender-systems
以上がレコメンダー システムとは何か、またその使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。