基於python和TensorFlow的電影推薦系統——慕課課程

電影推薦系統——慕課課程(一)

這門課感覺挺有意思,而且老師講的也很好,便決定爲代碼添上註釋自己做一下總結。
第一步:數據準備
打開網址https://grouplens.org/datasets/movielens/,找到下圖所示數據集進行下載解壓。
在這裏插入圖片描述
第二步:數據準備
讀取ratings.csv和movies.csv文件,觀察一下兩個數據集的內容。
會用到的函數:
tail():查看後幾行的數據,默認5行
head():查看前幾行的數據,默認5行

ratings數據集:
在這裏插入圖片描述
movies數據集:
在這裏插入圖片描述
對數據進行一些處理

#增加行號信息
movies_df['movieRow'] = movies_df.index
# movies_df.tail()

##篩選movies_df中的特徵
movies_df = movies_df[['movieRow', 'movieId', 'title']]
movies_df.to_csv('movieProcessed.csv', index=False, header=True, encoding='utf-8')
# movies_df.tail()

#moviesId遠大於行號,將ratings_df中的movieId替換爲行號
ratings_df = pd.merge(ratings_df, movies_df, on='movieId')
#使用head查看前幾行數據,默認前5行
# ratings_df.head()

ratings_df = ratings_df[['userId', 'movieRow', 'rating']]
#處理後的數據保存到文件中
ratings_df.to_csv('ratingsProcessed.csv', index=False, header=True, encoding='utf-8')
# ratings_df.head()

接着創建電影評分矩陣rating和評分記錄矩陣record,即用戶是否對電影進行了評分,評分則1,未評分則爲0。

userNo = ratings_df['userId'].max() + 1
movieNo = ratings_df['movieRow'].max() + 1

rating = np.zeros((movieNo, userNo))

flag = 0
ratings_df_length = np.shape(ratings_df)[0]  #ratings_df的樣本個數

利用pycharm中的腳本,可以觀察到用戶樣本數,電影樣本數,rating矩陣,ratings_df樣本個數.
在這裏插入圖片描述
填寫rating

#填寫rating
for index, row in ratings_df.iterrows():
    #將rating當中對應的電影編號及用戶編號填上row當中的評分
    rating[int(row['movieRow']), int(row['userId'])] = row['rating']
    flag += 1
    print('processed %d, %d left' % (flag, ratings_df_length - flag))

在電影評分表中,>0表示電影被用戶評分,等於0表示未被用戶評分。
將布爾值的矩陣轉換爲0 1表示,即可生成record矩陣。如下三圖:

#電影評分表中,>0表示已經評分,=0表示未被評分
record = rating > 0
#bool值轉換爲0和1
record = np.array(record, dtype=int)

布爾值的record矩陣轉變爲0 1的record矩陣
在這裏插入圖片描述
有了這兩個矩陣,便可以開始構建模型。
第三步:構建模型
先定義一個對評分取值範圍進行縮放的函數,這樣能使評分系統性能好一些。

def normalizeRatings(rating, record):
    m, n = rating.shape
    rating_mean = np.zeros((m, 1))  #初始化對於每部電影每個用戶的平均評分
    rating_norm = np.zeros((m, n))  #保存處理後的數據
    #原始評分-平均評分,最後將計算結果和平均評分返回。
    for i in range(m):
        idx = record[i, :] != 0  #獲取已經評分的電影的下標
        rating_mean[i] = np.mean(rating[i,  idx])  #計算平均值,右邊式子代表第i行已經評分的電影的平均值
        rating_norm[i, idx] = rating[i, idx] - rating_mean[i]
    return rating_norm, rating_mean
    
rating_norm, rating_mean = normalizeRatings(rating, record)

rating_norm = np.nan_to_num(rating_norm)
rating_mean = np.nan_to_num(rating_mean)

注1:慕課網課程中的rating_norm[i, idx] 的計算代碼有問題,感謝在評論下解惑的大牛們( ̄▽ ̄)~*
注2:如果不對rating_norm,rating_mean進行處理,會報RuntimeWarning: Mean of empty slice.

初始化電影矩陣、用戶喜好矩陣,便可以開始計算損失,代價函數即爲理論課定義的函數,如圖。
注:初始化矩陣產生的參數都是隨機數,且服從正態分佈:random_normal()
在這裏插入圖片描述
代碼如下:

