總結
本系列是機器學習課程的系列課程,主要介紹機器學習中關聯規則
參考
機器學習(三):Apriori算法(算法精講)
Apriori 算法 理論 重點
MovieLens:一個常用的電影推薦系統領域的數據集
23張圖,帶你入門推薦系統
本門課程的目標
完成一個特定行業的算法應用全過程:
懂業務+會選擇合適的算法+數據處理+算法訓練+算法調優+算法融合
+算法評估+持續調優+工程化接口實現
機器學習定義
關于機器學習的定義,Tom Michael Mitchell的這段話被廣泛引用:
對于某類任務T和性能度量P,如果一個計算機程序在T上其性能P隨著經驗E而自我完善,那么我們稱這個計算機程序從經驗E中學習。
要構建一個包含用戶、商品和評分的數據集,并基于 Python 實現基于用戶的商品推薦,我們可以使用協同過濾算法(Collaborative Filtering)。以下是實現的步驟:
基于用戶的協同過濾推薦案例
在真實的推薦系統場景中,用戶通常只會對少量商品進行評分,而大部分商品的評分為 0
(表示未評分)。為了模擬這種稀疏性,我們可以調整數據生成邏輯,使得每個用戶的評分矩陣中有更多的 0
值。
以下是如何生成稀疏評分矩陣的完整代碼實現:
1. 構建稀疏評分矩陣
我們將通過隨機生成的方式,確保每個用戶只對少量商品評分(例如每個用戶平均評分 3-5 個商品),其余商品的評分為 0
。
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity# 設置隨機種子以確保結果可復現
np.random.seed(42)# 參數設置
num_users = 10 # 用戶數量
num_items = 10 # 商品數量
max_ratings_per_user = 5 # 每個用戶最多評分的商品數量# 初始化評分矩陣 (初始值為 0)
ratings = np.zeros((num_users, num_items))# 隨機生成稀疏評分數據
for i in range(num_users):# 隨機選擇該用戶評分的商品數量(1 到 max_ratings_per_user)num_rated_items = np.random.randint(1, max_ratings_per_user + 1)# 隨機選擇該用戶評分的商品索引rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)# 隨機生成評分(1 到 5)ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)# 構建 DataFrame
user_ids = [f"用戶{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)# 打印評分矩陣
print("用戶-商品評分矩陣:")
print(df)
輸出示例:
2. 計算用戶相似度并預測評分
接下來,我們基于稀疏評分矩陣計算用戶相似度,并為目標用戶預測未評分商品的評分。
# 計算用戶之間的相似度
user_similarity = cosine_similarity(df)
user_similarity_df = pd.DataFrame(user_similarity, index=df.index, columns=df.index)print("\n用戶相似度矩陣:")
print(user_similarity_df)# 預測目標用戶對未評分商品的評分
def predict_ratings(target_user, df, user_similarity_df):# 獲取目標用戶的評分target_ratings = df.loc[target_user]# 修改這里:初始化預測評分為float類型predicted_ratings = pd.Series(0.0, index=df.columns, dtype='float64')for item in df.columns:if target_ratings[item] == 0: # 只預測未評分的商品# 獲取對該商品評分過的用戶users_who_rated = df[df[item] > 0].index# 計算加權平均評分weighted_sum = 0.0similarity_sum = 0.0for user in users_who_rated:rating = df.loc[user, item]similarity = user_similarity_df.loc[target_user, user]weighted_sum += rating * similaritysimilarity_sum += similarityif similarity_sum > 0:predicted_ratings[item] = weighted_sum / similarity_sumreturn predicted_ratings# 目標用戶
target_user = '用戶1'# 預測評分
predicted_ratings = predict_ratings(target_user, df, user_similarity_df)print(f"\n為目標用戶 {target_user} 預測的評分:")
print(predicted_ratings)# 推薦商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推薦給用戶 {target_user} 的商品:")
print(recommended_items)
3. 運行結果解釋
假設運行上述代碼后,輸出如下:
用戶相似度矩陣(部分):
為目標用戶 用戶1
預測的評分:
推薦給用戶 用戶1
的商品:
4. 總結
通過引入稀疏評分矩陣,我們更貼近真實場景,其中大多數商品的評分為 0
。對于目標用戶 用戶1
,我們預測了其對未評分商品的評分,并推薦了預測評分最高的商品(如 商品3
、商品10
等)。
你可以根據需要進一步優化算法,例如:
- 調整評分稀疏度(例如減少評分的商品數量)。
- 使用其他相似度計算方法(如皮爾遜相關系數)。
- 引入隱式反饋數據(如點擊、瀏覽等行為)。
5.代碼改進方法
在計算用戶相似度時,如果用戶評分數據過于稀疏(比如某些用戶沒有共同評分的商品),可能會導致計算相似度時出現問題。以下是改進后的代碼,增加了數據預處理和異常處理:
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity# 設置隨機種子以確保結果可復現
np.random.seed(42)# 參數設置
num_users = 10 # 用戶數量
num_items = 10 # 商品數量
max_ratings_per_user = 5 # 每個用戶最多評分的商品數量# 初始化評分矩陣 (初始值為 0)
ratings = np.zeros((num_users, num_items))# 隨機生成稀疏評分數據
for i in range(num_users):# 隨機選擇該用戶評分的商品數量(1 到 max_ratings_per_user)num_rated_items = np.random.randint(1, max_ratings_per_user + 1)# 隨機選擇該用戶評分的商品索引rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)# 隨機生成評分(1 到 5)ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)# 構建 DataFrame
user_ids = [f"用戶{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)# 打印評分矩陣
print("用戶-商品評分矩陣:")
print(df)# 計算用戶之間的相似度(改進版)
def calculate_user_similarity(df):# 填充缺失值為0(如果還沒有填充)df_filled = df.fillna(0)# 計算余弦相似度user_similarity = cosine_similarity(df_filled)# 將對角線設置為0(避免用戶與自己比較)np.fill_diagonal(user_similarity, 0)# 轉換為DataFrameuser_similarity_df = pd.DataFrame(user_similarity, index=df.index, columns=df.index)return user_similarity_dfuser_similarity_df = calculate_user_similarity(df)# 計算用戶之間的相似度
# user_similarity = cosine_similarity(df)
# user_similarity_df = pd.DataFrame(user_similarity, index=df.index, columns=df.index)print("\n用戶相似度矩陣:")
print(user_similarity_df)# 預測目標用戶對未評分商品的評分
# def predict_ratings(target_user, df, user_similarity_df):
# # 獲取目標用戶的評分
# target_ratings = df.loc[target_user]# # 修改這里:初始化預測評分為float類型
# predicted_ratings = pd.Series(0.0, index=df.columns, dtype='float64')# for item in df.columns:
# if target_ratings[item] == 0: # 只預測未評分的商品
# # 獲取對該商品評分過的用戶
# users_who_rated = df[df[item] > 0].index# # 計算加權平均評分
# weighted_sum = 0.0
# similarity_sum = 0.0
# for user in users_who_rated:
# rating = df.loc[user, item]
# similarity = user_similarity_df.loc[target_user, user]
# weighted_sum += rating * similarity
# similarity_sum += similarity# if similarity_sum > 0:
# predicted_ratings[item] = weighted_sum / similarity_sum# return predicted_ratings# 預測目標用戶對未評分商品的評分(改進版)
def predict_ratings(target_user, df, user_similarity_df, min_similar_users=1):target_ratings = df.loc[target_user]predicted_ratings = pd.Series(0.0, index=df.columns,dtype='float64')for item in df.columns:if target_ratings[item] == 0:users_who_rated = df[df[item] > 0].indexweighted_sum = 0similarity_sum = 0valid_users = 0for user in users_who_rated:similarity = user_similarity_df.loc[target_user, user]# 只考慮正相似度的用戶if similarity > 0:rating = df.loc[user, item]weighted_sum += rating * similaritysimilarity_sum += similarityvalid_users += 1# 至少有min_similar_users個相似用戶才進行預測if valid_users >= min_similar_users and similarity_sum > 0:predicted_ratings[item] = weighted_sum / similarity_sumreturn predicted_ratings# 目標用戶
target_user = '用戶1'# 預測評分
predicted_ratings = predict_ratings(target_user, df, user_similarity_df)print(f"\n為目標用戶 {target_user} 預測的評分:")
print(predicted_ratings)# 推薦商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推薦給用戶 {target_user} 的商品:")
print(recommended_items)
輸出如下:
主要改進點:
增加了calculate_user_similarity函數來封裝相似度計算邏輯
在計算相似度前確保數據已填充缺失值
將對角線相似度設為0(避免用戶與自己比較)
在預測評分時增加了min_similar_users參數,確保有足夠多的相似用戶才進行預測
只考慮正相似度的用戶參與預測
這些改進可以解決以下潛在問題:
處理缺失值問題
避免用戶與自己的相似度影響結果
確保預測時有足夠的參考用戶
提高預測結果的可靠性
基于物品的協同過濾推薦案例
基于物品的協同過濾(Item-Based Collaborative Filtering)是一種推薦算法,其核心思想是:如果兩個商品被相似的用戶評分,那么這兩個商品可能是相似的。我們可以根據商品之間的相似性,為目標用戶推薦他們未評分但可能感興趣的商品。
以下是基于上述稀疏評分矩陣實現基于物品的協同過濾的完整代碼:
1. 數據準備
我們使用之前生成的稀疏評分矩陣 df
,其中包含 10 個用戶和 10 個商品。
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity# 設置隨機種子以確保結果可復現
np.random.seed(42)# 參數設置
num_users = 10 # 用戶數量
num_items = 10 # 商品數量
max_ratings_per_user = 5 # 每個用戶最多評分的商品數量# 初始化評分矩陣 (初始值為 0)
ratings = np.zeros((num_users, num_items))# 隨機生成稀疏評分數據
for i in range(num_users):# 隨機選擇該用戶評分的商品數量(1 到 max_ratings_per_user)num_rated_items = np.random.randint(1, max_ratings_per_user + 1)# 隨機選擇該用戶評分的商品索引rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)# 隨機生成評分(1 到 5)ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)# 構建 DataFrame
user_ids = [f"用戶{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)print("用戶-商品評分矩陣:")
print(df)
輸出如下:
2. 計算商品相似度
在基于物品的協同過濾中,我們需要計算商品之間的相似度。可以使用余弦相似度來衡量商品之間的相似性。
# 轉置評分矩陣,使得行表示商品,列表示用戶
item_similarity = cosine_similarity(df.T) # 對轉置后的矩陣計算相似度
item_similarity_df = pd.DataFrame(item_similarity, index=df.columns, columns=df.columns)print("\n商品相似度矩陣:")
print(item_similarity_df)
輸出示例:
3. 基于商品相似度預測評分
對于目標用戶未評分的商品,我們可以利用商品相似度和用戶已評分的商品來預測評分。
def predict_item_based(target_user, df, item_similarity_df):# 獲取目標用戶的評分target_ratings = df.loc[target_user]# 初始化預測評分predicted_ratings = pd.Series(0, index=df.columns)for item in df.columns:if target_ratings[item] == 0: # 只預測未評分的商品# 獲取與當前商品相似的商品similar_items = item_similarity_df[item]# 計算加權平均評分weighted_sum = 0similarity_sum = 0for other_item in df.columns:if target_ratings[other_item] > 0 and similar_items[other_item] > 0:rating = target_ratings[other_item]similarity = similar_items[other_item]weighted_sum += rating * similaritysimilarity_sum += similarityif similarity_sum > 0:predicted_ratings[item] = weighted_sum / similarity_sumreturn predicted_ratings# 目標用戶
target_user = '用戶1'# 預測評分
predicted_ratings = predict_item_based(target_user, df, item_similarity_df)print(f"\n為目標用戶 {target_user} 預測的評分:")
print(predicted_ratings)# 推薦商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推薦給用戶 {target_user} 的商品:")
print(recommended_items)
輸出如下:
4. 總結
通過基于物品的協同過濾算法,我們成功為目標用戶 用戶1
推薦了未評分但可能感興趣的商品(如 商品3
、商品10
等)。這種算法的核心在于計算商品之間的相似性,并利用相似商品的評分來預測目標用戶對未評分商品的興趣。
你可以根據需要進一步優化算法,例如:
- 使用其他相似度計算方法(如皮爾遜相關系數)。
- 引入隱式反饋數據(如點擊、瀏覽等行為)。
- 結合基于用戶的協同過濾和基于物品的協同過濾,形成混合推薦系統。
推薦算法流程優化版本-召回過濾精排混排強規則
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity# 設置隨機種子以確保結果可復現
np.random.seed(42)# 參數設置
num_users = 10 # 用戶數量
num_items = 10 # 商品數量
max_ratings_per_user = 5 # 每個用戶最多評分的商品數量# 初始化評分矩陣 (初始值為 0)
ratings = np.zeros((num_users, num_items))# 隨機生成稀疏評分數據
for i in range(num_users):# 隨機選擇該用戶評分的商品數量(1 到 max_ratings_per_user)num_rated_items = np.random.randint(1, max_ratings_per_user + 1)# 隨機選擇該用戶評分的商品索引rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)# 隨機生成評分(1 到 5)ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)# 構建 DataFrame
user_ids = [f"用戶{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)# 打印評分矩陣
print("用戶-商品評分矩陣:")
print(df)# 計算用戶之間的相似度(改進版)
def calculate_user_similarity(df):# 填充缺失值為0(如果還沒有填充)df_filled = df.fillna(0)# 計算余弦相似度user_similarity = cosine_similarity(df_filled)# 將對角線設置為0(避免用戶與自己比較)np.fill_diagonal(user_similarity, 0)# 轉換為DataFrameuser_similarity_df = pd.DataFrame(user_similarity, index=df.index, columns=df.index)return user_similarity_dfuser_similarity_df = calculate_user_similarity(df)print("\n用戶相似度矩陣:")
print(user_similarity_df)# 預測目標用戶對未評分商品的評分(改進版)
def predict_ratings(target_user, df, user_similarity_df, min_similar_users=1):target_ratings = df.loc[target_user]predicted_ratings = pd.Series(0.0, index=df.columns,dtype='float64')for item in df.columns:if target_ratings[item] == 0:users_who_rated = df[df[item] > 0].indexweighted_sum = 0similarity_sum = 0valid_users = 0for user in users_who_rated:similarity = user_similarity_df.loc[target_user, user]# 只考慮正相似度的用戶if similarity > 0:rating = df.loc[user, item]weighted_sum += rating * similaritysimilarity_sum += similarityvalid_users += 1# 至少有min_similar_users個相似用戶才進行預測if valid_users >= min_similar_users and similarity_sum > 0:predicted_ratings[item] = weighted_sum / similarity_sumreturn predicted_ratings# 目標用戶
target_user = '用戶1'# 預測評分
predicted_ratings = predict_ratings(target_user, df, user_similarity_df)print(f"\n為目標用戶 {target_user} 預測的評分:")
print(predicted_ratings)# 推薦商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推薦給用戶 {target_user} 的商品:")
print(recommended_items)# 評估推薦系統
def evaluate_recommendation(df, user_similarity_df, test_ratio=0.2):from sklearn.model_selection import train_test_split# 轉換為長格式melted_df = df.reset_index().melt(id_vars='index', var_name='item', value_name='rating')melted_df.columns = ['user', 'item', 'rating']# 分割訓練集和測試集train_df, test_df = train_test_split(melted_df[melted_df['rating'] > 0], test_size=test_ratio)# 重建訓練矩陣train_matrix = pd.pivot_table(train_df, values='rating', index='user', columns='item').fillna(0)# 計算用戶相似度train_similarity = calculate_user_similarity(train_matrix)# 評估每個測試用戶mae = 0test_users = test_df['user'].unique()for user in test_users:# 獲取測試用戶的實際評分actual_ratings = test_df[test_df['user'] == user].set_index('item')['rating']# 預測評分predicted = predict_ratings(user, train_matrix, train_similarity)# 計算MAEcommon_items = actual_ratings.index.intersection(predicted.index)if len(common_items) > 0:mae += np.mean(np.abs(actual_ratings[common_items] - predicted[common_items]))mae /= len(test_users)print(f"\n推薦系統評估結果(MAE): {mae:.4f}")# 運行評估
evaluate_recommendation(df, user_similarity_df)# ... 已有代碼保持不變 ...# 1. 召回階段 - 多種召回策略
def recall_strategies(target_user, df, user_similarity_df):# 策略1: 基于用戶的協同過濾召回cf_recall = predict_ratings(target_user, df, user_similarity_df)cf_items = cf_recall[cf_recall > 0].index.tolist()# 策略2: 熱門商品召回popular_items = df.sum().sort_values(ascending=False).head(5).index.tolist()# 策略3: 新商品召回new_items = df.columns[-3:].tolist() # 假設最后3個是新商品# 合并召回結果并去重recalled_items = list(set(cf_items + popular_items + new_items))return recalled_items# 2. 過濾階段 - 過濾掉不合適的商品
def filter_items(target_user, recalled_items, df):# 獲取用戶已購買/已評價的商品rated_items = df.loc[target_user][df.loc[target_user] > 0].index.tolist()# 過濾掉用戶已經購買/評價過的商品filtered_items = [item for item in recalled_items if item not in rated_items]# 強規則過濾示例:過濾掉特定商品blacklist = ['商品5'] # 假設商品5被列入黑名單filtered_items = [item for item in filtered_items if item not in blacklist]return filtered_items# 3. 精排階段 - 對過濾后的商品進行精細排序
def ranking(target_user, filtered_items, df, user_similarity_df):# 計算每個商品的預測評分predicted_ratings = predict_ratings(target_user, df, user_similarity_df)# 計算商品熱度item_popularity = df.sum()# 綜合評分 = 預測評分 * 0.7 + 熱度 * 0.3 (加權得分)ranked_items = {}for item in filtered_items:score = predicted_ratings[item] * 0.7 + item_popularity[item] * 0.3ranked_items[item] = score# 按得分排序ranked_items = sorted(ranked_items.items(), key=lambda x: x[1], reverse=True)return ranked_items# 4. 混排階段 - 結合多種策略生成最終推薦列表
def mixed_sorting(ranked_items):final_list = []# 強規則:確保特定商品排在前面promoted_item = '商品2' # 假設商品2是推廣商品for i, (item, score) in enumerate(ranked_items):if item == promoted_item:final_list.insert(0, (item, score)) # 推廣商品置頂else:final_list.append((item, score))# 多樣性控制:避免同類型商品扎堆# 這里簡化為限制連續出現相似商品diversified_list = []prev_item_type = Nonefor item, score in final_list:current_type = item[-1] # 假設商品類型由商品ID最后一位決定if current_type == prev_item_type:score *= 0.9 # 相似類型商品降權diversified_list.append((item, score))prev_item_type = current_typereturn sorted(diversified_list, key=lambda x: x[1], reverse=True)# 5. 完整推薦流程
def full_recommendation_pipeline(target_user, df, user_similarity_df):print(f"\n開始為用戶 {target_user} 生成推薦...")# 召回recalled_items = recall_strategies(target_user, df, user_similarity_df)print(f"\n召回階段結果: {recalled_items}")# 過濾filtered_items = filter_items(target_user, recalled_items, df)print(f"過濾后結果: {filtered_items}")# 精排ranked_items = ranking(target_user, filtered_items, df, user_similarity_df)print(f"精排后結果: {ranked_items}")# 混排final_recommendations = mixed_sorting(ranked_items)print(f"最終推薦列表: {final_recommendations}")return final_recommendations# 運行完整推薦流程
final_recommendations = full_recommendation_pipeline(target_user, df, user_similarity_df)# 輸出最終推薦結果
print("\n=== 最終推薦結果 ===")
for item, score in final_recommendations:print(f"{item}: {score:.2f}")
輸出如下:
基于scikit-surprise實現推薦
scikit-surprise
是一個用于構建推薦系統的 Python 庫,專注于協同過濾(Collaborative Filtering)算法。以下是基于 scikit-surprise
實現一個簡單的推薦系統的完整代碼示例。
1. 安裝依賴
首先,確保你已經安裝了 scikit-surprise
:
pip install scikit-surprise==1.1.4
2. 數據準備
我們使用 scikit-surprise
提供的內置數據集(例如 MovieLens 數據集),或者自定義數據集。
示例:加載 MovieLens 數據集
from surprise import Dataset
from surprise import Reader
from surprise.model_selection import train_test_split# 加載內置的 MovieLens 數據集
data = Dataset.load_builtin('ml-100k')# 將數據劃分為訓練集和測試集
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)
如果你有自己的數據集(例如用戶、物品、評分),可以按照以下方式加載:
import pandas as pd
from surprise import Dataset, Reader# 假設你的數據是一個 Pandas DataFrame
ratings_dict = {"user_id": [1, 1, 1, 2, 2, 3, 3, 3],"item_id": [101, 102, 103, 101, 104, 102, 103, 104],"rating": [5, 3, 4, 4, 2, 5, 3, 1],
}
df = pd.DataFrame(ratings_dict)# 定義評分范圍
reader = Reader(rating_scale=(1, 5))# 加載自定義數據集
data = Dataset.load_from_df(df[["user_id", "item_id", "rating"]], reader)# 劃分訓練集和測試集
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)
3. 構建推薦模型
scikit-surprise
提供了多種協同過濾算法,例如 SVD(奇異值分解)、KNN(最近鄰算法)等。以下以 SVD 為例:
from surprise import SVD
from surprise import accuracy# 初始化 SVD 模型
model = SVD()# 在訓練集上訓練模型
model.fit(trainset)# 在測試集上進行預測
predictions = model.test(testset)# 計算 RMSE(均方根誤差)
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse}")
4. 推薦物品
我們可以為特定用戶生成推薦物品列表。以下是一個示例函數,用于獲取某個用戶的前 N 個推薦物品:
def get_top_n_recommendations(model, user_id, items, n=5):# 預測用戶對所有物品的評分predictions = [(item, model.predict(user_id, item).est) for item in items]# 按評分排序predictions.sort(key=lambda x: x[1], reverse=True)# 返回前 N 個推薦物品return predictions[:n]# 獲取所有物品 ID
items = df["item_id"].unique()# 為用戶 1 生成推薦
user_id = 1
top_n_recommendations = get_top_n_recommendations(model, user_id, items, n=5)
print(f"為用戶 {user_id} 推薦的物品:")
for item, score in top_n_recommendations:print(f"物品 ID: {item}, 預測評分: {score:.2f}")
5. 使用 KNN 算法
如果你想使用 KNN 算法(基于用戶的協同過濾或基于物品的協同過濾),可以按照以下方式實現:
from surprise import KNNBasic# 初始化 KNN 模型(基于用戶的協同過濾)
sim_options = {"name": "cosine", # 相似度計算方法"user_based": True # 基于用戶(True)還是基于物品(False)
}
model = KNNBasic(sim_options=sim_options)# 在訓練集上訓練模型
model.fit(trainset)# 在測試集上進行預測
predictions = model.test(testset)# 計算 RMSE
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse}")
6. 完整代碼整合
以下是完整的代碼示例,包含數據加載、模型訓練、評估和推薦:
import pandas as pd
from surprise import Dataset, Reader, SVD, accuracy
from surprise.model_selection import train_test_split# 自定義數據集
ratings_dict = {"user_id": [1, 1, 1, 2, 2, 3, 3, 3],"item_id": [101, 102, 103, 101, 104, 102, 103, 104],"rating": [5, 3, 4, 4, 2, 5, 3, 1],
}
df = pd.DataFrame(ratings_dict)# 定義評分范圍
reader = Reader(rating_scale=(1, 5))# 加載數據集
data = Dataset.load_from_df(df[["user_id", "item_id", "rating"]], reader)# 劃分訓練集和測試集
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)# 初始化 SVD 模型
model = SVD()# 在訓練集上訓練模型
model.fit(trainset)# 在測試集上進行預測
predictions = model.test(testset)# 計算 RMSE
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse}")# 獲取所有物品 ID
items = df["item_id"].unique()# 為用戶生成推薦
def get_top_n_recommendations(model, user_id, items, n=5):predictions = [(item, model.predict(user_id, item).est) for item in items]predictions.sort(key=lambda x: x[1], reverse=True)return predictions[:n]# 為用戶 1 生成推薦
user_id = 1
top_n_recommendations = get_top_n_recommendations(model, user_id, items, n=5)
print(f"為用戶 {user_id} 推薦的物品:")
for item, score in top_n_recommendations:print(f"物品 ID: {item}, 預測評分: {score:.2f}")
7. 輸出結果
運行上述代碼后,你會得到以下輸出:
- RMSE:模型在測試集上的均方根誤差。
- 推薦列表:為指定用戶生成的前 N 個推薦物品及其預測評分。
8. 擴展功能
-
超參數調優:
- 使用
GridSearchCV
或手動調整模型參數(如n_factors
、lr_all
等)來優化模型性能。
- 使用
-
交叉驗證:
- 使用
cross_validate
函數評估模型的穩定性和泛化能力。
- 使用
-
其他算法:
- 嘗試其他算法(如 NMF、SlopeOne 或 CoClustering)并比較效果。
通過上述代碼,你可以快速構建一個基于協同過濾的推薦系統!