• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • 數據科學

    使用 NetworkX、Jaccard Similarity 和 cuGraph 預測您下一部最喜歡的電影

    隨著全球每個人可用的數據量不斷增加,消費者做出明智決策的能力也越來越難。幸運的是,對于推薦系統而言,大型數據集是一個非常有用的組件,有時這會讓某些情況下的決策變得更加容易。

    對于為推薦系統提供支持的數據中固有的關系建模而言,圖形是一個很好的選擇,而 NetworkX 是許多數據科學家在 Python 中進行圖形分析時非常喜歡的選擇。NetworkX 易于學習和使用,擁有各種圖形算法,并由龐大而友好的社區提供支持,并且在 Notebook、文檔、Stack Overflow 和您喜歡的 LLM 中提供了大量示例。然而,令無數開發人員失望的是,他們使用 NetworkX 或甚至因為 NetworkX 而涉足圖形分析,但眾所周知,它在典型推薦系統使用的規模上的性能表現不佳。

    這就引出了一個問題:能否用 Python 的幾行簡單代碼編寫有效的基于圖形的推薦系統?更一般地說,開發者和數據科學家能否同時進行易于使用的高性能圖形分析?

    這兩個問題的答案都是“Yes”

    請繼續閱讀,了解如何使用 NetworkX、Jaccard Similarity 算法和 NVIDIA cuGraph 后端 (可將現代大規模圖形數據所需的速度提高 250 倍以上),在 Python 中創建簡單有效的推薦系統,使用 3300 萬條電影評論的數據集。

    MovieLens 數據集?

    我們先從系統中最重要的部分開始:數據。MovieLens 數據集 1 可供公開 下載 README 文件 中有更詳細的說明。該系列包括大約 331k 匿名用戶,他們在觀看 87k 部電影,獲得了 34M 的評分。

    Image showing how the MovieLens data can be shown as a graph.
    圖 1、MovieLens 數據可以表示為一個圖形,其中各個評分可輕松映射到用戶和電影節點之間的邊緣。

    從數據中提取建議:二分圖和 Jaccard Similarity

    我們根據 MovieLens 數據創建的圖形類型是二部圖,因為只有兩種類型的節點:電影節點和用戶節點,并且評論(邊緣)只能在用戶和電影之間發生。這使得應用 Jaccard Similarity 算法來查找電影之間的相似性變得特別容易。Jaccard Similarity 比較節點對,并使用它們在圖形中的關系計算相似性系數。在這種情況下,電影根據用戶選擇的觀看和審查方式相互關聯。

    Image showing how the  Jaccard Similarity algorithm can be used to find similarities between movies.
    圖 3、Jaccard Similarity 使用所比較的兩個節點的近鄰集的大小來計算相似性系數。根據用戶的觀看偏好,我們可以看到 m3 與 m2 更相似,電影 m4 和 m1 完全不相似。此系統會向喜歡 m3 的用戶推薦 m2,而不會向喜歡 m4 的用戶推薦 m1。

    NetworkX 可以輕松處理較小的圖形

    不足為奇的是,NetworkX 支持我們上述的分析類型,而且只需使用幾行 Python 代碼即可輕松查看結果。但正如我們將看到的,當使用無 GPU 加速的 cuGraph 后端的 NetworkX 時,大型圖形 (例如我們的電影推薦系統所需的圖形) 的性能會受到限制。

    我們將在下方查看推薦系統的關鍵部分,但可在 此處 獲取完整源代碼。

    由于我們使用的 Jaccard Similarity 算法未考慮邊緣權重,因此會將所有評論視為相同。我們不希望推薦好評度低的電影,因此我們會過濾掉某個值下的所有好評度,這會導致圖形也變小。

    # Create a separate DataFrame containing only "good" reviews (rating >= 3).
    good_ratings_df = ratings_df[ratings_df["rating"] >= 3]
    good_user_ids = good_ratings_df["userId"].unique()
    good_movie_ids = good_ratings_df["movieId"].unique()

    如果我們打印正在處理的數據的大小,我們會看到好評圖大約有 330k 個節點,28M 個邊緣,平均度數 (每個節點的近鄰數) 為 84:

    total number of users: 330975
    total number of reviews: 33832162
    average number of total reviews/user: 102.22
    total number of users with good ratings: 329127
    total number of good reviews: 27782577
    average number of good reviews/user: 84.41

    如上所述,這種規模的圖形通常會給 NetworkX 帶來挑戰,但使用 cuGraph 后端的 GPU 加速消除了通常與如此多的數據相關的性能限制。不過,我們將繼續使用 CPU 環境來演示默認性能。

    注意 以下所有示例均在使用 NetworkX 3.4.2 和 Intel(R) Xeon(R) Platinum 8480CL@2.0GHz(2TB RAM)的工作站上運行

    使用由用戶創建的 NetworkX 圖形和優秀的電影評論,我們來選擇一個用戶,找到他們評分最高的電影之一,并使用 Jaccard Similarity 找到類似的其他電影。

    # Pick a user and one of their highly-rated movies
    user = good_user_ids[321]
    user_reviews = good_user_movie_G[user]
    highest_rated_movie = max(
        user_reviews,
        key=lambda n: user_reviews[n].get("rating", 0)
    )

    當我們在電影名稱貼圖中查找節點 ID 時,我們會發現該用戶評分最高的電影之一是動畫電影“Mulan”:

    highest rated movie for user=289308 is Mulan (1998), id: 1907, rated: {'rating': 5.0}

    我們現在可以使用 Jaccard Similarity 根據用戶的偏好和觀看歷史記錄來推薦電影:

    %%time
    # Run Jaccard Similarity
    jacc_coeffs = list(nx.jaccard_coefficient(good_user_movie_G, ebunch))

    CPU times: user 2min 5s, sys: 15.4 ms, total: 2min 5s
    Wall time: 2min 14s

    使用默認 NetworkX 實現的 Jaccard 相似性計算運行了兩分鐘以上。根據這些結果,我們現在可以提供推薦。

    # Sort by coefficient value, which is the 3rd item in the tuples
    jacc_coeffs.sort(key=lambda t: t[2], reverse=True)
      
    # Create a list of recommendations ordered by "best" to "worst" based on the
    # Jaccard Similarity coefficients and the movies already seen
    movies_seen = list(good_user_movie_G.neighbors(user))
    recommendations = [mid for (_, mid, _) in jacc_coeffs
                      if mid not in movies_seen]

    現在,我們只需在已排序的推薦列表中打印出第一部電影:

    User ID 289308 might like Tarzan (1999) (movie ID: 2687)

    代碼很簡單,結果看起來不錯,但性能卻拖累了我們

    如我們所見,這個推薦似乎是合理的;喜歡“Mulan”的人似乎也喜歡 1999 年的迪士尼動畫電影“Tarzan”。

    但是,如果我們的目標是提供服務,或分析數百乃至數千部電影,那么兩分鐘的運行時間就能讓我們開始尋找 NetworkX 的替代方案。我們可以看到,使用此系統查找其他電影相似點的速度并沒有加快:

    %%time
    # 1196: "Star Wars: Episode V - The Empire Strikes Back (1980)"
    print_similar_movies(1196)

    movies similar to Star Wars: Episode V - The Empire Strikes Back (1980):
    movieId=260, Star Wars: Episode IV - A New Hope (1977)
    movieId=1210, Star Wars: Episode VI - Return of the Jedi (1983)
    movieId=1198, Raiders of the Lost Ark (Indiana Jones and the Raiders of the Lost Ark) (1981)
    CPU times: user 13min 47s, sys: 71.8 ms, total: 13min 47s
    Wall time: 11min 30s

    %%time
    # 318: "Shawshank Redemption, The (1994)"
    print_similar_movies(318)

    movies similar to "Shawshank Redemption, The (1994)":
    movieId=296, Pulp Fiction (1994)
    movieId=593, "Silence of the Lambs, The (1991)"
    movieId=356, Forrest Gump (1994)
    CPU times: user 28min 28s, sys: 172 ms, total: 28min 28s
    Wall time: 16min 49s

    鑒于此系統僅由幾行代碼組成,因此所返回的推薦內容的質量令人印象深刻。但是,運行時性能使其幾乎無法使用。如上所述,根據“Shawshank Redemption, The (1994)”查找推薦內容大約需要 17 分鐘。

    NVIDIA cuGraph 使其變革性地加快

    上述工作流程中的圖形算法成本高昂,但通過使用 NVIDIA cuGraph 后端和兼容的 GPU,我們可以在不更改代碼的情況下顯著提高性能。

    nx-cugraph 版本 25.02 或更高版本支持 Jaccard Similarity。版本 25.02 可在 nightly builds 中使用,并將于本月晚些時候納入未來的穩定版本中。有關如何使用 conda 或 pip 從 nightly 和 stable 通道安裝 nx-cugraph 以及其他 RAPIDS 包的說明,請參閱 RAPIDS Installation Guide

    安裝后,只需設置環境變量即可啟用 nx-cugraph:

    NX_CUGRAPH_AUTOCONFIG=True

    cuGraph 利用 GPU 顯著加速近鄰查找,并設置 Jaccard 相似性計算所需的比較結果。此外,隨著圖形規模以及每部電影的電影和評論數量的增加,性能幾乎保持不變。

    該系統最優秀的部分,即代碼的簡單性,并沒有改變,結果也是一樣的,但在過去近 17 分鐘的運行中,性能提高了 250 倍以上,縮短到 4 秒以內。

    Barchart showing how Jaccard Similarity speedup with cuGraph over NetworkX for Movie Recommendations.
    圖 4、圖表顯示了各種電影的 cuGraph over NetworkX for Jaccard Similarity 計算速度 軟件:NetworkX 3.4.2,cuGraph/nx-cugraph 25.02 CPU:Intel(R) Xeon(R) Platinum 8480CL@2.0GHz 2TB RAM GPU:NVIDIA Quadro RTX 8000 48GB RAM

    結束語?

    這篇博文介紹了一個簡單而有效的推薦系統,它可以使用 NetworkX 輕松地用 Python 編寫。雖然我們可以采用許多其他方法(如此處所述),但很少有方法能夠做到與開始探索 NetworkX 圖形分析提供的數據所需的工作量不相上下。然而,高效和有意義的數據探索需要快速的周轉,而 NetworkX 傳統上一直難以擴展到更大的實際問題規模。

    適用于 NetworkX 的 NVIDIA cuGraph 后端可對熟悉且靈活的 NetworkX API 進行加速,還可大規模提升其性能,在幾秒鐘 (而非數十分鐘) 內生成結果,從而讓您專注工作并高效工作。現在,用戶只需向環境中添加 GPU 和 cuGraph 后端,即可繼續使用熱門的圖形分析庫 NetworkX,而無需擔心擴展問題。

    如需了解有關使用 NetworkX 和 NVIDIA cuGraph 進行加速圖形分析的更多信息,請訪問 https://rapids.ai/nx-cugraph

    ?

    0

    標簽

    人人超碰97caoporen国产