#假設有10中類型的電影
num_features = 10
#初始化電影矩陣X,用戶喜好矩陣Theta,這裏產生的參數都是隨機數,並且是正態分佈
X_parameters = tf.Variable(tf.random_normal([movieNo, num_features], stddev=0.35))
Theta_paramters = tf.Variable(tf.random_normal([userNo, num_features], stddev=0.35))
#理論課定義的代價函數
#tf.matmul(X_parameters, Theta_paramters, transpose_b=True)代表X_parameters和Theta_paramters的轉置相乘
loss = 1/2 * tf.reduce_sum(((tf.matmul(X_parameters, Theta_paramters, transpose_b=True)
                             - rating_norm) * record) ** 2) \
       + 1/2 * (tf.reduce_sum(X_parameters**2)+tf.reduce_sum(Theta_paramters**2))  #正則化項,這裏λ=1,可以調整來觀察模型性能變化。

#創建優化器和優化目標
optimizer = tf.train.AdamOptimizer(1e-4)
train = optimizer.minimize(loss)

第四步:訓練模型
使用TensorFlow中的tf.summary模塊,它用於將TensorFlow的數據導出,從而變得可視化,因爲loss是標量,所以使用scalar函數。
代碼如下:

#Step4:訓練模型
#使用TensorFlow中的tf.summary模塊,它用於將TensorFlow的數據導出,從而變得可視化,因爲loss是標量,所以使用scalar函數
tf.summary.scalar('loss', loss)
#將所有summary信息彙總
summaryMerged = tf.summary.merge_all()
#定義保存信息的路徑
filename = 'F:\datasets\慕課電影推薦系統數據集\ml-latest-small\movie_tensorboard'
#把信息保存在文件當中
writer = tf.summary.FileWriter(filename)

#創建tensorflow繪畫
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

接下來便開始訓練模型,設置10000次迭代,訓練過程時間有點長,如果只是想看一下結果,設幾十次就好了,但是誤差就會比較大。

#開始訓練模型
for i in range(10000):
    #不重要的變量可用下劃線表示,每次train的結果都會保存到"_",summaryMerged的訓練結果保存到"movie_summary"
    _, movie_summary = sess.run([train, summaryMerged])
    writer.add_summary(movie_summary, i)
    #記錄一下次數,有沒有都無所謂,只是看看還有多久
    print('i=', i, 'loss=', loss)

之前提到可視化,所以接着就是利用可視化觀察運行的結果。
進入cmd命令,進入文件位置後,輸入"tensorboard --logdir=./ --host=127.0.0.1"
運行後,在瀏覽器輸入127.0.0.1:6006,即可打開可視化TensorFlow的頁面觀察代價函數

在這裏插入圖片描述
詳細步驟可以看這篇https://blog.csdn.net/qq_30377909/article/details/89946818

第五步:評估模型

Current_X_paramters, Current_Theta_parameters = sess.run([X_parameters, Theta_paramters])
#將電影內容矩陣和用戶喜好矩陣相乘,再加上每一行的均值,便得到一個完整的電影評分表
predicts = np.dot(Current_X_paramters, Current_Theta_parameters.T) + rating_mean
#計算預測值與真實值的殘差平方和的算術平方根,將它作爲誤差error,隨着迭代次數增加而減少
errors = np.sqrt(np.sum((predicts - rating)**2))

這是爲了趕時間看一下結果,所設置訓練50次生成的結果,不出所料,誤差很大,但是暫時先忽略⑧
在這裏插入圖片描述
最後一步:構建完整系統
獲取對該用戶的電影評分的列表,predicts[:, int(user_id)]是該用戶對應的所有電影的評分,即系統預測的用戶對於電影的評分。
推薦系統需要從高分開始,所以採用argsort()[::-1]從大到小排序

sortedResult = predicts[:, int(user_id)].argsort()[::-1]

idx用於保存已經推薦了多少部電影

idx = 0
#後邊的center函數只是爲了美觀一點點,不重要
print('爲該用戶推薦的評分最高的20部電影是:'.center(80, '='))
for i in sortedResult:
    print('評分: %.2f, 電影名: %s' % (predicts[i, int(user_id)], movies_df.iloc[i]['title']))
    idx += 1
    if idx == 20:
        break

以下就是運行後的結果:
在這裏插入圖片描述
可以看到,爲用戶推薦的電影已經從高評分到低排列並顯示了出來。
一個電影推薦系統便完成了。

注:

#假設有10中類型的電影
num_features = 10
1/2 * (tf.reduce_sum(X_parameters**2)+tf.reduce_sum(Theta_paramters**2))  
#正則化項,這裏λ=1,可以調整來觀察模型性能變化。
#開始訓練模型
for i in range(1000):

這些都是影響系統性能的重要因素,可以修改這些參數來調整系統性能。

附上代碼鏈接:
https://github.com/jiangnanxiaoshuaigua/movies_recommend_system
附上慕課課程鏈接:
https://www.imooc.com/learn/990

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章