首頁 >後端開發 >Python教學 >什麼是推薦系統以及如何使用它們

什麼是推薦系統以及如何使用它們

DDD
DDD原創
2024-11-09 02:05:02945瀏覽

What are Recommender Systems and how to use them

推薦系統,或者說推薦系統,是一種用於過濾資訊的演算法。收集資訊提供與特定使用者最相關的建議。當有人需要在資訊量龐大的平台上做出決定時,這會很有幫助。

協同過濾

What are Recommender Systems and how to use them

協作過濾使用使用者過去的決策(例如過去的觀看次數或對某個產品的評分)以及其他使用者的類似行為來建立模型,以預測使用者可能喜歡什麼。它使用用戶評分矩陣,並且不需要其他用戶信息,例如人口統計數據或除評分之外的其他信息。這是協同過濾的主要優勢,因為它依賴最少的信息,並且可以在不了解項目內容的情況下推薦項目。

Last.fm 透過觀察用戶經常收聽的樂團和個人曲目並將其與其他用戶的聆聽行為進行比較來推薦歌曲。 Last.fm 將播放未出現在用戶庫中但經常被具有相似興趣的其他用戶播放的曲目。由於這種方法利用了使用者的行為,因此它是協作過濾技術的一個範例。 Last.fm 需要大量有關使用者的資訊才能做出準確的推薦。這是協同過濾系統中常見的冷啟動問題的一個例子。 (資料來源:維基百科,https://en.wikipedia.org/wiki/Recommender_system)

協同過濾假設過去同意的人將來也會同意。它識別具有與當前用戶相似的歷史記錄的另一個用戶,並使用該鄰域產生預測。這些方法被認為是基於記憶體和基於模型的方法。

可能幹擾協同過濾演算法的一些問題是冷啟動、可擴展性和稀疏性。 冷啟動是指缺乏數據來做準確的建議。還需要大量的計算能力,這通常是計算建議所必需的,這使得演算法可擴展性較差。此外,網路上有大量的產品和物品,這意味著評級相當稀疏

用Python實現協同過濾

我們將使用包含頂級品牌和化妝品評論的資料集。此資料集可在 Kaggle 網站上找到: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 

基於內容的過濾

What are Recommender Systems and how to use them

基於內容的過濾方法利用項目的一系列離散的、預先標記的特徵來推薦具有相似屬性的其他項目。它使用項目功能來選擇並傳回與使用者正在尋找的內容相關的項目。一些基於內容的推薦演算法根據項目的描述而不是實際內容來匹配項目。

Pandora 使用歌曲或藝術家的屬性來播種播放具有相似屬性的音樂的隊列。使用者回饋用於完善電台的結果,當使用者「不喜歡」某首特定歌曲時,不強調某些屬性,而當使用者「喜歡」一首歌曲時,則強調其他屬性。這是基於內容的方法的一個範例。 Pandora 需要很少的資訊來啟動,它的範圍更加有限(例如,它只能提出與原始種子類似的建議)。 (資料來源:維基百科,https://en.wikipedia.org/wiki/Recommender_system)

此方法使用產品的描述和使用者的個人資料,使其適合已知商品資料但不知道使用者資料的情況。基於內容的推薦器將推薦視為特定於使用者的分類問題,並根據項目的特徵學習使用者喜歡和不喜歡的分類器。關鍵字用於描述項目,並建立使用者設定檔來列出使用者的喜好和厭惡。將各種候選項目與使用者先前評分的項目進行比較,並推薦最匹配的項目。一種廣泛使用的演算法是 TF-IDF 表示。有機器學習技術,如貝葉斯分類器、聚類分析、決策樹和人工神經網路來估計使用者喜歡該項目的機率。

但是,基於內容的過濾通常會建議與用戶已經喜歡的內容非常相似的項目,從而限制了多樣性並使發現新事物變得更加困難。這可能會產生“泡沫”,讓用戶只能看到某些類型的內容。它還取決於項目的標籤或描述程度,如果資訊不足或用戶是新用戶並且尚未與太多內容進行交互,這可能會成為問題。

在 Python 中實現基於內容的過濾(使用 BOW)

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(詞袋)模型計算單字在文件中出現的次數(稀疏,向量中的大多數條目都是 0)

TF-IDF(詞頻 - 逆文檔頻率) 模型計算單字在文件中出現的次數,但也考慮單字在所有文件中出現的頻率。它降低了文件中頻繁出現的單字的權重,使其資訊量低於那些很少出現的單字。每個情節摘要都被編碼為單一向量,其長度等於所有情節摘要的詞彙表的大小,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)

混合系統

您也可以結合這兩種演算法來提供更精細的推薦。推薦系​​統幫助使用者發現他們可能找不到的物品。推薦系​​統通常使用索引非傳統資料的搜尋引擎來實現。

結論

總之,推薦系統透過提供個人化建議,在幫助使用者發現相關內容和產品方面發揮關鍵作用。他們透過減少尋找自己感興趣的內容所需的時間和精力來增強體驗。

** 在 GitHub 上查看完整程式碼:https://github.com/alexiacismaru/recommender-systems

以上是什麼是推薦系統以及如何使用它們的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn