CINXE.COM
Recommending movies: retrieval | TensorFlow Recommenders
<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="157101835696-ooapojlodmuabs2do2vuhhnf90bccmoi.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="TensorFlow"> <meta property="og:type" content="website"><meta name="theme-color" content="#ff6f00"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/tensorflow/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/css/app.css"> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/images/favicon.png"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/images/apple-touch-icon-180x180.png"><link rel="canonical" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval"><link rel="search" type="application/opensearchdescription+xml" title="TensorFlow" href="https://www.tensorflow.org/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval" /><link rel="alternate" hreflang="x-default" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval" /><link rel="alternate" hreflang="ar" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=ar" /><link rel="alternate" hreflang="bn" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=bn" /><link rel="alternate" hreflang="fa" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=fa" /><link rel="alternate" hreflang="fr" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=fr" /><link rel="alternate" hreflang="he" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=he" /><link rel="alternate" hreflang="hi" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=hi" /><link rel="alternate" hreflang="id" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=id" /><link rel="alternate" hreflang="it" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=it" /><link rel="alternate" hreflang="ja" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=ja" /><link rel="alternate" hreflang="ko" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=ko" /><link rel="alternate" hreflang="pl" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=pt-br" /><link rel="alternate" hreflang="ru" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=ru" /><link rel="alternate" hreflang="es-419" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=es-419" /><link rel="alternate" hreflang="th" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=th" /><link rel="alternate" hreflang="tr" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=tr" /><link rel="alternate" hreflang="vi" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval?hl=vi" /><title>Recommending movies: retrieval | TensorFlow Recommenders</title> <meta property="og:title" content="Recommending movies: retrieval | TensorFlow Recommenders"><meta property="og:url" content="https://www.tensorflow.org/recommenders/examples/basic_retrieval"><meta property="og:image" content="https://www.tensorflow.org/static/site-assets/images/project-logos/tensorflow-recommenders-logo-social.png"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="675"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Recommending movies: retrieval" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Recommenders", "item": "https://www.tensorflow.org/recommenders" },{ "@type": "ListItem", "position": 2, "name": "Recommending movies: retrieval", "item": "https://www.tensorflow.org/recommenders/examples/basic_retrieval" }] } </script> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="page" theme="tensorflow-theme" type="article" layout="docs" display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <a href="#main-content" class="skip-link button"> Skip to main content </a> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner"> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="tensorFlow" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <img src="https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/images/lockup.svg" class="devsite-site-logo" alt="TensorFlow"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <devsite-tabs class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab > <a href="https://www.tensorflow.org/install" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/install" track-type="nav" track-metadata-position="nav - install" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Install" track-name="install" > Install </a> </tab> <tab class="devsite-dropdown "> <a href="https://www.tensorflow.org/learn" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/learn" track-type="nav" track-metadata-position="nav - learn" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" > Learn </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Learn" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/learn" track-metadata-position="nav - learn" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column tfo-menu-column-learn"> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/learn" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/learn" track-metadata-position="nav - learn" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Introduction </div> <div class="devsite-nav-item-description"> New to TensorFlow? </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/tutorials" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/tutorials" track-metadata-position="nav - learn" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Tutorials </div> <div class="devsite-nav-item-description"> Learn how to use TensorFlow with end-to-end examples </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/guide" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/guide" track-metadata-position="nav - learn" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Guide </div> <div class="devsite-nav-item-description"> Learn framework concepts and components </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/resources/learn-ml" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/resources/learn-ml" track-metadata-position="nav - learn" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Learn ML </div> <div class="devsite-nav-item-description"> Educational resources to master your path with TensorFlow </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown "> <a href="https://www.tensorflow.org/api" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/api" track-type="nav" track-metadata-position="nav - api" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: API" track-name="api" > API </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for API" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/api" track-metadata-position="nav - api" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: API" track-name="api" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/api/stable" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/api/stable" track-metadata-position="nav - api" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> TensorFlow (v2.16.1) </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/versions" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/versions" track-metadata-position="nav - api" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Versions… </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://js.tensorflow.org/api/latest/" track-type="nav" track-metadata-eventdetail="https://js.tensorflow.org/api/latest/" track-metadata-position="nav - api" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> TensorFlow.js </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/lite/api_docs" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/lite/api_docs" track-metadata-position="nav - api" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> TensorFlow Lite </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/tfx/api_docs" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/tfx/api_docs" track-metadata-position="nav - api" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> TFX </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown devsite-active "> <a href="https://www.tensorflow.org/resources" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/resources" track-type="nav" track-metadata-position="nav - resources" track-metadata-module="primary nav" aria-label="Resources, selected" data-category="Site-Wide Custom Events" data-label="Tab: Resources" track-name="resources" > Resources </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Resources" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/resources" track-metadata-position="nav - resources" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Resources" track-name="resources" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-title" role="heading" tooltip>LIBRARIES</li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/js" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/js" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> TensorFlow.js </div> <div class="devsite-nav-item-description"> Develop web ML applications in JavaScript </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/lite" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/lite" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> TensorFlow Lite </div> <div class="devsite-nav-item-description"> Deploy ML on mobile, microcontrollers and other edge devices </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/tfx" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/tfx" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> TFX </div> <div class="devsite-nav-item-description"> Build production ML pipelines </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/resources/libraries-extensions" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/resources/libraries-extensions" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="libraries" tooltip > <div class="devsite-nav-item-title"> All libraries </div> <div class="devsite-nav-item-description"> Create advanced models and extend TensorFlow </div> </a> </li> </ul> </div> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-title" role="heading" tooltip>RESOURCES</li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/resources/models-datasets" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/resources/models-datasets" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="resources" tooltip > <div class="devsite-nav-item-title"> Models & datasets </div> <div class="devsite-nav-item-description"> Pre-trained models and datasets built by Google and the community </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/resources/tools" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/resources/tools" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="resources" tooltip > <div class="devsite-nav-item-title"> Tools </div> <div class="devsite-nav-item-description"> Tools to support and accelerate TensorFlow workflows </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/responsible_ai" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/responsible_ai" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="resources" tooltip > <div class="devsite-nav-item-title"> Responsible AI </div> <div class="devsite-nav-item-description"> Resources for every stage of the ML workflow </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/resources/recommendation-systems" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/resources/recommendation-systems" track-metadata-position="nav - resources" track-metadata-module="tertiary nav" track-metadata-module_headline="resources" tooltip > <div class="devsite-nav-item-title"> Recommendation systems </div> <div class="devsite-nav-item-description"> Build recommendation systems with open source tools </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown "> <a href="https://www.tensorflow.org/community" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/community" track-type="nav" track-metadata-position="nav - community" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" > Community </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Community" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/community" track-metadata-position="nav - community" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/community/groups" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/community/groups" track-metadata-position="nav - community" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Groups </div> <div class="devsite-nav-item-description"> User groups, interest groups and mailing lists </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/community/contribute" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/community/contribute" track-metadata-position="nav - community" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Contribute </div> <div class="devsite-nav-item-description"> Guide for contributing to code and documentation </div> </a> </li> <li class="devsite-nav-item"> <a href="https://blog.tensorflow.org/" track-type="nav" track-metadata-eventdetail="https://blog.tensorflow.org/" track-metadata-position="nav - community" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Blog </div> <div class="devsite-nav-item-description"> Stay up to date with all things TensorFlow </div> </a> </li> <li class="devsite-nav-item"> <a href="https://discuss.tensorflow.org" track-type="nav" track-metadata-eventdetail="https://discuss.tensorflow.org" track-metadata-position="nav - community" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Forum </div> <div class="devsite-nav-item-description"> Discussion platform for the TensorFlow community </div> </a> </li> </ul> </div> </div> </div> </tab> <tab class="devsite-dropdown "> <a href="https://www.tensorflow.org/about" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/about" track-type="nav" track-metadata-position="nav - why tensorflow" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Why TensorFlow" track-name="why tensorflow" > Why TensorFlow </a> <button aria-haspopup="menu" aria-expanded="false" aria-label="Dropdown menu for Why TensorFlow" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/about" track-metadata-position="nav - why tensorflow" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Why TensorFlow" track-name="why tensorflow" class="devsite-tabs-dropdown-toggle devsite-icon devsite-icon-arrow-drop-down"></button> <div class="devsite-tabs-dropdown" role="menu" aria-label="submenu" hidden> <div class="devsite-tabs-dropdown-content"> <div class="devsite-tabs-dropdown-column "> <ul class="devsite-tabs-dropdown-section "> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/about" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/about" track-metadata-position="nav - why tensorflow" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> About </div> </a> </li> <li class="devsite-nav-item"> <a href="https://www.tensorflow.org/about/case-studies" track-type="nav" track-metadata-eventdetail="https://www.tensorflow.org/about/case-studies" track-metadata-position="nav - why tensorflow" track-metadata-module="tertiary nav" tooltip > <div class="devsite-nav-item-title"> Case studies </div> </a> </li> </ul> </div> </div> </div> </tab> </nav> </devsite-tabs> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion project-name="TensorFlow Recommenders" tenant-name="TensorFlow" > <form class="devsite-search-form" action="https://www.tensorflow.org/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <a class="devsite-header-link devsite-top-button button gc-analytics-event" href="//github.com/tensorflow" data-category="Site-Wide Custom Events" data-label="Site header link" > GitHub </a> <devsite-user enable-profiles id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section "> <div class="devsite-header-background"> <div class="devsite-product-id-row" > <div class="devsite-product-description-row"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://www.tensorflow.org/recommenders" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="TensorFlow Recommenders" > Recommenders </a> </li> </ul> </div> </div> <div class="devsite-doc-set-nav-row"> <devsite-tabs class="lower-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Lower tabs"> <tab > <a href="https://www.tensorflow.org/recommenders" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/recommenders" track-type="nav" track-metadata-position="nav - overview" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" > Overview </a> </tab> <tab class="devsite-active"> <a href="https://www.tensorflow.org/recommenders/examples/quickstart" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/recommenders/examples/quickstart" track-type="nav" track-metadata-position="nav - guide & tutorials" track-metadata-module="primary nav" aria-label="Guide & Tutorials, selected" data-category="Site-Wide Custom Events" data-label="Tab: Guide & Tutorials" track-name="guide & tutorials" > Guide & Tutorials </a> </tab> <tab > <a href="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/all_symbols" class="devsite-tabs-content gc-analytics-event " track-metadata-eventdetail="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/all_symbols" track-type="nav" track-metadata-position="nav - api" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: API" track-name="api" > API </a> </tab> </nav> </devsite-tabs> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars > <div class="devsite-book-nav-filter" > <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="tensorFlow" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <img src="https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/images/lockup.svg" class="devsite-site-logo" alt="TensorFlow"> </picture> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/install" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Install" track-name="install" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Install" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Install </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/learn" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" > <span class="devsite-nav-text" tooltip menu="Learn"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Learn"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/api" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: API" track-name="api" data-category="Site-Wide Custom Events" data-label="Responsive Tab: API" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > API </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: API" track-name="api" > <span class="devsite-nav-text" tooltip menu="API"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="API"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/resources" class="devsite-nav-title gc-analytics-event devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Resources" track-name="resources" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Resources" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Resources </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Resources" track-name="resources" > <span class="devsite-nav-text" tooltip menu="Resources"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Resources"> </span> </span> </li> </ul> <ul class="devsite-nav-responsive-tabs"> <li class="devsite-nav-item"> <a href="/recommenders" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> </a> </li> <li class="devsite-nav-item"> <a href="/recommenders/examples/quickstart" class="devsite-nav-title gc-analytics-event devsite-nav-has-children devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Guide & Tutorials" track-name="guide & tutorials" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Guide & Tutorials" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip menu="_book"> Guide & Tutorials </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="_book"> </span> </a> </li> <li class="devsite-nav-item"> <a href="/recommenders/api_docs/python/tfrs/all_symbols" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: API" track-name="api" data-category="Site-Wide Custom Events" data-label="Responsive Tab: API" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > API </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/community" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Community" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Community </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Community" track-name="community" > <span class="devsite-nav-text" tooltip menu="Community"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Community"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="/about" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Why TensorFlow" track-name="why tensorflow" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Why TensorFlow" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Why TensorFlow </span> </a> <ul class="devsite-nav-responsive-tabs devsite-nav-has-menu "> <li class="devsite-nav-item"> <span class="devsite-nav-title" tooltip data-category="Site-Wide Custom Events" data-label="Tab: Why TensorFlow" track-name="why tensorflow" > <span class="devsite-nav-text" tooltip menu="Why TensorFlow"> More </span> <span class="devsite-nav-icon material-icons" data-icon="forward" menu="Why TensorFlow"> </span> </span> </li> </ul> </li> <li class="devsite-nav-item"> <a href="//github.com/tensorflow" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: GitHub" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > GitHub </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="_book"> <li class="devsite-nav-item"><a href="/recommenders/examples/quickstart" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/quickstart" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/quickstart" ><span class="devsite-nav-text" tooltip>Quickstart</span></a></li> <li class="devsite-nav-item devsite-nav-divider devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Beginner</span> </div></li> <li class="devsite-nav-item devsite-nav-expandable devsite-nav-accordion"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Recommender basics</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/recommenders/examples/basic_retrieval" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/basic_retrieval" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/basic_retrieval" ><span class="devsite-nav-text" tooltip>Recommending movies: retrieval</span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/basic_ranking" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/basic_ranking" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/basic_ranking" ><span class="devsite-nav-text" tooltip>Recommending movies: ranking</span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/diststrat_retrieval" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/diststrat_retrieval" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/diststrat_retrieval" ><span class="devsite-nav-text" tooltip>Retrieval with distribution strategy</span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/sequential_retrieval" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/sequential_retrieval" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/sequential_retrieval" ><span class="devsite-nav-text" tooltip>Retrieval with sequential model</span></a></li><li class="devsite-nav-item devsite-nav-external"><a href="/tfx/tutorials/tfx/recommenders" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /tfx/tutorials/tfx/recommenders" track-type="bookNav" track-name="click" track-metadata-eventdetail="/tfx/tutorials/tfx/recommenders" ><span class="devsite-nav-text" tooltip>Retrieval with TFX</span><span class="devsite-nav-icon material-icons" data-icon="external" data-title="External" aria-hidden="true"></span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/ranking_tfx" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/ranking_tfx" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/ranking_tfx" ><span class="devsite-nav-text" tooltip>Ranking with TFX</span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/tpu_embedding_layer" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/tpu_embedding_layer" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/tpu_embedding_layer" ><span class="devsite-nav-text" tooltip>Large Embeddings with TPU</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-expandable devsite-nav-accordion"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Using rich features</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/recommenders/examples/featurization" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/featurization" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/featurization" ><span class="devsite-nav-text" tooltip>Feature preprocessing</span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/context_features" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/context_features" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/context_features" ><span class="devsite-nav-text" tooltip>Leveraging context features</span></a></li><li class="devsite-nav-item"><a href="/recommenders/examples/deep_recommenders" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/deep_recommenders" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/deep_recommenders" ><span class="devsite-nav-text" tooltip>Building deep retrieval models</span></a></li></ul></div></li> <li class="devsite-nav-item devsite-nav-divider devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Intermediate</span> </div></li> <li class="devsite-nav-item"><a href="/recommenders/examples/multitask" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/multitask" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/multitask" ><span class="devsite-nav-text" tooltip>Multitask recommenders</span></a></li> <li class="devsite-nav-item"><a href="/recommenders/examples/dcn" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/dcn" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/dcn" ><span class="devsite-nav-text" tooltip>Cross networks</span></a></li> <li class="devsite-nav-item"><a href="/recommenders/examples/efficient_serving" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/efficient_serving" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/efficient_serving" ><span class="devsite-nav-text" tooltip>Efficient serving</span></a></li> <li class="devsite-nav-item"><a href="/recommenders/examples/listwise_ranking" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /recommenders/examples/listwise_ranking" track-type="bookNav" track-name="click" track-metadata-eventdetail="/recommenders/examples/listwise_ranking" ><span class="devsite-nav-text" tooltip>Listwise ranking</span></a></li> </ul> <ul class="devsite-nav-list" menu="Learn" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/learn" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Introduction" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Introduction </span> </a> </li> <li class="devsite-nav-item"> <a href="/tutorials" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Tutorials" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Tutorials </span> </a> </li> <li class="devsite-nav-item"> <a href="/guide" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Guide" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Guide </span> </a> </li> <li class="devsite-nav-item"> <a href="/resources/learn-ml" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn ML" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn ML </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="API" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/api/stable" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TensorFlow (v2.16.1)" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TensorFlow (v2.16.1) </span> </a> </li> <li class="devsite-nav-item"> <a href="/versions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Versions…" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Versions… </span> </a> </li> <li class="devsite-nav-item"> <a href="https://js.tensorflow.org/api/latest/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TensorFlow.js" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TensorFlow.js </span> </a> </li> <li class="devsite-nav-item"> <a href="/lite/api_docs" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TensorFlow Lite" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TensorFlow Lite </span> </a> </li> <li class="devsite-nav-item"> <a href="/tfx/api_docs" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TFX" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TFX </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Resources" aria-label="Side menu" hidden> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > LIBRARIES </span> </span> </li> <li class="devsite-nav-item"> <a href="/js" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TensorFlow.js" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TensorFlow.js </span> </a> </li> <li class="devsite-nav-item"> <a href="/lite" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TensorFlow Lite" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TensorFlow Lite </span> </a> </li> <li class="devsite-nav-item"> <a href="/tfx" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: TFX" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > TFX </span> </a> </li> <li class="devsite-nav-item"> <a href="/resources/libraries-extensions" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: All libraries" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > All libraries </span> </a> </li> <li class="devsite-nav-item devsite-nav-heading"> <span class="devsite-nav-title" tooltip > <span class="devsite-nav-text" tooltip > RESOURCES </span> </span> </li> <li class="devsite-nav-item"> <a href="/resources/models-datasets" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Models & datasets" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Models & datasets </span> </a> </li> <li class="devsite-nav-item"> <a href="/resources/tools" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Tools" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Tools </span> </a> </li> <li class="devsite-nav-item"> <a href="/responsible_ai" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Responsible AI" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Responsible AI </span> </a> </li> <li class="devsite-nav-item"> <a href="/resources/recommendation-systems" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Recommendation systems" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Recommendation systems </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Community" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/community/groups" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Groups" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Groups </span> </a> </li> <li class="devsite-nav-item"> <a href="/community/contribute" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Contribute" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Contribute </span> </a> </li> <li class="devsite-nav-item"> <a href="https://blog.tensorflow.org/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Blog" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Blog </span> </a> </li> <li class="devsite-nav-item"> <a href="https://discuss.tensorflow.org" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Forum" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Forum </span> </a> </li> </ul> <ul class="devsite-nav-list" menu="Why TensorFlow" aria-label="Side menu" hidden> <li class="devsite-nav-item"> <a href="/about" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: About" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > About </span> </a> </li> <li class="devsite-nav-item"> <a href="/about/case-studies" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Case studies" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Case studies </span> </a> </li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" id="main-content" class="devsite-main-content" has-book-nav has-sidebar > <div class="devsite-sidebar"> <div class="devsite-sidebar-content"> <devsite-toc class="devsite-nav" role="navigation" aria-label="On this page" depth="2" scrollbars ></devsite-toc> <devsite-recommendations-sidebar class="nocontent devsite-nav"> </devsite-recommendations-sidebar> </div> </div> <devsite-content> <article class="devsite-article"><style> /* Styles inlined from /site-assets/css/style.css */ /* override theme */ table img { max-width: 100%; } /* .devsite-terminal virtualenv prompt */ .tfo-terminal-venv::before { content: "(venv) $ " !important; } /* .devsite-terminal root prompt */ .tfo-terminal-root::before { content: "# " !important; } /* Used in links for type annotations in function/method signatures */ .tfo-signature-link a, .tfo-signature-link a:visited, .tfo-signature-link a:hover, .tfo-signature-link a:focus, .tfo-signature-link a:hover *, .tfo-signature-link a:focus * { text-decoration: none !important; } .tfo-signature-link a, .tfo-signature-link a:visited { border-bottom: 1px dotted #1a73e8; } .tfo-signature-link a:focus { border-bottom-style: solid; } /* .devsite-terminal Windows prompt */ .tfo-terminal-windows::before { content: "C:\\> " !important; } /* .devsite-terminal Windows prompt w/ virtualenv */ .tfo-terminal-windows-venv::before { content: "(venv) C:\\> " !important; } .tfo-diff-green-one-level + * { background: rgba(175, 245, 162, .6) !important; } .tfo-diff-green + * > * { background: rgba(175, 245, 162, .6) !important; } .tfo-diff-green-list + ul > li:first-of-type { background: rgba(175, 245, 162, .6) !important; } .tfo-diff-red-one-level + * { background: rgba(255, 230, 230, .6) !important; text-decoration: line-through !important; } .tfo-diff-red + * > * { background: rgba(255, 230, 230, .6) !important; text-decoration: line-through !important; } .tfo-diff-red-list + ul > li:first-of-type { background: rgba(255, 230, 230, .6) !important; text-decoration: line-through !important; } devsite-code .tfo-notebook-code-cell-output { max-height: 300px; overflow: auto; background: rgba(255, 247, 237, 1); /* orange bg to distinguish from input code cells */ } devsite-code .tfo-notebook-code-cell-output + .devsite-code-buttons-container button { background: rgba(255, 247, 237, .7); /* orange bg to distinguish from input code cells */ } devsite-code[dark-code] .tfo-notebook-code-cell-output { background: rgba(64, 78, 103, 1); /* medium slate */ } devsite-code[dark-code] .tfo-notebook-code-cell-output + .devsite-code-buttons-container button { background: rgba(64, 78, 103, .7); /* medium slate */ } /* override default table styles for notebook buttons */ .devsite-table-wrapper .tfo-notebook-buttons { display: inline-block; margin-left: 3px; width: auto; } .tfo-notebook-buttons td { padding-left: 0; padding-right: 20px; } .tfo-notebook-buttons a, .tfo-notebook-buttons :link, .tfo-notebook-buttons :visited { border-radius: 8px; box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .3), 0 1px 3px 1px rgba(60, 64, 67, .15); color: #202124; padding: 12px 17px; transition: box-shadow 0.2s; } .tfo-notebook-buttons a:hover, .tfo-notebook-buttons a:focus { box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .3), 0 2px 6px 2px rgba(60, 64, 67, .15); } .tfo-notebook-buttons tr { background: 0; border: 0; } /* on rendered notebook page, remove link to webpage since we're already here */ .tfo-notebook-buttons:not(.tfo-api) td:first-child { display: none; } .tfo-notebook-buttons td > a { -webkit-box-align: center; -ms-flex-align: center; align-items: center; display: -webkit-box; display: -ms-flexbox; display: flex; } .tfo-notebook-buttons td > a > img { margin-right: 8px; } /* landing pages */ .tfo-landing-row-item-inset-white { background-color: #fff; padding: 32px; } .tfo-landing-row-item-inset-white ol, .tfo-landing-row-item-inset-white ul { padding-left: 20px; } /* colab callout button */ .colab-callout-row devsite-code { border-radius: 8px 8px 0 0; box-shadow: none; } .colab-callout-footer { background: #e3e4e7; border-radius: 0 0 8px 8px; color: #37474f; padding: 20px; } .colab-callout-row devsite-code[dark-code] + .colab-callout-footer { background: #3f4f66; } .colab-callout-footer > .button { margin-top: 4px; color: #ff5c00; } .colab-callout-footer > a > span { vertical-align: middle; color: #37474f; padding-left: 10px; font-size: 14px; } .colab-callout-row devsite-code[dark-code] + .colab-callout-footer > a > span { color: #fff; } a.colab-button { background: rgba(255, 255, 255, .75); border: solid 1px rgba(0, 0, 0, .08); border-bottom-color: rgba(0, 0, 0, .15); border-radius: 4px; color: #aaa; display: inline-block; font-size: 11px !important; font-weight: 300; line-height: 16px; padding: 4px 8px; text-decoration: none; text-transform: uppercase; } a.colab-button:hover { background: white; border-color: rgba(0, 0, 0, .2); color: #666; } a.colab-button span { background: url(/images/colab_logo_button.svg) no-repeat 1px 1px / 20px; border-radius: 4px; display: inline-block; padding-left: 24px; text-decoration: none; } @media screen and (max-width: 600px) { .tfo-notebook-buttons td { display: block; } } /* guide and tutorials landing page cards and sections */ .tfo-landing-page-card { padding: 16px; box-shadow: 0 0 36px rgba(0,0,0,0.1); border-radius: 10px; } /* Page section headings */ .tfo-landing-page-heading h2, h2.tfo-landing-page-heading { font-family: "Google Sans", sans-serif; color: #425066; font-size: 30px; font-weight: 700; line-height: 40px; } /* Item title headings */ .tfo-landing-page-heading h3, h3.tfo-landing-page-heading, .tfo-landing-page-card h3, h3.tfo-landing-page-card { font-family: "Google Sans", sans-serif; color: #425066; font-size: 20px; font-weight: 500; line-height: 26px; } /* List of tutorials notebooks for subsites */ .tfo-landing-page-resources-ul { padding-left: 15px } .tfo-landing-page-resources-ul > li { margin: 6px 0; } /* Temporary fix to hide product description in header on landing pages */ devsite-header .devsite-product-description { display: none; } </style> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://www.tensorflow.org/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="TensorFlow" > TensorFlow </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://www.tensorflow.org/resources" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="" > Resources </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://www.tensorflow.org/recommenders" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="TensorFlow Recommenders" > Recommenders </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://www.tensorflow.org/recommenders/examples/quickstart" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="4" track-type="globalNav" track-name="breadcrumb" track-metadata-position="4" track-metadata-eventdetail="" > Guide & Tutorials </a> </li> </ul> <devsite-thumb-rating position="header"> </devsite-thumb-rating> </div> <h1 class="devsite-page-title" tabindex="-1"> Recommending movies: retrieval </h1> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <div class="devsite-page-title-meta"><devsite-view-release-notes></devsite-view-release-notes></div> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded > </devsite-toc> <div class="devsite-article-body clearfix "> <p><devsite-mathjax config="TeX-AMS-MML_SVG"></devsite-mathjax> </p> <!-- DO NOT EDIT! Automatically generated file. --> <div itemscope itemtype="http://developers.google.com/ReferenceObject"> <meta itemprop="name" content="Recommending movies: retrieval" /> <meta itemprop="path" content="Guide & Tutorials" /> <meta itemprop="property" content="tfrs.layers.factorized_top_k.BruteForce"/> <meta itemprop="property" content="tfrs.layers.factorized_top_k.ScaNN"/> <meta itemprop="property" content="tfrs.metrics.FactorizedTopK"/> <meta itemprop="property" content="tfrs.models.Model"/> <meta itemprop="property" content="tfrs.tasks.Retrieval"/> </div> <table class="tfo-notebook-buttons" align="left"> <td> <a target="_blank" href="https://www.tensorflow.org/recommenders/examples/basic_retrieval"><img src="https://www.tensorflow.org/images/tf_logo_32px.png">View on TensorFlow.org</a> </td> <td> <a target="_blank" href="https://colab.research.google.com/github/tensorflow/recommenders/blob/main/docs/examples/basic_retrieval.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png">Run in Google Colab</a> </td> <td> <a target="_blank" href="https://github.com/tensorflow/recommenders/blob/main/docs/examples/basic_retrieval.ipynb"><img src="https://www.tensorflow.org/images/GitHub-Mark-32px.png">View source on GitHub</a> </td> <td> <a href="https://storage.googleapis.com/tensorflow_docs/recommenders/docs/examples/basic_retrieval.ipynb"><img src="https://www.tensorflow.org/images/download_logo_32px.png">Download notebook</a> </td> </table> <p>Real-world recommender systems are often composed of two stages:</p> <ol> <li>The retrieval stage is responsible for selecting an initial set of hundreds of candidates from all possible candidates. The main objective of this model is to efficiently weed out all candidates that the user is not interested in. Because the retrieval model may be dealing with millions of candidates, it has to be computationally efficient.</li> <li>The ranking stage takes the outputs of the retrieval model and fine-tunes them to select the best possible handful of recommendations. Its task is to narrow down the set of items the user may be interested in to a shortlist of likely candidates.</li> </ol> <p>In this tutorial, we're going to focus on the first stage, retrieval. If you are interested in the ranking stage, have a look at our <a href="/recommenders/examples/basic_ranking">ranking</a> tutorial.</p> <p>Retrieval models are often composed of two sub-models:</p> <ol> <li>A query model computing the query representation (normally a fixed-dimensionality embedding vector) using query features.</li> <li>A candidate model computing the candidate representation (an equally-sized vector) using the candidate features</li> </ol> <p>The outputs of the two models are then multiplied together to give a query-candidate affinity score, with higher scores expressing a better match between the candidate and the query.</p> <p>In this tutorial, we're going to build and train such a two-tower model using the Movielens dataset.</p> <p>We're going to:</p> <ol> <li>Get our data and split it into a training and test set.</li> <li>Implement a retrieval model.</li> <li>Fit and evaluate it.</li> <li>Export it for efficient serving by building an approximate nearest neighbours (ANN) index.</li> </ol> <h2 id="the_dataset" data-text="The dataset" tabindex="-1">The dataset</h2> <p>The Movielens dataset is a classic dataset from the <a href="https://grouplens.org/datasets/movielens/">GroupLens</a> research group at the University of Minnesota. It contains a set of ratings given to movies by a set of users, and is a workhorse of recommender system research.</p> <p>The data can be treated in two ways:</p> <ol> <li>It can be interpreted as expressesing which movies the users watched (and rated), and which they did not. This is a form of implicit feedback, where users' watches tell us which things they prefer to see and which they'd rather not see.</li> <li>It can also be seen as expressesing how much the users liked the movies they did watch. This is a form of explicit feedback: given that a user watched a movie, we can tell roughly how much they liked by looking at the rating they have given.</li> </ol> <p>In this tutorial, we are focusing on a retrieval system: a model that predicts a set of movies from the catalogue that the user is likely to watch. Often, implicit data is more useful here, and so we are going to treat Movielens as an implicit system. This means that every movie a user watched is a positive example, and every movie they have not seen is an implicit negative example.</p> <h2 id="imports" data-text="Imports" tabindex="-1">Imports</h2> <p>Let's first get our imports out of the way.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code class='devsite-terminal' translate="no" dir="ltr">pip<span class="devsite-syntax-w"> </span>install<span class="devsite-syntax-w"> </span>-q<span class="devsite-syntax-w"> </span>tensorflow-recommenders</code> <code class='devsite-terminal' translate="no" dir="ltr">pip<span class="devsite-syntax-w"> </span>install<span class="devsite-syntax-w"> </span>-q<span class="devsite-syntax-w"> </span>--upgrade<span class="devsite-syntax-w"> </span>tensorflow-datasets</code> <code class='devsite-terminal' translate="no" dir="ltr">pip<span class="devsite-syntax-w"> </span>install<span class="devsite-syntax-w"> </span>-q<span class="devsite-syntax-w"> </span>scann</code></pre></devsite-code> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">os</span> <span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">pprint</span> <span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tempfile</span> <span class="devsite-syntax-kn">from</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">typing</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-kn">import</span> <span class="devsite-syntax-n">Dict</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">Text</span> <span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">numpy</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">as</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">np</span> <span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tensorflow</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">as</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tf</span> <span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tensorflow_datasets</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">as</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tfds</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> 2022-12-14 12:14:44.722984: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory 2022-12-14 12:14:44.723084: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory 2022-12-14 12:14:44.723093: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly. </pre></devsite-code> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-kn">import</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tensorflow_recommenders</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">as</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nn">tfrs</span> </code></pre></devsite-code> <h2 id="preparing_the_dataset" data-text="Preparing the dataset" tabindex="-1">Preparing the dataset</h2> <p>Let's first have a look at the data.</p> <p>We use the MovieLens dataset from <a href="https://www.tensorflow.org/datasets">Tensorflow Datasets</a>. Loading <code translate="no" dir="ltr">movielens/100k_ratings</code> yields a <code translate="no" dir="ltr">tf.data.Dataset</code> object containing the ratings data and loading <code translate="no" dir="ltr">movielens/100k_movies</code> yields a <code translate="no" dir="ltr">tf.data.Dataset</code> object containing only the movies data.</p> <p>Note that since the MovieLens dataset does not have predefined splits, all data are under <code translate="no" dir="ltr">train</code> split.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-c1"># Ratings data.</span> <span class="devsite-syntax-n">ratings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tfds</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">load</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s2">"movielens/100k-ratings"</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">split</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"train"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Features of all the available movies.</span> <span class="devsite-syntax-n">movies</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tfds</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">load</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s2">"movielens/100k-movies"</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">split</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-s2">"train"</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <p>The ratings dataset returns a dictionary of movie id, user id, the assigned rating, timestamp, movie information, and user information:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-k">for</span> <span class="devsite-syntax-n">x</span> <span class="devsite-syntax-ow">in</span> <span class="devsite-syntax-n">ratings</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">take</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">1</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">as_numpy_iterator</span><span class="devsite-syntax-p">():</span> <span class="devsite-syntax-n">pprint</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">pprint</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> {'bucketized_user_age': 45.0, 'movie_genres': array([7]), 'movie_id': b'357', 'movie_title': b"One Flew Over the Cuckoo's Nest (1975)", 'raw_user_age': 46.0, 'timestamp': 879024327, 'user_gender': True, 'user_id': b'138', 'user_occupation_label': 4, 'user_occupation_text': b'doctor', 'user_rating': 4.0, 'user_zip_code': b'53211'} 2022-12-14 12:14:51.221818: W tensorflow/core/kernels/data/cache_dataset_ops.cc:856] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead. </pre></devsite-code> <p>The movies dataset contains the movie id, movie title, and data on what genres it belongs to. Note that the genres are encoded with integer labels.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-k">for</span> <span class="devsite-syntax-n">x</span> <span class="devsite-syntax-ow">in</span> <span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">take</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">1</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">as_numpy_iterator</span><span class="devsite-syntax-p">():</span> <span class="devsite-syntax-n">pprint</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">pprint</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> {'movie_genres': array([4]), 'movie_id': b'1681', 'movie_title': b'You So Crazy (1994)'} 2022-12-14 12:14:51.385630: W tensorflow/core/kernels/data/cache_dataset_ops.cc:856] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead. </pre></devsite-code> <p>In this example, we're going to focus on the ratings data. Other tutorials explore how to use the movie information data as well to improve the model quality.</p> <p>We keep only the <code translate="no" dir="ltr">user_id</code>, and <code translate="no" dir="ltr">movie_title</code> fields in the dataset.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">ratings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">ratings</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">map</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-k">lambda</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-s2">"movie_title"</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"movie_title"</span><span class="devsite-syntax-p">],</span> <span class="devsite-syntax-s2">"user_id"</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"user_id"</span><span class="devsite-syntax-p">],</span> <span class="devsite-syntax-p">})</span> <span class="devsite-syntax-n">movies</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">map</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-k">lambda</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"movie_title"</span><span class="devsite-syntax-p">])</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tensorflow/python/autograph/pyct/static_analysis/liveness.py:83: Analyzer.lamba_check (from tensorflow.python.autograph.pyct.static_analysis.liveness) is deprecated and will be removed after 2023-09-23. Instructions for updating: Lambda fuctions will be no more assumed to be used in the statement where they are used, or at least in the same block. https://github.com/tensorflow/tensorflow/issues/56089 WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tensorflow/python/autograph/pyct/static_analysis/liveness.py:83: Analyzer.lamba_check (from tensorflow.python.autograph.pyct.static_analysis.liveness) is deprecated and will be removed after 2023-09-23. Instructions for updating: Lambda fuctions will be no more assumed to be used in the statement where they are used, or at least in the same block. https://github.com/tensorflow/tensorflow/issues/56089 </pre></devsite-code> <p>To fit and evaluate the model, we need to split it into a training and evaluation set. In an industrial recommender system, this would most likely be done by time: the data up to time \(T\) would be used to predict interactions after \(T\).</p> <p>In this simple example, however, let's use a random split, putting 80% of the ratings in the train set, and 20% in the test set.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">random</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">set_seed</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">42</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">shuffled</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">ratings</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">shuffle</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">100_000</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">seed</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-mi">42</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">reshuffle_each_iteration</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-kc">False</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">train</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">shuffled</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">take</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">80_000</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">test</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">shuffled</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">skip</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">80_000</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">take</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">20_000</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <p>Let's also figure out unique user ids and movie titles present in the data. </p> <p>This is important because we need to be able to map the raw values of our categorical features to embedding vectors in our models. To do that, we need a vocabulary that maps a raw feature value to an integer in a contiguous range: this allows us to look up the corresponding embeddings in our embedding tables.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">movie_titles</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">1_000</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">user_ids</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">ratings</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">1_000_000</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">map</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-k">lambda</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">x</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"user_id"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-n">unique_movie_titles</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">np</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">unique</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">np</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">concatenate</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nb">list</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">movie_titles</span><span class="devsite-syntax-p">)))</span> <span class="devsite-syntax-n">unique_user_ids</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">np</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">unique</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">np</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">concatenate</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nb">list</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">user_ids</span><span class="devsite-syntax-p">)))</span> <span class="devsite-syntax-n">unique_movie_titles</span><span class="devsite-syntax-p">[:</span><span class="devsite-syntax-mi">10</span><span class="devsite-syntax-p">]</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> array([b"'Til There Was You (1997)", b'1-900 (1994)', b'101 Dalmatians (1996)', b'12 Angry Men (1957)', b'187 (1997)', b'2 Days in the Valley (1996)', b'20,000 Leagues Under the Sea (1954)', b'2001: A Space Odyssey (1968)', b'3 Ninjas: High Noon At Mega Mountain (1998)', b'39 Steps, The (1935)'], dtype=object) </pre></devsite-code> <h2 id="implementing_a_model" data-text="Implementing a model" tabindex="-1">Implementing a model</h2> <p>Choosing the architecture of our model is a key part of modelling.</p> <p>Because we are building a two-tower retrieval model, we can build each tower separately and then combine them in the final model.</p> <h3 id="the_query_tower" data-text="The query tower" tabindex="-1">The query tower</h3> <p>Let's start with the query tower.</p> <p>The first step is to decide on the dimensionality of the query and candidate representations:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">embedding_dimension</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-mi">32</span> </code></pre></devsite-code> <p>Higher values will correspond to models that may be more accurate, but will also be slower to fit and more prone to overfitting.</p> <p>The second is to define the model itself. Here, we're going to use Keras preprocessing layers to first convert user ids to integers, and then convert those to user embeddings via an <code translate="no" dir="ltr">Embedding</code> layer. Note that we use the list of unique user ids we computed earlier as a vocabulary:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">user_model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Sequential</span><span class="devsite-syntax-p">([</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">StringLookup</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">vocabulary</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">unique_user_ids</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">mask_token</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-kc">None</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-c1"># We add an additional embedding to account for unknown tokens.</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Embedding</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nb">len</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">unique_user_ids</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-mi">1</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">embedding_dimension</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">])</span> </code></pre></devsite-code> <p>A simple model like this corresponds exactly to a classic <a href="https://ieeexplore.ieee.org/abstract/document/4781121">matrix factorization</a> approach. While defining a subclass of <a href="https://www.tensorflow.org/api_docs/python/tf/keras/Model"><code translate="no" dir="ltr">tf.keras.Model</code></a> for this simple model might be overkill, we can easily extend it to an arbitrarily complex model using standard Keras components, as long as we return an <code translate="no" dir="ltr">embedding_dimension</code>-wide output at the end.</p> <h3 id="the_candidate_tower" data-text="The candidate tower" tabindex="-1">The candidate tower</h3> <p>We can do the same with the candidate tower.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">movie_model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Sequential</span><span class="devsite-syntax-p">([</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">StringLookup</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">vocabulary</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">unique_movie_titles</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">mask_token</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-kc">None</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Embedding</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nb">len</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">unique_movie_titles</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-mi">1</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">embedding_dimension</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">])</span> </code></pre></devsite-code> <h3 id="metrics" data-text="Metrics" tabindex="-1">Metrics</h3> <p>In our training data we have positive (user, movie) pairs. To figure out how good our model is, we need to compare the affinity score that the model calculates for this pair to the scores of all the other possible candidates: if the score for the positive pair is higher than for all other candidates, our model is highly accurate.</p> <p>To do this, we can use the <a href="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/metrics/FactorizedTopK"><code translate="no" dir="ltr">tfrs.metrics.FactorizedTopK</code></a> metric. The metric has one required argument: the dataset of candidates that are used as implicit negatives for evaluation.</p> <p>In our case, that's the <code translate="no" dir="ltr">movies</code> dataset, converted into embeddings via our movie model:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">metrics</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tfrs</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">FactorizedTopK</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">candidates</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">128</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">map</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <h3 id="loss" data-text="Loss" tabindex="-1">Loss</h3> <p>The next component is the loss used to train our model. TFRS has several loss layers and tasks to make this easy.</p> <p>In this instance, we'll make use of the <code translate="no" dir="ltr">Retrieval</code> task object: a convenience wrapper that bundles together the loss function and metric computation:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">task</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tfrs</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">tasks</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Retrieval</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">metrics</span> <span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <p>The task itself is a Keras layer that takes the query and candidate embeddings as arguments, and returns the computed loss: we'll use that to implement the model's training loop.</p> <h3 id="the_full_model" data-text="The full model" tabindex="-1">The full model</h3> <p>We can now put it all together into a model. TFRS exposes a base model class (<a href="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/models/Model"><code translate="no" dir="ltr">tfrs.models.Model</code></a>) which streamlines building models: all we need to do is to set up the components in the <code translate="no" dir="ltr">__init__</code> method, and implement the <code translate="no" dir="ltr">compute_loss</code> method, taking in the raw features and returning a loss value.</p> <p>The base model will then take care of creating the appropriate training loop to fit our model.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-k">class</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nc">MovielensModel</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">tfrs</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Model</span><span class="devsite-syntax-p">):</span> <span class="devsite-syntax-k">def</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-fm">__init__</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">):</span> <span class="devsite-syntax-nb">super</span><span class="devsite-syntax-p">()</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-fm">__init__</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">movie_model</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">user_model</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">task</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Layer</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">task</span> <span class="devsite-syntax-k">def</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nf">compute_loss</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">Dict</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Text</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Tensor</span><span class="devsite-syntax-p">],</span> <span class="devsite-syntax-n">training</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-kc">False</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">-</span>> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Tensor</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-c1"># We pick out the user features and pass them into the user model.</span> <span class="devsite-syntax-n">user_embeddings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"user_id"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-c1"># And pick out the movie features and pass them into the movie model,</span> <span class="devsite-syntax-c1"># getting embeddings back.</span> <span class="devsite-syntax-n">positive_movie_embeddings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"movie_title"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-c1"># The task computes the loss and the metrics.</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">task</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">user_embeddings</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">positive_movie_embeddings</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <p>The <a href="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/models/Model"><code translate="no" dir="ltr">tfrs.Model</code></a> base class is a simply convenience class: it allows us to compute both training and test losses using the same method.</p> <p>Under the hood, it's still a plain Keras model. You could achieve the same functionality by inheriting from <a href="https://www.tensorflow.org/api_docs/python/tf/keras/Model"><code translate="no" dir="ltr">tf.keras.Model</code></a> and overriding the <code translate="no" dir="ltr">train_step</code> and <code translate="no" dir="ltr">test_step</code> functions (see <a href="https://www.tensorflow.org/guide/keras/customizing_what_happens_in_fit">the guide</a> for details):</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-k">class</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nc">NoBaseClassMovielensModel</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Model</span><span class="devsite-syntax-p">):</span> <span class="devsite-syntax-k">def</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-fm">__init__</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">):</span> <span class="devsite-syntax-nb">super</span><span class="devsite-syntax-p">()</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-fm">__init__</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">movie_model</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">user_model</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">task</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Layer</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">task</span> <span class="devsite-syntax-k">def</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nf">train_step</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">Dict</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Text</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Tensor</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-o">-</span>> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Tensor</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-c1"># Set up a gradient tape to record gradients.</span> <span class="devsite-syntax-k">with</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">GradientTape</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-k">as</span> <span class="devsite-syntax-n">tape</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-c1"># Loss computation.</span> <span class="devsite-syntax-n">user_embeddings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"user_id"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-n">positive_movie_embeddings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"movie_title"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-n">loss</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">task</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">user_embeddings</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">positive_movie_embeddings</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Handle regularization losses as well.</span> <span class="devsite-syntax-n">regularization_loss</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-nb">sum</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">losses</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">total_loss</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">loss</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-n">regularization_loss</span> <span class="devsite-syntax-n">gradients</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tape</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">gradient</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">total_loss</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">trainable_variables</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">optimizer</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">apply_gradients</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nb">zip</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">gradients</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">trainable_variables</span><span class="devsite-syntax-p">))</span> <span class="devsite-syntax-n">metrics</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-p">{</span><span class="devsite-syntax-n">metric</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">name</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">metric</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">result</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-k">for</span> <span class="devsite-syntax-n">metric</span> <span class="devsite-syntax-ow">in</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"loss"</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">loss</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"regularization_loss"</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">regularization_loss</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"total_loss"</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">total_loss</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">metrics</span> <span class="devsite-syntax-k">def</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nf">test_step</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">Dict</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Text</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Tensor</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-o">-</span>> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Tensor</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-c1"># Loss computation.</span> <span class="devsite-syntax-n">user_embeddings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"user_id"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-n">positive_movie_embeddings</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">features</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"movie_title"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-n">loss</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">task</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">user_embeddings</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">positive_movie_embeddings</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Handle regularization losses as well.</span> <span class="devsite-syntax-n">regularization_loss</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-nb">sum</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">losses</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">total_loss</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">loss</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-n">regularization_loss</span> <span class="devsite-syntax-n">metrics</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-p">{</span><span class="devsite-syntax-n">metric</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">name</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">metric</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">result</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-k">for</span> <span class="devsite-syntax-n">metric</span> <span class="devsite-syntax-ow">in</span> <span class="devsite-syntax-bp">self</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"loss"</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">loss</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"regularization_loss"</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">regularization_loss</span> <span class="devsite-syntax-n">metrics</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"total_loss"</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">total_loss</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">metrics</span> </code></pre></devsite-code> <p>In these tutorials, however, we stick to using the <a href="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/models/Model"><code translate="no" dir="ltr">tfrs.Model</code></a> base class to keep our focus on modelling and abstract away some of the boilerplate.</p> <h2 id="fitting_and_evaluating" data-text="Fitting and evaluating" tabindex="-1">Fitting and evaluating</h2> <p>After defining the model, we can use standard Keras fitting and evaluation routines to fit and evaluate the model.</p> <p>Let's first instantiate the model.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">model</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">MovielensModel</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">compile</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">optimizer</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">keras</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">optimizers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Adagrad</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">learning_rate</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-mf">0.1</span><span class="devsite-syntax-p">))</span> </code></pre></devsite-code> <p>Then shuffle, batch, and cache the training and evaluation data.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">cached_train</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">train</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">shuffle</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">100_000</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">8192</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">cache</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">cached_test</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">test</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">4096</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">cache</span><span class="devsite-syntax-p">()</span> </code></pre></devsite-code> <p>Then train the model:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">fit</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">cached_train</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">epochs</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-mi">3</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> Epoch 1/3 10/10 [==============================] - 6s 309ms/step - factorized_top_k/top_1_categorical_accuracy: 7.2500e-04 - factorized_top_k/top_5_categorical_accuracy: 0.0063 - factorized_top_k/top_10_categorical_accuracy: 0.0140 - factorized_top_k/top_50_categorical_accuracy: 0.0753 - factorized_top_k/top_100_categorical_accuracy: 0.1471 - loss: 69820.5881 - regularization_loss: 0.0000e+00 - total_loss: 69820.5881 Epoch 2/3 10/10 [==============================] - 3s 302ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0011 - factorized_top_k/top_5_categorical_accuracy: 0.0119 - factorized_top_k/top_10_categorical_accuracy: 0.0260 - factorized_top_k/top_50_categorical_accuracy: 0.1403 - factorized_top_k/top_100_categorical_accuracy: 0.2616 - loss: 67457.6612 - regularization_loss: 0.0000e+00 - total_loss: 67457.6612 Epoch 3/3 10/10 [==============================] - 3s 301ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0014 - factorized_top_k/top_5_categorical_accuracy: 0.0189 - factorized_top_k/top_10_categorical_accuracy: 0.0400 - factorized_top_k/top_50_categorical_accuracy: 0.1782 - factorized_top_k/top_100_categorical_accuracy: 0.3056 - loss: 66284.5682 - regularization_loss: 0.0000e+00 - total_loss: 66284.5682 <keras.callbacks.History at 0x7f6039c48160> </pre></devsite-code> <p>If you want to monitor the training process with TensorBoard, you can add a TensorBoard callback to fit() function and then start TensorBoard using <code translate="no" dir="ltr">%tensorboard --logdir logs/fit</code>. Please refer to <a href="https://www.tensorflow.org/tensorboard/get_started">TensorBoard documentation</a> for more details.</p> <p>As the model trains, the loss is falling and a set of top-k retrieval metrics is updated. These tell us whether the true positive is in the top-k retrieved items from the entire candidate set. For example, a top-5 categorical accuracy metric of 0.2 would tell us that, on average, the true positive is in the top 5 retrieved items 20% of the time.</p> <p>Note that, in this example, we evaluate the metrics during training as well as evaluation. Because this can be quite slow with large candidate sets, it may be prudent to turn metric calculation off in training, and only run it in evaluation.</p> <p>Finally, we can evaluate our model on the test set:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">evaluate</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">cached_test</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">return_dict</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-kc">True</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> 5/5 [==============================] - 3s 191ms/step - factorized_top_k/top_1_categorical_accuracy: 0.0010 - factorized_top_k/top_5_categorical_accuracy: 0.0087 - factorized_top_k/top_10_categorical_accuracy: 0.0212 - factorized_top_k/top_50_categorical_accuracy: 0.1218 - factorized_top_k/top_100_categorical_accuracy: 0.2334 - loss: 31086.5010 - regularization_loss: 0.0000e+00 - total_loss: 31086.5010 {'factorized_top_k/top_1_categorical_accuracy': 0.0010000000474974513, 'factorized_top_k/top_5_categorical_accuracy': 0.008700000122189522, 'factorized_top_k/top_10_categorical_accuracy': 0.021150000393390656, 'factorized_top_k/top_50_categorical_accuracy': 0.121799997985363, 'factorized_top_k/top_100_categorical_accuracy': 0.23340000212192535, 'loss': 28256.8984375, 'regularization_loss': 0, 'total_loss': 28256.8984375} </pre></devsite-code> <p>Test set performance is much worse than training performance. This is due to two factors:</p> <ol> <li>Our model is likely to perform better on the data that it has seen, simply because it can memorize it. This overfitting phenomenon is especially strong when models have many parameters. It can be mediated by model regularization and use of user and movie features that help the model generalize better to unseen data.</li> <li>The model is re-recommending some of users' already watched movies. These known-positive watches can crowd out test movies out of top K recommendations.</li> </ol> <p>The second phenomenon can be tackled by excluding previously seen movies from test recommendations. This approach is relatively common in the recommender systems literature, but we don't follow it in these tutorials. If not recommending past watches is important, we should expect appropriately specified models to learn this behaviour automatically from past user history and contextual information. Additionally, it is often appropriate to recommend the same item multiple times (say, an evergreen TV series or a regularly purchased item).</p> <h2 id="making_predictions" data-text="Making predictions" tabindex="-1">Making predictions</h2> <p>Now that we have a model, we would like to be able to make predictions. We can use the <a href="https://www.tensorflow.org/recommenders/api_docs/python/tfrs/layers/factorized_top_k/BruteForce"><code translate="no" dir="ltr">tfrs.layers.factorized_top_k.BruteForce</code></a> layer to do this.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-c1"># Create a model that takes in raw query features, and</span> <span class="devsite-syntax-n">index</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tfrs</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">factorized_top_k</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">BruteForce</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># recommends movies out of the entire movies dataset.</span> <span class="devsite-syntax-n">index</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">index_from_dataset</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Dataset</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">zip</span><span class="devsite-syntax-p">((</span><span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">100</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">100</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">map</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">)))</span> <span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Get recommendations.</span> <span class="devsite-syntax-n">_</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">titles</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">index</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">constant</span><span class="devsite-syntax-p">([</span><span class="devsite-syntax-s2">"42"</span><span class="devsite-syntax-p">]))</span> <span class="devsite-syntax-nb">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-sa">f</span><span class="devsite-syntax-s2">"Recommendations for user 42: </span><span class="devsite-syntax-si">{</span><span class="devsite-syntax-n">titles</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-mi">0</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-mi">3</span><span class="devsite-syntax-p">]</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">"</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> Recommendations for user 42: [b'Christmas Carol, A (1938)' b'Rudy (1993)' b'Bridges of Madison County, The (1995)'] </pre></devsite-code> <p>Of course, the <code translate="no" dir="ltr">BruteForce</code> layer is going to be too slow to serve a model with many possible candidates. The following sections shows how to speed this up by using an approximate retrieval index.</p> <h2 id="model_serving" data-text="Model serving" tabindex="-1">Model serving</h2> <p>After the model is trained, we need a way to deploy it.</p> <p>In a two-tower retrieval model, serving has two components:</p> <ul> <li>a serving query model, taking in features of the query and transforming them into a query embedding, and</li> <li>a serving candidate model. This most often takes the form of an approximate nearest neighbours (ANN) index which allows fast approximate lookup of candidates in response to a query produced by the query model.</li> </ul> <p>In TFRS, both components can be packaged into a single exportable model, giving us a model that takes the raw user id and returns the titles of top movies for that user. This is done via exporting the model to a <code translate="no" dir="ltr">SavedModel</code> format, which makes it possible to serve using <a href="https://www.tensorflow.org/tfx/guide/serving">TensorFlow Serving</a>.</p> <p>To deploy a model like this, we simply export the <code translate="no" dir="ltr">BruteForce</code> layer we created above:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-c1"># Export the query model.</span> <span class="devsite-syntax-k">with</span> <span class="devsite-syntax-n">tempfile</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">TemporaryDirectory</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-k">as</span> <span class="devsite-syntax-n">tmp</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">path</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">os</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">path</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">join</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">tmp</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-s2">"model"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Save the index.</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">saved_model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">save</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">index</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">path</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Load it back; can also be done in TensorFlow Serving.</span> <span class="devsite-syntax-n">loaded</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">saved_model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">load</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">path</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Pass a user id in, get top predicted movie titles back.</span> <span class="devsite-syntax-n">scores</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">titles</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">loaded</span><span class="devsite-syntax-p">([</span><span class="devsite-syntax-s2">"42"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-nb">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-sa">f</span><span class="devsite-syntax-s2">"Recommendations: </span><span class="devsite-syntax-si">{</span><span class="devsite-syntax-n">titles</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-mi">0</span><span class="devsite-syntax-p">][:</span><span class="devsite-syntax-mi">3</span><span class="devsite-syntax-p">]</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">"</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> WARNING:absl:Found untraced functions such as query_with_exclusions while saving (showing 1 of 1). These functions will not be directly callable after loading. INFO:tensorflow:Assets written to: /tmpfs/tmp/tmptfkkd57q/model/assets INFO:tensorflow:Assets written to: /tmpfs/tmp/tmptfkkd57q/model/assets Recommendations: [b'Christmas Carol, A (1938)' b'Rudy (1993)' b'Bridges of Madison County, The (1995)'] </pre></devsite-code> <p>We can also export an approximate retrieval index to speed up predictions. This will make it possible to efficiently surface recommendations from sets of tens of millions of candidates.</p> <p>To do so, we can use the <code translate="no" dir="ltr">scann</code> package. This is an optional dependency of TFRS, and we installed it separately at the beginning of this tutorial by calling <code translate="no" dir="ltr">!pip install -q scann</code>.</p> <p>Once installed we can use the TFRS <code translate="no" dir="ltr">ScaNN</code> layer:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-n">scann_index</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tfrs</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">layers</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">factorized_top_k</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">ScaNN</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">user_model</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">scann_index</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">index_from_dataset</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">Dataset</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">zip</span><span class="devsite-syntax-p">((</span><span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">100</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-n">movies</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">batch</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">100</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">map</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">movie_model</span><span class="devsite-syntax-p">)))</span> <span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> <tensorflow_recommenders.layers.factorized_top_k.ScaNN at 0x7f5fa01ff130> </pre></devsite-code> <p>This layer will perform <em>approximate</em> lookups: this makes retrieval slightly less accurate, but orders of magnitude faster on large candidate sets.</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-c1"># Get recommendations.</span> <span class="devsite-syntax-n">_</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">titles</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">scann_index</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">constant</span><span class="devsite-syntax-p">([</span><span class="devsite-syntax-s2">"42"</span><span class="devsite-syntax-p">]))</span> <span class="devsite-syntax-nb">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-sa">f</span><span class="devsite-syntax-s2">"Recommendations for user 42: </span><span class="devsite-syntax-si">{</span><span class="devsite-syntax-n">titles</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-mi">0</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-mi">3</span><span class="devsite-syntax-p">]</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">"</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> Recommendations for user 42: [b'Little Big League (1994)' b'Miracle on 34th Street (1994)' b'Cinderella (1950)'] </pre></devsite-code> <p>Exporting it for serving is as easy as exporting the <code translate="no" dir="ltr">BruteForce</code> layer:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python"><code translate="no" dir="ltr"><span class="devsite-syntax-c1"># Export the query model.</span> <span class="devsite-syntax-k">with</span> <span class="devsite-syntax-n">tempfile</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">TemporaryDirectory</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-k">as</span> <span class="devsite-syntax-n">tmp</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">path</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">os</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">path</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">join</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">tmp</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-s2">"model"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Save the index.</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">saved_model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">save</span><span class="devsite-syntax-p">(</span> <span class="devsite-syntax-n">scann_index</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">path</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">options</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">saved_model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">SaveOptions</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">namespace_whitelist</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s2">"Scann"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Load it back; can also be done in TensorFlow Serving.</span> <span class="devsite-syntax-n">loaded</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">tf</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">saved_model</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">load</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">path</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1"># Pass a user id in, get top predicted movie titles back.</span> <span class="devsite-syntax-n">scores</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">titles</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">loaded</span><span class="devsite-syntax-p">([</span><span class="devsite-syntax-s2">"42"</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-nb">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-sa">f</span><span class="devsite-syntax-s2">"Recommendations: </span><span class="devsite-syntax-si">{</span><span class="devsite-syntax-n">titles</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-mi">0</span><span class="devsite-syntax-p">][:</span><span class="devsite-syntax-mi">3</span><span class="devsite-syntax-p">]</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-s2">"</span><span class="devsite-syntax-p">)</span> </code></pre></devsite-code> <div></div><devsite-code><pre class="tfo-notebook-code-cell-output" translate="no" dir="ltr" is-upgraded> WARNING:absl:Found untraced functions such as query_with_exclusions while saving (showing 1 of 1). These functions will not be directly callable after loading. INFO:tensorflow:Assets written to: /tmpfs/tmp/tmpxpt22mi0/model/assets INFO:tensorflow:Assets written to: /tmpfs/tmp/tmpxpt22mi0/model/assets Recommendations: [b'Little Big League (1994)' b'Miracle on 34th Street (1994)' b'Cinderella (1950)'] </pre></devsite-code> <p>To learn more about using and tuning fast approximate retrieval models, have a look at our <a href="https://tensorflow.org/recommenders/examples/efficient_serving">efficient serving</a> tutorial.</p> <h2 id="item-to-item_recommendation" data-text="Item-to-item recommendation" tabindex="-1">Item-to-item recommendation</h2> <p>In this model, we created a user-movie model. However, for some applications (for example, product detail pages) it's common to perform item-to-item (for example, movie-to-movie or product-to-product) recommendations.</p> <p>Training models like this would follow the same pattern as shown in this tutorial, but with different training data. Here, we had a user and a movie tower, and used (user, movie) pairs to train them. In an item-to-item model, we would have two item towers (for the query and candidate item), and train the model using (query item, candidate item) pairs. These could be constructed from clicks on product detail pages.</p> <h2 id="next_steps" data-text="Next steps" tabindex="-1">Next steps</h2> <p>This concludes the retrieval tutorial.</p> <p>To expand on what is presented here, have a look at:</p> <ol> <li>Learning multi-task models: jointly optimizing for ratings and clicks.</li> <li>Using movie metadata: building a more complex movie model to alleviate cold-start.</li> </ol> </div> <devsite-thumb-rating position="footer"> </devsite-thumb-rating> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p> <p>Last updated 2023-05-27 UTC.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2023-05-27 UTC."],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Stay connected</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//blog.tensorflow.org" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Blog </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//discuss.tensorflow.org" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Forum </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//github.com/tensorflow/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > GitHub </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//twitter.com/tensorflow" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Twitter </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//youtube.com/tensorflow" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > YouTube </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Support</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//github.com/tensorflow/tensorflow/issues" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Issue tracker </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//github.com/tensorflow/tensorflow/blob/master/RELEASE.md" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Release notes </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//stackoverflow.com/questions/tagged/tensorflow" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Stack Overflow </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/extras/tensorflow_brand_guidelines.pdf" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Brand guidelines </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/about/bib" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Cite TensorFlow </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/terms" data-category="Site-Wide Custom Events" data-label="Footer Terms link" > Terms </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> <li class="devsite-footer-utility-item devsite-footer-utility-button"> <span class="devsite-footer-utility-description">Sign up for the TensorFlow newsletter</span> <a class="devsite-footer-utility-link gc-analytics-event" href="//www.tensorflow.org/subscribe" data-category="Site-Wide Custom Events" data-label="Footer Subscribe link" > Subscribe </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[{"dimensions": {"dimension6": "en", "dimension5": "en", "dimension1": "Signed out", "dimension4": "TensorFlow Recommenders", "dimension3": false, "dimension12": false}, "gaid": "UA-69864048-1", "metrics": {"ratings_value": "metric1", "ratings_count": "metric2"}, "purpose": 0}]</script> <script type="application/json" tag-management>{"at": "True", "ga4": [], "ga4p": [], "gtm": [{"id": "GTM-MXSL34P", "purpose": 0}], "parameters": {"internalUser": "False", "language": {"machineTranslated": "False", "requested": "en", "served": "en"}, "pageType": "article", "projectName": "TensorFlow Recommenders", "signedIn": "False", "tenant": "tensorflow", "recommendations": {"sourcePage": "", "sourceType": 0, "sourceRank": 0, "sourceIdenticalDescriptions": 0, "sourceTitleWords": 0, "sourceDescriptionWords": 0, "experiment": ""}, "experiment": {"ids": ""}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <script nonce="KVms3iDNvAMHgXNN1dkR1oOAPSaNEw"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/js/app_loader.js', '[15,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f","https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow","https://tensorflow-dot-devsite-v2-prod-3p.appspot.com",null,null,["/_pwa/tensorflow/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/images/favicon.png","https://www.gstatic.com/devrel-devsite/prod/v38a693baeb774512feb42f10aac8f755d8791ed41119b5be7a531f8e16f8279f/tensorflow/images/lockup.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyCNm9YxQumEXwGJgTDjxoxXK6m1F-9720Q","AIzaSyCc76DZePGtoyUjqKrLdsMGk_ry7sljLbY","www.tensorflow.org","AIzaSyB9bqgQ2t11WJsOX8qNsCQ6U-w91mmqF-I","AIzaSyAdYnStPdzjcJJtQ0mvIaeaMKj7_t6J_Fg",null,null,null,["Profiles__enable_page_saving","Profiles__require_profile_eligibility_for_signin","Profiles__enable_complete_playlist_endpoint","Cloud__enable_cloud_dlp_service","MiscFeatureFlags__enable_variable_operator","Cloud__enable_free_trial_server_call","BookNav__enable_tenant_cache_key","Search__enable_ai_eligibility_checks","CloudShell__cloud_code_overflow_menu","Profiles__enable_public_developer_profiles","DevPro__enable_developer_subscriptions","Profiles__enable_completecodelab_endpoint","Analytics__enable_clearcut_logging","Experiments__reqs_query_experiments","Profiles__enable_completequiz_endpoint","Profiles__enable_awarding_url","Profiles__enable_dashboard_curated_recommendations","Cloud__enable_cloud_shell_fte_user_flow","Search__enable_dynamic_content_confidential_banner","MiscFeatureFlags__developers_footer_dark_image","Cloud__enable_cloudx_experiment_ids","TpcFeatures__enable_unmirrored_page_left_nav","Cloud__enable_legacy_calculator_redirect","SignIn__enable_refresh_access_tokens","Cloud__enable_cloud_shell","Profiles__enable_recognition_badges","Search__enable_page_map","MiscFeatureFlags__enable_firebase_utm","Profiles__enable_stripe_subscription_management","Cloud__enable_cloudx_ping","Profiles__enable_profile_collections","Search__enable_suggestions_from_borg","TpcFeatures__enable_mirror_tenant_redirects","MiscFeatureFlags__developers_footer_image","Profiles__enable_developer_profiles_callout","MiscFeatureFlags__emergency_css","Cloud__enable_llm_concierge_chat","EngEduTelemetry__enable_engedu_telemetry","Profiles__enable_join_program_group_endpoint","Profiles__enable_release_notes_notifications","MiscFeatureFlags__enable_project_variables","Cloud__enable_cloud_facet_chat","CloudShell__cloud_shell_button","DevPro__enable_cloud_innovators_plus","MiscFeatureFlags__enable_explain_this_code","Concierge__enable_pushui","MiscFeatureFlags__enable_view_transitions"],null,null,"AIzaSyA58TaKli1DculwmAmbpzLVGuWc8eCQgQc","https://developerscontentserving-pa.googleapis.com","AIzaSyDWBU60w0P9hEkr29kkksYs8Z7gvZ8u_wc","https://developerscontentsearch-pa.googleapis.com",2,4,null,"https://developerprofiles-pa.googleapis.com",[15,"tensorflow","TensorFlow","www.tensorflow.org",null,"tensorflow-dot-devsite-v2-prod-3p.appspot.com",null,null,[null,1,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],[1,null,null,[1]],null,null,null,[1,null,1],[1,1,null,1,1]],null,[25,null,null,null,null,null,"/images/lockup.svg","/images/logo.png",null,null,null,1,1,null,null,null,null,null,null,null,null,1,null,null,null,null,[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[6,1],null,[[],[1,1]],[[["UA-69864048-1"],["UA-69864048-4"],null,null,["UA-69864048-5"],["GTM-MXSL34P"],null,null,[["UA-69864048-1",1]],null,[["UA-69864048-5",1]],[["GTM-MXSL34P",1]],1],[[1,1],[12,8],[3,2],[4,3],[6,5],[5,4]],[[1,1],[2,2]]],null,4],null,null,1]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>