推薦系統(Recommender systems)
這里討論推薦系統有兩個深層原因或者說動機,第一個原因在於它是機器學習的一個重要應用,在過去的幾年中在參觀硅谷的各種科技類公司中,經常在那些公司里與開發機器學習應用的人交流,談及什么才是機器學習最重要的應用,或者什么樣的機器學習的應用是最想讓它的表現得到改進的,最常聽到的回答其中之一就是現在硅谷有好多個團隊正試圖建立更好的推薦系統。比如亞馬遜、Netflix、eBay或者蘋果公司的iTunes Genius做的事情,有很多網站或者很多系統試圖向用戶推薦新產品,比如說亞馬遜會推薦新書,Netflix推薦新電影等等。這些推薦系統可能會看看你以前購買過什么書或者以前你給哪些電影進行過評分,這些系統貢獻了現今亞馬遜收入的相當大一部分,而對像Netflix這樣的公司,他們向用戶推薦的電影占了用戶觀看的電影的相當大一部分,於是一個推薦系統其表現的一些改進就能帶來顯著且即刻產生的影響這種影響關系到許多公司的最終業績。
第二個動機是我們已經在前面章節中看到對於機器學習來說特征量(features)的重要性,所選擇的特征對於學習算法的表現有很大影響,在機器學習領域有這么一個宏大的想法就是對於一些問題而言存在一些算法能自動地替代人類學習到一組優良的特征量,即有些情形下能夠采用一種算法來學習到使用什么特征量,而推薦系統就是這種情形的一個例子,還有其他很多例子但通過學習推薦系統我們將能夠對這種學習特征量的想法有一點理解。
1.預測電影評分
假想有一個影評網站,比方說允許評分在0顆星至5顆星之間,這里有5部電影《愛到最后》、《浪漫永遠》、《小愛犬》、《無盡狂飆》還有《劍與空手道》,我們有4位用戶名叫Alice,Bob,Carol和Dave。或稱他們用戶1、2、3和4,比方說Alice她非常喜歡《愛到最后》把它評為5顆星,她還喜歡《浪漫永遠》也把它評為5顆星,她沒看過《小愛犬》也就沒評分這樣我們沒有這個評分數據,Alice很不喜歡《無盡狂飆》或是《劍與空手道》把它們評為0顆星。其他3位用戶的的評價如下:
\(n_u\):表示用戶的數目 |
---|
\(n_m\):表示電影的數目 |
\(r(i,j)=1\):表示用戶j對電影i做了評分(否則即為做評分時為零) |
\(y^{(i,j)}\):用戶j對電影i的評分(前提做了評分) |
首先介紹第一種構造推薦系統的方法,這種方法叫做“基於內容的推薦”(content-based recommendations)。應該如何預測這些缺少的問號評分值呢?假設對這些電影的每一部,都用一些特征來描述,具體來講,假設每部電影有兩種特征分別用x1和x2代表,x1表示這部電影屬於愛情電影的程度,x2表示這部電影是動作電影的程度,因此對於電影《愛到最后》那么這部電影是愛情電影的比率為0.9,但是它屬於動作電影的比率為0,《浪漫永遠》愛情比率1.0,動作比率0.01,等等如下所示:
我們可以把對每個觀眾打分的預測當成一個獨立的線性回歸問題,具體來說,比如每一個用戶j,我們都學習出一個參數\(\theta^{(j)}\)(這里是一個三維向量),然后要根據參數向量θ與特征\(x^{(i)}\)的內積來預測用戶j對電影i的評分即\((\theta^{(j)})^Tx^{(i)}\)。
看一個具體的例子,對於用戶1即Alice對應的參數向量就應該是\(\theta^{(1)}\),現在假如我們想預測Alice對電影《小愛犬》是如何評價的那么這部電影,有一個參數向量\(x^{(3)}\)等於[1,0.99,0],其中1是截距項,另外兩個是特征0.99和0。假如說對於這個例子,已經知道Alice的參數向量\(\theta^{(1)}\)(后面會詳細講到如何獲得這個參數)等於[0,5,0]。因此這兩個向量的內積就等於5×0.99結果為4.95,故我們預測Alice得評分結果將為4.95。
現在可以把這個問題寫成如下更正式一些,用r(i,j)=1來表示用戶j對電影i進行了評分,y(i,j)則表示用戶j對電影i的評分值,\(\theta^{(j)}\)表示用戶j對應的參數向量,\(x^{(i)}\)是某部電影i的特征向量,那么某個用戶對某部電影的評分就是\((\theta^{(j)})^Tx^{(i)}\)。
現在臨時介紹一個額外的表示符號\(m^{(j)}\),用來表示用戶j評價過的電影數量,預測評分是一個基本的線性回歸問題,因此我們要做的就是選擇一個參數向量\(\theta^{(j)}\),使得預測的結果盡可能接近我們在訓練集中的觀測值。因此我們要關於\(\theta^{(j)}\)最小化下面這個求和值:\(min_{\theta^{(j)}}\left[\frac{1}{2m^{(j)}}\Sigma_{i:r(i,j)=1}((\theta^{(j)})^T(x^{(i)})-y^{(i,j)})^2+\frac{\lambda}{2m^{(j)}}\Sigma_{k=1}^n(\theta_k^{(j)})^2\right]\)
對於推薦系統,這里把符號稍微簡化一下,去掉常數項\(m^(j)\),去掉這一項不改變θ(j)的最優化結果,\(min_{\theta^{(j)}}\left[\frac{1}{2}\Sigma_{i:r(i,j)=1}((\theta^{(j)})^T(x^{(i)})-y^{(i,j)})^2+\frac{\lambda}{2}\Sigma_{k=1}^n(\theta_k^{(j)})^2\right]\) 。
在構建推薦系統的時候我們也不想只對某一個用戶學習出參數向量,我們想對所有的用戶都學習出θ,因為有\(n_u\)個用戶,所以希望學習出所有的參數,那么要做的是將上面這個最優化目標再加上一個求和:\(min_{\theta^{(j)}}\left[\frac{1}{2}\Sigma_{j=1}^{n_u}\Sigma_{i:r(i,j)=1}((\theta^{(j)})^T(x^{(i)})-y^{(i,j)})^2+\frac{\lambda}{2}\Sigma_{j=1}^{n_u}\Sigma_{k=1}^n(\theta_k^{(j)})^2\right]\) ,這里把想要最優化的項稱為:\(J(\theta^{(1)},..., \theta^{(n_u)})\),同樣地J還是我們要最小化的最優化目標函數。
如果想要用梯度下降來求出這個J的最小值,可能會用到這些式子:
2.協同過濾(collaborative filtering)
協同濾波算法能夠自行學習所要使用的特征,在上一小節中的基於內容的推薦中,每一部電影都有明確的浪漫指數是多少,動作指數是多少,但細想可以知道這樣做難度很大,花費時間很多,要讓每個人看完每一部電影后說出每一部電影有多浪漫多動作是一件不容易的事情,而且通常除這兩個特征之外的其他指數有很多。
所以讓我們轉移一下問題,假如我們有一個數據集,但並不知道特征的值是多少,當我們得到一些不同用戶對電影的評分,我們並不知道每部電影到底有多少浪漫的成分,或動作成分,於是把所有的特征都打上問號,如下圖所示:
更一般的,假設用戶告訴了我們的偏好,即已經給我們提供了\(\theta^{(1)}\)到\(\theta^{(n_u)}\)的值,而我們想知道電影i的特征向量\(x^{(i)}\),我們可以列出以下的最優化的問題:
我們要做的是學習出所有電影的所有特征,所以現在要做的是在此加上另外的一個求和,即對所有的電影n_m求和,然后最小化整個這個目標函數,針對所有的電影這樣就會得到如下的最優化的問題:
上一小節“基於內容的推薦”算法講的是,若有對一系列電影的評分,那么根據不同電影的特征\(x^{(1)},..., x^{(n_m)}\),我們可以得到參數θ。本節中我們主要講的是如果用戶願意提供參數θ,那么可以為不同的電影估計特征。
有點像先有雞還是先有蛋的問題,如果我們能知道θ就能學習到x,相對的如果我們知道x也會學出θ,所以實際上應該隨機猜θ的值,接着基於一開始隨機猜測出的θ的值繼而學習出不同電影的特征,給出已有的一些電影的原始特征,再運用上一個小節中討論過的方法,得到對參數θ的更好估計,為用戶提供更好的參數θ集,接着繼續迭代,不停重復優化θ、x、θ、x、θ。算法將會收斂到一組合理的特征以及一組合理的用戶參數的估計。
具體算法實現
如果給出電影的幾個特征,我們可以使用這些資料去獲得用戶的參數數據,如果給出用戶的參數數據,那么可以使用這些資料去獲得電影的特征,我們將它們合並成協同過濾算法(Collaborative Filtering Algorithm)。即不停地重復下面的式子的計算,隨機地初始化這些參數,然后解出θ,解出x,解出θ,解出x...實際上存在一個更有效率的算法,不再需要像這樣不停地計算x和θ,而是能夠將x和θ同時計算出來。
此外,當我們以這樣的方法學習特征量時,之前的前提是我們所使用的特征x0(即截距量)等於1,當我們以這種形式去學習特征量時,我們必須要去掉這個截距量,我們這里移除的理由是:我們沒有必要去將這個等於一的特征值固定,因為如果算法想要的話,可以將特征值x1設為1,所以沒有必要去將1這個特征定死,這樣算法有了靈活性去自行學習。
總結一下,首先我們會把\(x^{(1)},...,x^{(n_m)}\)和\(\theta^{(1)},...,\theta^{(n_u)}\)初始為小的隨機值,接下來我們要用梯度下降或者某些其他的高級優化算法把這個代價函數\(J(x^{(1)},...,x^{(n_m)}, \theta^{(1)},...,\theta^{(n_u)})\)最小化,梯度下降法寫出來的更新公式如下:
3.協同過濾算法的向量化實現
我們有五部電影的數據集(如下圖),首先將要做的是將這些用戶的電影評分進行分組並存到一個矩陣中,我們共有五部電影以及四位用戶,那么這個矩陣Y就是一個5行4列的矩陣,它將這些電影的用戶評分數據都存在矩陣里,包括問號標注出的。
本節最后談一談均值歸一化(Mean Normalization),它可以讓協同濾波算法算法運行得更好。
首先我們了解均值歸一化這個想法的動機,還是之前的電影評分的例子,考慮一下有一個用戶沒有給任何電影評分,即第五個用戶Eve她沒有給任何電影評分,我們來看看協同過濾算法會對這個用戶做什么。
假如n等於2,即我們要學習兩個特征變量還要學習出一個參數向量\(\theta^{(5)}\),任然提醒一下,這個向量是n維的而不是n+1維的,根據優化函數,用戶Eve沒給任何電影打過分,所以對用戶Eve來說沒有電影滿足r(i,j)=1這個條件,所以優化函數中的第一項(與實際評分差)完全不影響\(\theta^{(5)}\)的值,所以影響\(\theta^{(5)}\)值的唯一一項是最后的正則化項,優化的目的是盡可能地讓正則化項小,換句話說我們想要最小化\(\frac{\lambda}{2}[(\theta_1^{(5)})^2+(\theta_2^{(5)})^2]\),所以最終得到的就會是\(\theta^{(5)}\)=[0;0]。
因為正則化項會讓你的參數接近0,如果沒有數據能夠使得參數遠離0,那么就會得到\(\theta^{(5)}\)等於零向量。所以當我們要預測用戶5給電影打分結果,有\((\theta^{(5)})^Tx^{(i)}\),易見對任意i結果都會等於0,因此我們根據結果會預測Eve給所有電影的評分都是零星,這個結果我們還是沒有任何好方法來把電影推薦給她,因為預測結果是所有這些電影都會被Eve給出一樣的評分,沒有一部電影擁有高一點兒的預測評分讓我們能推薦給她。
均值歸一化的想法可以讓我們解決這個問題,把所有這些評分全部整合到矩陣Y中,全部是問號的這列對應着Eve沒有給任何電影評分。為了實現均值歸一化,首先計算每個電影所得評分的均值,把它們存在一個向量µ中,接着重新定義Y矩陣,將Y的每一列減去向量µ重新更新每一列,這樣把每個電影都歸一化為平均評分為零,當然未打分的這些問號沒變。
因為Eve從來沒有給任何電影打分,所以學習到的用戶5的參數仍然還是零向量,這樣我們預測Eve的評分是\((\theta^{(5)})^Tx^{(i)}+\mu_i\),所以如果學習的等於0的話,對電影i的評分我們最終會預測為µi,即對於電影1我們會預測Eve對它的評分是2.5,對於電影2我們會預測Eve給它2.5星,對於電影3我們會預測Eve給它2星等等。我們就對這個新的觀影用戶Eve一無所知,我們預測她對每個電影的評分就是這些電影所得的平均評分,就是這些電影所得的平均評分。