Python使用矩陣分解法找到相似的音樂

這篇文章是如何使用幾種不一樣的矩陣分解算法計算相關藝術家的分步指南。代碼用Python編寫,使用 Pandas 和SciPy進行計算,D3.js以交互方式可視化結果。算法

加載數據

對於這裏的帖子,我使用與 個人第一篇文章中相同的Last.fm數據集。這可使用Pandas加載到稀疏矩陣中,只有幾行代碼:dom

# read in triples of user/artist/playcount from the input datasetdata = pandas.read_table("usersha1-artmbid-artname-plays.tsv",

                        usecols=[0, 2, 3],

                        names=['user', 'artist', 'plays'])# map each artist and user to a unique numeric valuedata['user'] = data['user'].astype("category")data['artist'] = data['artist'].astype("category")# create a sparse matrix of all the artist/user/play triplesplays = coo_matrix((data['plays'].astype(float),

                  (data['artist'].cat.codes,

                    data['user'].cat.codes)))

這裏返回的矩陣有300,000名藝術家和360,000名用戶,總共有大約1700萬條目。每一個條目都是用戶播放藝術家的次數,其中的數據是從2008年的Last.fm API收集的。ide

矩陣分解

一般用於此問題的一種技術是將用戶 - 藝術家 - 戲劇的矩陣投影到低等級近似中,而後計算該空間中的距離。函數

咱們的想法是採用原始的播放計數矩陣,而後將其減小到兩個小得多的矩陣,這些矩陣在乘以時接近原始矩陣:學習

![clipboard.png](/img/bVbc6R1)


Artist/User/Play CountsArtist FactorsUser Factors=×

代替將每一個藝術家表示爲全部360,000個可能用戶的遊戲計數的稀疏向量,在對矩陣進行因式分解以後,每一個藝術家將由50維密集向量表示。ui

經過減小這樣的數據的維數,咱們實際上將輸入矩陣壓縮爲兩個小得多的矩陣。這種壓縮會強制輸入數據的泛化,而這種推廣能夠更好地理解數據。spa

潛在語義分析

分解輸入矩陣的一種簡單方法是在適當加權的矩陣上計算奇異值分解 code

SVD是那些很是有用的技術之一,也能夠用於 主成分分析或 多維縮放等。個人目的包括它是如何工做的總結,可是Jeremy Kun最近寫了一篇關於SVD的精彩概述 ,我甚至不打算嘗試這樣作。出於本文的目的,咱們只須要知道SVD生成輸入矩陣的低秩近似,而且咱們可使用該低秩表示來生成看法。orm

像這樣使用SVD稱爲潛在語義分析(LSA)。全部真正涉及的是在這個分解空間中經過餘弦距離得到最相關的藝術家,這能夠經過如下方式完成:blog

class TopRelated(object): def __init__(self, artist_factors): # fully normalize artist_factors, so can compare with only the dot product norms = numpy.linalg.norm(artist_factors, axis=-1) self.factors = artist_factors / norms[:, numpy.newaxis] def get_related(self, artistid, N=10): scores = self.factors.dot(self.factors[artistid]) best = numpy.argpartition(scores, -N)[-N:] return sorted(zip(best, scores[best]), key=lambda x: -x[1])

潛在語義分析之因此得名,是由於在對矩陣進行分解以後,能夠暴露輸入數據中潛在的隱藏結構 - 這能夠被認爲是揭示輸入數據的語義。

例如,'Arcade Fire'和'The Arcade Fire'在我正在使用的數據集中沒有共同的監聽器:它是由Last.fm歷史生成的,人們在他們的音樂庫中使用了一個標籤或另外一個標籤。

這意味着全部比較藝術家的直接方法都認爲這兩個樂隊徹底不一樣。然而,這兩個標籤都指的是同一個頻段 - 這是LSA設法接受的事實,由於它們被排名爲彼此最類似:

clipboard.png

LSA

相似於LSA的'Arcade Fire':

你也能夠看到與 「槍炮玫瑰」和「槍炮玫瑰」, 「尼克洞穴和壞種子」與「尼克洞穴和壞種子」相同的效果。隨意進入其餘藝術家,但請記住,這個數據集是從2008年開始的,所以這裏沒有更多的現代藝術家。

