UNPKG

@mhg/blog

Version:
25 lines 274 kB
<!DOCTYPE html><html lang="zh-Hans"><head hexo-theme="https://github.com/volantis-x/hexo-theme-volantis/#6.0.3"><meta name="generator" content="Hexo 8.1.2"><meta name="Volantis" content="6.0.3"><meta charset="utf-8"><meta name="robots" content="index,follow,max-image-preview:large"><link rel="canonical" href="https://blog.mhuig.top/notes/Spark/als"><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="https://static.mhuig.top"><link rel="preconnect" href="https://static.mhuig.top" crossorigin=""><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><meta name="HandheldFriendly" content="True"><meta name="mobile-web-app-capable" content="yes"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"><meta content="black-translucent" name="apple-mobile-web-app-status-bar-style"><meta content="telephone=no" name="format-detection"><script>function registerServiceWorker(e){"localhost"!=window.location.hostname&&"serviceWorker"in navigator&&navigator.serviceWorker.register(`${e}`).then((function(e){"localhost"==window.location.hostname&&(e.onupdatefound=function(){var r=e.installing;r.onstatechange=function(){switch(r.state){case"installed":navigator.serviceWorker.controller?console.log("Updated Service Worker."):console.log("Service Worker Sucess!");break;case"redundant":console.log("The installing service worker became redundant.")}}})})).catch((function(e){console.error("Error during service worker registration:",e),"undefined"==typeof swinstallretry&&(swinstallretry=1,registerServiceWorker("/jquery.js"))}))}registerServiceWorker("/jquery.js")</script><link rel="apple-touch-icon" sizes="180x180" href="/lib/favicon/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/lib/favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="192x192" href="/lib/favicon/android-chrome-192x192.png"><link rel="icon" type="image/png" sizes="144x144" href="/lib/favicon/android-chrome-144x144.png"><link rel="icon" type="image/png" sizes="16x16" href="/lib/favicon/favicon-16x16.png"><link rel="manifest" href="/lib/favicon/site.webmanifest"><link rel="mask-icon" href="/lib/favicon/safari-pinned-tab.svg" color="#5bbad5"><meta name="apple-mobile-web-app-title" content="MHuiG Magicland"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="application-name" content="MHuiG Magicland"><meta name="msapplication-TileColor" content="#87ceeb"><meta name="msapplication-TileImage" content="/lib/favicon/mstile-144x144.png"><meta name="theme-color" content="#87ceeb" media="(prefers-color-scheme: light)"><meta name="theme-color" content="#21232f" media="(prefers-color-scheme: dark)"><link href="/opensearch.xml" rel="search" title="MHuiG Magicland" type="application/opensearchdescription+xml"><link rel="sitemap" type="application/xml" title="MHuiG Blog Site Map" href="https://blog.mhuig.top/sitemap.xml"><link rel="author" href="https://mhuig.top"><meta name="author" content="MHuiG"><meta name="creator" content="MHuiG"><link rel="archives" href="https://blog.mhuig.top/archives/"><link rel="preload" href="/css/style.css" as="style"><link rel="preload" href="https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/fonts/VarelaRound/VarelaRound-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous"><link rel="preload" href="https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/fonts/VarelaRound/VarelaRound-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous"><link rel="alternate" href="/atom.xml" title="Magicland" type="application/atom+xml"><link rel="alternate" href="/rss2.xml" title="Magicland" type="application/rss+xml"><title>Spark-快速大数据分析技术: 基于Audioscrobbler数据集的音乐推荐(pyspark) - Magicland</title><meta name="keywords" content="大数据,Spark, BigData,推荐系统,Data mining,ALS算法,音乐推荐系统,隐式反馈数据,ALS协同过滤,音乐推荐系统,PySpark,MHuiG, @MHuiG, Blog, 博客, Magicland, 魔法世界"><meta desc="" name="description" content="本文基于Audioscrobbler数据集(含14.1万用户、160万艺术家及2420万条播放记录),使用PySpark实现ALS协同过滤算法构建音乐推荐系统。通过交替最小二乘法处理隐式反馈数据,将用户-艺术家交互分解为矩阵乘积,设置rank=10、最大迭代15次,最终AUC评估达0.909,衡量推荐质量。 - MHuiG - Magicland"><meta property="og:type" content="website"><meta property="og:title" content="Magicland"><meta property="og:url" content="https://blog.mhuig.top/notes/Spark/als"><meta property="og:site_name" content="Magicland"><meta property="og:description" content="本文基于Audioscrobbler数据集(含14.1万用户、160万艺术家及2420万条播放记录),使用PySpark实现ALS协同过滤算法构建音乐推荐系统。通过交替最小二乘法处理隐式反馈数据,将用户-艺术家交互分解为矩阵乘积,设置rank=10、最大迭代15次,最终AUC评估达0.909,衡量推荐质量。"><meta property="og:locale"><meta property="og:image" content="https://blog.mhuig.top/lib/favicon/android-chrome-192x192.png"><meta property="article:published_time" content="2020-08-02T07:34:00.000Z"><meta property="article:modified_time" content="2025-11-20T10:18:00.000Z"><meta property="article:author" content="MHuiG"><meta property="article:tag" content="ALS协同过滤"><meta property="article:tag" content="ALS算法"><meta property="article:tag" content="BigData"><meta property="article:tag" content="Data mining"><meta property="article:tag" content="PySpark"><meta property="article:tag" content="推荐系统"><meta property="article:tag" content="隐式反馈数据"><meta property="article:tag" content="音乐推荐系统"><meta property="article:tag" content="音乐推荐系统"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://blog.mhuig.top/lib/favicon/android-chrome-192x192.png"><meta name="twitter:creator" content="@iMHuiG"><meta name="twitter:site" content="@iMHuiG"><style>#safearea{display:none}.post-story+.post-story{content-visibility:auto;contain-intrinsic-size:10px 500px}:root{--color-site-body:#87ceeb;--color-site-bg:#87ceeb;--color-site-inner:#555;--color-site-footer:#666;--color-card:#fff;--color-text:#444;--color-block:#f6f6f6;--color-inlinecode:#d56d28;--color-codeblock:#fff7ea;--color-h1:#3a3a3a;--color-h2:#3a3a3a;--color-h3:#333;--color-h4:#444;--color-h5:#555;--color-h6:#666;--color-p:#444;--color-list:#666;--color-list-hl:#1a78c2;--color-meta:#888;--color-read-bkg:#e0d8c8;--color-read-post:#f8f1e2;--color-copyright-bkg:#f5f5f5}*{box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;outline:0;margin:0;padding:0}::-webkit-scrollbar{height:4px;width:4px}::-webkit-scrollbar-track-piece{background:0 0}::-webkit-scrollbar-thumb{background:#2196f3;cursor:pointer;border-radius:2px;-webkit-border-radius:2px}::-webkit-scrollbar-thumb:hover{background:#ff5722}html{color:var(--color-text);width:100%;height:100%;font-family:"Varela Round","PingFang SC","Microsoft YaHei",Helvetica,Arial,Menlo,Monaco,monospace,sans-serif;font-size:16px}html>::-webkit-scrollbar{height:4px;width:4px}html>::-webkit-scrollbar-track-piece{background:0 0}html>::-webkit-scrollbar-thumb{background:#2196f3;cursor:pointer;border-radius:2px;-webkit-border-radius:2px}html>::-webkit-scrollbar-thumb:hover{background:#ff5722}body{background-color:var(--color-site-body);text-rendering:optimizelegibility;-webkit-tap-highlight-color:transparent;line-height:1.6;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body.modal-active{overflow:hidden}@media screen and (max-width:680px){body.modal-active{position:fixed;top:0;right:0;bottom:0;left:0}}a{color:#2196f3;cursor:pointer;text-decoration:none;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}a:hover{color:#ff5722}a:active,a:hover{outline:0}ol,ul{padding-left:0}ol li,ul li{list-style:none}header{display:-webkit-box;display:-moz-box;display:block}img{border:0;background:0 0;max-width:100%}svg:not(:root){overflow:hidden}hr{-moz-box-sizing:content-box;box-sizing:content-box;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;height:0;border:0;border-radius:1px;-webkit-border-radius:1px;border-bottom:1px solid rgba(68,68,68,.1)}button,input{color:inherit;font:inherit;margin:0}button{overflow:visible;text-transform:none;-webkit-appearance:button;cursor:pointer}@supports (backdrop-filter:blur(20px)){.blur{background:rgba(255,255,255,.9)!important;backdrop-filter:saturate(200%) blur(20px)}}.shadow{box-shadow:0 1px 2px 0 rgba(0,0,0,.1);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,.1)}.shadow.floatable{transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}.shadow.floatable:hover{box-shadow:0 2px 4px 0 rgba(0,0,0,.1),0 4px 8px 0 rgba(0,0,0,.1),0 8px 16px 0 rgba(0,0,0,.1);-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.1),0 4px 8px 0 rgba(0,0,0,.1),0 8px 16px 0 rgba(0,0,0,.1)}#l_cover{min-height:64px}.cover-wrapper{top:0;left:0;max-width:100%;height:100vh;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;flex-wrap:nowrap;-webkit-flex-wrap:nowrap;-khtml-flex-wrap:nowrap;-moz-flex-wrap:nowrap;-o-flex-wrap:nowrap;-ms-flex-wrap:nowrap;-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;align-items:center;align-self:center;align-content:center;color:var(--color-site-inner);padding:0 16px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;position:relative;overflow:hidden;margin-bottom:-100px}.cover-wrapper .cover-bg{position:absolute;width:100%;height:100%;background-position:center;background-size:cover;-webkit-background-size:cover;-moz-background-size:cover}.cover-wrapper .cover-bg.lazyload:not(.loaded){opacity:0;-webkit-opacity:0;-moz-opacity:0}.cover-wrapper .cover-bg.lazyload.loaded{animation-delay:0s;animation-duration:.5s;animation-fill-mode:forwards;animation-timing-function:ease-out;animation-name:fadeIn}@-moz-keyframes fadeIn{0%{opacity:0;-webkit-opacity:0;-moz-opacity:0;filter:blur(12px);transform:scale(1.02);-webkit-transform:scale(1.02);-khtml-transform:scale(1.02);-moz-transform:scale(1.02);-o-transform:scale(1.02);-ms-transform:scale(1.02)}100%{opacity:1;-webkit-opacity:1;-moz-opacity:1}}@-webkit-keyframes fadeIn{0%{opacity:0;-webkit-opacity:0;-moz-opacity:0;filter:blur(12px);transform:scale(1.02);-webkit-transform:scale(1.02);-khtml-transform:scale(1.02);-moz-transform:scale(1.02);-o-transform:scale(1.02);-ms-transform:scale(1.02)}100%{opacity:1;-webkit-opacity:1;-moz-opacity:1}}@-o-keyframes fadeIn{0%{opacity:0;-webkit-opacity:0;-moz-opacity:0;filter:blur(12px);transform:scale(1.02);-webkit-transform:scale(1.02);-khtml-transform:scale(1.02);-moz-transform:scale(1.02);-o-transform:scale(1.02);-ms-transform:scale(1.02)}100%{opacity:1;-webkit-opacity:1;-moz-opacity:1}}@keyframes fadeIn{0%{opacity:0;-webkit-opacity:0;-moz-opacity:0;filter:blur(12px);transform:scale(1.02);-webkit-transform:scale(1.02);-khtml-transform:scale(1.02);-moz-transform:scale(1.02);-o-transform:scale(1.02);-ms-transform:scale(1.02)}100%{opacity:1;-webkit-opacity:1;-moz-opacity:1}}.cover-wrapper .cover-body{z-index:1;position:relative;width:100%;height:100%}.cover-wrapper#full{height:calc(100vh + 100px);padding-bottom:100px}.cover-wrapper#half{max-height:640px;min-height:400px;height:calc(36vh - 64px + 200px)}.cover-wrapper #scroll-down{width:100%;height:64px;position:absolute;bottom:100px;text-align:center;cursor:pointer}.cover-wrapper #scroll-down .scroll-down-effects{color:#fff;font-size:24px;line-height:64px;position:absolute;width:24px;left:calc(50% - 12px);text-shadow:0 1px 2px rgba(0,0,0,.1);animation:scroll-down-effect 1.5s infinite;-webkit-animation:scroll-down-effect 1.5s infinite;-khtml-animation:scroll-down-effect 1.5s infinite;-moz-animation:scroll-down-effect 1.5s infinite;-o-animation:scroll-down-effect 1.5s infinite;-ms-animation:scroll-down-effect 1.5s infinite}@-moz-keyframes scroll-down-effect{0%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}50%{top:-16px;opacity:.4;-webkit-opacity:0.4;-moz-opacity:0.4}100%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}}@-webkit-keyframes scroll-down-effect{0%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}50%{top:-16px;opacity:.4;-webkit-opacity:0.4;-moz-opacity:0.4}100%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}}@-o-keyframes scroll-down-effect{0%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}50%{top:-16px;opacity:.4;-webkit-opacity:0.4;-moz-opacity:0.4}100%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}}@keyframes scroll-down-effect{0%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}50%{top:-16px;opacity:.4;-webkit-opacity:0.4;-moz-opacity:0.4}100%{top:0;opacity:1;-webkit-opacity:1;-moz-opacity:1}}.cover-wrapper .cover-body{margin-top:64px;margin-bottom:100px}.cover-wrapper .cover-body,.cover-wrapper .cover-body .bottom,.cover-wrapper .cover-body .top{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;align-items:center;justify-content:center;-webkit-justify-content:center;-khtml-justify-content:center;-moz-justify-content:center;-o-justify-content:center;-ms-justify-content:center;max-width:100%}.cover-wrapper .cover-body .bottom{margin-top:32px}.cover-wrapper .cover-body .title{font-family:"Varela Round","PingFang SC","Microsoft YaHei",Helvetica,Arial,Helvetica,monospace;font-size:3.125rem;line-height:1.2;text-shadow:0 1px 2px rgba(0,0,0,.1)}.cover-wrapper .cover-body .subtitle{font-size:20px}.cover-wrapper .cover-body .logo{max-height:120px;max-width:calc(100% - 4 * 16px)}@media screen and (min-height:1024px){.cover-wrapper .cover-body .title{font-size:3rem}.cover-wrapper .cover-body .subtitle{font-size:1.05rem}.cover-wrapper .cover-body .logo{max-height:150px}}.cover-wrapper .cover-body .m_search{position:relative;max-width:calc(100% - 16px);width:320px;vertical-align:middle}.cover-wrapper .cover-body .m_search .form{position:relative;display:-webkit-box;display:-moz-box;display:block;width:100%}.cover-wrapper .cover-body .m_search .icon,.cover-wrapper .cover-body .m_search .input{transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}.cover-wrapper .cover-body .m_search .icon{position:absolute;display:-webkit-box;display:-moz-box;display:block;line-height:2.5rem;width:32px;top:0;left:5px;color:rgba(68,68,68,.75)}.cover-wrapper .cover-body .m_search .input{display:-webkit-box;display:-moz-box;display:block;height:2.5rem;width:100%;box-shadow:none;-webkit-box-shadow:none;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;font-size:.875rem;-webkit-appearance:none;padding-left:36px;border-radius:1.4rem;-webkit-border-radius:1.4rem;background:rgba(255,255,255,.6);backdrop-filter:blur(10px);border:none;color:var(--color-text)}@media screen and (max-width:500px){.cover-wrapper .cover-body .m_search .input{padding-left:36px}}.cover-wrapper .cover-body .m_search .input:hover{background:rgba(255,255,255,.8)}.cover-wrapper .cover-body .m_search .input:focus{background:#fff}.cover-wrapper .list-h{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;flex-wrap:wrap;-webkit-flex-wrap:wrap;-khtml-flex-wrap:wrap;-moz-flex-wrap:wrap;-o-flex-wrap:wrap;-ms-flex-wrap:wrap;align-items:stretch;border-radius:4px;-webkit-border-radius:4px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.cover-wrapper .list-h a{-webkit-box-flex:1;-moz-box-flex:1;-webkit-flex:1 0;-ms-flex:1 0;flex:1 0;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;font-weight:600}.cover-wrapper .list-h a img{display:-webkit-box;display:-moz-box;display:block;border-radius:2px;-webkit-border-radius:2px;margin:4px;min-width:40px;max-width:44px}@media screen and (max-width:768px){.cover-wrapper .list-h a img{min-width:36px;max-width:40px}}@media screen and (max-width:500px){.cover-wrapper .list-h a img{margin:2px 4px;min-width:32px;max-width:36px}}@media screen and (max-width:375px){.cover-wrapper .list-h a img{min-width:28px;max-width:32px}}.cover-wrapper{max-width:100%}.cover-wrapper.search .bottom .menu{margin-top:16px}.cover-wrapper.search .bottom .menu .list-h a{white-space:nowrap;-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;align-items:baseline;padding:2px;margin:4px;color:var(--color-site-inner);opacity:.75;-webkit-opacity:0.75;-moz-opacity:0.75;text-shadow:0 1px 2px rgba(0,0,0,.05);border-bottom:2px solid transparent}.cover-wrapper.search .bottom .menu .list-h a i{margin-right:4px}.cover-wrapper.search .bottom .menu .list-h a p{font-size:.9375rem}.cover-wrapper.search .bottom .menu .list-h a.active,.cover-wrapper.search .bottom .menu .list-h a:active,.cover-wrapper.search .bottom .menu .list-h a:hover{opacity:1;-webkit-opacity:1;-moz-opacity:1;border-bottom:2px solid var(--color-site-inner)}.cover-wrapper.dock .menu,.cover-wrapper.featured .menu,.cover-wrapper.focus .menu{border-radius:6px;-webkit-border-radius:6px}.cover-wrapper.dock .menu .list-h a,.cover-wrapper.featured .menu .list-h a,.cover-wrapper.focus .menu .list-h a{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;align-items:center;padding:12px;line-height:24px;border-radius:4px;-webkit-border-radius:4px;border-bottom:none;text-align:center;align-content:flex-end;color:rgba(68,68,68,.7);font-size:1.5rem}@media screen and (max-width:500px){.cover-wrapper.dock .menu .list-h a,.cover-wrapper.featured .menu .list-h a,.cover-wrapper.focus .menu .list-h a{padding:12px 8px}}.cover-wrapper.dock .menu .list-h a i,.cover-wrapper.featured .menu .list-h a i,.cover-wrapper.focus .menu .list-h a i{margin:8px}.cover-wrapper.dock .menu .list-h a p,.cover-wrapper.featured .menu .list-h a p,.cover-wrapper.focus .menu .list-h a p{font-size:.875rem}.cover-wrapper.dock .menu .list-h a.active,.cover-wrapper.featured .menu .list-h a.active,.cover-wrapper.focus .menu .list-h a.active{background:var(--color-card);backdrop-filter:none}.cover-wrapper.dock .menu .list-h a.active i,.cover-wrapper.dock .menu .list-h a.active i+p,.cover-wrapper.featured .menu .list-h a.active i,.cover-wrapper.featured .menu .list-h a.active i+p,.cover-wrapper.focus .menu .list-h a.active i,.cover-wrapper.focus .menu .list-h a.active i+p{color:#2196f3}.cover-wrapper.dock .menu .list-h a.active img+p,.cover-wrapper.featured .menu .list-h a.active img+p,.cover-wrapper.focus .menu .list-h a.active img+p{color:var(--color-text)}.cover-wrapper.dock .menu .list-h a:hover,.cover-wrapper.featured .menu .list-h a:hover,.cover-wrapper.focus .menu .list-h a:hover{background:var(--color-card)}.cover-wrapper.featured .menu .list-h{margin:-2px}.cover-wrapper.featured .menu .list-h a{margin:2px;background:rgba(255,255,255,.5)}@supports (backdrop-filter:blur(20px)){.cover-wrapper.featured .menu .list-h a{background:rgba(255,255,255,.5);backdrop-filter:saturate(200%) blur(20px)}}@media (prefers-color-scheme:dark){:root{--color-mode:'dark'}:root:not([color-scheme]){--color-site-body:#121212;--color-read-bkg:#21232f;--color-read-post:#252d38;--color-site-bg:#21232f;--color-site-inner:#efefef;--color-site-footer:#666;--color-card:#252d38;--color-text:rgba(238,238,238,0.871);--color-block:rgba(68,68,68,0.65);--color-codeblock:#444;--color-inlinecode:#d56d28;--color-h1:rgba(255,255,255,0.871);--color-h2:rgba(255,255,255,0.871);--color-h3:rgba(255,255,255,0.6);--color-h4:rgba(255,255,255,0.6);--color-h5:rgba(255,255,255,0.6);--color-h6:rgba(255,255,255,0.6);--color-p:rgba(217,217,217,0.871);--color-list:rgba(217,217,217,0.871);--color-list-hl:#4dabf5;--color-meta:rgba(191,191,191,0.871);--color-link:rgba(191,191,191,0.871);--color-copyright-bkg:#21252b}:root:not([color-scheme]) img{filter:brightness(70%)!important}:root:not([color-scheme]) .blur{background:rgba(33,35,47,.9)!important}:root:not([color-scheme]) .white-box.blur{background:rgba(37,45,56,.9)!important}:root:not([color-scheme]) .nav-main .u-search-input{background:var(--color-card)!important}:root:not([color-scheme]) #l_main .article .prev-next>a{background:var(--color-block)!important}:root:not([color-scheme]) #l_main .article .prev-next>a:hover{background:var(--color-site-bg)!important}:root:not([color-scheme]) .article blockquote{background:var(--color-block)!important}:root:not([color-scheme]) .article-title a{color:var(--color-h1)!important}:root:not([color-scheme]) details>summary{color:var(--color-p)!important;background:var(--color-site-bg)!important}:root:not([color-scheme]) details{border:1px solid var(--color-site-bg)!important;background:var(--color-site-bg)!important}:root:not([color-scheme]) #u-search .modal,:root:not([color-scheme]) #u-search .modal-body,:root:not([color-scheme]) #u-search .modal-header{background:var(--color-card)!important}:root:not([color-scheme]) #u-search .modal-body .modal-results .result:hover{background:var(--color-block)!important}:root:not([color-scheme]) .u-search-input:hover{background:var(--color-block)!important}:root:not([color-scheme]) .u-search-input:focus{background:var(--color-site-body)!important}}[color-scheme=dark]{--color-site-body:#121212;--color-read-bkg:#21232f;--color-read-post:#252d38;--color-site-bg:#21232f;--color-site-inner:#efefef;--color-site-footer:#666;--color-card:#252d38;--color-text:rgba(238,238,238,0.871);--color-block:rgba(68,68,68,0.65);--color-codeblock:#444;--color-inlinecode:#d56d28;--color-h1:rgba(255,255,255,0.871);--color-h2:rgba(255,255,255,0.871);--color-h3:rgba(255,255,255,0.6);--color-h4:rgba(255,255,255,0.6);--color-h5:rgba(255,255,255,0.6);--color-h6:rgba(255,255,255,0.6);--color-p:rgba(217,217,217,0.871);--color-list:rgba(217,217,217,0.871);--color-list-hl:#4dabf5;--color-meta:rgba(191,191,191,0.871);--color-link:rgba(191,191,191,0.871);--color-copyright-bkg:#21252b}[color-scheme=dark] img{filter:brightness(70%)!important}[color-scheme=dark] .blur{background:rgba(33,35,47,.9)!important}[color-scheme=dark] .white-box.blur{background:rgba(37,45,56,.9)!important}[color-scheme=dark] .nav-main .u-search-input{background:var(--color-card)!important}[color-scheme=dark] #l_main .article .prev-next>a{background:var(--color-block)!important}[color-scheme=dark] #l_main .article .prev-next>a:hover{background:var(--color-site-bg)!important}[color-scheme=dark] .article blockquote{background:var(--color-block)!important}[color-scheme=dark] .article-title a{color:var(--color-h1)!important}[color-scheme=dark] details>summary{color:var(--color-p)!important;background:var(--color-site-bg)!important}[color-scheme=dark] details{border:1px solid var(--color-site-bg)!important;background:var(--color-site-bg)!important}[color-scheme=dark] #u-search .modal,[color-scheme=dark] #u-search .modal-body,[color-scheme=dark] #u-search .modal-header{background:var(--color-card)!important}[color-scheme=dark] #u-search .modal-body .modal-results .result:hover{background:var(--color-block)!important}[color-scheme=dark] .u-search-input:hover{background:var(--color-block)!important}[color-scheme=dark] .u-search-input:focus{background:var(--color-site-body)!important}@media screen and (max-width:500px){[color-scheme=dark] .l_header .m_search{background:var(--color-site-bg)!important}}@font-face{font-family:'Varela Round';src:url("https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/fonts/VarelaRound/VarelaRound-Regular.ttf");font-weight:'normal';font-style:'normal';font-display:swap}@font-face{font-family:'Varela Round';src:url("https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/fonts/VarelaRound/VarelaRound-Regular.ttf");font-weight:'normal';font-style:'normal';font-display:swap}.l_header{position:fixed;z-index:1000;top:0;width:100%;height:64px;background:var(--color-card);box-shadow:0 1px 2px 0 rgba(0,0,0,.1);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,.1)}.l_header.auto{transition:opacity .4s ease;-webkit-transition:opacity .4s ease;-khtml-transition:opacity 0.4s ease;-moz-transition:opacity .4s ease;-o-transition:opacity .4s ease;-ms-transition:opacity .4s ease;visibility:hidden}.l_header.auto.show{opacity:1!important;-webkit-opacity:1!important;-moz-opacity:1!important;visibility:visible}.l_header .container{margin-left:16px;margin-right:16px}.l_header #wrapper{height:100%;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.l_header #wrapper .nav-main,.l_header #wrapper .nav-sub{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;flex-wrap:nowrap;-webkit-flex-wrap:nowrap;-khtml-flex-wrap:nowrap;-moz-flex-wrap:nowrap;-o-flex-wrap:nowrap;-ms-flex-wrap:nowrap;justify-content:space-between;-webkit-justify-content:space-between;-khtml-justify-content:space-between;-moz-justify-content:space-between;-o-justify-content:space-between;-ms-justify-content:space-between;align-items:center}.l_header #wrapper .nav-main{transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}.l_header #wrapper.sub .nav-main{transform:translateY(-64px);-webkit-transform:translateY(-64px);-khtml-transform:translateY(-64px);-moz-transform:translateY(-64px);-o-transform:translateY(-64px);-ms-transform:translateY(-64px)}.l_header #wrapper .nav-sub{transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease;opacity:0;-webkit-opacity:0;-moz-opacity:0;height:64px;width:calc(100% - 2 * 16px);position:absolute}.l_header #wrapper .nav-sub ::-webkit-scrollbar{display:-webkit-box;display:-moz-box;display:none}@media screen and (min-width:2048px){.l_header #wrapper .nav-sub{max-width:55vw;margin:auto}}.l_header #wrapper.sub .nav-sub{opacity:1;-webkit-opacity:1;-moz-opacity:1}.l_header #wrapper .title{position:relative;color:var(--color-text);padding-left:24px;max-height:64px}.l_header #wrapper .nav-main .title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex-shrink:0;line-height:64px;padding:0 24px;font-size:1.25rem;font-family:"Varela Round","PingFang SC","Microsoft YaHei",Helvetica,Arial,Helvetica,monospace}.l_header #wrapper .nav-main .title img{height:64px}.l_header .nav-sub{max-width:1080px;margin:auto}.l_header .nav-sub .title{font-weight:700;font-family:"Varela Round","PingFang SC","Microsoft YaHei",Helvetica,Arial,Menlo,Monaco,monospace,sans-serif;line-height:1.2;max-height:64px;white-space:normal;flex-shrink:1}.l_header .switcher{display:-webkit-box;display:-moz-box;display:none;line-height:64px;align-items:center}.l_header .switcher .s-toc{display:-webkit-box;display:-moz-box;display:none}@media screen and (max-width:768px){.l_header .switcher .s-toc{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex}}.l_header .switcher>li{height:48px;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease;margin:2px}@media screen and (max-width:500px){.l_header .switcher>li{margin:0 1px;height:48px}}.l_header .switcher>li>a{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;justify-content:center;-webkit-justify-content:center;-khtml-justify-content:center;-moz-justify-content:center;-o-justify-content:center;-ms-justify-content:center;align-items:center;width:48px;height:48px;padding:.85em 1.1em;border-radius:100px;-webkit-border-radius:100px;border:none;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease;color:#2196f3}.l_header .switcher>li>a:hover{border:none}.l_header .switcher>li>a.active,.l_header .switcher>li>a:active{border:none;background:var(--color-site-bg)}@media screen and (max-width:500px){.l_header .switcher>li>a{width:36px;height:48px}}.l_header .nav-sub .switcher{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex}.l_header .m_search{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;height:64px;width:240px;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}@media screen and (max-width:1024px){.l_header .m_search{width:44px;min-width:44px}.l_header .m_search input::placeholder{opacity:0;-webkit-opacity:0;-moz-opacity:0}.l_header .m_search:hover{width:240px}.l_header .m_search:hover input::placeholder{opacity:1;-webkit-opacity:1;-moz-opacity:1}}@media screen and (min-width:500px){.l_header .m_search:hover .input{width:100%}.l_header .m_search:hover .input::placeholder{opacity:1;-webkit-opacity:1;-moz-opacity:1}}@media screen and (max-width:500px){.l_header .m_search{min-width:0}.l_header .m_search input::placeholder{opacity:1;-webkit-opacity:1;-moz-opacity:1}}.l_header .m_search .form{position:relative;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;width:100%;align-items:center}.l_header .m_search .icon{position:absolute;width:36px;left:5px;color:var(--color-meta)}@media screen and (max-width:500px){.l_header .m_search .icon{display:-webkit-box;display:-moz-box;display:none}}.l_header .m_search .input{display:-webkit-box;display:-moz-box;display:block;padding-top:8px;padding-bottom:8px;line-height:1.3;width:100%;color:var(--color-text);background:#fafafa;box-shadow:none;-webkit-box-shadow:none;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;padding-left:40px;font-size:.875rem;border-radius:8px;-webkit-border-radius:8px;border:none;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}@media screen and (min-width:500px){.l_header .m_search .input:focus{box-shadow:0 4px 8px 0 rgba(0,0,0,.1);-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.1)}}@media screen and (max-width:500px){.l_header .m_search .input{background:var(--color-block);padding-left:8px;border:none}.l_header .m_search .input:focus,.l_header .m_search .input:hover{border:none}}@media (max-width:500px){.l_header .m_search{left:0;width:0;overflow:hidden;position:absolute;background:#fff;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}.l_header .m_search .input{border-radius:32px;-webkit-border-radius:32px;margin-left:16px;padding-left:16px}.l_header.z_search-open .m_search{width:100%}.l_header.z_search-open .m_search .input{width:calc(100% - 120px)}}ul.m-pc>li>a{color:inherit;border-bottom:2px solid transparent}ul.m-pc>li>a.active,ul.m-pc>li>a:active{border-bottom:2px solid #2196f3}ul.list-v li:hover>ul.list-v,ul.m-pc li:hover>ul.list-v{display:-webkit-box;display:-moz-box;display:block}ul.nav-list-h{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;align-items:stretch}ul.nav-list-h>li{position:relative;justify-content:center;-webkit-justify-content:center;-khtml-justify-content:center;-moz-justify-content:center;-o-justify-content:center;-ms-justify-content:center;height:100%;line-height:2.4;border-radius:4px;-webkit-border-radius:4px}ul.nav-list-h>li>a{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:600}ul.list-v{z-index:1;display:-webkit-box;display:-moz-box;display:none;position:absolute;background:var(--color-card);box-shadow:0 2px 4px 0 rgba(0,0,0,.08),0 4px 8px 0 rgba(0,0,0,.08),0 8px 16px 0 rgba(0,0,0,.08);-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.08),0 4px 8px 0 rgba(0,0,0,.08),0 8px 16px 0 rgba(0,0,0,.08);margin-top:-6px;border-radius:4px;-webkit-border-radius:4px;padding:8px 0}ul.list-v.show{display:-webkit-box;display:-moz-box;display:block}ul.list-v hr{margin-top:8px;margin-bottom:8px}ul.list-v>li{white-space:nowrap;word-break:keep-all}ul.list-v>li.header{font-size:.78125rem;font-weight:700;line-height:2em;color:var(--color-meta);margin:8px 16px 4px}ul.list-v>li.header i{margin-right:8px}ul.list-v>li ul{margin-left:0;display:-webkit-box;display:-moz-box;display:none;margin-top:-40px}ul.list-v .aplayer-container{min-height:64px;padding:6px 16px}ul.list-v>li>a{transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease;display:-webkit-box;display:-moz-box;display:block;color:var(--color-list);font-size:.875rem;font-weight:700;line-height:36px;padding:0 20px 0 16px;text-overflow:ellipsis;margin:0 4px;border-radius:4px;-webkit-border-radius:4px}@media screen and (max-width:1024px){ul.list-v>li>a{line-height:40px}}ul.list-v>li>a>i{margin-right:8px}ul.list-v>li>a.active,ul.list-v>li>a:active{color:var(--color-list-hl)}ul.list-v>li>a:hover{color:var(--color-list-hl);background:var(--color-site-bg)}.l_header .menu>ul>li>a{display:-webkit-box;display:-moz-box;display:block;padding:0 8px}.l_header .menu>ul>li>a>i{margin-right:4px}.l_header ul.nav-list-h>li{color:var(--color-list);line-height:64px}.l_header ul.nav-list-h>li>a{max-height:64px;overflow:hidden;color:inherit}.l_header ul.nav-list-h>li>a.active,.l_header ul.nav-list-h>li>a:active{color:#2196f3}.l_header ul.nav-list-h>li:hover>a{color:var(--color-list-hl)}.l_header ul.nav-list-h>li i.music{animation:rotate-effect 1.5s linear infinite;-webkit-animation:rotate-effect 1.5s linear infinite;-khtml-animation:rotate-effect 1.5s linear infinite;-moz-animation:rotate-effect 1.5s linear infinite;-o-animation:rotate-effect 1.5s linear infinite;-ms-animation:rotate-effect 1.5s linear infinite}@-moz-keyframes rotate-effect{0%{transform:rotate(0);-webkit-transform:rotate(0);-khtml-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0)}25%{transform:rotate(90deg);-webkit-transform:rotate(90deg);-khtml-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg)}50%{transform:rotate(180deg);-webkit-transform:rotate(180deg);-khtml-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg)}75%{transform:rotate(270deg);-webkit-transform:rotate(270deg);-khtml-transform:rotate(270deg);-moz-transform:rotate(270deg);-o-transform:rotate(270deg);-ms-transform:rotate(270deg)}100%{transform:rotate(360deg);-webkit-transform:rotate(360deg);-khtml-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg)}}@-webkit-keyframes rotate-effect{0%{transform:rotate(0);-webkit-transform:rotate(0);-khtml-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0)}25%{transform:rotate(90deg);-webkit-transform:rotate(90deg);-khtml-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg)}50%{transform:rotate(180deg);-webkit-transform:rotate(180deg);-khtml-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg)}75%{transform:rotate(270deg);-webkit-transform:rotate(270deg);-khtml-transform:rotate(270deg);-moz-transform:rotate(270deg);-o-transform:rotate(270deg);-ms-transform:rotate(270deg)}100%{transform:rotate(360deg);-webkit-transform:rotate(360deg);-khtml-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg)}}@-o-keyframes rotate-effect{0%{transform:rotate(0);-webkit-transform:rotate(0);-khtml-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0)}25%{transform:rotate(90deg);-webkit-transform:rotate(90deg);-khtml-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg)}50%{transform:rotate(180deg);-webkit-transform:rotate(180deg);-khtml-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg)}75%{transform:rotate(270deg);-webkit-transform:rotate(270deg);-khtml-transform:rotate(270deg);-moz-transform:rotate(270deg);-o-transform:rotate(270deg);-ms-transform:rotate(270deg)}100%{transform:rotate(360deg);-webkit-transform:rotate(360deg);-khtml-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg)}}@keyframes rotate-effect{0%{transform:rotate(0);-webkit-transform:rotate(0);-khtml-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0)}25%{transform:rotate(90deg);-webkit-transform:rotate(90deg);-khtml-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg)}50%{transform:rotate(180deg);-webkit-transform:rotate(180deg);-khtml-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg)}75%{transform:rotate(270deg);-webkit-transform:rotate(270deg);-khtml-transform:rotate(270deg);-moz-transform:rotate(270deg);-o-transform:rotate(270deg);-ms-transform:rotate(270deg)}100%{transform:rotate(360deg);-webkit-transform:rotate(360deg);-khtml-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg)}}.menu-phone li ul.list-v{right:calc(100% - .5 * 16px)}.menu-phone li ul.list-v ul{right:calc(100% - .5 * 16px)}#wrapper{max-width:1080px;margin:auto}@media screen and (min-width:2048px){#wrapper{max-width:55vw}}#wrapper .menu{-webkit-box-flex:1;-moz-box-flex:1;-webkit-flex:1 1;-ms-flex:1 1;flex:1 1;margin:0 16px 0 0}#wrapper .menu .list-v ul{left:calc(100% - .5 * 16px)}.menu-phone{display:-webkit-box;display:-moz-box;display:none;margin-top:16px;right:8px;transition:all .28s ease;-webkit-transition:all .28s ease;-khtml-transition:all 0.28s ease;-moz-transition:all .28s ease;-o-transition:all .28s ease;-ms-transition:all .28s ease}.menu-phone ul{right:calc(100% - .5 * 16px)}@media screen and (max-width:500px){.menu-phone{display:-webkit-box;display:-moz-box;display:block}}.l_header{max-width:65vw;left:calc((100% - 65vw) * .5);border-bottom-left-radius:8px;border-bottom-right-radius:8px}@media screen and (max-width:2048px){.l_header{max-width:1112px;left:calc((100% - 1112px) * .5)}}@media screen and (max-width:1112px){.l_header{left:0;border-radius:0;-webkit-border-radius:0;max-width:100%}}@media screen and (max-width:500px){.l_header .container{margin-left:0;margin-right:0}.l_header #wrapper .nav-main .title{padding-left:16px;padding-right:16px}.l_header #wrapper .nav-sub{width:100%}.l_header #wrapper .nav-sub .title{overflow-y:scroll;margin-top:2px;padding:8px 16px}.l_header #wrapper .switcher{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;display:flex;margin-right:8px}.l_header .menu{display:-webkit-box;display:-moz-box;display:none}}@media screen and (max-width:500px){.list-v li{max-width:270px}}#u-search{display:-webkit-box;display:-moz-box;display:none;position:fixed;top:0;left:0;width:100%;height:100%;padding:60px 20px;z-index:1001}@media screen and (max-width:680px){#u-search{padding:0}}@media screen and (prefers-color-scheme:dark) and (max-width:500px){.l_header .m_search{background:var(--color-site-bg)!important}}.cover-wrapper .cover-body .subtitle{font-size:.875rem}.fa-brands.color-github,.fa-duotone.color-github,.fa-light.color-github,.fa-regular.color-github,.fa-solid.color-github,.fa-thin.color-github,.fa.color-github,.fad.color-github,.fal.color-github,.far.color-github,.fas.color-github,.iziToast>.iziToast-body .iziToast-icon.color-github{color:#000}.fa-brands.color-friends,.fa-duotone.color-friends,.fa-light.color-friends,.fa-regular.color-friends,.fa-solid.color-friends,.fa-thin.color-friends,.fa.color-friends,.fad.color-friends,.fal.color-friends,.far.color-friends,.fas.color-friends,.iziToast>.iziToast-body .iziToast-icon.color-friends{color:#d31ee9}.fa-brands.color-about,.fa-duotone.color-about,.fa-light.color-about,.fa-regular.color-about,.fa-solid.color-about,.fa-thin.color-about,.fa.color-about,.fad.color-about,.fal.color-about,.far.color-about,.fas.color-about,.iziToast>.iziToast-body .iziToast-icon.color-about{color:#0095ff}.fa-brands.color-travellings,.fa-duotone.color-travellings,.fa-light.color-travellings,.fa-regular.color-travellings,.fa-solid.color-travellings,.fa-thin.color-travellings,.fa.color-travellings,.fad.color-travellings,.fal.color-travellings,.far.color-travellings,.fas.color-travellings,.iziToast>.iziToast-body .iziToast-icon.color-travellings{color:#734ae6}mjx-container{padding:0 0!important}mjx-container:not([display=true]){padding:4px 2px 4px 6px!important}mjx-container[jax=SVG]{direction:ltr}mjx-container[jax=SVG]>svg{overflow:visible}mjx-container[jax=SVG][display=true]{display:-webkit-box;display:-moz-box;display:block;text-align:center;margin:1em 0}mjx-container[jax=SVG][justify=left]{text-align:left}mjx-container[jax=SVG][justify=right]{text-align:right}g[data-mml-node=merror]>g{fill:#f00;stroke:#f00}g[data-mml-node=merror]>rect[data-background]{fill:#ff0;stroke:none}g[data-mml-node=mtable]>line[data-line]{stroke-width:70px;fill:none}g[data-mml-node=mtable]>rect[data-frame]{stroke-width:70px;fill:none}g[data-mml-node=mtable]>.mjx-dashed{stroke-dasharray:140}g[data-mml-node=mtable]>.mjx-dotted{stroke-linecap:round;stroke-dasharray:0,140}g[data-mml-node=mtable]>svg{overflow:visible}[jax=SVG] mjx-tool{display:-webkit-box;display:-moz-box;display:inline-block;position:relative;width:0;height:0}[jax=SVG] mjx-tool>mjx-tip{position:absolute;top:0;left:0}mjx-tool>mjx-tip{display:-webkit-box;display:-moz-box;display:inline-block;padding:.2em;border:1px solid #888;font-size:70%;background-color:#f8f8f8;color:#000;box-shadow:2px 2px 5px #aaa;-webkit-box-shadow:2px 2px 5px #aaa}g[data-mml-node=maction][data-toggle]{cursor:pointer}mjx-status{display:-webkit-box;display:-moz-box;display:block;position:fixed;left:1em;bottom:1em;min-width:25%;padding:.2em .4em;border:1px solid #888;font-size:90%;background-color:#f8f8f8;color:#000}foreignObject[data-mjx-xml]{font-family:initial;line-height:normal;overflow:visible}.MathJax path{stroke-width:3}mjx-container[display=true]{overflow:auto hidden}mjx-container[display=true]+br{display:-webkit-box;display:-moz-box;display:none}</style><link rel="stylesheet" href="/css/style.css" media="print" onload='this.media="all",this.onload=null'><noscript><link rel="stylesheet" href="/css/style.css"></noscript><script>let userColorScheme=localStorage.getItem("color-scheme");userColorScheme&&document.documentElement.setAttribute("color-scheme",userColorScheme)</script><script>window.MSInputMethodContext&&document.documentMode&&document.write('<style>html{overflow-x: hidden !important;overflow-y: hidden !important;}.kill-ie{text-align:center;height: 100%;margin-top: 15%;margin-bottom: 5500%;}.kill-t{font-size: 2rem;}.kill-c{font-size: 1.2rem;}#l_header,#l_body{display: none;}</style><div class="kill-ie"><span class="kill-t"><b>抱歉,您的浏览器无法访问本站</b></span><br/><span class="kill-c">微软已经于2016年终止了对 Internet Explorer (IE) 10 及更早版本的支持,<br/>继续使用存在极大的安全隐患,请使用当代主流的浏览器进行访问。</span><br/><a target="_blank" rel="noopener" href="https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge/"><strong>了解详情 ></strong></a></div>')</script><noscript><style>html{overflow-x:hidden!important;overflow-y:hidden!important}.kill-noscript{text-align:center;height:100%;margin-top:15%;margin-bottom:5500%}.kill-t{font-size:2rem}.kill-c{font-size:1.2rem}#l_body,#l_header{display:none}</style><div class="kill-noscript"> <span class="kill-t"><b>抱歉,您的浏览器无法访问本站</b></span><br> <span class="kill-c">本页面需要浏览器支持(启用)JavaScript</span><br> <a target="_blank" rel="external nofollow noopener noreferrer" href="https://www.baidu.com/s?wd=启用JavaScript"><strong>了解详情 ></strong></a></div></noscript><script>function volantisEventListener(e,t,n){this.type=e,this.f=t,this.ele=n}function volantisDom(e){return e||(e=document.createElement("div")),this.ele=e,this.ele.find=e=>{let t=this.ele.querySelector(e);if(t)return new volantisDom(t)},this.ele.hasClass=e=>this.ele.className.match(new RegExp("(\\s|^)"+e+"(\\s|$)")),this.ele.addClass=e=>(this.ele.classList.add(e),this.ele),this.ele.removeClass=e=>(this.ele.classList.remove(e),this.ele),this.ele.toggleClass=e=>(this.ele.hasClass(e)?this.ele.removeClass(e):this.ele.addClass(e),this.ele),this.ele.on=(e,t,n=1)=>(this.ele.addEventListener(e,t,!1),n&&volantis.EventListener.list.push(new volantisEventListener(e,t,this.ele)),this.ele),this.ele.click=(e,t)=>(this.ele.on("click",e,t),this.ele),this.ele.scroll=(e,t)=>(this.ele.on("scroll",e,t),this.ele),this.ele.html=e=>(this.ele.innerHTML=e,this.ele),this.ele.hide=e=>(this.ele.style.display="none",this.ele),this.ele.show=e=>(this.ele.style.display="block",this.ele),this.ele}function RunItem(){function e(e,t){this.name=t||volantis.getFunctionHash(e),this.run=()=>{try{e()}catch(e){console.log(e)}}}this.list=[],this.start=()=>{for(var e=0;e<this.list.length;e++)this.list[e].run()},this.push=(t,n,o=!0)=>{if("function"!=typeof t)return;let l=t;o&&(l=()=>{volantis.requestAnimationFrame(t)}),n=n||volantis.getFunctionHash(t);const i=this.list.findIndex((e=>e.name===n));-1===i?this.list.push(new e(l,n)):this.list[i]=new e(l,n)},this.remove=e=>{for(let t=0;t<this.list.length;t++){this.list[t].name==e&&this.list.splice(t,1)}}}function errorImgAvatar(e){e.src="https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/placeholder/avatar/round/3442075.svg",e.onerror=null}function errorImgCover(e){e.src="https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/placeholder/cover/76b86c0226ffd.svg",e.onerror=null}!function(){const e=new WeakMap,t=new Proxy({},{get(n,o){const l=e.get(t);return l?.[o]},set(n,o,l){e.has(t)||e.set(t,Object.create(null));return e.get(t)[o]=l,!0},deleteProperty(n,o){const l=e.get(t);return!(!l||!Object.prototype.hasOwnProperty.call(l,o))&&(delete l[o],0===Object.keys(l).length&&e.delete(t),!0)},ownKeys(n){const o=e.get(t);return o?Object.keys(o):[]},getOwnPropertyDescriptor(n,o){const l=e.get(t);if(l&&Object.prototype.hasOwnProperty.call(l,o))return{value:l[o],writable:!0,enumerable:!0,configurable:!0}}});Object.defineProperty(window,"volantis",{value:t,writable:!0,configurable:!0,enumerable:!0})}(),volantis.debug="false",volantis.dom={},volantis.simpleTextHash=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n),t&=t;return t.toString(16).padStart(8,"0")},volantis.getFunctionHash=e=>{const t=e.toString();return volantis.simpleTextHash(t)},volantis.EventListener={},volantis.EventListener.list=[],volantis.EventListener.remove=()=>{volantis.EventListener.list.forEach((function(e){e.ele.removeEventListener(e.type,e.f,!1)})),volantis.EventListener.list=[]},volantis.dom.$=e=>e?new volantisDom(e):null,volantis.pjax={},volantis.pjax.method={complete:new RunItem,error:new RunItem,send:new RunItem},volantis.pjax=Object.assign(volantis.pjax,{push:volantis.pjax.method.complete.push,error:volantis.pjax.method.error.push,send:volantis.pjax.method.send.push}),volantis.rightmenu={},volantis.rightmenu.method={handle:new RunItem},volantis.rightmenu=Object.assign(volantis.rightmenu,{handle:volantis.rightmenu.method.handle.push}),volantis.dark={},volantis.dark.method={toggle:new RunItem},volantis.dark=Object.assign(volantis.dark,{push:volantis.dark.method.toggle.push}),volantis.js=(e,t)=>new Promise((n=>{setTimeout((function(){var o=document.getElementsByTagName("head")[0]||document.documentElement,l=document.createElement("script");if(l.setAttribute("type","text/javascript"),t)if(JSON.stringify(t))for(let e in t)"onload"==e?l[e]=()=>{t[e](),n()}:(l[e]=t[e],l.onload=n);else l.onload=()=>{t(),n()};else l.onload=n;l.setAttribute("src",e),o.appendChild(l)}))})),volantis.css=e=>new Promise((t=>{setTimeout((function(){var n=document.createElement("link");n.rel="stylesheet",n.href=e,n.onload=t,document.getElementsByTagName("head")[0].appendChild(n)}))})),volantis.import={jQuery:()=>"undefined"==typeof jQuery?volantis.js("https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"):new Promise((e=>{e()}))},volantis.throttle=(e,t=200)=>{let n=0;return function(...o){const l=Date.now();l-n>=t&&(e.apply(this,o),n=l)}},volantis.debounce=(e,t=200)=>{let n=null;return function(){n&&clearTimeout(n),n=setTimeout((()=>{e.apply(this,arguments),n=null}),t)}},volantis.requestAnimationFrame=e=>(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(e){return window.setTimeout(e,1e3/60)}),window.requestAnimationFrame(e)),volantis.layoutHelper=(e,t,n)=>{function o(e,t,n){volantis.tempDiv=document.createElement("div"),volantis.tempDiv.innerHTML=t;let o=document.querySelector("#layoutHelper-"+e);o&&(n&&(o.innerHTML=""),o.append(volantis.tempDiv))}n=Object.assign({clean:!1,pjax:!0},n),o(e,t,n.clean),n.pjax&&volantis.pjax.push((()=>{o(e,t,n.clean)}),"layoutHelper-"+e)},volantis.scroll={engine:new RunItem,unengine:new RunItem},volantis.scroll=Object.assign(volantis.scroll,{push:volantis.scroll.engine.push}),volantis.scroll.getScrollTop=()=>{let e;return window.pageYOffset?e=window.pageYOffset:document.compatMode&&"BackCompat"!=document.compatMode?e=document.documentElement.scrollTop:document.body&&(e=document.body.scrollTop),e},volantis.scroll.scrollHeight=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},volantis.scroll.offsetHeight=function(){return Math.min(document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},volantis.scroll.progress=function(){return volantis.scroll.getScrollTop()/(volantis.scroll.scrollHeight()-volantis.scroll.offsetHeight())},volantis.scroll.handleScrollEvents=()=>{volantis.scroll.lastScrollTop=volantis.scroll.getScrollTop(),volantis.requestAnimationFrame((function e(){const t=volantis.scroll.getScrollTop();volantis.scroll.lastScrollTop!==t?(volantis.scroll.del=t-volantis.scroll.lastScrollTop,volantis.scroll.lastScrollTop=t,volantis.scroll.unengine.list=[],volantis.scroll.engine.start()):volantis.scroll.unengine.start(),volantis.requestAnimationFrame(e)}))},volantis.scroll.handleScrollEvents(),volantis.scroll.ele=null,volantis.scroll.to=(e,t={})=>{e&&(volantis.scroll.ele=e,opt={top:e.getBoundingClientRect().top+document.documentElement.scrollTop,behavior:"smooth"},"top"in t&&(opt.top=t.top),"behavior"in t&&(opt.behavior=t.behavior),"addTop"in t&&(opt.top+=t.addTop),"observerDic"in t||(t.observerDic=100),window.scrollTo(opt),t.observer&&setTimeout((()=>{volantis.scroll.ele==e&&volantis.scroll.unengine.push((()=>{let n=e.getBoundingClientRect().top;n>=-t.observerDic&&n<=t.observerDic||volantis.scroll.to(e,t),volantis.scroll.unengine.remove("unengineObserver")}),"unengineObserver")}),1e3))},volantis.cleanContentVisibility=()=>{document.querySelector(".post-story")&&(console.log("cleanContentVisibility"),document.querySelectorAll(".post-story").forEach((e=>{e.classList.remove("post-story")})))};const nativeSetTimeout=window.setTimeout,nativeSetInterval=window.setInterval,nativeClearTimeout=window.clearTimeout,nativeClearInterval=window.clearInterval;volantis.activeTimeout=[],volantis.activeInterval=[],window.setTimeout=function(e,t,...n){const o=nativeSetTimeout((function(...t){try{return e.apply(this,t)}finally{const e=volantis.activeTimeout.indexOf(o);-1!==e&&volantis.activeTimeout.splice(e,1)}}),t,...n);return volantis.activeTimeout.push(o),o},window.setInterval=function(e,t,...n){const o=nativeSetInterval(e,t,...n);return volantis.activeInterval.push(o),o},window.clearTimeout=function(e){nativeClearTimeout(e);const t=volantis.activeTimeout.indexOf(e);-1!==t&&volantis.activeTimeout.splice(t,1)},window.clearInterval=function(e){nativeClearInterval(e);const t=volantis.activeInterval.indexOf(e);-1!==t&&volantis.activeInterval.splice(t,1)},volantis.getActiveInterval=function(){return[...volantis.activeInterval]},volantis.getActiveTimeout=function(){return[...volantis.activeTimeout]},volantis.clearAllTimers=function(){volantis.getActiveInterval().forEach((function(e){clearInterval(e)})),volantis.getActiveTimeout().forEach((function(e){clearTimeout(e)}))},volantis.pjax.send(volantis.clearAllTimers,"clearAllTimers")</script><script>volantis.GLOBAL_CONFIG={root:"/",debug:!1,default:{avatar:"https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/placeholder/avatar/round/3442075.svg",link:"https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/placeholder/link/8f277b4ee0ecd.svg",cover:"https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/placeholder/cover/76b86c0226ffd.svg",image:"https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/media/placeholder/image/2659360.svg"},lastupdate:new Date(1779510804521),cdn:{izitoast_css:"https://cdn.bootcdn.net/ajax/libs/izitoast/1.4.0/css/iziToast.min.css",izitoast_js:"https://cdn.bootcdn.net/ajax/libs/izitoast/1.4.0/js/iziToast.min.js",fancybox_css:"https://cdn.bootcdn.net/ajax/libs/fancyapps-ui/4.0.31/fancybox.min.css",fancybox_js:"https://cdn.bootcdn.net/ajax/libs/fancyapps-ui/4.0.31/fancybox.umd.min.js"},sidebar:{for_page:["blogger","navigation","webinfo"],for_post:["toc"],webinfo:{lastupd:{enable:!1,friendlyShow:!0},runtime:{data:"2019/08/19",unit:"天"}}},plugins:{message:{enable:!1,icon:{default:"fa-solid fa-info-circle light-blue",quection:"fa-solid fa-question-circle light-blue"},time:{default:5e3,quection:2e4},position:"topRight",transitionIn:"bounceInLeft",transitionOut:"fadeOutRight",titleColor:"var(--color-text)",messageColor:"var(--color-text)",backgroundColor:"var(--color-card)",zindex:2147483647,copyright:{enable:!0,title:"知识共享许可协议",message:"请遵守 CC BY-NC-SA 4.0 协议。",icon:"far fa-copyright light-blue"},aplayer:{enable:!0,play:"fa-solid fa-play",pause:"fa-solid fa-pause"},rightmenu:{enable:!0,notice:!0}},aplayer:{id:1480000098,enable:!0}},search:{dataPath:("/".endsWith("/")?"/":"//")+"content.json"},languages:{search:{hits_empty:"找不到您查询的内容:${query}",hits_stats:"找到 ${hits} 条结果,用时 ${time} 毫秒"}}}</script><script type="application/ld+json">[{"@context":"http://schema.org","@type":"Organization","name":"MHuiG Magicland","url":"https://blog.mhuig.top/","logo":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png","width":192,"height":192}},{"@context":"http://schema.org","@type":"Person","name":"MHuiG","image":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png"},"url":"https://blog.mhuig.top/","sameAs":["https://github.com/MHuiG","https://twitter.com/iMHuiG","https://t.me/MHuiG","https://keybase.io/MHuiG"],"description":"「Be Yourself, Make a Difference.」"},{"@context":"http://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"https://blog.mhuig.top/","name":"Magicland"}},{"@type":"ListItem","position":2,"item":{"@id":"https://blog.mhuig.top/categories/大数据/","name":"大数据"}},{"@type":"ListItem","position":2,"item":{"@id":"https://blog.mhuig.top/categories/大数据/Spark/","name":"Spark"}},{"@type":"ListItem","position":3,"item":{"@id":"https://blog.mhuig.top/notes/Spark/als.html","name":"基于Audioscrobbler数据集的音乐推荐(pyspark)"}}]},{"@context":"http://schema.org","@type":"WebSite","name":"MHuiG Magicland","url":"https://blog.mhuig.top/","keywords":"MHuiG, @MHuiG, Blog, 博客, Magicland, 魔法世界","description":"宠辱不惊,看庭前花开花落;去留无意,望天上云卷云舒。「Be Yourself, Make a Difference.」 - Magic Island","author":{"@type":"Person","name":"MHuiG","image":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png"},"url":"https://blog.mhuig.top/","description":"「Be Yourself, Make a Difference.」"},"publisher":{"@type":"Organization","name":"MHuiG Magicland","url":"https://blog.mhuig.top/","logo":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png","width":192,"height":192}},"potentialAction":{"@type":"SearchAction","name":"Coco | The Cat of MHuiG","target":{"@type":"EntryPoint","urlTemplate":"https://blog.mhuig.top/havefun/Coco/?s={search_term_string}"},"query-input":"required name=search_term_string"}},{"@context":"http://schema.org","@type":"BlogPosting","headline":"基于Audioscrobbler数据集的音乐推荐(pyspark)","description":"本文基于Audioscrobbler数据集(含14.1万用户、160万艺术家及2420万条播放记录),使用PySpark实现ALS协同过滤算法构建音乐推荐系统。通过交替最小二乘法处理隐式反馈数据,将用户-艺术家交互分解为矩阵乘积,设置rank=10、最大迭代15次,最终AUC评估达0.909,衡量推荐质量。","inLanguage":"zh-Hans","mainEntityOfPage":{"@type":"WebPage","@id":"https://blog.mhuig.top/notes/Spark/als"},"author":{"@type":"Person","name":"MHuiG","image":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png"},"url":"https://blog.mhuig.top/"},"publisher":{"@type":"Organization","name":"MHuiG Magicland","logo":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png","width":192,"height":192}},"url":"https://blog.mhuig.top/notes/Spark/als","wordCount":0,"datePublished":"2020-08-02T07:34:00.000Z","dateModified":"2025-11-20T10:18:00.000Z","articleSection":"大数据","keywords":"BigData,推荐系统,Data mining,ALS算法,音乐推荐系统,隐式反馈数据,ALS协同过滤,音乐推荐系统,PySpark","image":{"@type":"ImageObject","url":"/lib/favicon/android-chrome-192x192.png","width":192,"height":192}}]</script></head><body itemscope="" itemtype="http://schema.org/WebPage"><pjax></pjax><header itemscope="" itemtype="http://schema.org/WPHeader" id="l_header" class="l_header auto shadow floatable blur show" style="opacity:0"><div class="container"><div id="wrapper"><div class="nav-sub"><p class="title"></p><ul class="switcher nav-list-h m-phone" id="pjax-header-nav-list"><li><a id="s-comment" class="fa-solid fa-comments fa-fw" target="_self" title="comment"></a></li><li><a id="s-toc" class="s-toc fa-solid fa-list fa-fw" target="_self" title="toc"></a></li></ul></div><div class="nav-main"> <a class="title flat-box" target="_self" href="/">MHuiG</a><div class="menu navigation"><ul class="nav-list-h m-pc"><li><a class="menuitem flat-box faa-parent animated-hover" title="索引"><i class="fa-duotone fa-list-alt fa-fw"></i> 索引</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/notes/" title="便签" active-action="action-notes"><i class="fa-duotone fa-books fa-fw"></i> 便签</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" title="分类" active-action="action-categories"><i class="fa-duotone fa-folder-open fa-fw"></i> 分类</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" title="标签" active-action="action-tags"><i class="fa-duotone fa-tags fa-fw"></i> 标签</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" title="归档" active-action="action-archives"><i class="fa-duotone fa-archive fa-fw"></i> 归档</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/friends/" title="友链" active-action="action-pagesfriends"><i class="fa-duotone fa-link fa-fw"></i> 友链</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="https://www.travellings.cn/go-by-clouds.html" title="Travelling" target="_blank" active-action="action-https:wwwtravellingscngo-by-cloudshtml" rel="external nofollow noopener noreferrer"><i class="fa-duotone fa-subway fa-fw"></i> Travelling</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/about/" title="关于" active-action="action-pagesabout"><i class="fa-duotone fa-user-tie fa-fw"></i> 关于</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/time-machine/" title="时光机" active-action="action-pagestime-machine"><i class="fa-duotone fa-clock fa-fw"></i> 时光机</a></li><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="noopener" href="https://mhuig.top/privacy-policy/" title="隐私政策" active-action="action-https:mhuigtopprivacy-policy"><i class="fa-duotone fa-user-secret fa-fw"></i> 隐私政策</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover" title="更多"><i class="fa-duotone fa-fan fa-spin fa-fw"></i> 更多</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/beer/" title="Sponsor" active-action="action-pagesbeer"><i class="fa-duotone fa-heart-square fa-fw"></i> Sponsor</a></li><hr><li><a class="menuitem flat-box faa-parent animated-hover" title="博客管理"><i class="fa-duotone fa-user-shield fa-fw"></i> 博客管理</a><ul class="list-v"><li><a class="menuitem flat-box header toggle-mode-btn"><i class="fa-duotone fa-bat fa-fw"></i> 暗黑模式</a></li><li></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/rss/" title="RSS订阅" active-action="action-pagesrss"><i class="fa-duotone fa-rss fa-fw"></i> RSS订阅</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/sitemap.xml" title="站点地图" active-action="action-sitemapxml"><i class="fa-duotone fa-sitemap fa-fw"></i> 站点地图</a></li><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://mhuig.instatus.com/" title="Monitors" active-action="action-https:mhuiginstatuscom"><i class="fa-duotone fa-telescope fa-fw"></i> Monitors</a></li><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://ssl.mhuig.top/" title="SSL Status" active-action="action-https:sslmhuigtop"><i class="fa-brands fa-expeditedssl fa-fw"></i> SSL Status</a></li></ul></li><hr><li><a class="menuitem flat-box faa-parent animated-hover" title="工具箱"><i class="fa-duotone fa-tools fa-fw"></i> 工具箱</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://rssbox.mhuig.top/" title="RSS Box" active-action="action-https:rssboxmhuigtop"><i class="fa-duotone fa-conveyor-belt-boxes fa-fw"></i> RSS Box</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/havefun/Coco/" title="My Cat" active-action="action-havefunCoco"><i class="fa-duotone fa-cat fa-fw"></i> My Cat</a></li><li><a class="menuitem flat-box"><i class="fa-duotone fa-compact-disc fa-spin fa-fw music"></i> Music</a><ul class="list-v"><li><div class="aplayer-container"><div class="aplayer-local"></div></div></li></ul></li><li></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/talk/" title="碎言碎语" active-action="action-pagestalk"><i class="fa-duotone fa-comments fa-fw"></i> 碎言碎语</a></li></ul></li><hr><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://github.com/MHuiG" title="GitHub" active-action="action-https:githubcomMHuiG"><i class="fa-brands fa-github fa-fw"></i> GitHub</a></li></ul></li></ul></div><div class="m_search"><form name="searchform" class="form u-search-form"><i class="icon fa-solid fa-search fa-fw"></i> <input type="text" class="input u-search-input" placeholder="Search..."></form></div><ul class="switcher nav-list-h m-phone"><li><a class="s-search fa-solid fa-search fa-fw" target="_self" title="search"></a></li><li><a class="s-menu fa-solid fa-bars fa-fw" target="_self" title="menu"></a><ul class="menu-phone list-v navigation white-box"><li><a class="menuitem flat-box faa-parent animated-hover" title="索引"><i class="fa-duotone fa-list-alt fa-fw"></i> 索引</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/notes/" title="便签" active-action="action-notes"><i class="fa-duotone fa-books fa-fw"></i> 便签</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" title="分类" active-action="action-categories"><i class="fa-duotone fa-folder-open fa-fw"></i> 分类</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" title="标签" active-action="action-tags"><i class="fa-duotone fa-tags fa-fw"></i> 标签</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" title="归档" active-action="action-archives"><i class="fa-duotone fa-archive fa-fw"></i> 归档</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/friends/" title="友链" active-action="action-pagesfriends"><i class="fa-duotone fa-link fa-fw"></i> 友链</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="https://www.travellings.cn/go-by-clouds.html" title="Travelling" target="_blank" active-action="action-https:wwwtravellingscngo-by-cloudshtml" rel="external nofollow noopener noreferrer"><i class="fa-duotone fa-subway fa-fw"></i> Travelling</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/about/" title="关于" active-action="action-pagesabout"><i class="fa-duotone fa-user-tie fa-fw"></i> 关于</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/time-machine/" title="时光机" active-action="action-pagestime-machine"><i class="fa-duotone fa-clock fa-fw"></i> 时光机</a></li><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="noopener" href="https://mhuig.top/privacy-policy/" title="隐私政策" active-action="action-https:mhuigtopprivacy-policy"><i class="fa-duotone fa-user-secret fa-fw"></i> 隐私政策</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover" title="更多"><i class="fa-duotone fa-fan fa-spin fa-fw"></i> 更多</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/beer/" title="Sponsor" active-action="action-pagesbeer"><i class="fa-duotone fa-heart-square fa-fw"></i> Sponsor</a></li><hr><li><a class="menuitem flat-box faa-parent animated-hover" title="博客管理"><i class="fa-duotone fa-user-shield fa-fw"></i> 博客管理</a><ul class="list-v"><li><a class="menuitem flat-box header toggle-mode-btn"><i class="fa-duotone fa-bat fa-fw"></i> 暗黑模式</a></li><li></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/rss/" title="RSS订阅" active-action="action-pagesrss"><i class="fa-duotone fa-rss fa-fw"></i> RSS订阅</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/sitemap.xml" title="站点地图" active-action="action-sitemapxml"><i class="fa-duotone fa-sitemap fa-fw"></i> 站点地图</a></li><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://mhuig.instatus.com/" title="Monitors" active-action="action-https:mhuiginstatuscom"><i class="fa-duotone fa-telescope fa-fw"></i> Monitors</a></li><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://ssl.mhuig.top/" title="SSL Status" active-action="action-https:sslmhuigtop"><i class="fa-brands fa-expeditedssl fa-fw"></i> SSL Status</a></li></ul></li><hr><li><a class="menuitem flat-box faa-parent animated-hover" title="工具箱"><i class="fa-duotone fa-tools fa-fw"></i> 工具箱</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://rssbox.mhuig.top/" title="RSS Box" active-action="action-https:rssboxmhuigtop"><i class="fa-duotone fa-conveyor-belt-boxes fa-fw"></i> RSS Box</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/havefun/Coco/" title="My Cat" active-action="action-havefunCoco"><i class="fa-duotone fa-cat fa-fw"></i> My Cat</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/pages/talk/" title="碎言碎语" active-action="action-pagestalk"><i class="fa-duotone fa-comments fa-fw"></i> 碎言碎语</a></li></ul></li><hr><li><a class="menuitem flat-box faa-parent animated-hover" target="_blank" rel="external nofollow noopener noreferrer" href="https://github.com/MHuiG" title="GitHub" active-action="action-https:githubcomMHuiG"><i class="fa-brands fa-github fa-fw"></i> GitHub</a></li></ul></li></ul></li></ul></div></div></div></header><div id="l_body"><div id="l_cover"><div id="none" class="cover-wrapper docs featured" style="display:none"><div class="cover-bg lazyload placeholder" data-bg=""></div><div class="cover-body"><div class="top"><p class="title">Magicland</p><p class="subtitle">「看庭前花开花落,望天上云卷云舒」</p></div><div class="bottom"><div class="menu navigation"><div class="list-h"><a target="_blank" rel="external nofollow noopener noreferrer" href="https://github.com/MHuiG" active-action="action-https:githubcomMHuiG"><i class="fa-brands fa-github color-github fa-fw"></i><p>Github</p></a><a href="/pages/friends/" active-action="action-pagesfriends"><i class="fa-duotone fa-link color-friends fa-fw"></i><p>友链</p></a><a href="/pages/about/" active-action="action-pagesabout"><i class="fa-duotone fa-user-tie color-about fa-fw"></i><p>关于</p></a><a href="https://www.travellings.cn/go-by-clouds.html" target="_blank" active-action="action-https:wwwtravellingscngo-by-cloudshtml" rel="external nofollow noopener noreferrer"><i class="fa-duotone fa-subway color-travellings fa-fw"></i><p>Travelling</p></a></div></div></div></div><div id="scroll-down" style="display:none"><i class="fa fa-chevron-down scroll-down-effects"></i></div></div></div><div id="safearea"><div class="body-wrapper"><div id="l_main" class=""><article itemscope="" itemtype="http://schema.org/Article" class="article post white-box reveal md shadow floatable blur article-type-docs" id="docs" itemprop="blogPost"><link itemprop="mainEntityOfPage" href="https://blog.mhuig.top/notes/Spark/als"><span hidden="" itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization"><meta itemprop="name" content="Magicland"></span><span hidden="" itemprop="post" itemscope="" itemtype="http://schema.org/CreativeWork"><meta itemprop="name" content="基于Audioscrobbler数据集的音乐推荐(pyspark)"><meta itemprop="description" content="本文基于Audioscrobbler数据集(含14.1万用户、160万艺术家及2420万条播放记录),使用PySpark实现ALS协同过滤算法构建音乐推荐系统。通过交替最小二乘法处理隐式反馈数据,将用户-艺术家交互分解为矩阵乘积,设置rank=10、最大迭代15次,最终AUC评估达0.909,衡量推荐质量。"></span><span hidden=""><meta itemprop="image" content="/lib/favicon/android-chrome-192x192.png"></span><div class="article-meta" id="top"><span hidden="" itemprop="name headline"></span></div><div id="layoutHelper-page-plugins"></div><div id="post-body" itemprop="articleBody"><p> <span class="p logo center large">ALS</span></p><br><h1 hidden="">基于 Audioscrobbler 数据集的音乐推荐 (pyspark)</h1><p>根据用户播放次数数据使用协同过滤算法完成音乐推荐。</p><div class="story post-story"><h2 id="数据集"><a href="#数据集" class="headerlink" title="数据集"></a>数据集</h2><p>Audioscrobbler 数据集</p><span class="btn center large"><a class="button" target="_blank" rel="external nofollow noopener noreferrer" href="/go.html?u=aHR0cDovL3d3dy5pcm8udW1vbnRyZWFsLmNhL35saXNhL2RhdGFzZXRzL3Byb2ZpbGVkYXRhXzA2LU1heS0yMDA1LnRhci5neg" title="下载 Audioscrobbler 数据集"><i class="fas fa-download"></i> 下载 Audioscrobbler 数据集</a></span><h3 id="user-artist-data-txt"><a href="#user-artist-data-txt" class="headerlink" title="user_artist_data.txt"></a><strong>user_artist_data.txt</strong></h3><p>它包含 141000 个用户和 160 万个艺术家,记录了约 2420 万条用户播放艺术家歌曲的信息,其中包括播放次数信息。播放次数较多意味着该用户更喜欢对应艺术家的作品。</p><table><thead><tr><th><strong>userid</strong></th><th><strong>artistid</strong></th><th><strong>playcount</strong></th></tr></thead><tbody><tr><td>用户 ID</td><td>艺术家 ID</td><td>播放次数</td></tr><tr><td>1000002</td><td>1</td><td>55</td></tr></tbody></table><h3 id="artist-data-txt"><a href="#artist-data-txt" class="headerlink" title="artist_data.txt"></a><strong>artist_data.txt</strong></h3><p>该文件包含两列: artistid artist_name 艺术家 ID 艺术家名字。文件中给出了每个艺术家的 ID 和对应的名字。此文件用于 ID 与名字的转换。</p><table><thead><tr><th><strong>artistid</strong></th><th><strong>artist_name</strong></th></tr></thead><tbody><tr><td>艺术家 ID</td><td>艺术家名</td></tr><tr><td>1134999</td><td>06Crazy Life</td></tr></tbody></table><h3 id="artist-alias-txt"><a href="#artist-alias-txt" class="headerlink" title="artist_alias.txt"></a><strong>artist_alias.txt</strong></h3><p>该文件包含两列: badid, goodid 坏 ID 好 ID 。该文件包含已知错误拼写的艺术家 ID 及其对应艺术家的正规的,用于将拼写错误的艺术家 ID 或 ID 变体对应到该艺术家正确的 ID。</p><table><thead><tr><th><strong>badid</strong></th><th><strong>goodid</strong></th></tr></thead><tbody><tr><td>坏 ID</td><td>好 ID</td></tr><tr><td>1092764</td><td>1000311</td></tr></tbody></table></div><div class="story post-story"><h2 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h2><h3 id="交替最小二乘推荐算法-Alternating-Least-Squares,ALS"><a href="#交替最小二乘推荐算法-Alternating-Least-Squares,ALS" class="headerlink" title="交替最小二乘推荐算法 (Alternating Least Squares,ALS)"></a><strong>交替最小二乘推荐算法 (Alternating Least Squares,ALS)</strong></h3><p>人们虽然经常听音乐,但很少给音乐评分。因此 Audioscrobbler 数据集覆盖了更多的用户和艺术家,也包含了更多的总体信息,虽然单条记录的信息比较少。这种类型的数据通常被称为隐式反馈数据,因为用户和艺术家的关系是通过其他行动隐含体现出来的,而不是通过显式的评分或点赞得到的。</p><p>根据两个用户的相似行为判断他们有相同的偏好,学习算法不需要用户和艺术家的属性信息。这类算法通常称为<strong>协同过滤算法</strong>。</p><p><strong>潜在因素模型</strong>:试图通过数据相对少的未被观察到的底层原因,来解释大量用户和产品之间可观察到的交互。因子分析方法背后的理论是,有关观测变量之间的相互依赖性的信息可以稍后用于减少数据集中的变量集。</p><p><strong>矩阵分解模型</strong>:数学上,算法把用户和产品数据当成一个大矩阵 R,矩阵第 i 行和第 j 列上的元素有值,代表用户 i 播放过艺术家 j 的音乐。矩阵 R 是稀疏的:R 中大多数元素都是 0,因为相对于所有可能的用户 - 艺术家组合,只有很少一部分组合会出现在数据中。算法将 R 分解为两个小矩阵 U 和 P 的乘积。矩阵 U 和矩阵 P 非常 “瘦”。因为 A 有很多行和列,但 U 和 P 的行很多而列很少(列数用 k 表示)。这 k 个列就是潜在因素,用于解释数据中的交互关系。由于 k 的值小,矩阵分解算法只能是某种近似。</p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992482915/202082144833.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992482915/202082144833.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="矩阵分解模型"></p><p>为了使低秩矩阵 P 和 U 尽可能的逼近 R,可以通过最小化如下损失函数 L 来完成。</p><p><mjx-container class="MathJax" jax="SVG" overflow="overflow" display="true" width="full" style="min-width:54.368ex"><svg style="vertical-align:-2.021ex;min-width:54.368ex" xmlns="http://www.w3.org/2000/svg" width="100%" height="5.173ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -1393.2)"><g data-mml-node="math" data-latex="
L(U,P)=\sum_{i,J}(r_{ij}-u_i^TP_j)^2+λ(|u_i|^2+|p_j|^2)^2
"><g data-mml-node="mtable" data-latex="
L(U,P)=\sum_{i,J}(r_{ij}-u_i^TP_j)^2 +λ(|u_i|^2 +|p_j|^2 )^2 
" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 1393.2) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveAspectRatio="xMidYMid" viewBox="9937.2 -1393.2 1 2286.4"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr" transform="translate(0,443.2)"><g data-mml-node="mtd"><g data-mml-node="mi" data-latex="L"><path data-c="1D43F" d="M520 667C520 678 513 683 500 683L354 680 223 683C208 684 200 676 200 659 200 652 203 647 209 646 218 645 226 644 231 644 262 643 279 641 284 640 289 639 292 636 292 631 292 629 291 623 288 613L156 82C150 60 140 47 125 42 119 40 101 39 70 39 49 39 39 31 39 15 39 5 49 0 70 0L527 0C552 0 554 0 561 19L639 233C642 240 643 245 643 248 643 258 638 263 627 263 617 263 612 254 607 240 588 191 570 154 555 131 518 75 455 39 363 39L270 39C259 39 252 39 249 40 242 40 239 42 239 45 239 47 241 54 244 67L377 601C383 624 396 637 415 642 421 643 442 644 478 644 506 644 520 644 520 667Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(681,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="mi" data-latex="U" transform="translate(1070,0)"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mo" data-latex="," transform="translate(1830,0)"><path data-c="2C" d="M139 106C107 106 86 82 86 50 86 20 109-5 139-5 153-5 165-1 174 8L175 0C175-63 154-117 112-160 105-168 101-174 101-178 101-188 105-193 114-193 123-193 135-181 152-158 186-110 203-57 203 0 203 53 185 106 139 106Z"></path></g><g data-mml-node="mi" data-latex="P" transform="translate(2274.7,0)"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mo" data-latex=")" transform="translate(3028.7,0)"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g><g data-mml-node="mo" data-latex="=" transform="translate(3695.4,0)"><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="munder" data-latex="\sum_{i,J}" transform="translate(4751.2,0)"><g data-mml-node="mo" data-latex="\sum"><path data-c="2211" d="M1265-450 1389-124 1355-124C1336-174 1304-216 1258-250 1145-334 1000-356 791-356L200-356 700 232C707 239 710 246 710 251L244 894 781 894C970 894 1127 870 1230 804 1290 766 1332 719 1356 663L1389 663 1265 950 88 950C70 950 60 947 57 941 56 938 56 926 56 905L581 187 68-415C61-423 57-430 57-435 57-445 67-450 88-450Z"></path></g><g data-mml-node="TeXAtom" transform="translate(277.9,-1100) scale(0.707)" data-latex="{i,J}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g><g data-mml-node="mo" data-latex="," transform="translate(345,0)"><path data-c="2C" d="M139 106C107 106 86 82 86 50 86 20 109-5 139-5 153-5 165-1 174 8L175 0C175-63 154-117 112-160 105-168 101-174 101-178 101-188 105-193 114-193 123-193 135-181 152-158 186-110 203-57 203 0 203 53 185 106 139 106Z"></path></g><g data-mml-node="mi" data-latex="J" transform="translate(623,0)"><path data-c="1D43D" d="M633 667C633 678 627 683 615 683 596 683 525 680 506 680L361 683C344 683 336 675 336 659 336 649 349 644 374 644 419 644 446 642 453 637 456 635 457 632 457 627 457 624 456 617 454 607L340 153C324 89 273 8 202 8 157 8 128 25 114 60L120 60C156 60 188 91 188 127 188 158 172 173 141 173 97 173 71 134 71 90 71 20 132-22 205-22 255-22 301-6 344 26 387 58 415 97 427 144L542 606C551 642 555 644 602 644 623 644 633 646 633 667Z"></path></g></g></g><g data-mml-node="mo" data-latex="(" transform="translate(6195.2,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="msub" data-latex="r_{i j}" transform="translate(6584.2,0)"><g data-mml-node="mi" data-latex="r"><path data-c="1D45F" d="M436 374C436 416 395 442 351 442 302 442 261 419 227 372 217 411 183 442 136 442 95 442 65 410 44 345 34 312 29 293 29 287 29 278 34 273 45 273 50 273 53 274 56 276 61 285 64 292 65 299 83 375 106 413 133 413 150 413 159 399 159 371 159 358 154 331 144 290L87 63C84 50 78 24 78 19 78-1 89-11 110-11 130-11 143-1 150 19L169 91C180 134 187 162 190 175L221 303C223 311 231 324 244 343 271 381 302 413 351 413 363 413 373 411 382 406 352 397 337 378 337 351 337 325 351 312 378 312 411 312 436 341 436 374Z"></path></g><g data-mml-node="TeXAtom" transform="translate(484,-150) scale(0.707)" data-latex="{i j}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g><g data-mml-node="mi" data-latex="j" transform="translate(345,0)"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g></g><g data-mml-node="mo" data-latex="-" transform="translate(7875.7,0)"><path data-c="2212" d="M698 270 80 270C64 270 56 263 56 250 56 237 64 230 80 230L698 230C714 230 722 237 722 250 722 262 710 270 698 270Z"></path></g><g data-mml-node="msubsup" data-latex="u_i^T" transform="translate(8875.9,0)"><g data-mml-node="mi" data-latex="u"><path data-c="1D462" d="M543 144C543 153 538 158 527 158 518 158 513 151 510 137 505 118 500 99 493 80 480 39 462 18 440 18 422 18 413 32 413 60 413 77 420 111 433 161L460 267C469 303 477 328 483 359L489 386C491 393 492 398 492 401 492 421 481 431 459 431 437 431 423 419 417 394L343 98C342 95 338 88 330 76 314 50 275 18 235 18 197 18 178 44 178 95 178 136 196 202 231 294 242 324 248 345 248 357 248 407 213 442 163 442 118 442 83 417 58 367 39 328 29 301 29 287 29 278 34 273 45 273 58 273 60 279 64 293 87 373 119 413 160 413 174 413 181 403 181 384 181 369 175 348 164 319 126 218 107 148 107 111 107 34 155-11 232-11 275-11 314 9 347 50 361 9 391-11 437-11 506-11 527 70 543 144Z"></path></g><g data-mml-node="mi" transform="translate(605,413) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g><g data-mml-node="mi" transform="translate(605,-247) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g><g data-mml-node="msub" data-latex="P_j" transform="translate(10028.7,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(675,-150) scale(0.707)" data-latex="j"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g><g data-mml-node="msup" data-latex=")^2" transform="translate(11045.1,0)"><g data-mml-node="mo" data-latex=")"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g><g data-mml-node="mn" transform="translate(422,413) scale(0.707)" data-latex="2"><path data-c="32" d="M237 666C186 666 143 648 106 612 69 576 50 534 50 483 50 449 75 424 106 424 136 424 161 450 161 480 161 513 137 536 105 536 102 536 100 536 98 535 117 584 161 627 224 627 306 627 352 556 352 470 352 403 318 331 250 255L62 43C49 28 50 29 50 0L421 0 450 180 417 180C409 129 402 100 396 91 391 86 361 84 306 84L139 84 236 179C304 243 390 312 419 365 439 400 449 435 449 470 449 588 357 666 237 666Z"></path></g></g><g data-mml-node="mo" data-latex="+" transform="translate(12092.9,0)"><path data-c="2B" d="M698 274 413 274 413 559C413 575 405 583 389 583 373 583 365 575 365 559L365 274 80 274C64 274 56 266 56 250 56 234 64 226 80 226L365 226 365-59C365-75 373-83 389-83 405-83 413-75 413-59L413 226 698 226C714 226 722 234 722 250 722 263 711 274 698 274Z"></path></g><g data-mml-node="mi" data-latex="λ" transform="translate(13093.1,0)"><path data-c="1D706" d="M86-13C97-13 109-6 122 9L355 285C390 189 416 117 433 68 444 37 451 19 456 12 467-3 486-11 512-11L533-11C543-10 548-6 548 3 548 5 546 9 542 14 535 21 528 36 520 59L319 621C302 670 261 694 196 694 181 694 174 689 174 679 174 672 180 667 191 664 205 660 214 655 219 649 226 641 236 621 247 589L342 322 72 53C59 40 53 29 53 20 53 2 68-13 86-13Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(13676.1,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="mo" data-latex="|" transform="translate(14065.1,0)"><path data-c="7C" d="M139-250C152-250 159-242 159-226L159 726C159 742 152 750 139 750 126 750 119 742 119 726L119-226C119-242 126-250 139-250Z"></path></g><g data-mml-node="msub" data-latex="u_i" transform="translate(14343.1,0)"><g data-mml-node="mi" data-latex="u"><path data-c="1D462" d="M543 144C543 153 538 158 527 158 518 158 513 151 510 137 505 118 500 99 493 80 480 39 462 18 440 18 422 18 413 32 413 60 413 77 420 111 433 161L460 267C469 303 477 328 483 359L489 386C491 393 492 398 492 401 492 421 481 431 459 431 437 431 423 419 417 394L343 98C342 95 338 88 330 76 314 50 275 18 235 18 197 18 178 44 178 95 178 136 196 202 231 294 242 324 248 345 248 357 248 407 213 442 163 442 118 442 83 417 58 367 39 328 29 301 29 287 29 278 34 273 45 273 58 273 60 279 64 293 87 373 119 413 160 413 174 413 181 403 181 384 181 369 175 348 164 319 126 218 107 148 107 111 107 34 155-11 232-11 275-11 314 9 347 50 361 9 391-11 437-11 506-11 527 70 543 144Z"></path></g><g data-mml-node="mi" transform="translate(605,-150) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g><g data-mml-node="msup" data-latex="|^2" transform="translate(15242,0)"><g data-mml-node="mo" data-latex="|"><path data-c="7C" d="M139-250C152-250 159-242 159-226L159 726C159 742 152 750 139 750 126 750 119 742 119 726L119-226C119-242 126-250 139-250Z"></path></g><g data-mml-node="mn" transform="translate(311,413) scale(0.707)" data-latex="2"><path data-c="32" d="M237 666C186 666 143 648 106 612 69 576 50 534 50 483 50 449 75 424 106 424 136 424 161 450 161 480 161 513 137 536 105 536 102 536 100 536 98 535 117 584 161 627 224 627 306 627 352 556 352 470 352 403 318 331 250 255L62 43C49 28 50 29 50 0L421 0 450 180 417 180C409 129 402 100 396 91 391 86 361 84 306 84L139 84 236 179C304 243 390 312 419 365 439 400 449 435 449 470 449 588 357 666 237 666Z"></path></g></g><g data-mml-node="mo" data-latex="+" transform="translate(16178.8,0)"><path data-c="2B" d="M698 274 413 274 413 559C413 575 405 583 389 583 373 583 365 575 365 559L365 274 80 274C64 274 56 266 56 250 56 234 64 226 80 226L365 226 365-59C365-75 373-83 389-83 405-83 413-75 413-59L413 226 698 226C714 226 722 234 722 250 722 263 711 274 698 274Z"></path></g><g data-mml-node="mo" data-latex="|" transform="translate(17179,0)"><path data-c="7C" d="M139-250C152-250 159-242 159-226L159 726C159 742 152 750 139 750 126 750 119 742 119 726L119-226C119-242 126-250 139-250Z"></path></g><g data-mml-node="msub" data-latex="p_j" transform="translate(17457,0)"><g data-mml-node="mi" data-latex="p"><path data-c="1D45D" d="M355 442C311 442 269 419 228 373 217 419 186 442 137 442 96 442 66 409 45 344 35 311 30 292 30 286 30 277 35 272 46 272 51 272 54 273 57 275 62 284 65 291 66 298 84 374 107 412 134 412 152 412 161 398 161 371 161 356 159 339 154 321L44-118C35-151 34-155-5-155-23-155-32-163-32-178-32-189-26-194-15-194 0-194 52-191 67-191 86-191 146-194 165-194 180-194 187-186 187-170 187-160 178-155 159-155 141-155 114-156 114-144 114-131 155 26 159 43 179 6 209-13 249-13 314-13 371 20 421 87 467 148 490 213 490 280 490 367 438 442 355 442M352 412C391 412 411 382 411 323 411 296 405 260 394 215 371 128 342 71 307 42 286 25 267 16 248 16 219 16 199 29 188 56 179 77 174 92 174 100L225 309C230 331 248 354 276 377 304 400 329 412 352 412Z"></path></g><g data-mml-node="mi" transform="translate(536,-150) scale(0.707)" data-latex="j"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g><g data-mml-node="msup" data-latex="|^2" transform="translate(18334.4,0)"><g data-mml-node="mo" data-latex="|"><path data-c="7C" d="M139-250C152-250 159-242 159-226L159 726C159 742 152 750 139 750 126 750 119 742 119 726L119-226C119-242 126-250 139-250Z"></path></g><g data-mml-node="mn" transform="translate(311,413) scale(0.707)" data-latex="2"><path data-c="32" d="M237 666C186 666 143 648 106 612 69 576 50 534 50 483 50 449 75 424 106 424 136 424 161 450 161 480 161 513 137 536 105 536 102 536 100 536 98 535 117 584 161 627 224 627 306 627 352 556 352 470 352 403 318 331 250 255L62 43C49 28 50 29 50 0L421 0 450 180 417 180C409 129 402 100 396 91 391 86 361 84 306 84L139 84 236 179C304 243 390 312 419 365 439 400 449 435 449 470 449 588 357 666 237 666Z"></path></g></g><g data-mml-node="msup" data-latex=")^2" transform="translate(19048.9,0)"><g data-mml-node="mo" data-latex=")"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g><g data-mml-node="mn" transform="translate(422,413) scale(0.707)" data-latex="2"><path data-c="32" d="M237 666C186 666 143 648 106 612 69 576 50 534 50 483 50 449 75 424 106 424 136 424 161 450 161 480 161 513 137 536 105 536 102 536 100 536 98 535 117 584 161 627 224 627 306 627 352 556 352 470 352 403 318 331 250 255L62 43C49 28 50 29 50 0L421 0 450 180 417 180C409 129 402 100 396 91 391 86 361 84 306 84L139 84 236 179C304 243 390 312 419 365 439 400 449 435 449 470 449 588 357 666 237 666Z"></path></g></g></g></g></g></svg><svg data-labels="true" preserveAspectRatio="xMaxYMid" viewBox="1278 -1393.2 1 2286.4"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:1" transform="translate(0,1191.2)"><text data-id-align="true"></text><g data-idbox="true" transform="translate(0,-748)"><g data-mml-node="mtext" data-latex="\text{(1)}"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path><path data-c="31" d="M269 666C228 624 168 603 89 603L89 564C141 564 184 572 217 588L217 82C217 64 213 52 204 47 195 42 170 39 130 39L95 39 95 0C120 2 174 3 257 3 340 3 394 2 419 0L419 39 384 39C343 39 318 42 310 47 302 52 297 64 297 82L297 636C297 660 295 666 269 666Z" transform="translate(389,0)"></path><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z" transform="translate(889,0)"></path></g></g></g></g></svg></g></g></g></g></svg></mjx-container></p><p>损失函数公式与上图对应:<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.357ex" xmlns="http://www.w3.org/2000/svg" width="2.034ex" height="1.357ex" role="img" focusable="false" viewBox="0 -442 899 599.8"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="u_i"><g data-mml-node="msub" data-latex="u_i"><g data-mml-node="mi" data-latex="u"><path data-c="1D462" d="M543 144C543 153 538 158 527 158 518 158 513 151 510 137 505 118 500 99 493 80 480 39 462 18 440 18 422 18 413 32 413 60 413 77 420 111 433 161L460 267C469 303 477 328 483 359L489 386C491 393 492 398 492 401 492 421 481 431 459 431 437 431 423 419 417 394L343 98C342 95 338 88 330 76 314 50 275 18 235 18 197 18 178 44 178 95 178 136 196 202 231 294 242 324 248 345 248 357 248 407 213 442 163 442 118 442 83 417 58 367 39 328 29 301 29 287 29 278 34 273 45 273 58 273 60 279 64 293 87 373 119 413 160 413 174 413 181 403 181 384 181 369 175 348 164 319 126 218 107 148 107 111 107 34 155-11 232-11 275-11 314 9 347 50 361 9 391-11 437-11 506-11 527 70 543 144Z"></path></g><g data-mml-node="mi" transform="translate(605,-150) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g></g></g></svg></mjx-container>表示用户 i 的偏好隐含向量,<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.667ex" xmlns="http://www.w3.org/2000/svg" width="1.985ex" height="1.667ex" role="img" focusable="false" viewBox="0 -442 877.3 737"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="p_j"><g data-mml-node="msub" data-latex="p_j"><g data-mml-node="mi" data-latex="p"><path data-c="1D45D" d="M355 442C311 442 269 419 228 373 217 419 186 442 137 442 96 442 66 409 45 344 35 311 30 292 30 286 30 277 35 272 46 272 51 272 54 273 57 275 62 284 65 291 66 298 84 374 107 412 134 412 152 412 161 398 161 371 161 356 159 339 154 321L44-118C35-151 34-155-5-155-23-155-32-163-32-178-32-189-26-194-15-194 0-194 52-191 67-191 86-191 146-194 165-194 180-194 187-186 187-170 187-160 178-155 159-155 141-155 114-156 114-144 114-131 155 26 159 43 179 6 209-13 249-13 314-13 371 20 421 87 467 148 490 213 490 280 490 367 438 442 355 442M352 412C391 412 411 382 411 323 411 296 405 260 394 215 371 128 342 71 307 42 286 25 267 16 248 16 219 16 199 29 188 56 179 77 174 92 174 100L225 309C230 331 248 354 276 377 304 400 329 412 352 412Z"></path></g><g data-mml-node="mi" transform="translate(536,-150) scale(0.707)" data-latex="j"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g></g></g></svg></mjx-container>表示艺术家 j 包含的隐含特征向量,<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.667ex" xmlns="http://www.w3.org/2000/svg" width="2.419ex" height="1.667ex" role="img" focusable="false" viewBox="0 -442 1069.3 737"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="r_{ij}"><g data-mml-node="msub" data-latex="r_{ij}"><g data-mml-node="mi" data-latex="r"><path data-c="1D45F" d="M436 374C436 416 395 442 351 442 302 442 261 419 227 372 217 411 183 442 136 442 95 442 65 410 44 345 34 312 29 293 29 287 29 278 34 273 45 273 50 273 53 274 56 276 61 285 64 292 65 299 83 375 106 413 133 413 150 413 159 399 159 371 159 358 154 331 144 290L87 63C84 50 78 24 78 19 78-1 89-11 110-11 130-11 143-1 150 19L169 91C180 134 187 162 190 175L221 303C223 311 231 324 244 343 271 381 302 413 351 413 363 413 373 411 382 406 352 397 337 378 337 351 337 325 351 312 378 312 411 312 436 341 436 374Z"></path></g><g data-mml-node="TeXAtom" transform="translate(484,-150) scale(0.707)" data-latex="{i j}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g><g data-mml-node="mi" data-latex="j" transform="translate(345,0)"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g></g></g></g></svg></mjx-container>表示用户 i 对艺术家 j 的评分,<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.667ex" xmlns="http://www.w3.org/2000/svg" width="4.908ex" height="2.572ex" role="img" focusable="false" viewBox="0 -841.7 2169.1 1136.7"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="u_i^TP_j"><g data-mml-node="msubsup" data-latex="u_i^T"><g data-mml-node="mi" data-latex="u"><path data-c="1D462" d="M543 144C543 153 538 158 527 158 518 158 513 151 510 137 505 118 500 99 493 80 480 39 462 18 440 18 422 18 413 32 413 60 413 77 420 111 433 161L460 267C469 303 477 328 483 359L489 386C491 393 492 398 492 401 492 421 481 431 459 431 437 431 423 419 417 394L343 98C342 95 338 88 330 76 314 50 275 18 235 18 197 18 178 44 178 95 178 136 196 202 231 294 242 324 248 345 248 357 248 407 213 442 163 442 118 442 83 417 58 367 39 328 29 301 29 287 29 278 34 273 45 273 58 273 60 279 64 293 87 373 119 413 160 413 174 413 181 403 181 384 181 369 175 348 164 319 126 218 107 148 107 111 107 34 155-11 232-11 275-11 314 9 347 50 361 9 391-11 437-11 506-11 527 70 543 144Z"></path></g><g data-mml-node="mi" transform="translate(605,363) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g><g data-mml-node="mi" transform="translate(605,-284.4) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g><g data-mml-node="msub" data-latex="P_j" transform="translate(1152.8,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(675,-150) scale(0.707)" data-latex="j"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g></g></g></svg></mjx-container>是用户 i 对艺术家 j 评分的近似。其中 λ 是正则化项的系数,损失函数一般需要加入正则化项来避免过拟合等问题。</p><p>于是就简化为一个最小化损失函数 L 的优化问题。用户 - 特征矩阵<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.05ex" xmlns="http://www.w3.org/2000/svg" width="1.719ex" height="1.595ex" role="img" focusable="false" viewBox="0 -683 760 705"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="U"><g data-mml-node="mi" data-latex="U"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g></g></g></svg></mjx-container>和特征 - 艺术家矩阵<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:0" xmlns="http://www.w3.org/2000/svg" width="1.706ex" height="1.545ex" role="img" focusable="false" viewBox="0 -683 754 683"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="P"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g></g></g></svg></mjx-container>的乘积的结果是对整个稠密的用户 - 艺术家相互关系矩阵<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.05ex" xmlns="http://www.w3.org/2000/svg" width="4.865ex" height="1.954ex" role="img" focusable="false" viewBox="0 -841.7 2150.4 863.7"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="UP^T"><g data-mml-node="mi" data-latex="U"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="msup" data-latex="P^T" transform="translate(760,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(842.6,363) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g></g></g></svg></mjx-container>的完整估计。该乘积可以理解成艺术家与其属性之间的一个映射,然后按用户属性进行加权。</p><p><mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.566ex" xmlns="http://www.w3.org/2000/svg" width="1.717ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 759 1000"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="R=UP^T"><g data-mml-node="mi" data-latex="R"><path data-c="1D445" d="M739 531C739 582 713 621 662 649 621 672 572 683 517 683L235 683C212 683 202 682 202 659 202 652 205 647 211 646 221 645 229 644 234 644 264 643 281 641 286 640 291 639 294 636 294 631 294 629 293 623 290 613L158 82C153 60 143 46 128 41 121 39 103 38 72 38 50 38 41 37 41 15 41 4 47-1 59 0L183 3 309 0C325-1 333 8 333 23 333 33 322 38 301 38 261 38 241 43 241 52 241 52 242 54 244 68L308 327 423 327C492 327 527 298 527 241 527 232 522 210 513 174 502 132 497 104 497 89 497 13 556-22 632-22 660-22 687-9 714 16 741 41 755 68 755 96 755 106 750 111 739 111 732 111 726 106 723 95 712 64 698 41 682 28 666 15 651 8 636 8 613 8 601 27 601 64 601 88 604 125 611 176 614 197 615 212 615 223 615 276 587 315 531 339 625 362 739 429 739 531M609 616C629 603 639 581 639 550 639 530 635 507 626 480 599 398 531 357 422 357L316 357 379 610C384 631 392 642 403 643 408 644 428 644 463 644 528 644 566 642 609 616Z"></path></g></g></g></svg><mjx-break size="4"></mjx-break><svg style="vertical-align:-.566ex" xmlns="http://www.w3.org/2000/svg" width="7.254ex" height="2.47ex" role="img" focusable="false" viewBox="0 -841.7 3206.2 1091.7"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="R=UP^T"><g data-mml-node="mo" data-latex="="><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="mi" data-latex="U" transform="translate(1055.8,0)"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="msup" data-latex="P^T" transform="translate(1815.8,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(842.6,363) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g></g></g></svg></mjx-container>通常没有确切的解,因为 U 和 P 通常不够大,不足以完全表示 R,<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.05ex" xmlns="http://www.w3.org/2000/svg" width="4.865ex" height="1.954ex" role="img" focusable="false" viewBox="0 -841.7 2150.4 863.7"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="UP^T"><g data-mml-node="mi" data-latex="U"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="msup" data-latex="P^T" transform="translate(760,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(842.6,363) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g></g></g></svg></mjx-container>应该尽可能逼近 R。然而不幸的是,想直接同时得到 U 和 P 的最优解是不可能的。</p><p>如果 P 已知,求 U 的最优解是非常容易的,反之亦然。但 P 和 U 事先都是未知的。</p><p>虽然 P 是未知的,但可以把 P 初始化为随机行向量矩阵。接着运用简单的线性代数,就能在给定 R 和 P 的条件下求出 U 的最优解。实际上,U 的第 i 行是 R 的第 i 行和 P 的函数。</p><p><mjx-container class="MathJax" jax="SVG" overflow="overflow" display="true" width="full" style="min-width:27.712ex"><svg style="vertical-align:-.726ex;min-width:27.712ex" xmlns="http://www.w3.org/2000/svg" width="100%" height="2.583ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -820.9)"><g data-mml-node="math" data-latex="
R_iP(P^TP)^{-1}=U_i
"><g data-mml-node="mtable" data-latex="
R_iP(P^TP)^{-1}=U_i
" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 820.9) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveAspectRatio="xMidYMid" viewBox="4046.3 -820.9 1 1141.7"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr" transform="translate(0,-70.9)"><g data-mml-node="mtd"><g data-mml-node="msub" data-latex="R_i"><g data-mml-node="mi" data-latex="R"><path data-c="1D445" d="M739 531C739 582 713 621 662 649 621 672 572 683 517 683L235 683C212 683 202 682 202 659 202 652 205 647 211 646 221 645 229 644 234 644 264 643 281 641 286 640 291 639 294 636 294 631 294 629 293 623 290 613L158 82C153 60 143 46 128 41 121 39 103 38 72 38 50 38 41 37 41 15 41 4 47-1 59 0L183 3 309 0C325-1 333 8 333 23 333 33 322 38 301 38 261 38 241 43 241 52 241 52 242 54 244 68L308 327 423 327C492 327 527 298 527 241 527 232 522 210 513 174 502 132 497 104 497 89 497 13 556-22 632-22 660-22 687-9 714 16 741 41 755 68 755 96 755 106 750 111 739 111 732 111 726 106 723 95 712 64 698 41 682 28 666 15 651 8 636 8 613 8 601 27 601 64 601 88 604 125 611 176 614 197 615 212 615 223 615 276 587 315 531 339 625 362 739 429 739 531M609 616C629 603 639 581 639 550 639 530 635 507 626 480 599 398 531 357 422 357L316 357 379 610C384 631 392 642 403 643 408 644 428 644 463 644 528 644 566 642 609 616Z"></path></g><g data-mml-node="mi" transform="translate(792,-150) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g><g data-mml-node="mi" data-latex="P" transform="translate(1086,0)"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(1840,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="msup" data-latex="P^T" transform="translate(2229,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(842.6,413) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g><g data-mml-node="mi" data-latex="P" transform="translate(3619.4,0)"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="msup" data-latex=")^{-1}" transform="translate(4373.4,0)"><g data-mml-node="mo" data-latex=")"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g><g data-mml-node="TeXAtom" transform="translate(422,413) scale(0.707)" data-latex="{-1}" data-mjx-texclass="ORD"><g data-mml-node="mo" data-latex="-"><path data-c="2212" d="M698 270 80 270C64 270 56 263 56 250 56 237 64 230 80 230L698 230C714 230 722 237 722 250 722 262 710 270 698 270Z"></path></g><g data-mml-node="mn" data-latex="1" transform="translate(778,0)"><path data-c="31" d="M269 666C228 624 168 603 89 603L89 564C141 564 184 572 217 588L217 82C217 64 213 52 204 47 195 42 170 39 130 39L95 39 95 0C120 2 174 3 257 3 340 3 394 2 419 0L419 39 384 39C343 39 318 42 310 47 302 52 297 64 297 82L297 636C297 660 295 666 269 666Z"></path></g></g></g><g data-mml-node="mo" data-latex="=" transform="translate(6026.8,0)"><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="msub" data-latex="U_i" transform="translate(7082.6,0)"><g data-mml-node="mi" data-latex="U"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mi" transform="translate(716,-150) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g></g></g></g></svg><svg data-labels="true" preserveAspectRatio="xMaxYMid" viewBox="1278 -820.9 1 1141.7"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:2" transform="translate(0,677.1)"><text data-id-align="true"></text><g data-idbox="true" transform="translate(0,-748)"><g data-mml-node="mtext" data-latex="\text{(2)}"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path><path data-c="32" d="M237 666C186 666 143 648 106 612 69 576 50 534 50 483 50 449 75 424 106 424 136 424 161 450 161 480 161 513 137 536 105 536 102 536 100 536 98 535 117 584 161 627 224 627 306 627 352 556 352 470 352 403 318 331 250 255L62 43C49 28 50 29 50 0L421 0 450 180 417 180C409 129 402 100 396 91 391 86 361 84 306 84L139 84 236 179C304 243 390 312 419 365 439 400 449 435 449 470 449 588 357 666 237 666Z" transform="translate(389,0)"></path><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z" transform="translate(889,0)"></path></g></g></g></g></svg></g></g></g></g></svg></mjx-container></p><p>因此可以很容易分开计算 U 的每一行。因为 U 的每一行可以分开计算,所以我们可以将其并行化,而并行化是大规模计算的一大优点。</p><p>ALS 是求解<mjx-container class="MathJax" jax="SVG" overflow="overflow"><svg style="vertical-align:-.561ex" xmlns="http://www.w3.org/2000/svg" width="6.739ex" height="2.253ex" role="img" focusable="false" viewBox="0 -748 2978.7 996"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math" data-latex="L(u,p)"><g data-mml-node="mi" data-latex="L"><path data-c="1D43F" d="M520 667C520 678 513 683 500 683L354 680 223 683C208 684 200 676 200 659 200 652 203 647 209 646 218 645 226 644 231 644 262 643 279 641 284 640 289 639 292 636 292 631 292 629 291 623 288 613L156 82C150 60 140 47 125 42 119 40 101 39 70 39 49 39 39 31 39 15 39 5 49 0 70 0L527 0C552 0 554 0 561 19L639 233C642 240 643 245 643 248 643 258 638 263 627 263 617 263 612 254 607 240 588 191 570 154 555 131 518 75 455 39 363 39L270 39C259 39 252 39 249 40 242 40 239 42 239 45 239 47 241 54 244 67L377 601C383 624 396 637 415 642 421 643 442 644 478 644 506 644 520 644 520 667Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(681,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="mi" data-latex="u" transform="translate(1070,0)"><path data-c="1D462" d="M543 144C543 153 538 158 527 158 518 158 513 151 510 137 505 118 500 99 493 80 480 39 462 18 440 18 422 18 413 32 413 60 413 77 420 111 433 161L460 267C469 303 477 328 483 359L489 386C491 393 492 398 492 401 492 421 481 431 459 431 437 431 423 419 417 394L343 98C342 95 338 88 330 76 314 50 275 18 235 18 197 18 178 44 178 95 178 136 196 202 231 294 242 324 248 345 248 357 248 407 213 442 163 442 118 442 83 417 58 367 39 328 29 301 29 287 29 278 34 273 45 273 58 273 60 279 64 293 87 373 119 413 160 413 174 413 181 403 181 384 181 369 175 348 164 319 126 218 107 148 107 111 107 34 155-11 232-11 275-11 314 9 347 50 361 9 391-11 437-11 506-11 527 70 543 144Z"></path></g><g data-mml-node="mo" data-latex="," transform="translate(1642,0)"><path data-c="2C" d="M139 106C107 106 86 82 86 50 86 20 109-5 139-5 153-5 165-1 174 8L175 0C175-63 154-117 112-160 105-168 101-174 101-178 101-188 105-193 114-193 123-193 135-181 152-158 186-110 203-57 203 0 203 53 185 106 139 106Z"></path></g><g data-mml-node="mi" data-latex="p" transform="translate(2086.7,0)"><path data-c="1D45D" d="M355 442C311 442 269 419 228 373 217 419 186 442 137 442 96 442 66 409 45 344 35 311 30 292 30 286 30 277 35 272 46 272 51 272 54 273 57 275 62 284 65 291 66 298 84 374 107 412 134 412 152 412 161 398 161 371 161 356 159 339 154 321L44-118C35-151 34-155-5-155-23-155-32-163-32-178-32-189-26-194-15-194 0-194 52-191 67-191 86-191 146-194 165-194 180-194 187-186 187-170 187-160 178-155 159-155 141-155 114-156 114-144 114-131 155 26 159 43 179 6 209-13 249-13 314-13 371 20 421 87 467 148 490 213 490 280 490 367 438 442 355 442M352 412C391 412 411 382 411 323 411 296 405 260 394 215 371 128 342 71 307 42 286 25 267 16 248 16 219 16 199 29 188 56 179 77 174 92 174 100L225 309C230 331 248 354 276 377 304 400 329 412 352 412Z"></path></g><g data-mml-node="mo" data-latex=")" transform="translate(2589.7,0)"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g></g></g></svg></mjx-container>的著名算法,固定 P 或 U 对其对应的隐含向量求偏导数并令导数为 0,得到求解公式:</p><p><mjx-container class="MathJax" jax="SVG" overflow="overflow" display="true" width="full" style="min-width:33.413ex"><svg style="vertical-align:-.726ex;min-width:33.413ex" xmlns="http://www.w3.org/2000/svg" width="100%" height="2.583ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -820.9)"><g data-mml-node="math" data-latex="
u_i=(P^TP+λI)^{-1}P^Tr_i
"><g data-mml-node="mtable" data-latex="
u_i=(P^TP+λI)^{-1}P^Tr_i
" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 820.9) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveAspectRatio="xMidYMid" viewBox="5306.2 -820.9 1 1141.7"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr" transform="translate(0,-70.9)"><g data-mml-node="mtd"><g data-mml-node="msub" data-latex="u_i"><g data-mml-node="mi" data-latex="u"><path data-c="1D462" d="M543 144C543 153 538 158 527 158 518 158 513 151 510 137 505 118 500 99 493 80 480 39 462 18 440 18 422 18 413 32 413 60 413 77 420 111 433 161L460 267C469 303 477 328 483 359L489 386C491 393 492 398 492 401 492 421 481 431 459 431 437 431 423 419 417 394L343 98C342 95 338 88 330 76 314 50 275 18 235 18 197 18 178 44 178 95 178 136 196 202 231 294 242 324 248 345 248 357 248 407 213 442 163 442 118 442 83 417 58 367 39 328 29 301 29 287 29 278 34 273 45 273 58 273 60 279 64 293 87 373 119 413 160 413 174 413 181 403 181 384 181 369 175 348 164 319 126 218 107 148 107 111 107 34 155-11 232-11 275-11 314 9 347 50 361 9 391-11 437-11 506-11 527 70 543 144Z"></path></g><g data-mml-node="mi" transform="translate(605,-150) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g><g data-mml-node="mo" data-latex="=" transform="translate(1176.7,0)"><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(2232.5,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="msup" data-latex="P^T" transform="translate(2621.5,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(842.6,413) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g><g data-mml-node="mi" data-latex="P" transform="translate(4011.9,0)"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mo" data-latex="+" transform="translate(4988.1,0)"><path data-c="2B" d="M698 274 413 274 413 559C413 575 405 583 389 583 373 583 365 575 365 559L365 274 80 274C64 274 56 266 56 250 56 234 64 226 80 226L365 226 365-59C365-75 373-83 389-83 405-83 413-75 413-59L413 226 698 226C714 226 722 234 722 250 722 263 711 274 698 274Z"></path></g><g data-mml-node="mi" data-latex="λ" transform="translate(5988.4,0)"><path data-c="1D706" d="M86-13C97-13 109-6 122 9L355 285C390 189 416 117 433 68 444 37 451 19 456 12 467-3 486-11 512-11L533-11C543-10 548-6 548 3 548 5 546 9 542 14 535 21 528 36 520 59L319 621C302 670 261 694 196 694 181 694 174 689 174 679 174 672 180 667 191 664 205 660 214 655 219 649 226 641 236 621 247 589L342 322 72 53C59 40 53 29 53 20 53 2 68-13 86-13Z"></path></g><g data-mml-node="mi" data-latex="I" transform="translate(6571.4,0)"><path data-c="1D43C" d="M497 667C497 678 491 683 478 683L349 680 218 683C202 684 194 676 194 659 194 649 205 644 226 644 269 644 290 639 290 630 290 625 289 620 288 615L155 82C150 60 140 47 125 42 118 40 100 39 69 39 44 39 34 38 34 15 34 5 40 0 53 0L181 3 313 0C329-1 337 7 337 23 337 39 325 39 303 39 264 39 240 37 240 53 240 58 241 65 244 75L376 602C381 623 391 636 406 641 413 643 431 644 462 644 486 644 497 645 497 667Z"></path></g><g data-mml-node="msup" data-latex=")^{-1}" transform="translate(7068.4,0)"><g data-mml-node="mo" data-latex=")"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g><g data-mml-node="TeXAtom" transform="translate(422,413) scale(0.707)" data-latex="{-1}" data-mjx-texclass="ORD"><g data-mml-node="mo" data-latex="-"><path data-c="2212" d="M698 270 80 270C64 270 56 263 56 250 56 237 64 230 80 230L698 230C714 230 722 237 722 250 722 262 710 270 698 270Z"></path></g><g data-mml-node="mn" data-latex="1" transform="translate(778,0)"><path data-c="31" d="M269 666C228 624 168 603 89 603L89 564C141 564 184 572 217 588L217 82C217 64 213 52 204 47 195 42 170 39 130 39L95 39 95 0C120 2 174 3 257 3 340 3 394 2 419 0L419 39 384 39C343 39 318 42 310 47 302 52 297 64 297 82L297 636C297 660 295 666 269 666Z"></path></g></g></g><g data-mml-node="msup" data-latex="P^T" transform="translate(8444,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mi" transform="translate(842.6,413) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g><g data-mml-node="msub" data-latex="r_i" transform="translate(9834.4,0)"><g data-mml-node="mi" data-latex="r"><path data-c="1D45F" d="M436 374C436 416 395 442 351 442 302 442 261 419 227 372 217 411 183 442 136 442 95 442 65 410 44 345 34 312 29 293 29 287 29 278 34 273 45 273 50 273 53 274 56 276 61 285 64 292 65 299 83 375 106 413 133 413 150 413 159 399 159 371 159 358 154 331 144 290L87 63C84 50 78 24 78 19 78-1 89-11 110-11 130-11 143-1 150 19L169 91C180 134 187 162 190 175L221 303C223 311 231 324 244 343 271 381 302 413 351 413 363 413 373 411 382 406 352 397 337 378 337 351 337 325 351 312 378 312 411 312 436 341 436 374Z"></path></g><g data-mml-node="mi" transform="translate(484,-150) scale(0.707)" data-latex="i"><path data-c="1D456" d="M284 621C284 648 271 661 244 661 216 661 188 633 188 605 188 578 202 565 229 565 257 565 284 593 284 621M259 138C237 59 205 19 164 19 151 19 144 28 144 47 144 64 173 150 232 306 240 329 244 347 244 360 244 409 210 445 161 445 118 445 84 420 59 369 39 328 29 301 29 288 29 279 34 275 45 275 58 275 60 281 64 295 87 375 118 415 158 415 171 415 178 406 178 387 178 373 175 357 168 338 145 275 121 208 101 155 86 115 78 88 78 74 78 25 114-11 162-11 205-11 239 14 264 64 283 103 293 130 293 145 293 154 288 159 277 159 274 159 259 150 259 138Z"></path></g></g></g></g></g></svg><svg data-labels="true" preserveAspectRatio="xMaxYMid" viewBox="1278 -820.9 1 1141.7"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:3" transform="translate(0,677.1)"><text data-id-align="true"></text><g data-idbox="true" transform="translate(0,-748)"><g data-mml-node="mtext" data-latex="\text{(3)}"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path><path data-c="33" d="M303 353C369 378 431 441 431 526 431 569 410 604 369 631 333 654 292 666 246 666 201 666 162 654 127 631 88 605 68 571 68 528 68 495 90 472 122 472 154 472 176 495 176 527 176 560 157 578 119 580 145 615 186 633 242 633 302 633 332 598 332 527 332 485 324 450 309 421 282 373 245 364 183 364 171 362 165 357 165 348 165 333 172 333 192 333L235 333C310 333 348 280 348 173 348 88 317 14 241 14 176 14 128 36 99 80 134 79 160 105 160 139 160 173 135 198 101 198 62 198 42 178 42 137 42 88 64 49 108 18 147-9 193-22 244-22 301-22 350-3 393 34 436 71 457 117 457 173 457 267 383 332 303 353Z" transform="translate(389,0)"></path><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z" transform="translate(889,0)"></path></g></g></g></g></svg></g></g></g></g></svg></mjx-container></p><p><mjx-container class="MathJax" jax="SVG" overflow="overflow" display="true" width="full" style="min-width:33.504ex"><svg style="vertical-align:-.777ex;min-width:33.504ex" xmlns="http://www.w3.org/2000/svg" width="100%" height="2.685ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -843.3)"><g data-mml-node="math" data-latex="
p_j=(U^TU+λI)^{-1}U^Tr_j
"><g data-mml-node="mtable" data-latex="
p_j=(U^TU+λI)^{-1}U^Tr_j
" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 843.3) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveAspectRatio="xMidYMid" viewBox="5326.3 -843.3 1 1186.7"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr" transform="translate(0,-48.4)"><g data-mml-node="mtd"><g data-mml-node="msub" data-latex="p_j"><g data-mml-node="mi" data-latex="p"><path data-c="1D45D" d="M355 442C311 442 269 419 228 373 217 419 186 442 137 442 96 442 66 409 45 344 35 311 30 292 30 286 30 277 35 272 46 272 51 272 54 273 57 275 62 284 65 291 66 298 84 374 107 412 134 412 152 412 161 398 161 371 161 356 159 339 154 321L44-118C35-151 34-155-5-155-23-155-32-163-32-178-32-189-26-194-15-194 0-194 52-191 67-191 86-191 146-194 165-194 180-194 187-186 187-170 187-160 178-155 159-155 141-155 114-156 114-144 114-131 155 26 159 43 179 6 209-13 249-13 314-13 371 20 421 87 467 148 490 213 490 280 490 367 438 442 355 442M352 412C391 412 411 382 411 323 411 296 405 260 394 215 371 128 342 71 307 42 286 25 267 16 248 16 219 16 199 29 188 56 179 77 174 92 174 100L225 309C230 331 248 354 276 377 304 400 329 412 352 412Z"></path></g><g data-mml-node="mi" transform="translate(536,-150) scale(0.707)" data-latex="j"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g><g data-mml-node="mo" data-latex="=" transform="translate(1155.1,0)"><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(2210.9,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="msup" data-latex="U^T" transform="translate(2599.9,0)"><g data-mml-node="mi" data-latex="U"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mi" transform="translate(846.9,413) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g><g data-mml-node="mi" data-latex="U" transform="translate(3994.5,0)"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mo" data-latex="+" transform="translate(4976.8,0)"><path data-c="2B" d="M698 274 413 274 413 559C413 575 405 583 389 583 373 583 365 575 365 559L365 274 80 274C64 274 56 266 56 250 56 234 64 226 80 226L365 226 365-59C365-75 373-83 389-83 405-83 413-75 413-59L413 226 698 226C714 226 722 234 722 250 722 263 711 274 698 274Z"></path></g><g data-mml-node="mi" data-latex="λ" transform="translate(5977,0)"><path data-c="1D706" d="M86-13C97-13 109-6 122 9L355 285C390 189 416 117 433 68 444 37 451 19 456 12 467-3 486-11 512-11L533-11C543-10 548-6 548 3 548 5 546 9 542 14 535 21 528 36 520 59L319 621C302 670 261 694 196 694 181 694 174 689 174 679 174 672 180 667 191 664 205 660 214 655 219 649 226 641 236 621 247 589L342 322 72 53C59 40 53 29 53 20 53 2 68-13 86-13Z"></path></g><g data-mml-node="mi" data-latex="I" transform="translate(6560,0)"><path data-c="1D43C" d="M497 667C497 678 491 683 478 683L349 680 218 683C202 684 194 676 194 659 194 649 205 644 226 644 269 644 290 639 290 630 290 625 289 620 288 615L155 82C150 60 140 47 125 42 118 40 100 39 69 39 44 39 34 38 34 15 34 5 40 0 53 0L181 3 313 0C329-1 337 7 337 23 337 39 325 39 303 39 264 39 240 37 240 53 240 58 241 65 244 75L376 602C381 623 391 636 406 641 413 643 431 644 462 644 486 644 497 645 497 667Z"></path></g><g data-mml-node="msup" data-latex=")^{-1}" transform="translate(7057,0)"><g data-mml-node="mo" data-latex=")"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g><g data-mml-node="TeXAtom" transform="translate(422,413) scale(0.707)" data-latex="{-1}" data-mjx-texclass="ORD"><g data-mml-node="mo" data-latex="-"><path data-c="2212" d="M698 270 80 270C64 270 56 263 56 250 56 237 64 230 80 230L698 230C714 230 722 237 722 250 722 262 710 270 698 270Z"></path></g><g data-mml-node="mn" data-latex="1" transform="translate(778,0)"><path data-c="31" d="M269 666C228 624 168 603 89 603L89 564C141 564 184 572 217 588L217 82C217 64 213 52 204 47 195 42 170 39 130 39L95 39 95 0C120 2 174 3 257 3 340 3 394 2 419 0L419 39 384 39C343 39 318 42 310 47 302 52 297 64 297 82L297 636C297 660 295 666 269 666Z"></path></g></g></g><g data-mml-node="msup" data-latex="U^T" transform="translate(8432.7,0)"><g data-mml-node="mi" data-latex="U"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mi" transform="translate(846.9,413) scale(0.707)" data-latex="T"><path data-c="1D447" d="M344 631C344 628 343 621 340 611L208 83C204 68 200 59 197 55 188 44 154 39 94 39 63 39 49 42 49 16 49 5 56 0 69 0 120 0 192 4 235 3L317 2C331 2 386 0 403 0 420 0 428 8 428 24 428 34 416 39 391 39 339 39 309 41 300 46 297 48 295 52 295 58L430 603C433 617 436 626 439 629 443 635 467 638 511 638 566 638 604 634 623 625 642 616 652 595 652 561 652 543 649 517 644 483 642 475 641 469 641 464 641 453 646 447 657 447 666 447 672 456 675 473L702 645C703 650 704 656 704 662 704 672 694 677 673 677L125 677C99 677 97 674 89 655L30 481C27 472 25 466 24 462 24 452 29 447 40 447 48 447 55 455 60 470 85 543 110 588 133 607 159 628 209 638 282 638L321 638C332 638 344 639 344 631Z"></path></g></g><g data-mml-node="msub" data-latex="r_j" transform="translate(9827.3,0)"><g data-mml-node="mi" data-latex="r"><path data-c="1D45F" d="M436 374C436 416 395 442 351 442 302 442 261 419 227 372 217 411 183 442 136 442 95 442 65 410 44 345 34 312 29 293 29 287 29 278 34 273 45 273 50 273 53 274 56 276 61 285 64 292 65 299 83 375 106 413 133 413 150 413 159 399 159 371 159 358 154 331 144 290L87 63C84 50 78 24 78 19 78-1 89-11 110-11 130-11 143-1 150 19L169 91C180 134 187 162 190 175L221 303C223 311 231 324 244 343 271 381 302 413 351 413 363 413 373 411 382 406 352 397 337 378 337 351 337 325 351 312 378 312 411 312 436 341 436 374Z"></path></g><g data-mml-node="mi" transform="translate(484,-150) scale(0.707)" data-latex="j"><path data-c="1D457" d="M397 621C397 648 383 661 356 661 328 661 300 633 300 605 300 578 313 565 340 565 368 565 397 593 397 621M267 444C214 444 169 404 147 369 120 326 107 299 107 287 107 278 112 274 122 274 127 274 130 275 133 276 138 284 141 291 144 296 176 375 216 414 264 414 282 414 291 400 291 373 291 358 289 341 284 323L192-46C178-104 138-175 75-175 66-175 57-174 48-171 73-161 85-143 85-118 85-92 71-79 44-79 12-79-13-108-13-140-13-184 30-205 77-205 120-205 160-190 197-160 232-131 254-94 265-51L356 311C359 324 361 337 361 349 361 404 322 444 267 444Z"></path></g></g></g></g></g></svg><svg data-labels="true" preserveAspectRatio="xMaxYMid" viewBox="1278 -843.3 1 1186.7"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:4" transform="translate(0,699.6)"><text data-id-align="true"></text><g data-idbox="true" transform="translate(0,-748)"><g data-mml-node="mtext" data-latex="\text{(4)}"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path><path data-c="34" d="M353 677C344 677 336 672 330 663L28 199 28 163 289 163 289 81C289 63 285 51 278 46 271 41 252 39 219 39L194 39 194 0C223 2 269 3 331 3 393 3 439 2 468 0L468 39 443 39C410 39 391 41 384 46 377 51 373 63 373 81L373 163 471 163 471 202 373 202 373 660C373 670 366 677 353 677M295 553 295 202 67 202Z" transform="translate(389,0)"></path><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z" transform="translate(889,0)"></path></g></g></g></g></svg></g></g></g></g></svg></mjx-container></p><p>随机对 P、Q 初始化,随后交替进行优化直到收敛。收敛标准是均方误差小于预定义阈值,或者到达最大迭代次数。</p><h3 id="推荐质量评价指标AUC"><a href="#推荐质量评价指标AUC" class="headerlink" title="推荐质量评价指标AUC"></a><strong>推荐质量评价指标 AUC</strong></h3><p>AUC 指标是一个 [0,1] 之间的实数,代表如果随机挑选一个正样本和一个负样本,分类算法将这个正样本排在负样本前面的概率。值越大,表示分类算法更有可能将正样本排在前面,也即算法准确性越好。</p><p>随机抽出一对样本(一个正样本,一个负样本),然后用训练得到的分类器来对这两个样本进行预测,预测得到正样本的概率大于负样本概率的概率。<br><mjx-container class="MathJax" jax="SVG" overflow="overflow" display="true" width="full" style="min-width:36.918ex"><svg style="vertical-align:-.643ex;min-width:36.918ex" xmlns="http://www.w3.org/2000/svg" width="100%" height="2.417ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -784.1)"><g data-mml-node="math" data-latex="
AUC=P(P_{正样本}>P_{负样本})
"><g data-mml-node="mtable" data-latex="
AUC=P(P_{正样本}>P_{负样本})
" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 784.1) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveAspectRatio="xMidYMid" viewBox="6080.9 -784.1 1 1068.2"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr" transform="translate(0,34.1)"><g data-mml-node="mtd"><g data-mml-node="mi" data-latex="A"><path data-c="1D434" d="M137 3C155 3 217 0 236 0 251 0 258 8 258 23 258 32 252 38 239 39 210 40 196 50 196 69 196 78 205 98 224 128 251 173 270 206 283 228L526 228C526 221 527 207 530 185 537 112 541 72 541 67 541 48 519 39 474 39 455 39 446 31 446 15 446 5 452 0 464 0 488 0 564 3 588 3 608 3 679 0 699 0 714 0 721 8 721 24 721 34 712 39 694 39 666 39 649 41 644 44 639 47 635 56 634 71L574 689C571 708 572 716 551 716 539 716 529 710 522 697L178 120C148 70 108 43 59 39 43 38 35 30 35 15 35 5 41 0 52 0 68 0 121 3 137 3M492 577 522 267 307 267Z"></path></g><g data-mml-node="mi" data-latex="U" transform="translate(750,0)"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mi" data-latex="C" transform="translate(1510,0)"><path data-c="1D436" d="M148 218C148 346 204 476 267 548 318 607 406 666 505 666 609 666 660 587 660 479 660 470 657 438 657 429 657 420 663 415 676 415 681 415 685 416 688 417 693 424 696 431 698 438L760 691C760 700 755 705 745 705 741 705 735 701 727 692L662 619C623 676 568 705 497 705 442 705 388 692 333 667 222 615 141 533 89 421 63 366 50 310 50 253 50 173 75 108 126 56 177 4 242-22 322-22 401-22 473 7 538 64 565 87 588 115 607 146 634 191 648 222 648 241 648 250 643 255 632 255 623 255 618 251 616 242 595 177 562 125 517 88 460 41 400 17 338 17 218 17 148 98 148 218Z"></path></g><g data-mml-node="mo" data-latex="=" transform="translate(2547.8,0)"><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="mi" data-latex="P" transform="translate(3603.6,0)"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(4357.6,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="msub" data-latex="P_{正样本}" transform="translate(4746.6,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="TeXAtom" transform="translate(675,-176.7) scale(0.707)" data-latex="{正样本}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="正"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">正</text></g><g data-mml-node="mi" data-latex="样" transform="translate(1000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">样</text></g><g data-mml-node="mi" data-latex="本" transform="translate(2000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">本</text></g></g></g><g data-mml-node="mo" data-latex=">" transform="translate(7870.7,0)"><path data-c="3E" d="M686 227C696 232 701 239 701 250 701 261 696 268 686 273L112 545C109 546 105 547 101 547 85 547 77 539 77 522 77 513 82 506 91 502L625 250 91-2C82-6 77-13 77-22 77-39 85-47 101-47 105-47 109-46 112-45Z"></path></g><g data-mml-node="msub" data-latex="P_{负样本}" transform="translate(8926.4,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="TeXAtom" transform="translate(675,-176.7) scale(0.707)" data-latex="{负样本}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="负"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">负</text></g><g data-mml-node="mi" data-latex="样" transform="translate(1000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">样</text></g><g data-mml-node="mi" data-latex="本" transform="translate(2000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">本</text></g></g></g><g data-mml-node="mo" data-latex=")" transform="translate(11772.8,0)"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g></g></g></g></svg><svg data-labels="true" preserveAspectRatio="xMaxYMid" viewBox="1278 -784.1 1 1068.2"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:5" transform="translate(0,782.1)"><text data-id-align="true"></text><g data-idbox="true" transform="translate(0,-748)"><g data-mml-node="mtext" data-latex="\text{(5)}"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path><path data-c="35" d="M118 315C123 315 129 319 134 326 164 371 205 393 257 393 292 393 319 373 337 332 348 305 354 264 354 209 354 146 346 102 331 76 306 35 272 14 229 14 162 14 109 62 91 114 94 113 96 114 100 114 130 114 155 137 155 167 155 198 130 219 100 219 65 219 50 200 50 163 50 63 131-22 231-22 292-22 344 0 386 44 428 88 449 141 449 202 449 260 432 310 398 353 361 400 315 423 259 423 212 423 171 408 138 378L138 556C165 548 191 544 218 544 264 544 304 555 338 578 369 597 390 616 402 634 408 642 411 648 411 651 411 661 406 666 396 666 341 645 294 634 256 634 211 634 168 643 127 662 122 664 118 665 114 665 105 665 100 656 100 637L100 345C100 324 100 315 118 315Z" transform="translate(389,0)"></path><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z" transform="translate(889,0)"></path></g></g></g></g></svg></g></g></g></g></svg></mjx-container><br>在有 M 个正样本, N 个负样本的数据集里。一共有 M×N 对样本(一对样本,一个正样本与一个负样本)。统计这 M×N 对样本里,正样本的预测概率大于负样本的预测概率的个数。<br><mjx-container class="MathJax" jax="SVG" overflow="overflow" display="true" width="full" style="min-width:38.087ex"><svg style="vertical-align:-1.939ex;min-width:38.087ex" xmlns="http://www.w3.org/2000/svg" width="100%" height="5.009ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -1357.1)"><g data-mml-node="math" data-latex="
AUC=\frac{\sum I(P_{正样本},P_{负样本})}{M\times N}
"><g data-mml-node="mtable" data-latex="
AUC=\frac{\sum I(P_{正样本},P_{负样本})}{M\times N}
" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 1357.1) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveAspectRatio="xMidYMid" viewBox="6339.3 -1357.1 1 2214.2"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr" transform="translate(0,-171.1)"><g data-mml-node="mtd"><g data-mml-node="mi" data-latex="A"><path data-c="1D434" d="M137 3C155 3 217 0 236 0 251 0 258 8 258 23 258 32 252 38 239 39 210 40 196 50 196 69 196 78 205 98 224 128 251 173 270 206 283 228L526 228C526 221 527 207 530 185 537 112 541 72 541 67 541 48 519 39 474 39 455 39 446 31 446 15 446 5 452 0 464 0 488 0 564 3 588 3 608 3 679 0 699 0 714 0 721 8 721 24 721 34 712 39 694 39 666 39 649 41 644 44 639 47 635 56 634 71L574 689C571 708 572 716 551 716 539 716 529 710 522 697L178 120C148 70 108 43 59 39 43 38 35 30 35 15 35 5 41 0 52 0 68 0 121 3 137 3M492 577 522 267 307 267Z"></path></g><g data-mml-node="mi" data-latex="U" transform="translate(750,0)"><path data-c="1D448" d="M642 680C623 680 559 683 540 683 525 683 518 675 518 659 518 650 525 645 539 644 582 644 603 631 603 605 603 599 602 592 600 585L511 232C496 175 467 126 424 84 377 39 325 17 269 17 195 17 152 67 152 141L153 150C153 169 156 191 163 217L259 602C264 623 273 636 286 641 292 643 309 644 338 644 364 644 375 644 375 668 375 678 369 683 358 683L231 680 104 683C88 683 81 674 81 659 81 652 84 647 89 646 99 645 107 644 112 644 143 643 161 641 166 640 171 639 173 636 173 631 173 629 172 622 169 611L74 230C69 211 67 192 67 172 67 57 150-22 265-22 330-22 390 3 445 54 498 102 532 158 548 223L636 574C649 625 677 643 739 644 753 645 760 653 760 668L760 672C757 679 752 683 743 683 724 683 661 680 642 680Z"></path></g><g data-mml-node="mi" data-latex="C" transform="translate(1510,0)"><path data-c="1D436" d="M148 218C148 346 204 476 267 548 318 607 406 666 505 666 609 666 660 587 660 479 660 470 657 438 657 429 657 420 663 415 676 415 681 415 685 416 688 417 693 424 696 431 698 438L760 691C760 700 755 705 745 705 741 705 735 701 727 692L662 619C623 676 568 705 497 705 442 705 388 692 333 667 222 615 141 533 89 421 63 366 50 310 50 253 50 173 75 108 126 56 177 4 242-22 322-22 401-22 473 7 538 64 565 87 588 115 607 146 634 191 648 222 648 241 648 250 643 255 632 255 623 255 618 251 616 242 595 177 562 125 517 88 460 41 400 17 338 17 218 17 148 98 148 218Z"></path></g><g data-mml-node="mo" data-latex="=" transform="translate(2547.8,0)"><path data-c="3D" d="M698 367 80 367C64 367 56 359 56 344 56 329 64 321 80 321L698 321C714 321 722 329 722 344 722 356 711 367 698 367M698 179 80 179C64 179 56 171 56 156 56 141 64 133 80 133L698 133C714 133 722 141 722 156 722 169 711 179 698 179Z"></path></g><g data-mml-node="mfrac" data-latex="\frac{\sum I(P_{正样本},P_{负样本})}{M\times N}" transform="translate(3603.6,0)"><g data-mml-node="mrow" data-latex="\sum I(P_{正样本},P_{负样本})" transform="translate(220,778.2)"><g data-mml-node="mo" data-latex="\sum"><path data-c="2211" d="M56 713 417 216 67-217C60-225 57-231 57-235 57-245 67-250 88-250L913-250 1001 5 967 5C954-33 933-66 902-95 825-166 719-188 565-188L152-188 490 232C497 240 500 246 500 250 500 254 498 259 493 266L175 702 560 702C682 702 764 691 854 644 907 616 944 571 967 510L1001 510 913 750 88 750C57 750 56 746 56 713Z"></path></g><g data-mml-node="mi" data-latex="I" transform="translate(1222.7,0)"><path data-c="1D43C" d="M497 667C497 678 491 683 478 683L349 680 218 683C202 684 194 676 194 659 194 649 205 644 226 644 269 644 290 639 290 630 290 625 289 620 288 615L155 82C150 60 140 47 125 42 118 40 100 39 69 39 44 39 34 38 34 15 34 5 40 0 53 0L181 3 313 0C329-1 337 7 337 23 337 39 325 39 303 39 264 39 240 37 240 53 240 58 241 65 244 75L376 602C381 623 391 636 406 641 413 643 431 644 462 644 486 644 497 645 497 667Z"></path></g><g data-mml-node="mo" data-latex="(" transform="translate(1719.7,0)"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path></g><g data-mml-node="msub" data-latex="P_{正样本}" transform="translate(2108.7,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="TeXAtom" transform="translate(675,-176.7) scale(0.707)" data-latex="{正样本}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="正"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">正</text></g><g data-mml-node="mi" data-latex="样" transform="translate(1000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">样</text></g><g data-mml-node="mi" data-latex="本" transform="translate(2000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">本</text></g></g></g><g data-mml-node="mo" data-latex="," transform="translate(4955,0)"><path data-c="2C" d="M139 106C107 106 86 82 86 50 86 20 109-5 139-5 153-5 165-1 174 8L175 0C175-63 154-117 112-160 105-168 101-174 101-178 101-188 105-193 114-193 123-193 135-181 152-158 186-110 203-57 203 0 203 53 185 106 139 106Z"></path></g><g data-mml-node="msub" data-latex="P_{负样本}" transform="translate(5399.7,0)"><g data-mml-node="mi" data-latex="P"><path data-c="1D443" d="M555 683 235 683C212 683 201 682 201 660 201 649 212 644 234 644 254 644 294 647 294 631 294 629 293 623 290 613L158 82C152 60 142 47 128 42 121 40 103 39 72 39 50 39 40 37 40 16 40 5 46 0 59 0L184 3 248 2C259 2 299 0 312 0 328 0 336 8 336 24 336 34 325 39 304 39 264 39 244 43 244 52 244 52 245 55 247 68L307 312 472 312C537 312 599 332 657 371 722 414 754 467 754 530 754 629 660 683 555 683M524 644C611 644 654 614 654 554 654 498 626 423 597 397 559 363 509 346 447 346L313 346 379 610C387 644 387 644 429 644Z"></path></g><g data-mml-node="TeXAtom" transform="translate(675,-176.7) scale(0.707)" data-latex="{负样本}" data-mjx-texclass="ORD"><g data-mml-node="mi" data-latex="负"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">负</text></g><g data-mml-node="mi" data-latex="样" transform="translate(1000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">样</text></g><g data-mml-node="mi" data-latex="本" transform="translate(2000,0)"><text data-variant="normal" transform="scale(1,-1)" font-size="884px" font-family="serif">本</text></g></g></g><g data-mml-node="mo" data-latex=")" transform="translate(8246,0)"><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z"></path></g></g><g data-mml-node="mrow" data-latex="M\times N" transform="translate(2963.8,-686)"><g data-mml-node="mi" data-latex="M"><path data-c="1D440" d="M594 16C594 5 600 0 613 0L736 3C759 4 840 0 859 0 874 0 882 8 882 24 882 34 872 39 851 39 810 39 790 43 790 52 790 55 792 62 795 75L927 602C932 623 942 636 955 641 961 643 979 644 1008 644 1033 644 1044 645 1044 668 1044 678 1034 683 1013 683L882 683C853 683 853 681 840 662L484 108 408 657C404 682 402 683 373 683L237 683C215 683 204 682 204 660 204 649 215 644 236 644 256 644 297 647 297 631 297 629 296 623 293 613L167 110C158 72 135 49 100 42 75 39 42 43 42 16 42 5 48 0 60 0 78 0 141 3 159 3 178 3 242 0 261 0 276 0 283 8 283 24 283 33 276 38 261 39 219 39 198 52 198 78 198 82 199 89 202 100L332 621 415 26C418 9 424 0 434 0 442 0 450 7 459 20L848 627 712 82C706 60 696 47 681 42 675 40 656 39 625 39 604 39 594 37 594 16Z"></path></g><g data-mml-node="mo" data-latex="\times" transform="translate(1266.2,0)"><path data-c="D7" d="M630 32C630 39 628 44 623 49L422 250 623 451C628 456 630 461 630 468 630 481 620 491 607 491 600 491 595 489 590 484L389 283 188 484C183 489 178 491 171 491 158 491 148 481 148 468 148 461 150 456 155 451L356 250 155 49C150 44 148 39 148 32 148 19 158 9 171 9 178 9 183 11 188 16L389 217 590 16C595 11 600 9 607 9 620 9 630 19 630 32Z"></path></g><g data-mml-node="mi" data-latex="N" transform="translate(2266.4,0)"><path data-c="1D441" d="M864 683C845 683 783 680 764 680 745 680 682 683 663 683 648 683 641 675 641 659 641 650 648 645 663 644 705 644 726 631 726 605 726 599 725 592 724 585L616 157 401 662C393 681 391 683 366 683L233 683C209 683 200 681 200 659 200 649 211 644 232 644 274 644 295 643 296 640L163 110C154 71 131 49 95 42 69 39 39 43 39 15 39 5 45 0 56 0 74 0 136 3 155 3 174 3 238 0 257 0 272 0 279 8 279 24 279 33 271 38 255 39 214 40 194 53 194 78 194 83 195 90 197 100L326 611 576 21C582 7 590 0 599 0 608 0 614 8 618 24L757 574C770 625 798 643 860 644 874 645 881 653 881 669 878 678 877 683 864 683Z"></path></g></g><rect width="8835" height="60" x="120" y="220"></rect></g></g></g></g></svg><svg data-labels="true" preserveAspectRatio="xMaxYMid" viewBox="1278 -1357.1 1 2214.2"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:6" transform="translate(0,576.9)"><text data-id-align="true"></text><g data-idbox="true" transform="translate(0,-748)"><g data-mml-node="mtext" data-latex="\text{(6)}"><path data-c="28" d="M318-248C327-248 332-243 332-234 332-231 330-227 327-223 275-183 233-117 202-26 175 53 161 131 161 208L161 292C161 369 175 447 202 526 233 617 275 683 327 723 330 726 332 730 332 734 332 743 327 748 318 748 317 748 314 747 311 745 251 699 201 631 160 540 121 453 101 371 101 292L101 208C101 129 121 47 160-40 201-131 251-199 311-245 314-247 317-248 318-248Z"></path><path data-c="36" d="M383 504C416 504 432 521 432 555 432 627 378 666 304 666 221 666 155 627 106 548 63 480 42 403 42 316 42 189 65 100 112 47 152 1 198-22 251-22 312-22 362 1 401 47 438 91 457 144 457 205 457 266 439 318 403 361 365 407 316 431 257 431 205 431 165 402 138 346L138 352C138 465 166 561 226 605 252 624 279 633 306 633 342 633 368 623 385 602 351 602 334 583 334 553 334 525 355 504 383 504M344 340C355 317 361 272 361 206 361 141 356 98 345 76 325 35 294 14 251 14 222 14 200 24 184 44 171 60 162 74 158 85 146 116 140 163 140 227 140 255 144 282 151 308 164 355 201 399 256 399 295 399 325 379 344 340Z" transform="translate(389,0)"></path><path data-c="29" d="M78-245C138-199 188-131 229-40 268 47 288 129 288 208L288 292C288 371 268 453 229 540 188 631 138 699 78 745 75 747 72 748 71 748 62 748 57 743 57 734 57 730 59 726 62 723 114 683 156 617 187 526 214 447 228 369 228 292L228 208C228 131 214 53 187-26 156-117 114-183 62-223 59-227 57-231 57-234 57-243 62-248 71-248 72-248 75-247 78-245Z" transform="translate(889,0)"></path></g></g></g></g></svg></g></g></g></g></svg></mjx-container><br>其中,</p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992541062/202082151944.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992541062/202082151944.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="推荐质量评价指标AUC"></p></div><div class="story post-story"><h2 id="实验过程"><a href="#实验过程" class="headerlink" title="实验过程"></a>实验过程</h2><h3 id="数据预处理"><a href="#数据预处理" class="headerlink" title="数据预处理"></a>数据预处理</h3><p><strong>artist_data.txt</strong> 文件</p><p>数据最终处理成以逗号分割</p><p><strong>artist_data.txt</strong> 文件</p><p>两列之间的间隔有的是空格有的是 Tab,第二列数据中包含空格</p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992773903/202082145015.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992773903/202082145015.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="第二列数据中包含空格"></p><p>因第二列数据中含有逗号和空格,数据最终处理成以 Tab 分割</p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992810226/20208214518.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992810226/20208214518.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="数据最终处理成以Tab分割"></p><p>去除第一列不是数字的行</p><p><strong>artist_alias.txt</strong> <strong>文件</strong></p><p>将拼写错误的艺术家 ID 或 ID 变体对应到该艺术家的规范 ID</p><p>两列之间的间隔有的是空格有的是 Tab</p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992843714/202082145144.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992843714/202082145144.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="两列之间的间隔有的是空格有的是Tab"></p><p>包含数据缺失的列</p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992871540/20208214526.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992871540/20208214526.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="包含数据缺失的列"></p><p>在数据处理时对拼写错误 ID 进行映射,用别名数据集将所有的艺术家 ID 转换成正规 ID。</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">aa={}</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/artist_alias.txt"</span>) <span class="keyword">as</span> f:</span><br><span class="line">    line = f.readline()</span><br><span class="line">    <span class="keyword">while</span> line:</span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(line.split())==<span class="number">2</span>:</span><br><span class="line">            aa[line.split()[<span class="number">0</span>]]=line.split()[<span class="number">1</span>]</span><br><span class="line">        line = f.readline()</span><br><span class="line"></span><br><span class="line">f3=<span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/user_artist_data.txt.data"</span>,<span class="string">"w+"</span>)</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/user_artist_data.txt"</span>) <span class="keyword">as</span> f2:</span><br><span class="line">    line = f2.readline()</span><br><span class="line">    <span class="keyword">while</span> line:</span><br><span class="line">        it=line.split()</span><br><span class="line">        <span class="keyword">if</span> it[<span class="number">1</span>] <span class="keyword">in</span> aa:</span><br><span class="line">            it[<span class="number">1</span>]=aa[it[<span class="number">1</span>]]</span><br><span class="line">        <span class="built_in">print</span>(it[<span class="number">0</span>]+<span class="string">","</span>+it[<span class="number">1</span>]+<span class="string">","</span>+it[<span class="number">2</span>],file=f3)</span><br><span class="line">        line = f2.readline()</span><br><span class="line">f3.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">f5=<span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/artist_data.txt.data"</span>,<span class="string">"w+"</span>)</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/artist_data.txt"</span>) <span class="keyword">as</span> f4:</span><br><span class="line">    line = f4.readline()</span><br><span class="line">    <span class="keyword">while</span> line:</span><br><span class="line">        it=line.split()</span><br><span class="line">        s=<span class="string">""</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(it)):</span><br><span class="line">            s+=it[i]</span><br><span class="line">            <span class="keyword">if</span> i==<span class="number">0</span>:</span><br><span class="line">                s+=<span class="string">"    "</span></span><br><span class="line">            <span class="keyword">elif</span> i==<span class="built_in">len</span>(it)-<span class="number">1</span>:</span><br><span class="line">                s+=<span class="string">""</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                s+=<span class="string">" "</span></span><br><span class="line">        <span class="built_in">print</span>(s,file=f5)</span><br><span class="line">        line = f4.readline()</span><br><span class="line"></span><br><span class="line">f7=<span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/artist_data.txt.data2"</span>,<span class="string">"w+"</span>)</span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"/export/work/F/1/data/artist_data.txt.data"</span>) <span class="keyword">as</span> f6:</span><br><span class="line">    line = f6.readline()</span><br><span class="line">    <span class="keyword">while</span> line:</span><br><span class="line">        it=line.split(<span class="string">"    "</span>)</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            a=<span class="built_in">int</span>(it[<span class="number">0</span>])</span><br><span class="line">            <span class="built_in">print</span>(<span class="built_in">str</span>(a)+<span class="string">"    "</span>+it[<span class="number">1</span>],file=f7,end=<span class="string">""</span>)</span><br><span class="line">        <span class="keyword">except</span>:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line">        line = f6.readline()</span><br></pre></td></tr></tbody></table></figure><p><strong>预处理后得到的数据集</strong></p><p><strong>artist_data</strong></p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992906605/202082145243.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992906605/202082145243.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="artist_data"></p><p><strong>user_artist_data</strong></p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992933044/202082145314.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992933044/202082145314.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="user_artist_data"></p><h3 id="获取数据文件,并上传至HDFS"><a href="#获取数据文件,并上传至HDFS" class="headerlink" title="获取数据文件,并上传至HDFS"></a>获取数据文件,并上传至 HDFS</h3><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992959556/202082145341.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992959556/202082145341.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="获取数据文件,并上传至HDFS"></p><p><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651992991812/20208214544.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651992991812/20208214544.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="获取数据文件,并上传至HDFS"></p><h3 id="读入数据,转换成DataFrame备用"><a href="#读入数据,转换成DataFrame备用" class="headerlink" title="读入数据,转换成DataFrame备用"></a>读入数据,转换成 DataFrame 备用</h3><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">from</span> pyspark.sql.types <span class="keyword">import</span> Row</span><br><span class="line"><span class="keyword">from</span> pyspark.sql.types <span class="keyword">import</span> StructType</span><br><span class="line"><span class="keyword">from</span> pyspark.sql.types <span class="keyword">import</span> StructField</span><br><span class="line"><span class="keyword">from</span> pyspark.sql.types <span class="keyword">import</span> StringType,IntegerType</span><br><span class="line"><span class="keyword">from</span> pyspark.conf <span class="keyword">import</span> SparkConf</span><br><span class="line"><span class="keyword">from</span> pyspark <span class="keyword">import</span> SparkContext</span><br><span class="line"><span class="keyword">from</span> pyspark.sql.session <span class="keyword">import</span> SparkSession</span><br><span class="line"><span class="comment"># 转换成DataFrame</span></span><br><span class="line">name1=[<span class="string">"user"</span>, <span class="string">"item"</span>, <span class="string">"rating"</span>]</span><br><span class="line">name2=[<span class="string">"id"</span>,<span class="string">"name"</span>]</span><br><span class="line"></span><br><span class="line">conf = SparkConf().setAppName(<span class="string">"applicaiton"</span>).<span class="built_in">set</span>(<span class="string">"spark.executor.heartbeatInterval"</span>,<span class="string">"500000"</span>).<span class="built_in">set</span>(<span class="string">"spark.network.timeout"</span>,<span class="string">"500000"</span>)</span><br><span class="line">sc = SparkContext.getOrCreate(conf)</span><br><span class="line">spark = SparkSession(sc)</span><br><span class="line">uaRDD = sc.textFile(<span class="string">"/1/user_artist_data.txt.data"</span>)</span><br><span class="line">fields = <span class="built_in">list</span>(<span class="built_in">map</span>( <span class="keyword">lambda</span> fieldName : StructField(fieldName, IntegerType(), nullable = <span class="literal">True</span>), name1))</span><br><span class="line">schema = StructType(fields)</span><br><span class="line">rowRDD = uaRDD.<span class="built_in">map</span>(<span class="keyword">lambda</span> line : line.split(<span class="string">","</span>)).<span class="built_in">map</span>(<span class="keyword">lambda</span> attr : Row(<span class="built_in">int</span>(attr[<span class="number">0</span>]),<span class="built_in">int</span>(attr[<span class="number">1</span>]),<span class="built_in">int</span>(attr[<span class="number">2</span>])))</span><br><span class="line">uaDF = spark.createDataFrame(rowRDD, schema)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">aRDD = sc.textFile(<span class="string">"/1/artist_data.txt.data2"</span>)</span><br><span class="line">fields = <span class="built_in">list</span>(<span class="built_in">map</span>( <span class="keyword">lambda</span> fieldName : StructField(fieldName, IntegerType(), nullable = <span class="literal">True</span>) <span class="keyword">if</span>  fieldName==<span class="string">"id"</span> <span class="keyword">else</span> StructField(fieldName, StringType(), nullable = <span class="literal">True</span>) , name2))</span><br><span class="line">schema = StructType(fields)</span><br><span class="line">rowRDD =aRDD.<span class="built_in">map</span>(<span class="keyword">lambda</span> line : line.split(<span class="string">"    "</span>)).<span class="built_in">map</span>(<span class="keyword">lambda</span> attr : Row(<span class="built_in">int</span>(attr[<span class="number">0</span>]),attr[<span class="number">1</span>]))</span><br><span class="line">aDF = spark.createDataFrame(rowRDD, schema)</span><br></pre></td></tr></tbody></table></figure><h3 id="展示数据格式基本统计信息"><a href="#展示数据格式基本统计信息" class="headerlink" title="展示数据格式基本统计信息"></a>展示数据格式基本统计信息</h3><p>数据格式</p><figure class="highlight shell"><table><tbody><tr><td class="code"><pre><span class="line">uaDF.show()</span><br><span class="line"></span><br><span class="line">+-------+-------+------+</span><br><span class="line">|   user|   item|rating|</span><br><span class="line">+-------+-------+------+</span><br><span class="line">|1000002|      1|    55|</span><br><span class="line">|1000002|1000006|    33|</span><br><span class="line">|1000002|1000007|     8|</span><br><span class="line">|1000002|1000009|   144|</span><br><span class="line">|1000002|1000010|   314|</span><br><span class="line">|1000002|1000013|     8|</span><br><span class="line">|1000002|1000014|    42|</span><br><span class="line">|1000002|1000017|    69|</span><br><span class="line">|1000002|1000024|   329|</span><br><span class="line">|1000002|1000025|     1|</span><br><span class="line">|1000002|1000028|    17|</span><br><span class="line">|1000002|1000031|    47|</span><br><span class="line">|1000002|1000033|    15|</span><br><span class="line">|1000002|1000042|     1|</span><br><span class="line">|1000002|1000045|     1|</span><br><span class="line">|1000002|1000054|     2|</span><br><span class="line">|1000002|1000055|    25|</span><br><span class="line">|1000002|1000056|     4|</span><br><span class="line">|1000002|1000059|     2|</span><br><span class="line">|1000002|1000062|    71|</span><br><span class="line">+-------+-------+------+</span><br><span class="line">only showing top 20 rows</span><br></pre></td></tr></tbody></table></figure><h3 id="基本统计信息"><a href="#基本统计信息" class="headerlink" title="基本统计信息"></a>基本统计信息</h3><p><strong>用户数</strong></p><figure class="highlight shell"><table><tbody><tr><td class="code"><pre><span class="line">a=uaDF.select(uaDF.user).distinct().count()</span><br><span class="line">print(a)</span><br><span class="line"></span><br><span class="line">148111</span><br></pre></td></tr></tbody></table></figure><p><strong>艺术家数目</strong></p><figure class="highlight shell"><table><tbody><tr><td class="code"><pre><span class="line">b=uaDF.select(uaDF.item).distinct().count()</span><br><span class="line">print(b)</span><br><span class="line"></span><br><span class="line">1568126</span><br></pre></td></tr></tbody></table></figure><p><strong>每用户平均播放次数</strong></p><figure class="highlight shell"><table><tbody><tr><td class="code"><pre><span class="line">uaDF.drop("item").groupBy("user").agg({"rating":"mean"}).show()</span><br><span class="line"></span><br><span class="line">+-------+------------------+</span><br><span class="line">|   user|       avg(rating)|</span><br><span class="line">+-------+------------------+</span><br><span class="line">|1000190|55.355432780847146|</span><br><span class="line">|1001043|6.0131578947368425|</span><br><span class="line">|1001129| 12.32748538011696|</span><br><span class="line">|1001139| 8.652557319223986|</span><br><span class="line">|1002431|12.833333333333334|</span><br><span class="line">|1002605|3.5392670157068062|</span><br><span class="line">|1004666|  9.79409594095941|</span><br><span class="line">|1005158|1.9245283018867925|</span><br><span class="line">|1005439|28.333333333333332|</span><br><span class="line">|1005697|11.733333333333333|</span><br><span class="line">|1005853|               2.5|</span><br><span class="line">|1007007| 2.443396226415094|</span><br><span class="line">|1007847|14.333333333333334|</span><br><span class="line">|1008081|31.232876712328768|</span><br><span class="line">|1008233|              90.0|</span><br><span class="line">|1008804|               9.0|</span><br><span class="line">|1009408| 4.666666666666667|</span><br><span class="line">|1012261|3.2887640449438202|</span><br><span class="line">|1015587|              9.46|</span><br><span class="line">|1016416| 8.241935483870968|</span><br><span class="line">+-------+------------------+</span><br><span class="line">only showing top 20 rows</span><br></pre></td></tr></tbody></table></figure><p><strong>每艺术家平均播放次数</strong></p><figure class="highlight shell"><table><tbody><tr><td class="code"><pre><span class="line">uaDF.drop("user").groupBy("item").agg({"rating":"mean"}).show()</span><br><span class="line"></span><br><span class="line">+-------+------------------+</span><br><span class="line">|   item|       avg(rating)|</span><br><span class="line">+-------+------------------+</span><br><span class="line">|1001129|10.578309692671395|</span><br><span class="line">|1003373|2.3333333333333335|</span><br><span class="line">|1007972|18.156831042845596|</span><br><span class="line">|1029443| 20.54196642685851|</span><br><span class="line">|1076507| 2.969264544456641|</span><br><span class="line">|1318111|5.6902654867256635|</span><br><span class="line">|    833| 9.483282674772036|</span><br><span class="line">|1239413| 3.821794871794872|</span><br><span class="line">|1000636|               2.0|</span><br><span class="line">|1002431|1.7142857142857142|</span><br><span class="line">|1005697|               3.5|</span><br><span class="line">|1040360|               1.0|</span><br><span class="line">|1043263|1.9166666666666667|</span><br><span class="line">|1245208|19.613390928725703|</span><br><span class="line">|    463|  34.3479262672811|</span><br><span class="line">|1043126|14.580645161290322|</span><br><span class="line">|1001601| 3.573529411764706|</span><br><span class="line">|1091589|               2.5|</span><br><span class="line">|1004021|  6.96403785488959|</span><br><span class="line">|1012885| 4.744927536231884|</span><br><span class="line">+-------+------------------+</span><br><span class="line">only showing top 20 rows</span><br></pre></td></tr></tbody></table></figure><h3 id="构建ALS模型"><a href="#构建ALS模型" class="headerlink" title="构建ALS模型"></a>构建 ALS 模型</h3><p>构建 ALS 模型,并记录所耗时间。初始参数:Rank 10, maxiter 15, RegParm 0.01 Alpha 1.0。</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">from</span>  pyspark.ml.recommendation <span class="keyword">import</span> ALS,ALSModel</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line">start = time.time()</span><br><span class="line">als = ALS(rank=<span class="number">10</span>,maxIter=<span class="number">15</span>,regParam=<span class="number">0.01</span>,alpha=<span class="number">1.0</span>,seed=<span class="built_in">int</span>(random.random()*<span class="number">100</span>))</span><br><span class="line">model=als.fit(uaDF)</span><br><span class="line">end = time.time()</span><br><span class="line"><span class="built_in">print</span> (<span class="string">"时间:"</span>+<span class="built_in">str</span>(end-start))</span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">时间:<span class="number">785.1817960739136</span></span><br></pre></td></tr></tbody></table></figure><p>这样我们就构建了一个 ALSModel 模型。</p><p>模型用两个不同的 DataFrame,它们分别表示 “用户 - 特征” 和 “产品 - 特征” 这两个大型矩阵。</p><h3 id="检查推荐结果"><a href="#检查推荐结果" class="headerlink" title="检查推荐结果"></a>检查推荐结果</h3><p>依据构建的模型,选择部分 ID 检查推荐结果。</p><p>看看模型给出的艺术家推荐直观上是否合理,检查一下用户播放过的艺术家,然后看看模型向用户推荐的艺术家。具体来看看用户 2093760 的例子。</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">userID = <span class="number">2093760</span></span><br><span class="line">a=uaDF.rdd.<span class="built_in">filter</span>(<span class="keyword">lambda</span> x:x[<span class="number">0</span>]==userID).collect()</span><br></pre></td></tr></tbody></table></figure><p>查看用户输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">[</span><br><span class="line">Row(user=<span class="number">2093760</span>, item=<span class="number">1180</span>, rating=<span class="number">1</span>), </span><br><span class="line">Row(user=<span class="number">2093760</span>, item=<span class="number">1255340</span>, rating=<span class="number">3</span>), </span><br><span class="line">Row(user=<span class="number">2093760</span>, item=<span class="number">378</span>, rating=<span class="number">1</span>), </span><br><span class="line">Row(user=<span class="number">2093760</span>, item=<span class="number">813</span>, rating=<span class="number">2</span>), </span><br><span class="line">Row(user=<span class="number">2093760</span>, item=<span class="number">942</span>, rating=<span class="number">7</span>)</span><br><span class="line">] </span><br></pre></td></tr></tbody></table></figure><p>获取艺术家 ID:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">artistid=[]</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> a:</span><br><span class="line">    artistid.append(i.item)</span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">[<span class="number">1180</span>, <span class="number">1255340</span>, <span class="number">378</span>, <span class="number">813</span>, <span class="number">942</span>] </span><br></pre></td></tr></tbody></table></figure><p>要提取该用户收听过的艺术家 ID 并打印他们的名字,这意味着先在输入数据中搜索该用户收听过的艺术家的 ID,然后用这些 ID 对艺术家集合进行过滤,这样我们就可以获取并按序打印这些艺术家的名字:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">b=aDF.rdd.<span class="built_in">filter</span>(**<span class="keyword">lambda</span>** x: x[<span class="number">0</span>] **<span class="keyword">in</span>** artistid).collect() </span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">[Row(<span class="built_in">id</span>=<span class="number">1180</span>, name=<span class="string">'David Gray'</span>),  </span><br><span class="line"></span><br><span class="line">Row(<span class="built_in">id</span>=<span class="number">378</span>, name=<span class="string">'Blackalicious'</span>),  </span><br><span class="line"></span><br><span class="line">Row(<span class="built_in">id</span>=<span class="number">813</span>, name=<span class="string">'Jurassic 5'</span>),  </span><br><span class="line"></span><br><span class="line">Row(<span class="built_in">id</span>=<span class="number">1255340</span>, name=<span class="string">'The Saw Doctors'</span>),  </span><br><span class="line"></span><br><span class="line">Row(<span class="built_in">id</span>=<span class="number">942</span>, name=<span class="string">'Xzibit'</span>)] </span><br></pre></td></tr></tbody></table></figure><p>用户播放过的艺术家既有大众流行音乐风格的也有嘻哈风格的。</p><p> 使用 Spark2.4.6 自带的 recommendForUserSubset 方法,对所有艺术家评分,并返回向用户 2093760 推荐其中分值最高的前 5 位。</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">d=sc.parallelize([(<span class="number">2093760</span>,<span class="number">1</span>)]).toDF([<span class="string">'user'</span>]) </span><br><span class="line"></span><br><span class="line">t=model.recommendForUserSubset(d,<span class="number">5</span>) </span><br><span class="line"></span><br><span class="line">t.show() </span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">+-------+--------------------+                                                  </span><br><span class="line">|   user|     recommendations|</span><br><span class="line">+-------+--------------------+</span><br><span class="line">|<span class="number">2093760</span>|[[<span class="number">6674945</span>, <span class="number">4997.0</span>...|</span><br><span class="line">+-------+--------------------+</span><br></pre></td></tr></tbody></table></figure><p>遍历打印一下:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">t.select(<span class="string">"recommendations"</span>).rdd.foreach(**<span class="keyword">lambda</span>** x:**<span class="built_in">print</span>**(x)) </span><br></pre></td></tr></tbody></table></figure><p>输出:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">Row(recommendations=[</span><br><span class="line">    Row(item=<span class="number">6674945</span>, rating=<span class="number">4997.056640625</span>), </span><br><span class="line">    Row(item=<span class="number">1170225</span>, rating=<span class="number">1805.596435546875</span>), </span><br><span class="line">    Row(item=<span class="number">1153293</span>, rating=<span class="number">1753.0908203125</span>), </span><br><span class="line">    Row(item=<span class="number">6730413</span>, rating=<span class="number">1233.61767578125</span>), </span><br><span class="line">    Row(item=<span class="number">183</span>, rating=<span class="number">1169.90234375</span>)</span><br><span class="line">])</span><br></pre></td></tr></tbody></table></figure><p>结果全部是嘻哈风格。能看出,这些推荐都不怎么样。虽然推荐的艺术家都受人欢迎,但好像并没有针对用户的收听习惯进行个性化。</p><h3 id="训练-验证切分"><a href="#训练-验证切分" class="headerlink" title="训练-验证切分"></a>训练 - 验证切分</h3><p>训练 - 验证切分,采用初始参数,重新训练模型。</p><p>为了利用输入数据,需要把它分成训练集和验证集。训练集只用于训练 ALS 模型,验证集用于评估模型。这里将 90% 的数据用于训练,剩余的 10% 用于交叉验证:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">train,test=uaDF.randomSplit([<span class="number">0.9</span>,<span class="number">0.1</span>])</span><br><span class="line">als = ALS(rank=<span class="number">10</span>,maxIter=<span class="number">15</span>,regParam=<span class="number">0.01</span>,alpha=<span class="number">1.0</span>,seed=<span class="built_in">int</span>(random.random()*<span class="number">100</span>),implicitPrefs=<span class="literal">True</span>)</span><br><span class="line">model=als.fit(train)</span><br><span class="line">train.cache()</span><br><span class="line">test.cache()</span><br></pre></td></tr></tbody></table></figure><h3 id="计算AUC"><a href="#计算AUC" class="headerlink" title="计算AUC"></a>计算 AUC</h3><p>接受一个交叉验证集和一个预测函数,交叉验证集代表每个用户对应的 “正面的” 或 “好的” 艺术家。预测函数把每个包含 “用户 - 艺术家” 对的 DataFrame 转换为一个同时包含 “用户 - 艺术家” 和 “预测” 的 DataFrame,“预测” 表示 “用户” 与 “艺术家” 之间关联的强度值,这个值越高,代表推荐的排名越高。</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">allArtistIDs = uaDF.select(<span class="string">"item"</span>).distinct().collect()</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> numpy</span><br><span class="line">allArtistID = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(allArtistIDs)):</span><br><span class="line">    allArtistID.append(allArtistIDs[i][<span class="string">"item"</span>])</span><br><span class="line"><span class="keyword">def</span> <span class="title function_">f</span>(<span class="params">a,b</span>):</span><br><span class="line">    posItemIDSet = <span class="built_in">set</span>(<span class="built_in">list</span>(b))</span><br><span class="line">    negative = []</span><br><span class="line">    i = <span class="number">0</span></span><br><span class="line">    <span class="keyword">while</span> (i &lt; <span class="built_in">len</span>(allArtistID)) <span class="keyword">and</span> (<span class="built_in">len</span>(negative) &lt; <span class="built_in">len</span>(posItemIDSet)):</span><br><span class="line">        artistID = allArtistID[numpy.random.randint(<span class="number">1</span>, high=<span class="built_in">len</span>(allArtistID), size=<span class="literal">None</span>, dtype=<span class="string">'l'</span>)]</span><br><span class="line">        <span class="keyword">if</span> artistID <span class="keyword">not</span> <span class="keyword">in</span> posItemIDSet:</span><br><span class="line">            negative.append(artistID)</span><br><span class="line">        i += <span class="number">1</span></span><br><span class="line">    s=<span class="built_in">list</span>()</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> negative:</span><br><span class="line">        s.append((a,i))</span><br><span class="line">    <span class="keyword">return</span> s</span><br><span class="line"></span><br><span class="line"><span class="comment"># 计算AUC</span></span><br><span class="line"><span class="keyword">import</span> pyspark.sql.functions <span class="keyword">as</span> func</span><br><span class="line"><span class="keyword">def</span> <span class="title function_">areaUnderCurve</span>(<span class="params">positiveData,allArtistIDs,predictFunction</span>):</span><br><span class="line">    positivePredictions = predictFunction(positiveData.select(<span class="string">"user"</span>, <span class="string">"item"</span>)).withColumnRenamed(<span class="string">"prediction"</span>, <span class="string">"positivePrediction"</span>)</span><br><span class="line">    negativeDatatmp = positiveData.select(<span class="string">"user"</span>, <span class="string">"item"</span>).rdd.groupByKey().<span class="built_in">map</span>(<span class="keyword">lambda</span> x: f(x[<span class="number">0</span>],x[<span class="number">1</span>])).collect()</span><br><span class="line">    negativeDatalist=[]</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> negativeDatatmp:</span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> i:</span><br><span class="line">           negativeDatalist.append(j) </span><br><span class="line">    negativeData=spark.createDataFrame(negativeDatalist,[<span class="string">'user'</span>,<span class="string">'item'</span>])</span><br><span class="line">    negativePredictions = predictFunction(negativeData.select(<span class="string">"user"</span>, <span class="string">"item"</span>)).withColumnRenamed(<span class="string">"prediction"</span>, <span class="string">"negativePrediction"</span>)</span><br><span class="line">    joinedPredictions = positivePredictions.join(negativePredictions, <span class="string">"user"</span>).select(<span class="string">"user"</span>, <span class="string">"positivePrediction"</span>, <span class="string">"negativePrediction"</span>)</span><br><span class="line">    allCounts = joinedPredictions.groupBy(<span class="string">"user"</span>).agg(func.count(func.lit(<span class="number">1</span>)).alias(<span class="string">"total"</span>)).select(<span class="string">"user"</span>, <span class="string">"total"</span>)</span><br><span class="line">    correctCounts = joinedPredictions.<span class="built_in">filter</span>(joinedPredictions[<span class="string">"positivePrediction"</span>] &gt; joinedPredictions[<span class="string">"negativePrediction"</span>]).groupBy(<span class="string">"user"</span>).agg(func.count(<span class="string">"user"</span>).alias(<span class="string">"correct"</span>)).select(<span class="string">"user"</span>, <span class="string">"correct"</span>)</span><br><span class="line">    meanAUCtemp = allCounts.join(correctCounts, <span class="string">"user"</span>, <span class="string">"left_outer"</span>)</span><br><span class="line">    meanAUC = meanAUCtemp.select(<span class="string">"user"</span>, (meanAUCtemp[<span class="string">"correct"</span>] / meanAUCtemp[<span class="string">"total"</span>]).alias(<span class="string">"auc"</span>)).agg(func.mean(<span class="string">"auc"</span>)).first()</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        joinedPredictions.unpersist()</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">return</span> meanAUC</span><br><span class="line">    </span><br><span class="line">mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line"><span class="built_in">print</span>(mostListenedAUC)</span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">Row(avg(auc)=<span class="number">0.9098560946043145</span>) </span><br></pre></td></tr></tbody></table></figure><p>有必要把上述方法和一个更简单方法做一个基准比对。举个例子,考虑下面的推荐方法:向每个用户推荐播放最多的艺术家。这个策略一点儿都不个性化,但它很简单,也可能有效。定义这个简单预测函数并评估它的 AUC 得分:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">predictMostListened</span>(<span class="params">data</span>):</span><br><span class="line">    listenCounts = train.groupBy(<span class="string">"item"</span>).agg({<span class="string">"rating"</span>:<span class="string">"sum"</span>}).withColumnRenamed(<span class="string">"sum(rating)"</span>, <span class="string">"prediction"</span>).select(<span class="string">"item"</span>, <span class="string">"prediction"</span>)</span><br><span class="line">    uaDF.join(listenCounts, [<span class="string">"item"</span>], <span class="string">"left_outer"</span>).select(<span class="string">"user"</span>, <span class="string">"item"</span>, <span class="string">"prediction"</span>)</span><br><span class="line">    listenCounts = uaDF.groupBy(<span class="string">"item"</span>).agg({<span class="string">"rating"</span>:<span class="string">"sum"</span>}).withColumnRenamed(<span class="string">"sum(rating)"</span>, <span class="string">"prediction"</span>).select(<span class="string">"item"</span>, <span class="string">"prediction"</span>)</span><br><span class="line">    <span class="keyword">return</span> data.join(listenCounts, [<span class="string">"item"</span>], <span class="string">"left_outer"</span>).select(<span class="string">"user"</span>, <span class="string">"item"</span>, <span class="string">"prediction"</span>)</span><br><span class="line">mostListenedAUC = areaUnderCurve(test, allArtistIDs, predictMostListened)</span><br><span class="line"><span class="built_in">print</span>(mostListenedAUC)</span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">Row(avg(auc)=<span class="number">0.9578054887285846</span>) </span><br></pre></td></tr></tbody></table></figure><p>结果得分大约是 0.96。这意味着,对 AUC 这个指标,非个性化的推荐表现已经不错了。然而,我们想要的是得分更高,也就是更为 “个性化” 的推荐。显然这个模型还有待改进。调整超参数,使推荐结果更合理。</p><h3 id="选择超参数"><a href="#选择超参数" class="headerlink" title="选择超参数"></a>选择超参数</h3><p>Rank 可选(5,30)RegParam 可选(4.0,0.0001),alpha 可选(1.0,40.0)。合计 8 种参数组合。</p><p>可以把 rank、regParam 和 alpha 看作模型的超参数。(maxIter 更像是对分解过程使用的资源的一种约束。)这些值不会体现在 ALSModel 的内部矩阵中,这些矩阵只是参数,其值由算法选定。超参数则是构建过程本身的参数。</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">TrainALS</span>(<span class="params">rank,regParam,alpha,<span class="built_in">dir</span></span>):</span><br><span class="line">    als = ALS(rank=rank,maxIter=<span class="number">15</span>,regParam=regParam,alpha=alpha,seed=<span class="built_in">int</span>(random.random()*<span class="number">100</span>),implicitPrefs=<span class="literal">True</span>)</span><br><span class="line">    model=als.fit(train)</span><br><span class="line">    model.save(<span class="string">"/model/ALS/Try2/"</span>+<span class="built_in">str</span>(<span class="built_in">dir</span>))</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        model.userFactors.unpersist()</span><br><span class="line">        model.itemFactors.unpersist()</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        <span class="keyword">pass</span></span><br></pre></td></tr></tbody></table></figure><p> 构建模型</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="built_in">dir</span>=<span class="number">0</span></span><br><span class="line"><span class="keyword">for</span> rank <span class="keyword">in</span> [<span class="number">5</span>,<span class="number">30</span>]:</span><br><span class="line">    <span class="keyword">for</span> regParam <span class="keyword">in</span> [<span class="number">4.0</span>,<span class="number">0.0001</span>]:</span><br><span class="line">        <span class="keyword">for</span> alpha <span class="keyword">in</span> [<span class="number">1.0</span>,<span class="number">40.0</span>]:</span><br><span class="line">            <span class="built_in">dir</span>=<span class="built_in">dir</span>+<span class="number">1</span></span><br><span class="line">            TrainALS(rank,regParam,alpha,<span class="built_in">dir</span>)</span><br></pre></td></tr></tbody></table></figure><p>加载模型计算 AUC 得分:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/1"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">5</span>,<span class="number">4.0</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">5</span>,<span class="number">4.0</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/2"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">5</span>,<span class="number">4.0</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">5</span>,<span class="number">4.0</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/3"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">5</span>,<span class="number">0.0001</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">5</span>,<span class="number">0.0001</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/4"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">5</span>,<span class="number">0.0001</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">5</span>,<span class="number">0.0001</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/5"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">30</span>,<span class="number">4.0</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">30</span>,<span class="number">4.0</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/6"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">30</span>,<span class="number">4.0</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">30</span>,<span class="number">4.0</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/7"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">30</span>,<span class="number">0.0001</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">30</span>,<span class="number">0.0001</span>,<span class="number">1.0</span>)))</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    model=ALSModel.load(<span class="string">"/model/ALS/Try2/8"</span>)</span><br><span class="line">    mostListenedAUC = areaUnderCurve(test, allArtistIDs, model.transform)</span><br><span class="line">    <span class="built_in">print</span>((mostListenedAUC,(<span class="number">30</span>,<span class="number">0.0001</span>,<span class="number">40.0</span>)))</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">    <span class="built_in">print</span>((<span class="string">"ERROR"</span>,(<span class="number">30</span>,<span class="number">0.0001</span>,<span class="number">40.0</span>)))</span><br></pre></td></tr></tbody></table></figure><p>输出结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">(Row(avg(auc)=<span class="number">0.9122637924972641</span>), (<span class="number">5</span>, <span class="number">4.0</span>, <span class="number">1.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9154223563144587</span>), (<span class="number">5</span>, <span class="number">4.0</span>, <span class="number">40.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9057761909633262</span>), (<span class="number">5</span>, <span class="number">0.0001</span>, <span class="number">1.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9146676967584815</span>), (<span class="number">5</span>, <span class="number">0.0001</span>, <span class="number">40.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9230010545570864</span>), (<span class="number">30</span>, <span class="number">4.0</span>, <span class="number">1.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9275148741094371</span>), (<span class="number">30</span>, <span class="number">4.0</span>, <span class="number">40.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9125799456221803</span>), (<span class="number">30</span>, <span class="number">0.0001</span>, <span class="number">1.0</span>))</span><br><span class="line">(Row(avg(auc)=<span class="number">0.9265221600644649</span>), (<span class="number">30</span>, <span class="number">0.0001</span>, <span class="number">40.0</span>))</span><br></pre></td></tr></tbody></table></figure><p>可以看出 rank = 30,regParam = 4.0,alpha = 40.0 时取得了最优的结果 avg (auc)=0.9275148741094371.</p><p>虽然这些值的绝对差很小,但对于 AUC 值来说,仍然具有一定的意义。有意思的是,参数 alpha 取 40 的时候看起来总是比取 1 表现好。这说明了模型在强调用户听过什么时的表现要比强调用户没听过什么时要好。</p><h3 id="产生推荐"><a href="#产生推荐" class="headerlink" title="产生推荐"></a>产生推荐</h3><p>选取 10 个用户展示推荐结果</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">model=ALSModel.load(<span class="string">"/model/ALS/Try2/6"</span>)</span><br><span class="line">d=sc.parallelize([(<span class="number">2093760</span>,<span class="number">1</span>),(<span class="number">1000002</span>,<span class="number">1</span>),(<span class="number">1006277</span>,<span class="number">1</span>),(<span class="number">1006282</span>,<span class="number">1</span>),(<span class="number">1006283</span>,<span class="number">1</span>),(<span class="number">1006285</span>,<span class="number">1</span>),(<span class="number">1041207</span>,<span class="number">1</span>),(<span class="number">1071489</span>,<span class="number">1</span>),(<span class="number">2025005</span>,<span class="number">1</span>),(<span class="number">2025007</span>,<span class="number">1</span>),]).toDF([<span class="string">'user'</span>])</span><br><span class="line">t=model.recommendForUserSubset(d,<span class="number">5</span>)</span><br><span class="line">t.select(<span class="string">"recommendations"</span>).rdd.foreach(<span class="keyword">lambda</span> x:<span class="built_in">print</span>(x))</span><br></pre></td></tr></tbody></table></figure><p>输出推荐结果:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">Row(recommendations=[Row(item=<span class="number">1010991</span>, rating=<span class="number">1.1815389394760132</span>), Row(item=<span class="number">1245226</span>, rating=<span class="number">1.139704942703247</span>), Row(item=<span class="number">4629</span>, rating=<span class="number">1.1092422008514404</span>), Row(item=<span class="number">1113701</span>, rating=<span class="number">1.1066040992736816</span>), Row(item=<span class="number">1019715</span>, rating=<span class="number">1.10056471824646</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1010921</span>, rating=<span class="number">1.225757122039795</span>), Row(item=<span class="number">1166169</span>, rating=<span class="number">1.1972994804382324</span>), Row(item=<span class="number">1183949</span>, rating=<span class="number">1.184556007385254</span>), Row(item=<span class="number">1082446</span>, rating=<span class="number">1.178223729133606</span>), Row(item=<span class="number">3892</span>, rating=<span class="number">1.1580229997634888</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1028958</span>, rating=<span class="number">1.146733283996582</span>), Row(item=<span class="number">1086774</span>, rating=<span class="number">1.1434733867645264</span>), Row(item=<span class="number">1037761</span>, rating=<span class="number">1.1272671222686768</span>), Row(item=<span class="number">1184419</span>, rating=<span class="number">1.1093372106552124</span>), Row(item=<span class="number">1148170</span>, rating=<span class="number">1.1065270900726318</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1010295</span>, rating=<span class="number">1.2554553747177124</span>), Row(item=<span class="number">3722</span>, rating=<span class="number">1.2187168598175049</span>), Row(item=<span class="number">1024674</span>, rating=<span class="number">1.2044183015823364</span>), Row(item=<span class="number">1009445</span>, rating=<span class="number">1.099776268005371</span>), Row(item=<span class="number">1018746</span>, rating=<span class="number">1.0894378423690796</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1002068</span>, rating=<span class="number">0.9575374126434326</span>), Row(item=<span class="number">1005288</span>, rating=<span class="number">0.9533681273460388</span>), Row(item=<span class="number">2430</span>, rating=<span class="number">0.9476644992828369</span>), Row(item=<span class="number">1002270</span>, rating=<span class="number">0.9428261518478394</span>), Row(item=<span class="number">3909</span>, rating=<span class="number">0.9334102869033813</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1034635</span>, rating=<span class="number">0.606441080570221</span>), Row(item=<span class="number">1000107</span>, rating=<span class="number">0.6010327935218811</span>), Row(item=<span class="number">1000024</span>, rating=<span class="number">0.59807950258255</span>), Row(item=<span class="number">4154</span>, rating=<span class="number">0.5966558456420898</span>), Row(item=<span class="number">1000157</span>, rating=<span class="number">0.5944067239761353</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1034635</span>, rating=<span class="number">0.290438175201416</span>), Row(item=<span class="number">930</span>, rating=<span class="number">0.2857869565486908</span>), Row(item=<span class="number">4267</span>, rating=<span class="number">0.2853849530220032</span>), Row(item=<span class="number">1205</span>, rating=<span class="number">0.2830250561237335</span>), Row(item=<span class="number">1000113</span>, rating=<span class="number">0.2829856276512146</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1002909</span>, rating=<span class="number">1.2324668169021606</span>), Row(item=<span class="number">1653</span>, rating=<span class="number">1.1938585042953491</span>), Row(item=<span class="number">988</span>, rating=<span class="number">1.1880080699920654</span>), Row(item=<span class="number">1003367</span>, rating=<span class="number">1.1807997226715088</span>), Row(item=<span class="number">1009545</span>, rating=<span class="number">1.1761128902435303</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1017017</span>, rating=<span class="number">0.8724791407585144</span>), Row(item=<span class="number">1032349</span>, rating=<span class="number">0.8424116373062134</span>), Row(item=<span class="number">1028433</span>, rating=<span class="number">0.8259942531585693</span>), Row(item=<span class="number">1240603</span>, rating=<span class="number">0.8185747265815735</span>), Row(item=<span class="number">1029602</span>, rating=<span class="number">0.8147093653678894</span>)])</span><br><span class="line">Row(recommendations=[Row(item=<span class="number">1013187</span>, rating=<span class="number">1.2516499757766724</span>), Row(item=<span class="number">1098360</span>, rating=<span class="number">1.2394661903381348</span>), Row(item=<span class="number">1289948</span>, rating=<span class="number">1.2353206872940063</span>), Row(item=<span class="number">1129243</span>, rating=<span class="number">1.2332189083099365</span>), Row(item=<span class="number">1245184</span>, rating=<span class="number">1.1997216939926147</span>)])</span><br></pre></td></tr></tbody></table></figure><p>按照用户顺序将最喜欢的推荐结果输出到文件</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">getp</span>(<span class="params">x</span>):</span><br><span class="line">    f=<span class="built_in">open</span>(<span class="string">"/export/work/result"</span>,<span class="string">"a+"</span>)</span><br><span class="line">    <span class="built_in">print</span>(x,file=f)</span><br><span class="line">u=uaDF.select(<span class="string">"user"</span>).distinct()</span><br><span class="line">t=model.recommendForUserSubset(u,<span class="number">1</span>)</span><br><span class="line">t.rdd.foreach(<span class="keyword">lambda</span> x:getp(x))</span><br></pre></td></tr></tbody></table></figure><p>推荐输出详见 result 文件,以下为部分推荐输出:</p><figure class="highlight python"><table><tbody><tr><td class="code"><pre><span class="line">Row(user=<span class="number">1000092</span>, recommendations=[Row(item=<span class="number">1002400</span>, rating=<span class="number">1.2386927604675293</span>)]) </span><br><span class="line">Row(user=<span class="number">1000144</span>, recommendations=[Row(item=<span class="number">5221</span>, rating=<span class="number">1.1728830337524414</span>)]) </span><br><span class="line">Row(user=<span class="number">3175</span>, recommendations=[Row(item=<span class="number">1022207</span>, rating=<span class="number">0.282743901014328</span>)]) </span><br><span class="line">Row(user=<span class="number">1000164</span>, recommendations=[Row(item=<span class="number">1034635</span>, rating=<span class="number">0.36578264832496643</span>)]) </span><br><span class="line">Row(user=<span class="number">7340</span>, recommendations=[Row(item=<span class="number">1007903</span>, rating=<span class="number">0.8722475171089172</span>)]) </span><br></pre></td></tr></tbody></table></figure></div></div><div class="footer"></div><div class="article-meta" id="bottom"><div class="new-meta-box"></div></div><div class="prev-next"><a class="prev" href="/notes/Spark/streaming-kafka"><p class="title"><i class="fa-solid fa-chevron-left" aria-hidden="true"></i>SparkStreaming 整合 Kafka</p><p class="content">Spark Streaming 整合 Kafka 需关注两个关键版本:Kafka-0.8 将偏移量(offset)存储于 Zookeeper,高并发场景存在瓶颈;Kafka-0.10 则将 offset 保存至 Kafka 内置特殊 topic,优化读写性能。实时处理需权衡数据一致性策略:At most once(可能丢失)、At least once(可能重复)及 Exactly once(精准一次),后者可通过关闭自动提交并结合 Spark 容错机制与事务实现。</p></a><a class="next" href="/notes/Spark/k-means"><p class="title">基于K均值聚类的网络流量异常检测(pyspark)<i class="fa-solid fa-chevron-right" aria-hidden="true"></i></p><p class="content">基于K均值聚类的网络流量异常检测方法通过PySpark实现,用于识别欺诈、网络攻击及设备故障等新型异常。使用KDD Cup 1999数据集(38个特征),通过迭代计算样本点到中心距离划分聚类,更新中心点至收敛。实验步骤含数据准备、HDFS上传、DataFrame构建及k值选择,评价指标为熵和准确率。</p></a></div><div class="recommended-article"><div class="recommended-article-header"><i class="fa-solid fa-bookmark fa-fw" aria-hidden="true"></i> <span>推荐阅读</span></div><div class="recommended-article-group"> <a class="recommended-article-item" href="/p/110850a/" title="手把手教你用 Python 开始第一个机器学习项目" rel="bookmark"><img src="https://static.mhuig.top/npm/imbox@0.0.15/c/78.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/imbox@0.0.15/c/78.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="手把手教你用 Python 开始第一个机器学习项目"> <span class="title">手把手教你用 Python 开始第一个机器学习项目</span></a> <a class="recommended-article-item" href="/notes/Spark/k-means.html" title="基于K均值聚类的网络流量异常检测(pyspark)" rel="bookmark"><img src="https://static.mhuig.top/npm/imbox@0.0.15/c/46.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/imbox@0.0.15/c/46.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="基于K均值聚类的网络流量异常检测(pyspark)"> <span class="title">基于K均值聚类的网络流量异常检测(pyspark)</span></a> <a class="recommended-article-item" href="/p/48f700eb/" title="BERT 预训练模型及其应用案例" rel="bookmark"><img src="https://static.mhuig.top/npm/mhgoos@0.0.1651974150318/2020116102430.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/mhgoos@0.0.1651974150318/2020116102430.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="BERT 预训练模型及其应用案例"> <span class="title">BERT 预训练模型及其应用案例</span></a> <a class="recommended-article-item" href="/notes/Spark/rdd.html" title="Spark RDD 编程" rel="bookmark"><img src="https://static.mhuig.top/npm/imbox@0.0.15/c/106.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/imbox@0.0.15/c/106.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Spark RDD 编程"> <span class="title">Spark RDD 编程</span></a> <a class="recommended-article-item" href="/notes/Django/ajax.html" title="Django将发布内容动态显示到页面上" rel="bookmark"><img src="https://static.mhuig.top/npm/imbox@0.0.15/c/62.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/imbox@0.0.15/c/62.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Django将发布内容动态显示到页面上"> <span class="title">Django将发布内容动态显示到页面上</span></a> <a class="recommended-article-item" href="/notes/51/temperature-humidity.html" title="AT89S52 或 STC89C52RC 串口发送温湿度数据" rel="bookmark"><img src="https://static.mhuig.top/npm/imbox@0.0.15/c/114.webp" class="lazyload" data-srcset="https://static.mhuig.top/npm/imbox@0.0.15/c/114.webp" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="AT89S52 或 STC89C52RC 串口发送温湿度数据"> <span class="title">AT89S52 或 STC89C52RC 串口发送温湿度数据</span></a></div></div></article><article class="post white-box shadow floatable blur" id="comments"><span hidden=""><meta itemprop="discussionUrl" content="/notes/Spark/als#comments"></span><p ct=""><i class="fa-duotone fa-comments"></i> 留言区</p><div id="layoutHelper-comments"></div></article></div><aside id="l_side" itemscope="" itemtype="http://schema.org/WPSideBar"><section class="widget text desktop mobile pjax"><header><a href="/notes/"><i class="fa-duotone fa-book fa-fw" aria-hidden="true"></i> <span class="name">Notes</span></a></header><div class="content"></div></section><section class="widget list group desktop mobile pjax"><header><i class="fa-duotone fa-comet fa-fw" aria-hidden="true"></i> <span class="name">Spark-快速大数据分析技术</span></header><div class="content"><ul class="list entry navigation"><li><a class="flat-box" title="/notes/Spark/" href="/notes/Spark/" active-action="action-notesSpark"><div class="name"> Welcome</div></a></li><li><a class="flat-box" title="/notes/Spark/env" href="/notes/Spark/env" active-action="action-notesSparkenv"><div class="name"> Environment Deployment</div></a></li><li><a class="flat-box" title="/notes/Spark/rdd" href="/notes/Spark/rdd" active-action="action-notesSparkrdd"><div class="name"> RDD</div></a></li><li><a class="flat-box" title="/notes/Spark/streaming" href="/notes/Spark/streaming" active-action="action-notesSparkstreaming"><div class="name"> Streaming</div></a></li><li><a class="flat-box" title="/notes/Spark/streaming-kafka" href="/notes/Spark/streaming-kafka" active-action="action-notesSparkstreaming-kafka"><div class="name"> Kafka</div></a></li><li><a class="flat-box" title="/notes/Spark/als" href="/notes/Spark/als" active-action="action-notesSparkals"><div class="name"> ALS</div></a></li><li><a class="flat-box" title="/notes/Spark/k-means" href="/notes/Spark/k-means" active-action="action-notesSparkk-means"><div class="name"> K-Means</div></a></li></ul></div></section><div class="widget-sticky pjax"><section class="widget toc-wrapper desktop mobile" id="toc-div"><header><i class="fa-duotone fa-list fa-fw" aria-hidden="true"></i> <span class="name">本文目录</span></header><div class="content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E9%9B%86"><span class="toc-text">数据集</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#user-artist-data-txt"><span class="toc-text">user_artist_data.txt</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#artist-data-txt"><span class="toc-text">artist_data.txt</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#artist-alias-txt"><span class="toc-text">artist_alias.txt</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%97%E6%B3%95"><span class="toc-text">算法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BA%A4%E6%9B%BF%E6%9C%80%E5%B0%8F%E4%BA%8C%E4%B9%98%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95-Alternating-Least-Squares%EF%BC%8CALS"><span class="toc-text">交替最小二乘推荐算法 (Alternating Least Squares,ALS)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A8%E8%8D%90%E8%B4%A8%E9%87%8F%E8%AF%84%E4%BB%B7%E6%8C%87%E6%A0%87AUC"><span class="toc-text">推荐质量评价指标 AUC</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%9E%E9%AA%8C%E8%BF%87%E7%A8%8B"><span class="toc-text">实验过程</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E9%A2%84%E5%A4%84%E7%90%86"><span class="toc-text">数据预处理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE%E6%96%87%E4%BB%B6%EF%BC%8C%E5%B9%B6%E4%B8%8A%E4%BC%A0%E8%87%B3HDFS"><span class="toc-text">获取数据文件,并上传至 HDFS</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AF%BB%E5%85%A5%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%BD%AC%E6%8D%A2%E6%88%90DataFrame%E5%A4%87%E7%94%A8"><span class="toc-text">读入数据,转换成 DataFrame 备用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B1%95%E7%A4%BA%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F%E5%9F%BA%E6%9C%AC%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF"><span class="toc-text">展示数据格式基本统计信息</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E6%9C%AC%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF"><span class="toc-text">基本统计信息</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9E%84%E5%BB%BAALS%E6%A8%A1%E5%9E%8B"><span class="toc-text">构建 ALS 模型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%A3%80%E6%9F%A5%E6%8E%A8%E8%8D%90%E7%BB%93%E6%9E%9C"><span class="toc-text">检查推荐结果</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%AD%E7%BB%83-%E9%AA%8C%E8%AF%81%E5%88%87%E5%88%86"><span class="toc-text">训练 - 验证切分</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%A1%E7%AE%97AUC"><span class="toc-text">计算 AUC</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%80%89%E6%8B%A9%E8%B6%85%E5%8F%82%E6%95%B0"><span class="toc-text">选择超参数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BA%A7%E7%94%9F%E6%8E%A8%E8%8D%90"><span class="toc-text">产生推荐</span></a></li></ol></li></ol></div></section></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div><div class="pjax"></div></aside><pjax><script>window.pdata={},pdata.ispage=!1,pdata.commentPath="",pdata.commentPlaceholder="",pdata.commentConfig={};var l_header=document.getElementById("l_header");l_header.classList.add("show");var cover_wrapper=document.querySelector("#l_cover .cover-wrapper"),scroll_down=document.getElementById("scroll-down");cover_wrapper.id="none",cover_wrapper.style.display="none",scroll_down.style.display="none"</script></pjax></div><footer class="footer clearfix" itemscope="" itemtype="http://schema.org/WPFooter"><br><br><div class="aplayer-container"><div class="aplayer-local"></div></div><br><div class="social-wrapper" itemprop="about" itemscope="" itemtype="http://schema.org/Thing"><a href="/atom.xml" class="social fa-duotone fa-rss flat-btn" target="_blank" rel="external nofollow noopener noreferrer" itemprop="url"></a><a href="https://mhuig.top/contact/" class="social fa-duotone fa-envelope flat-btn" target="_blank" rel="external nofollow noopener noreferrer" itemprop="url"></a><a href="https://github.com/MHuiG" class="social fa-brands fa-github flat-btn" target="_blank" rel="external nofollow noopener noreferrer" itemprop="url"></a><a href="https://t.me/MHuiG" class="social fa-brands fa-telegram flat-btn" target="_blank" rel="external nofollow noopener noreferrer" itemprop="url"></a></div><div><p>博客内容遵循 <a target="_blank" rel="external nofollow noopener noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans">署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</a></p></div><div class="copyright"><p><a href="https://icp.gov.moe" target="_blank" rel="external nofollow noopener noreferrer">萌ICP备</a> <a href="https://icp.gov.moe/?keyword=2020012138" target="_blank" rel="external nofollow noopener noreferrer">2020012138号</a><br><a target="_blank" rel="noopener" href="https://mhuig.top/">Copyright © Since 2018 MHuiG</a></p></div></footer><a id="s-top" class="fa-solid fa-arrow-up fa-fw" title="top"></a></div></div><div><script>volantis.dom.bodyAnchor=volantis.dom.$(document.getElementById("safearea")),volantis.dom.topBtn=volantis.dom.$(document.getElementById("s-top")),volantis.dom.wrapper=volantis.dom.$(document.getElementById("wrapper")),volantis.dom.coverAnchor=volantis.dom.$(document.querySelector("#l_cover .cover-wrapper")),volantis.dom.switcher=volantis.dom.$(document.querySelector("#l_header .switcher .s-search")),volantis.dom.header=volantis.dom.$(document.getElementById("l_header")),volantis.dom.search=volantis.dom.$(document.querySelector("#l_header .m_search")),volantis.dom.mPhoneList=volantis.dom.$(document.querySelectorAll("#l_header .m-phone .list-v"))</script><script>volantis.css("https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/libs/@fortawesome/fontawesome-pro/css/all.min.css")</script><script src="/js/app.js"></script><script>const rootElement=document.documentElement,darkModeStorageKey="color-scheme",rootElementDarkModeAttributeName="color-scheme",setLS=(e,t)=>{localStorage.setItem(e,t)},removeLS=e=>{localStorage.removeItem(e)},getLS=e=>localStorage.getItem(e),getModeFromCSSMediaQuery=()=>window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",resetRootDarkModeAttributeAndLS=()=>{rootElement.removeAttribute("color-scheme"),removeLS("color-scheme")},validColorModeKeys={dark:!0,light:!0},applyCustomDarkModeSettings=e=>{const t=e||getLS("color-scheme");getCustomDarkMode(),t===getModeFromCSSMediaQuery()?resetRootDarkModeAttributeAndLS():validColorModeKeys[t]?rootElement.setAttribute("color-scheme",t):resetRootDarkModeAttributeAndLS()},invertDarkModeObj={dark:"light",light:"dark"},getCustomDarkMode=()=>{let e=getLS("color-scheme");if(validColorModeKeys[e])e=invertDarkModeObj[e];else{if(null!==e)return;e=invertDarkModeObj[getModeFromCSSMediaQuery()]}volantis.dark.mode="dark"==e?"light":"dark"},toggleCustomDarkMode=()=>{let e=getLS("color-scheme");if(validColorModeKeys[e])e=invertDarkModeObj[e];else{if(null!==e)return;e=invertDarkModeObj[getModeFromCSSMediaQuery()]}return setLS("color-scheme",e),e};function bindToggleButton(){document.querySelectorAll("#wrapper .toggle-mode-btn,#rightmenu-wrapper .toggle-mode-btn").forEach((function(e){volantis.dom.$(e).on("click",volantis.dark.toggle)}))}volantis.dark.toggle=()=>{const e=toggleCustomDarkMode();applyCustomDarkModeSettings(e),volantis.dark.method.toggle.start()},applyCustomDarkModeSettings(),document.addEventListener("DOMContentLoaded",(()=>{volantis.requestAnimationFrame(bindToggleButton)})),volantis.pjax.push(bindToggleButton);const darkModelListeners={dark:e=>{e.matches&&(volantis.dark.mode="dark"),volantis.dark.method.toggle.start()},light:e=>{e.matches&&(volantis.dark.mode="light"),volantis.dark.method.toggle.start()}};window.matchMedia("(prefers-color-scheme: dark)").addListener(darkModelListeners.dark),window.matchMedia("(prefers-color-scheme: light)").addListener(darkModelListeners.light)</script><script>function loadIssuesJS(){null!=document.getElementById("sites-api")&&"undefined"==typeof SitesJS&&volantis.js("/js/plugins/tags/sites.js");null!=document.getElementById("friends-api")&&"undefined"==typeof FriendsJS&&volantis.js("/js/plugins/tags/friends.js");null!=document.getElementById("contributors-api")&&"undefined"==typeof ContributorsJS&&volantis.js("/js/plugins/tags/contributors.js")}loadIssuesJS(),volantis.pjax.push((()=>{loadIssuesJS()}))</script><script defer="" src="https://cdn.bootcdn.net/ajax/libs/vanilla-lazyload/17.1.0/lazyload.min.js"></script><script>window.lazyLoadOptions={elements_selector:".lazyload",threshold:0},window.addEventListener("LazyLoad::Initialized",(function(n){window.lazyLoadInstance=n.detail.instance}),!1),document.addEventListener("DOMContentLoaded",(function(){lazyLoadInstance.update()})),document.addEventListener("pjax:complete",(function(){lazyLoadInstance.update()}))</script><script>window.FPConfig={delay:0,ignoreKeywords:["#"],maxRPS:6,hoverDelay:0}</script><script defer="" src="https://static.mhuig.top/npm/volantis-static@0.0.1660614606622/libs/flying-pages/flying-pages.min.js"></script><script>volantis.css("https://cdn.bootcdn.net/ajax/libs/aplayer/1.10.1/APlayer.min.css"),volantis.js("https://cdn.bootcdn.net/ajax/libs/aplayer/1.10.1/APlayer.min.js").then((()=>{function e(){document.querySelector(".aplayer-local-min")&&document.querySelectorAll(".aplayer-local-min").forEach((e=>{new APlayer(Object.assign({container:e,mini:!0,order:"list",volume:"0.7",autoplay:!1,loop:"all",theme:"#1BCDFC",listMaxHeight:"320px",listFolded:"true",preload:"auto",lrcType:3,audio:[{name:"虹之间",artist:"钢琴版伴奏",url:"https://blog.mhuig.top/music-Archive/BetweenTheRainbow.mp3",lrc:"https://blog.mhuig.top/music-Archive/BetweenTheRainbow.lrc",cover:"https://blog.mhuig.top/music-Archive/BetweenTheRainbow.jpg"},{name:"Avem",artist:"Alan Walker",url:"https://blog.mhuig.top/music-Archive/Avem.mp3",lrc:"https://blog.mhuig.top/music-Archive/Avem.lrc",cover:"https://blog.mhuig.top/music-Archive/Avem.jpg"},{name:"Fly",artist:"Marshmello / Leau Culver",url:"https://blog.mhuig.top/music-Archive/fly.mp3",lrc:"https://blog.mhuig.top/music-Archive/fly.lrc",cover:"https://blog.mhuig.top/music-Archive/fly.jpg"},{name:"Alone",artist:"Marshmello",url:"https://blog.mhuig.top/music-Archive/alone.mp3",lrc:"https://blog.mhuig.top/music-Archive/alone.lrc",cover:"https://blog.mhuig.top/music-Archive/alone.jpg"}]},JSON.parse(e.querySelector(".aplayer-local-min-conf").innerText)))}))}document.querySelectorAll(".aplayer-local").forEach((e=>{new APlayer({container:e,fixed:!1,order:"list",volume:"0.7",autoplay:!1,loop:"all",theme:"#1BCDFC",listMaxHeight:"320px",listFolded:"true",preload:"auto",lrcType:3,audio:[{name:"虹之间",artist:"钢琴版伴奏",url:"https://blog.mhuig.top/music-Archive/BetweenTheRainbow.mp3",lrc:"https://blog.mhuig.top/music-Archive/BetweenTheRainbow.lrc",cover:"https://blog.mhuig.top/music-Archive/BetweenTheRainbow.jpg"},{name:"Avem",artist:"Alan Walker",url:"https://blog.mhuig.top/music-Archive/Avem.mp3",lrc:"https://blog.mhuig.top/music-Archive/Avem.lrc",cover:"https://blog.mhuig.top/music-Archive/Avem.jpg"},{name:"Fly",artist:"Marshmello / Leau Culver",url:"https://blog.mhuig.top/music-Archive/fly.mp3",lrc:"https://blog.mhuig.top/music-Archive/fly.lrc",cover:"https://blog.mhuig.top/music-Archive/fly.jpg"},{name:"Alone",artist:"Marshmello",url:"https://blog.mhuig.top/music-Archive/alone.mp3",lrc:"https://blog.mhuig.top/music-Archive/alone.lrc",cover:"https://blog.mhuig.top/music-Archive/alone.jpg"}]})})),e(),volantis.pjax.push(e,"aplayerMin")}))</script><script>function check_giscus(){return"dark"===volantis.dark.mode?volantis.giscus.Theme="dark":volantis.giscus.Theme="light",document.getElementById("giscus_container")}function pjax_giscus(){const t=check_giscus();if(!t)return;let s=Object.assign({theme:{light:"light",dark:"dark"},repo:"MHuiG/talk","repo-id":"MDEwOlJlcG9zaXRvcnkyODQ4NDg1NTg=",category:"Giscus","category-id":"DIC_kwDOEPpxrs4B_X67",mapping:"pathname","reactions-enabled":"1","emit-metadata":"1",lang:"zh-CN","input-position":"top"},pdata.commentConfig);const e=document.createElement("script");e.setAttribute("src","https://giscus.app/client.js"),Object.keys(s).forEach((t=>{"theme"!=t&&e.setAttribute("data-"+t,s[t])})),e.setAttribute("data-theme",volantis.giscus.Theme),e.setAttribute("crossorigin","anonymous"),t.appendChild(e)}function dark_giscus(){if(!check_giscus())return;const t={setConfig:{theme:volantis.giscus.Theme}};document.querySelector("iframe.giscus-frame").contentWindow.postMessage({giscus:t},"https://giscus.app")}volantis.layoutHelper("comments",'<div id="giscus_container"></div>'),volantis.giscus={},pjax_giscus(),volantis.pjax.push(pjax_giscus),volantis.dark.push(dark_giscus)</script><script>async function loadSearchScript(){return volantis.js("/js/search/hexo.js")}function loadSearchService(){loadSearchScript(),document.querySelectorAll(".input.u-search-input").forEach((e=>{e.removeEventListener("focus",loadSearchService,!1)})),document.querySelectorAll(".u-search-form").forEach((e=>{e.addEventListener("submit",(e=>{e.preventDefault()}),!1)}))}function OpenSearch(e){"undefined"==typeof SearchService?loadSearchScript().then((()=>{SearchService.setQueryText(e),SearchService.search()})):(SearchService.setQueryText(e),SearchService.search())}if(window.location.search&&/^\?s=/g.test(window.location.search)){OpenSearch(decodeURI(window.location.search).replace(/\ /g,"-").replace(/^\?s=/g,""))}document.querySelectorAll(".input.u-search-input").forEach((e=>{e.addEventListener("focus",loadSearchService,!1)}))</script><script>function pjax_highlightjs_copyCode(){(document.querySelector(".highlight .code pre")||document.querySelector(".article pre code"))&&VolantisApp.utilCopyCode(".highlight .code pre, .article pre code")}volantis.requestAnimationFrame(pjax_highlightjs_copyCode),volantis.pjax.push(pjax_highlightjs_copyCode)</script><script>function load_swiper(){document.querySelectorAll(".swiper-container")[0]&&(volantis.css("https://cdn.bootcdn.net/ajax/libs/Swiper/8.3.2/swiper-bundle.min.css"),volantis.js("https://cdn.bootcdn.net/ajax/libs/Swiper/8.3.2/swiper-bundle.min.js").then((()=>{pjax_swiper()})))}function pjax_swiper(){volantis.swiper=new Swiper(".swiper-container",{slidesPerView:"auto",spaceBetween:8,centeredSlides:!0,loop:!0,pagination:{el:".swiper-pagination",clickable:!0},navigation:{nextEl:".swiper-button-next",prevEl:".swiper-button-prev"}})}load_swiper(),volantis.pjax.push((()=>{document.querySelectorAll(".swiper-container")[0]&&(void 0===volantis.swiper?load_swiper():pjax_swiper())}))</script><script>volantis.css("https://cdn.bootcdn.net/ajax/libs/pace/1.2.4/themes/blue/pace-theme-minimal.min.css"),volantis.js("https://cdn.bootcdn.net/ajax/libs/pace/1.2.4/pace.min.js").then((()=>{Pace.options.restartOnPushState=!1,volantis.pjax.send(Pace.restart,"Pace.restart"),volantis.scroll.push(volantis.debounce((()=>{Pace.stop(),Pace.trigger("start"),Pace.bar.update(100*volantis.scroll.progress()),document.body.className=document.body.className.replaceAll("pace-running ","")})),"阅读进度")}))</script><pjax></pjax><script>function listenSidebarTOC(){const t=document.querySelectorAll(".toc li");if(!t.length)return;const e=[];Array.from(t).forEach((t=>{const n=t.querySelector(".toc-link"),i=document.getElementById(n.getAttribute("href")?decodeURI(n.getAttribute("href")).replace("#",""):n.getAttribute("toc-action").split("toc-")[1]);return e.push(i),n.getAttribute("href")&&(n.setAttribute("toc-action","toc-"+decodeURI(n.getAttribute("href")).replace("#","")),n.removeAttribute("href")),i&&i.id&&n.addEventListener("click",(t=>{t.preventDefault(),volantis.scroll.to(i,{addTop:5,observer:!0}),history.pushState(null,document.title,"#"+i.id)})),i}));function n(t){if(t.classList.contains("active-current"))return;document.querySelectorAll(".toc .active").forEach((t=>{t.classList.remove("active","active-current")})),t.classList.add("active","active-current");let e=t.parentNode;for(;!e.matches(".toc");)e.matches("li")&&e.classList.add("active"),e=e.parentNode}volantis.activateNavIndex=0,n(t[volantis.activateNavIndex]),e[0]&&volantis.scroll.push(volantis.debounce((()=>{if(e[0].getBoundingClientRect().top>=0)volantis.activateNavIndex=0;else if(e[e.length-1].getBoundingClientRect().top<0)volantis.activateNavIndex=e.length-1;else for(let t=0;t<e.length;t++){const n=e[t],i=e[(t+1)%e.length];if(n.getBoundingClientRect().top<0&&i.getBoundingClientRect().top>=0){volantis.activateNavIndex=t;break}}n(t[volantis.activateNavIndex])})),"sidebar-toc")}document.addEventListener("DOMContentLoaded",(()=>{volantis.requestAnimationFrame(listenSidebarTOC)})),volantis.pjax.push(listenSidebarTOC,"listenSidebarTOC")</script><script>try{let e=(e,t,n=2)=>Math.abs(e-t)<=n,t=(t,n)=>!e(t.width,n.width)||!e(t.height,n.height),n=new WeakMap,i=(e,i=e.getClientBoundingRect())=>{let o=n.get(e);o&&!t(o,i)||(n.set(e,i),e.style["contain-intrinsic-size"]=`${i.width}px ${i.height}px`)},o=new IntersectionObserver(((e,t)=>{e.forEach((e=>{i(e.target,e.boundingClientRect)}))}),{rootMargin:"500px 0px 500px 0px"}),r=new ResizeObserver(((e,t)=>{e.forEach((e=>{i(e.target,e.contentRect)}))})),s=e=>{let t=document.querySelectorAll(e);t.length&&(t.forEach((e=>{o.observe(e),r.observe(e)})),requestAnimationFrame((()=>{requestAnimationFrame((()=>{t[0].style["content-visibility"]="auto"}))})))},a=()=>{"content-visibility"in document.documentElement.style&&s(".post-story")};a(),volantis.pjax.push(a)}catch(e){console.log(e)}</script><script>document.onreadystatechange=function(){if("complete"==document.readyState){const{saveData:e,effectiveType:t}=navigator.connection||navigator.mozConnection||navigator.webkitConnection||{};("none"==getComputedStyle(document.querySelector("#safearea"),null).display||e||/2g/.test(t))&&(document.querySelectorAll(".reveal").forEach((function(e){e.style.opacity="1"})),document.querySelector("#safearea").style.display="block")}}</script><script src="https://cdn.bootcdn.net/ajax/libs/pjax/0.2.8/pjax.min.js"></script><script>const performanceMonitor={slowThreshold:800,slowCount:0,maxSlowAllowed:1,requestStartTime:0,start(){this.requestStartTime=Date.now()},check(){Date.now()-this.requestStartTime>this.slowThreshold?this.slowCount++:this.slowCount=0},res(){return this.slowCount>=this.maxSlowAllowed}};var pjax;document.addEventListener("DOMContentLoaded",(function(){pjax=new Pjax({elements:'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox]):not([onclick="return false;"]):not([onclick="return!1"]):not([target="_blank"]):not([target="view_window"]):not([href$=".xml"])',selectors:["head title","head meta[name=keywords]","head meta[name=description]","#l_main","#pjax-header-nav-list",".pjax","pjax","meta[name=robots]","link[rel=canonical]","meta[property='og:title']","meta[property='og:description']","meta[property='og:url']","meta[property='og:image']","script[type='application/ld+json']"],cacheBust:!1,timeout:900})})),document.addEventListener("pjax:send",(function(e){window.stop(),performanceMonitor.start();try{var t=window.location.pathname,o=e.triggerElement.href,n=[""];""!=n[0]&&n.forEach((e=>{-1==t.indexOf(e)&&-1==o.indexOf(e)||(window.location.href=o)})),performanceMonitor.res()&&(window.location.href=o)}catch(e){}volantis.pjax.method.send.start()})),document.addEventListener("pjax:complete",(function(){performanceMonitor.check(),document.querySelectorAll("script[data-pjax], .pjax-reload script").forEach((e=>{const t=e.text||e.textContent||e.innerHTML||"",o=document.createElement("script");Object.keys(e.attributes).forEach((t=>{o.setAttribute(e.attributes[t].nodeName,e.attributes[t].nodeValue)})),t&&o.appendChild(document.createTextNode(t)),e.parentNode.replaceChild(o,e)})),volantis.pjax.method.complete.start()})),document.addEventListener("pjax:error",(function(e){"pjax"===volantis.debug?(console.error(e),console.log("pjax error: \n"+JSON.stringify(e))):(volantis.pjax.method.error.start(),window.location.href=e.triggerElement.href)}))</script></div><pjax> <a style="display:none" target="_blank" rel="external nofollow noopener noreferrer" href="https://bot-trap.mhuig.top/">Are You A Robot?</a></pjax><script>(()=>{function t(){if("localhost:4000"!=window.location.host&&!/blog\.mhuig\.top/.test(window.location.host)){const t=document.createElement("meta");t.name="robots",t.content=atob("bm9pbmRleCwgbm9mb2xsb3csIG5vYXJjaGl2ZQ=="),document.head.appendChild(t)}}function o(){document.querySelector("figcaption")&&document.querySelectorAll("figcaption").forEach((t=>{volantis.dom.$(t).on("click",(function(){const t=!window.CodeBlockFullscreen;window.CodeBlockFullscreen=t;const o=document.getElementById("post")||document.getElementById("docs")||document.getElementById("page");if(!o)return;const e=this.parentElement,n=e.parentElement,l=document.documentElement,c=document.querySelectorAll(".highlight > table .gutter");o.classList.toggle("code-block-fullscreen",t),e.classList.toggle("code-block-fullscreen",t),n.classList.toggle("code-block-fullscreen",t),e.classList.toggle("code-block-fullscreen-overflow-auto",t),l.classList.toggle("code-block-fullscreen-html-scroll",t),c.forEach((o=>{o.classList.toggle("code-block-fullscreen-gutter",t)}))}))}))}t(),volantis.pjax.push(t),top.location!=self.location&&(top.location=self.location),"mhuig.github.io"==window.location.host||"localhost:4000"==window.location.host||/mhuig\.top$/.test(window.location.host)||/kix\.moe$/.test(window.location.host)||/mhuig/.test(window.location.host)||/ipfs/.test(window.location.host)||(window.location.href=atob("aHR0cHM6Ly9ibG9nLm1odWlnLnRvcC8=")),o(),volantis.pjax.push(o);const e=[{month:12,day:13},function(){const t=(new Date).getFullYear(),o=t%100,e=t>=2e3?4.81:5.59,n=Math.floor(o/4),l=Math.floor(.2422*o+e)-n;return{month:4,day:Math.max(4,l)}}(),{month:7,day:7},{month:9,day:18},{month:9,day:30}];function n(){document.documentElement.classList.remove("mourning-mode");if(!["/","/index.html","/index.htm","/index"].includes(window.location.pathname))return;const t=new Date,o=t.getMonth()+1,n=t.getDate();e.some((t=>t.month===o&&t.day===n))&&document.documentElement.classList.add("mourning-mode")}const l=document.createElement("style");l.textContent="\n      html.mourning-mode {\n        filter: grayscale(100%);\n        -webkit-filter: grayscale(100%);\n        transition: filter 0.5s ease;\n      }\n    ",document.head.appendChild(l),n(),document.addEventListener("pjax:complete",n)})()</script></body></html>