自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

預(yù)測電影偏好?如何利用自編碼器實現(xiàn)協(xié)同過濾方法

開發(fā) 開發(fā)工具 深度學習
深度自編碼器(Deep Autoencoder)由兩個對稱的深度信念網(wǎng)絡(luò)組成,它相比常見的自編碼器加入了更多隱藏層。在本文中,作者將嘗試使用該工具進行協(xié)同過濾,幫助人們研究和預(yù)測大量用戶對于不同電影的喜好。

推薦系統(tǒng)使用協(xié)同過濾的方法,通過收集用戶的偏好信息來預(yù)測特定用戶的興趣。協(xié)同過濾技術(shù)的基本假設(shè)是,如果用戶 A 對某個問題與人 B 有相同的口味或意見,那么 A 就更有可能在其他問題上擁有與 B 的相同的意見。

本文將介紹如何根據(jù)用戶的偏好、觀看歷史、相同評級和其他電影的其他用戶的評價預(yù)測用戶對電影的評分。

[[229848]]

一、介紹

自動編碼器是一種深度學習神經(jīng)網(wǎng)絡(luò)架構(gòu),可實現(xiàn)協(xié)同過濾領(lǐng)域最佳的性能。文章的第一部是理論概述,將會介紹簡單的自動編碼器及深度自編碼器的基礎(chǔ)數(shù)學概念。在第二部分中,我們將深入實際展示如何在 TensorFlow 中逐步應(yīng)用這一技術(shù)。本文僅覆蓋和評價模型中最重要的部分。

整個模型的輸入渠道和預(yù)處理可以在相應(yīng)的 GitHub 中查看:

https://github.com/artem-oppermann/Deep-Autoencoders-For-Collaborative-Filtering

二、深度自編碼器

1. 自編碼器

討論深度自編碼器之前,我們先來介紹它稍微簡單些的版本。自編碼器(Autoencoder)是一種人工神經(jīng)網(wǎng)絡(luò),用于學習一組輸入數(shù)據(jù)的表示(編碼),通常用于實現(xiàn)降維。

在結(jié)構(gòu)上,自編碼器的形式是一個前饋神經(jīng)網(wǎng)絡(luò),由輸入層、一個隱藏層和一個輸出層(圖 1)構(gòu)成。輸出層與輸入層的神經(jīng)元數(shù)量相同,因此自編碼器屬于無監(jiān)督學習,這意味著它不需要標記數(shù)據(jù)——只需要一組輸入數(shù)據(jù)即可,而不是輸入—輸出對。

典型的 AutoEncoder 架構(gòu)

圖 1. 典型的 AutoEncoder 架構(gòu)

自編碼器的隱藏層比輸入層小,這使得模型可以通過學習數(shù)據(jù)中的相關(guān)性在隱藏層中創(chuàng)建數(shù)據(jù)的壓縮表示。

輸入層到隱藏層的轉(zhuǎn)換被稱為編碼步驟,從隱藏層到輸出層的轉(zhuǎn)換稱為解碼步驟。我們也可以在數(shù)學上將這些轉(zhuǎn)換定義為映射:

該映射是通過將輸入數(shù)據(jù)向量乘以權(quán)重矩陣,添加一個偏差項并將所得到的向量應(yīng)用于非線性運算,如 sigmoid,tanh 或整流線性單元來實現(xiàn)的。

2. 自編碼器的訓練

在訓練期間,編碼器接收輸入數(shù)據(jù)樣本 x 并將其映射到所謂的隱藏層或隱層表示 z 上。然后解碼器將 z 映射到輸出向量 x' 上,后者是(在最好的情況下)輸入數(shù)據(jù) x 的準確表示。需要注意的是,通常情況下準確地重建 x 是不可能的。

具有輸出 x' 的訓練包括應(yīng)用隨機梯度下降以最小化預(yù)定損失,例如均方誤差:

3. 深度自編碼器

簡單自動編碼器的擴展版是 Deep Autoencoder(圖 2)。從圖 2 中可以看出,它與簡單的計數(shù)器部分唯一的區(qū)別在于隱藏層的數(shù)量。

深度自編碼器的架構(gòu)

圖 2. 深度自編碼器的架構(gòu)