雖然LSA成功地歸納了咱們數據的某些方面,但這裏的結果並非那麼好。看看Bob Dylan的結果就是一個例子。

爲了在保持這種歸納能力的同時作得更好,咱們須要提出一個更好的模型。

隱含的交替最小二乘法
推薦系統常用矩陣分解模型來 爲用戶生成個性化推薦。 已發現這些模型在推薦項目時效果很好,而且能夠很容易地重複用於計算相關藝術家。

推薦系統中使用的許多MF模型都採用了明確的數據,用戶使用相似5星級評定標準評估了他們喜歡和不喜歡的內容。它們一般經過將丟失的數據視爲未知數,而後使用SGD最小化重建錯誤來工做。

這裏的數據是隱含的 - 咱們能夠假設聽用藝術家的用戶意味着他們喜歡它,可是咱們沒有用戶不喜歡藝術家的相應信號。隱式數據一般比顯式數據更豐富,更容易收集 - 即便您讓用戶給出5星評級,絕大多數評級都只是積極的,所以您不管如何都須要考慮隱含行爲。

這意味着咱們不能僅僅將丟失的數據視爲未知數,而是將不聽藝術家的用戶視爲用戶可能不喜歡該藝術家的信號。

這對學習分解表示提出了一些挑戰。

第一個挑戰是有效地進行這種因式分解:經過將未知數視爲負數,天真的實現將查看輸入矩陣中的每一個條目。因爲此處的維度大約爲360K乘300K - 總共有超過1000億條目要考慮,而只有1700萬非零條目。

第二個問題是咱們不能肯定沒有聽藝術家的用戶實際上意味着他們不喜歡它。可能還有其餘緣由致使藝術家沒有被收聽,特別是考慮到咱們在數據集中每一個用戶只有最多50位藝術家。

隱式反饋數據集的協做過濾以優雅的方式解釋了這兩個挑戰。

爲了處理咱們對負面數據沒有信心的狀況,這種方法使用二元偏好的不一樣置信水平來學習分解矩陣表示:看不見的項目被視爲負面且置信度低,其中當前項目被視爲正面更高的信心。

clipboard.png

那麼目標是經過最小化平方偏差損失函數的置信加權和來學習用戶因子X u和藝術家因子Y i:

def alternating_least_squares(Cui, factors, regularization, iterations=20): users, items = Cui.shape

    X = np.random.rand(users, factors) * 0.01    Y = np.random.rand(items, factors) * 0.01    Ciu = Cui.T.tocsr()    for iteration in range(iterations):        least_squares(Cui, X, Y, regularization)        least_squares(Ciu, Y, X, regularization)    return X, Ydef least_squares(Cui, X, Y, regularization):    users, factors = X.shape

    YtY = Y.T.dot(Y)    for u in range(users):        # accumulate YtCuY + regularization * I in A        A = YtY + regularization * np.eye(factors)        # accumulate YtCuPu in b        b = np.zeros(factors)        for i, confidence in nonzeros(Cui, u):            factor = Y[i]            A += (confidence - 1) * np.outer(factor, factor)            b += confidence * factor

        # Xu = (YtCuY + regularization * I)^-1 (YtCuPu)        X[u] = np.linalg.solve(A, b)

爲了調用它,我使用與LSA中使用的置信矩陣相同的權重,而後以相同的方式計算相關的藝術家:

artist_factors ,user_factors = alternating_least_squares (bm25_weight (plays ),50 )

與僅使用LSA相比,該方法能夠產生明顯更好的結果。看一下 斜率圖,比較Bob Dylan的結果做爲一個例子:

這裏LSA返回的無關結果被推出列表的頭部,並被相關結果取代。

Implicit ALS的優勢在於它仍然成功地推廣了輸入。舉個例子,不管是Guns N'Roses仍是Nick Cave和The Bad Seeds都會提出他們的同義詞,只是沒有LSA返回的一些邊際結果。

相關文章
相關標籤/搜索