額外的隱藏層使自編碼器可以從數(shù)學上學習數(shù)據(jù)中更復雜的底層模式。深度自編碼器的第一層可以學習原始輸入中的一階特征(例如圖像中的邊緣)。第二層可以學習對應(yīng)于一階特征的外觀中的圖案的二階特征(例如,根據(jù)哪些邊緣傾向于一起發(fā)生——例如以形成輪廓或角檢測器)。深度自編碼器更深層的特性往往可以學習到更高階的特性。

把所有東西放在一起:我們需要更多的層來處理更為復雜的數(shù)據(jù)——比如我們在協(xié)作過濾中使用的數(shù)據(jù)。

三、實現(xiàn)

如前文所述,你將學會預(yù)測用戶對電影的評級。就此而言,我們將使用著名的 MovieLens 數(shù)據(jù)集

(https://grouplens.org/datasets/movielens/)。MovieLensis 是一個基于網(wǎng)絡(luò)的推薦系統(tǒng)和推薦用戶觀看電影的在線社區(qū)。

更具體地說,我們將使用 ml_1m.zip 數(shù)據(jù)集,該數(shù)據(jù)集包含 6,040 個 MovieLens 用戶制作的,約 3,900 部電影的 1,000,209 個匿名評級。我們需要的導入文件是 ratings.dat。該文件包含 1,000,209 行,全部格式如下:user_id :: movie_id :: rating:time_stamp。

例如 ratings.dat 中的第一行:

  1. 1::595::5::978824268   

這意味著用戶 1 給了 595 號電影打了五星評分。評分時間可以被忽略,因為在這里我們不會使用它。

我們的深度學習模型需要一個特定的數(shù)據(jù)結(jié)構(gòu)來進行訓練和測試。這種數(shù)據(jù)結(jié)構(gòu)是一個 UxM 矩陣,其中 U 是用戶數(shù)量,M 是電影數(shù)量。每行 i∈U 是唯一的用戶 ID,每列 j∈M 是唯一的電影 ID。這種矩陣的可視化效果如圖 3 所示。

矩陣的可視化效果

此矩陣中的每個條目都是用戶給出特定電影的評分。輸入 0 意味著用戶沒有給這部電影任何評價。例如。上圖中,1 號用戶給電影 3 的評級為四星,而電影第 1 則根本沒有評級。

由于本教程將重點介紹深度學習模型的實現(xiàn),因此不會在這里介紹使用 User-Movie-Matrix 超出 ratings.dat 文件的步驟。對于關(guān)于這個主題的進一步問題,你可以去我的 GitHub 頁面

(https://github.com/artem-oppermann/Deep-Autoencoders-For-Collaborative-Filtering/blob/master/data/preprocess_data.py), 查看相應(yīng)的 python 腳本。

1. 訓練和測試數(shù)據(jù)集

在模型實現(xiàn)和訓練之前,我們需要對數(shù)據(jù)進行其他重新處理步驟,將數(shù)據(jù)劃分為訓練和測試數(shù)據(jù)集。這一步驟簡單明了。到目前為止,我們有一個 User-Movie Matrix,其中每一行都是評級列表。要從列表中獲得訓練和測試集,我們需要從每一行中取一部分評級,并將它們用于訓練,其余子集則用于測試。

作為描述過程的一個例子,我們考慮一個僅包含 15 部電影的小得多的數(shù)據(jù)集。一個特定的用戶可能出給這樣的電影評級:

  1. Movie Nr. : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
  2. Rating:     5 0 2 4 0 0 2 1 5  1  0  4  5  1  3 

請記住,0 表示該電影未被評級。現(xiàn)在我們將前 10 部電影中的一部分作為訓練集并假設(shè)其余的還沒有被評分:

  1. Movie Nr. : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
  2. Rating:     5 0 2 4 0 0 2 1 5  0  0  0  0  0  0 

因此,原始數(shù)據(jù)的最后 5 個電影等級被用作測試數(shù)據(jù),而電影 1-10 被掩蓋為未被評級:

  1. Movie Nr. : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
  2. Rating:     0 0 0 0 0 0 0 0 0  1  0  4  5  1  3 

此處僅僅簡單演示了如何獲得不同的組合。在原始的 MovieLens 數(shù)據(jù)集中,我僅使用每個用戶的 10 個電影評級進行測試,其余(絕大多數(shù))用于模型的訓練。

2. TensorFlow 實現(xiàn)

(1) 模型架構(gòu)

深度自編碼器在這里作為一個類來實現(xiàn),其中包含所有必需的操作,如類內(nèi)的推理、優(yōu)化、損失、準確性等。

在構(gòu)造器中,內(nèi)核初始化器設(shè)置了權(quán)重和偏差。下一步,網(wǎng)絡(luò)中的所有權(quán)重和偏差都會被初始化。權(quán)重是遵從正態(tài)分布的,平均值為 0.0,方差為 0.02,而偏差在開始時都設(shè)置為 0.0。

在這個特定的例子中,網(wǎng)絡(luò)有三個隱藏層,每層包含 128 個神經(jīng)元。輸入層(和輸出層)的大小對應(yīng)于數(shù)據(jù)集中所有當前影片的數(shù)量。

  1. class DAE: 
  2.     ''' Implementation of Deep Autoencoder class''' 
  3.  
  4.     def __init__(self, FLAGS):     
  5.         self.FLAGS=FLAGS 
  6.         self.weight_initializer=model_helper._get_weight_initializer() 
  7.         self.bias_initializer=model_helper._get_bias_initializer() 
  8.         self.init_parameters() 
  9.  
  10.  
  11.     def init_parameters(self): 
  12.         ''' Initializing the weights and biasis of the neural network.''' 
  13.  
  14.         with tf.name_scope('weights'): 
  15.             self.W_1=tf.get_variable(name='weight_1'shape=(self.FLAGS.num_v,self.FLAGS.num_h),  
  16.                                      initializer=self.weight_initializer) 
  17.             self.W_2=tf.get_variable(name='weight_2'shape=(self.FLAGS.num_h,self.FLAGS.num_h),  
  18.                                      initializer=self.weight_initializer) 
  19.             self.W_3=tf.get_variable(name='weight_3'shape=(self.FLAGS.num_h,self.FLAGS.num_h),  
  20.                                      initializer=self.weight_initializer) 
  21.             self.W_4=tf.get_variable(name='weight_5'shape=(self.FLAGS.num_h,self.FLAGS.num_v),  
  22.                                      initializer=self.weight_initializer) 
  23.  
  24.         with tf.name_scope('biases'): 
  25.             self.b1=tf.get_variable(name='bias_1'shape=(self.FLAGS.num_h),  
  26.                                     initializer=self.bias_initializer) 
  27.             self.b2=tf.get_variable(name='bias_2'shape=(self.FLAGS.num_h),  
  28.                                     initializer=self.bias_initializer) 
  29.             self.b3=tf.get_variable(name='bias_3'shape=(self.FLAGS.num_h),  
  30.                                     initializer=self.bias_initializer) 

(2) 訓練

給定一個輸入數(shù)據(jù)樣本 x(用戶—電影矩陣的一行),正向傳遞并計算網(wǎng)絡(luò)輸出。隱藏層使用 sigmoid 作為激活函數(shù)。請注意,最后一層沒有非線性或偏置項。

  1. def _inference(self, x): 
  2.     '''Making one forward pass. Predicting the outputs, given the inputs.''' 
  3.  
  4.     with tf.name_scope('inference'): 
  5.          a1=tf.nn.sigmoid(tf.nn.bias_add(tf.matmul(x, self.W_1),self.b1)) 
  6.          a2=tf.nn.sigmoid(tf.nn.bias_add(tf.matmul(a1, self.W_2),self.b2)) 
  7.          a3=tf.nn.sigmoid(tf.nn.bias_add(tf.matmul(a2, self.W_3),self.b3))    
  8.          a4=tf.matmul(a3, self.W_4)  
  9.     return a4 

通過網(wǎng)絡(luò)預(yù)測,我們可以計算這些預(yù)測與相應(yīng)標簽(網(wǎng)絡(luò)輸入 x)之間的損失。為了計算損失的平均值,我們還需要知道非零標簽的數(shù)量——也就是訓練集中用戶的總評分數(shù)。

  1. def _compute_loss(self, predictions, labels,num_labels): 
  2.    ''' Computing the Mean Squared Error loss between the input and output of the network. 
  3.  
  4.     @param predictions: predictions of the stacked autoencoder 
  5.     @param labels: input values of the stacked autoencoder which serve as labels at the same time 
  6.     @param num_labels: number of labels !=0 in the data set to compute the mean 
  7.  
  8.     @return mean squared error loss tf-operation 
  9.     ''' 
  10.          with tf.name_scope('loss'): 
  11.          loss_op=tf.div(tf.reduce_sum(tf.square(tf.subtract(predictions,labels))),num_labels) 
  12.          return loss_op 

網(wǎng)絡(luò)的優(yōu)化/訓練步驟似乎有點棘手,讓我們一步一步討論。給定輸入 x,計算相應(yīng)的輸出。你可能已經(jīng)注意到,輸入 x 中的大部分值都是零值,因為用戶肯定沒有觀看和評估數(shù)據(jù)集中的所有 5953 部電影。因此,建議不要直接使用網(wǎng)絡(luò)的原始預(yù)測。相反,我們必須確定數(shù)據(jù)輸入 x 中零值的索引,并將與這些索引相對應(yīng)的預(yù)測向量中的值也設(shè)置為零。這種預(yù)測操縱極大地減少了網(wǎng)絡(luò)的訓練時間,使網(wǎng)絡(luò)有機會將訓練努力集中在用戶實際給出的評分上。

在此步驟之后,可以計算損失以及正則化損失(可選)。AdamOptimizer 會將損失函數(shù)最小化。請注意,該方法會返回一個均方根誤差(RMSE)而不是均方誤差(MSE),以測得更好的精度。

  1. def _optimizer(self, x): 
  2.         '''Optimization of the network parameter through stochastic gradient descent. 
  3.  
  4.             @param x: input values for the stacked autoencoder. 
  5.  
  6.             @return: tensorflow training operation 
  7.             @return: ROOT!! mean squared error 
  8.         ''' 
  9.  
  10.         outputs=self._inference(x) 
  11.         mask=tf.where(tf.equal(x,0.0), tf.zeros_like(x), x) # indices of zero values in the training set (no ratings) 
  12.         num_train_labels=tf.cast(tf.count_nonzero(mask),dtype=tf.float32) # number of non zero values in the training set 
  13.         bool_mask=tf.cast(mask,dtype=tf.bool) # boolean mask 
  14.         outputs=tf.where(bool_mask, outputs, tf.zeros_like(outputs)) # set the output values to zero if corresponding input values are zero 
  15.  
  16.         MSE_loss=self._compute_loss(outputs,x,num_train_labels) 
  17.  
  18.         if self.FLAGS.l2_reg==True: 
  19.             l2_loss = tf.add_n([tf.nn.l2_loss(v) for v in tf.trainable_variables()]) 
  20.             MSE_lossMSE_loss = MSE_loss +  self.FLAGS.lambda_ * l2_loss 
  21.  
  22.         train_op=tf.train.AdamOptimizer(self.FLAGS.learning_rate).minimize(MSE_loss) 
  23.         RMSE_loss=tf.sqrt(MSE_loss) 
  24.  
  25.         return train_op, RMSE_loss 

(3) 測試

訓練幾個 epoch 之后,神經(jīng)網(wǎng)絡(luò)已經(jīng)在訓練集中看到每個用戶的所有評分以及時間了。此時該模型應(yīng)該已經(jīng)了解數(shù)據(jù)中潛在的隱藏模式以及用戶對應(yīng)的電影評級規(guī)律。給定用戶評分訓練樣本 x,該模型預(yù)測輸出 x'。該向量由輸入值 x 的重構(gòu)(如預(yù)期)組成,但現(xiàn)在還包含輸入 x 中先前為零的值。這意味著該模型在給未評分的電影打分。這個評級對應(yīng)于用戶的偏好——模型從數(shù)據(jù)中已識別和學習到的偏好。

為了能夠測量模型的準確性,我們需要訓練和測試數(shù)據(jù)集。根據(jù)訓練集進行預(yù)測。類似于訓練階段,我們只考慮對應(yīng)于測試集中非零值的索引的輸出值。

現(xiàn)在我們可以計算預(yù)測值與實際評分之間的均方根誤差損失(RMSE)。RMSE 表示預(yù)測值與觀測值之間差異的樣本標準偏差。例如,RMSE 為 0.5 意味著平均預(yù)測評分與實際評分相差 0.5 星。

  1. def _validation_loss(self, x_train, x_test): 
  2.         ''' Computing the loss during the validation time. 
  3.         @param x_train: training data samples 
  4.         @param x_test: test data samples 
  5.         @return networks predictions 
  6.         @return root mean squared error loss between the predicted and actual ratings 
  7.         ''' 
  8.         outputs=self._inference(x_train) # use training sample to make prediction 
  9.         mask=tf.where(tf.equal(x_test,0.0), tf.zeros_like(x_test), x_test) # identify the zero values in the test ste 
  10.         num_test_labels=tf.cast(tf.count_nonzero(mask),dtype=tf.float32) # count the number of non zero values 
  11.         bool_mask=tf.cast(mask,dtype=tf.bool)  
  12.         outputs=tf.where(bool_mask, outputs, tf.zeros_like(outputs)) 
  13.  
  14.         MSE_loss=self._compute_loss(outputs, x_test, num_test_labels) 
  15.         RMSE_loss=tf.sqrt(MSE_loss) 
  16.  
  17.         return outputs, RMSE_loss 

(4) 訓練結(jié)果

最后一步包括執(zhí)行訓練過程并檢查模型性能。在這一點上,我不會詳細討論構(gòu)建數(shù)據(jù)輸入管道、圖表、會話等細節(jié)。因為這些步驟通常是已知的。對此主題感興趣的讀者可以在我的 GitHub 中查看這些步驟:https://github.com/artem-oppermann/Deep-Autoencoders-For-Collaborative-Filtering/blob/master/train.py

在這里,你可以看到前 50 個迭代次數(shù)的訓練和測試表現(xiàn)。50 次后,測試集的預(yù)測和實際評分間的偏差是 0.929 星。

  1. epoch_nr: 0, train_loss: 1.169, test_loss: 1.020 
  2. epoch_nr: 10, train_loss: 0.936, test_loss: 0.959  
  3. epoch_nr: 20, train_loss: 0.889, test_loss: 0.931  
  4. epoch_nr: 30, train_loss: 0.873, test_loss: 0.923  
  5. epoch_nr: 40, train_loss: 0.859, test_loss: 0.925  
  6. epoch_nr: 50, train_loss: 0.844, test_loss: 0.929 

原文地址:

https://towardsdatascience.com/deep-autoencoders-for-collaborative-filtering-6cf8d25bbf1d

【本文是51CTO專欄機構(gòu)“機器之心”的原創(chuàng)譯文,微信公眾號“機器之心( id: almosthuman2014)”】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2021-03-29 11:37:50

人工智能深度學習

2021-03-22 10:52:13

人工智能深度學習自編碼器

2017-07-19 13:40:42

卷積自編碼器降噪

2017-12-26 10:48:37

深度學習原始數(shù)據(jù)

2025-04-10 11:52:55

2016-08-18 01:36:14

協(xié)同過濾推薦電影用戶

2024-10-21 16:47:56

2021-02-20 20:57:16

深度學習編程人工智能

2017-11-10 12:45:16

TensorFlowPython神經(jīng)網(wǎng)絡(luò)

2023-10-31 16:46:45

2017-04-27 18:09:26

item embedd推薦系統(tǒng)算法

2024-06-18 08:52:50

LLM算法深度學習

2021-11-15 12:45:44

協(xié)同過濾算法架構(gòu)

2022-07-20 23:04:59

矩陣分解算法Spark

2020-06-28 07:30:00

推薦算法推薦系統(tǒng)

2020-04-26 11:26:02

人臉合成編碼器數(shù)據(jù)

2022-04-02 21:46:27

深度學習編碼器圖像修復

2019-05-05 09:00:00

數(shù)據(jù)分析算法推薦系統(tǒng)

2022-09-13 15:26:40

機器學習算法數(shù)據(jù)

2021-11-02 20:44:47

數(shù)字化
點贊
收藏

51CTO技術(shù)棧公眾號