├── .gitattributes
├── 978-1-4842-8953-2.jpg
├── Chapter - 1
└── Rule based - Popularity & Buy again (Chapter 1).ipynb
├── Chapter - 10
└── Graph_based_Rec_sys (Chapter 10).ipynb
├── Chapter - 2
└── EDA and Market Basket Analysis (Chapter 2).ipynb
├── Chapter - 3
└── Content based recommendation (Chapter 3).ipynb
├── Chapter - 4, 5
├── Collaborative Filtering (Chapter 4).ipynb
├── Collaborative Filtering (Chapter 5).ipynb
└── ~$apter5_doc.docx
├── Chapter - 6
└── Hybrid Recommenders (Chapter 6).ipynb
├── Chapter - 7
└── Clustering based (Chapter 7).ipynb
├── Chapter - 9
└── Deep_Learning_Recommendation_System (Chapter 9).ipynb
├── Contributing.md
├── Data
├── Rec_sys_content.csv
├── Rec_sys_data.xlsx
├── data.csv
└── mba_data
├── LICENSE.txt
├── README.md
└── errata.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/978-1-4842-8953-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/applied-recommender-systems-python/77609995cf4b7c0a672cdf94c4f43c4531ef37ce/978-1-4842-8953-2.jpg
--------------------------------------------------------------------------------
/Chapter - 10/Graph_based_Rec_sys (Chapter 10).ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "id": "gJj4YsmfFjMR"
7 | },
8 | "source": [
9 | "**Installing required libraries**"
10 | ]
11 | },
12 | {
13 | "cell_type": "code",
14 | "execution_count": null,
15 | "metadata": {
16 | "colab": {
17 | "base_uri": "https://localhost:8080/"
18 | },
19 | "id": "2uXQWKnlp7Uy",
20 | "outputId": "63f70534-1f34-4fd9-c83c-7c49547876f7"
21 | },
22 | "outputs": [
23 | {
24 | "name": "stdout",
25 | "output_type": "stream",
26 | "text": [
27 | "Collecting py2neo\n",
28 | " Downloading py2neo-2021.2.3-py2.py3-none-any.whl (177 kB)\n",
29 | "\u001b[?25l\r",
30 | "\u001b[K |█▉ | 10 kB 19.7 MB/s eta 0:00:01\r",
31 | "\u001b[K |███▊ | 20 kB 8.0 MB/s eta 0:00:01\r",
32 | "\u001b[K |█████▌ | 30 kB 5.1 MB/s eta 0:00:01\r",
33 | "\u001b[K |███████▍ | 40 kB 4.8 MB/s eta 0:00:01\r",
34 | "\u001b[K |█████████▎ | 51 kB 4.4 MB/s eta 0:00:01\r",
35 | "\u001b[K |███████████ | 61 kB 4.7 MB/s eta 0:00:01\r",
36 | "\u001b[K |█████████████ | 71 kB 4.7 MB/s eta 0:00:01\r",
37 | "\u001b[K |██████████████▉ | 81 kB 5.2 MB/s eta 0:00:01\r",
38 | "\u001b[K |████████████████▋ | 92 kB 5.2 MB/s eta 0:00:01\r",
39 | "\u001b[K |██████████████████▌ | 102 kB 5.1 MB/s eta 0:00:01\r",
40 | "\u001b[K |████████████████████▍ | 112 kB 5.1 MB/s eta 0:00:01\r",
41 | "\u001b[K |██████████████████████▏ | 122 kB 5.1 MB/s eta 0:00:01\r",
42 | "\u001b[K |████████████████████████ | 133 kB 5.1 MB/s eta 0:00:01\r",
43 | "\u001b[K |██████████████████████████ | 143 kB 5.1 MB/s eta 0:00:01\r",
44 | "\u001b[K |███████████████████████████▊ | 153 kB 5.1 MB/s eta 0:00:01\r",
45 | "\u001b[K |█████████████████████████████▋ | 163 kB 5.1 MB/s eta 0:00:01\r",
46 | "\u001b[K |███████████████████████████████▌| 174 kB 5.1 MB/s eta 0:00:01\r",
47 | "\u001b[K |████████████████████████████████| 177 kB 5.1 MB/s \n",
48 | "\u001b[?25hRequirement already satisfied: pygments>=2.0.0 in /usr/local/lib/python3.7/dist-packages (from py2neo) (2.6.1)\n",
49 | "Requirement already satisfied: certifi in /usr/local/lib/python3.7/dist-packages (from py2neo) (2021.10.8)\n",
50 | "Collecting interchange~=2021.0.4\n",
51 | " Downloading interchange-2021.0.4-py2.py3-none-any.whl (28 kB)\n",
52 | "Collecting pansi>=2020.7.3\n",
53 | " Downloading pansi-2020.7.3-py2.py3-none-any.whl (10 kB)\n",
54 | "Requirement already satisfied: urllib3 in /usr/local/lib/python3.7/dist-packages (from py2neo) (1.24.3)\n",
55 | "Requirement already satisfied: six>=1.15.0 in /usr/local/lib/python3.7/dist-packages (from py2neo) (1.15.0)\n",
56 | "Collecting monotonic\n",
57 | " Downloading monotonic-1.6-py2.py3-none-any.whl (8.2 kB)\n",
58 | "Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from py2neo) (21.3)\n",
59 | "Requirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from interchange~=2021.0.4->py2neo) (2018.9)\n",
60 | "Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->py2neo) (3.0.7)\n",
61 | "Installing collected packages: pansi, monotonic, interchange, py2neo\n",
62 | "Successfully installed interchange-2021.0.4 monotonic-1.6 pansi-2020.7.3 py2neo-2021.2.3\n"
63 | ]
64 | }
65 | ],
66 | "source": [
67 | "!pip install py2neo"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": null,
73 | "metadata": {
74 | "colab": {
75 | "base_uri": "https://localhost:8080/"
76 | },
77 | "id": "Oh9Mz4JGrqfA",
78 | "outputId": "36b32fb0-d7e4-4921-d62a-440fd5cd4cd4"
79 | },
80 | "outputs": [
81 | {
82 | "name": "stdout",
83 | "output_type": "stream",
84 | "text": [
85 | "Requirement already satisfied: openpyxl in /usr/local/lib/python3.7/dist-packages (3.0.9)\n",
86 | "Requirement already satisfied: et-xmlfile in /usr/local/lib/python3.7/dist-packages (from openpyxl) (1.1.0)\n"
87 | ]
88 | }
89 | ],
90 | "source": [
91 | "!pip install openpyxl --upgrade"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": null,
97 | "metadata": {
98 | "colab": {
99 | "base_uri": "https://localhost:8080/"
100 | },
101 | "id": "kAkE4IzRqY8R",
102 | "outputId": "81f21d4c-2c01-4f24-c1e9-69daf76be956"
103 | },
104 | "outputs": [
105 | {
106 | "name": "stdout",
107 | "output_type": "stream",
108 | "text": [
109 | "Collecting neo4j\n",
110 | " Downloading neo4j-4.4.1.tar.gz (89 kB)\n",
111 | "\u001b[?25l\r",
112 | "\u001b[K |███▊ | 10 kB 17.1 MB/s eta 0:00:01\r",
113 | "\u001b[K |███████▍ | 20 kB 12.9 MB/s eta 0:00:01\r",
114 | "\u001b[K |███████████ | 30 kB 9.8 MB/s eta 0:00:01\r",
115 | "\u001b[K |██████████████▊ | 40 kB 8.9 MB/s eta 0:00:01\r",
116 | "\u001b[K |██████████████████▍ | 51 kB 5.3 MB/s eta 0:00:01\r",
117 | "\u001b[K |██████████████████████ | 61 kB 5.9 MB/s eta 0:00:01\r",
118 | "\u001b[K |█████████████████████████▊ | 71 kB 5.8 MB/s eta 0:00:01\r",
119 | "\u001b[K |█████████████████████████████▍ | 81 kB 6.4 MB/s eta 0:00:01\r",
120 | "\u001b[K |████████████████████████████████| 89 kB 3.6 MB/s \n",
121 | "\u001b[?25hRequirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from neo4j) (2018.9)\n",
122 | "Building wheels for collected packages: neo4j\n",
123 | " Building wheel for neo4j (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
124 | " Created wheel for neo4j: filename=neo4j-4.4.1-py3-none-any.whl size=114783 sha256=40ae01c64a976931c7a1267b068deb7a375d68b29001d383170bfa9ae252f01a\n",
125 | " Stored in directory: /root/.cache/pip/wheels/fd/15/02/8379f87426cd1b74fd5891f49df9fb978423feb97650cd639b\n",
126 | "Successfully built neo4j\n",
127 | "Installing collected packages: neo4j\n",
128 | "Successfully installed neo4j-4.4.1\n"
129 | ]
130 | }
131 | ],
132 | "source": [
133 | "!pip install neo4j"
134 | ]
135 | },
136 | {
137 | "cell_type": "code",
138 | "execution_count": null,
139 | "metadata": {
140 | "colab": {
141 | "base_uri": "https://localhost:8080/"
142 | },
143 | "id": "OErgsIQT-1lR",
144 | "outputId": "efcfce6e-5fe5-4f2e-b3a1-aa79d9caf50d"
145 | },
146 | "outputs": [
147 | {
148 | "name": "stdout",
149 | "output_type": "stream",
150 | "text": [
151 | "Collecting neo4jupyter\n",
152 | " Downloading neo4jupyter-0.2.0.tar.gz (3.8 kB)\n",
153 | "Requirement already satisfied: IPython>=4.0.0 in /usr/local/lib/python3.7/dist-packages (from neo4jupyter) (5.5.0)\n",
154 | "Collecting ipython-cypher>=0.2.4\n",
155 | " Downloading ipython-cypher-0.2.6.tar.gz (13 kB)\n",
156 | "Requirement already satisfied: py2neo in /usr/local/lib/python3.7/dist-packages (from neo4jupyter) (2021.2.3)\n",
157 | "Requirement already satisfied: pickleshare in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (0.7.5)\n",
158 | "Requirement already satisfied: pygments in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (2.6.1)\n",
159 | "Requirement already satisfied: decorator in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (4.4.2)\n",
160 | "Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (57.4.0)\n",
161 | "Requirement already satisfied: prompt-toolkit<2.0.0,>=1.0.4 in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (1.0.18)\n",
162 | "Requirement already satisfied: traitlets>=4.2 in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (5.1.1)\n",
163 | "Requirement already satisfied: simplegeneric>0.8 in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (0.8.1)\n",
164 | "Requirement already satisfied: pexpect in /usr/local/lib/python3.7/dist-packages (from IPython>=4.0.0->neo4jupyter) (4.8.0)\n",
165 | "Collecting neo4jrestclient>=2.1.0\n",
166 | " Downloading neo4jrestclient-2.1.1.tar.gz (73 kB)\n",
167 | "\u001b[K |████████████████████████████████| 73 kB 1.1 MB/s \n",
168 | "\u001b[?25hRequirement already satisfied: prettytable in /usr/local/lib/python3.7/dist-packages (from ipython-cypher>=0.2.4->neo4jupyter) (3.0.0)\n",
169 | "Requirement already satisfied: requests>=2.1.0 in /usr/local/lib/python3.7/dist-packages (from neo4jrestclient>=2.1.0->ipython-cypher>=0.2.4->neo4jupyter) (2.23.0)\n",
170 | "Requirement already satisfied: wcwidth in /usr/local/lib/python3.7/dist-packages (from prompt-toolkit<2.0.0,>=1.0.4->IPython>=4.0.0->neo4jupyter) (0.2.5)\n",
171 | "Requirement already satisfied: six>=1.9.0 in /usr/local/lib/python3.7/dist-packages (from prompt-toolkit<2.0.0,>=1.0.4->IPython>=4.0.0->neo4jupyter) (1.15.0)\n",
172 | "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests>=2.1.0->neo4jrestclient>=2.1.0->ipython-cypher>=0.2.4->neo4jupyter) (3.0.4)\n",
173 | "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests>=2.1.0->neo4jrestclient>=2.1.0->ipython-cypher>=0.2.4->neo4jupyter) (1.24.3)\n",
174 | "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests>=2.1.0->neo4jrestclient>=2.1.0->ipython-cypher>=0.2.4->neo4jupyter) (2021.10.8)\n",
175 | "Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests>=2.1.0->neo4jrestclient>=2.1.0->ipython-cypher>=0.2.4->neo4jupyter) (2.10)\n",
176 | "Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.7/dist-packages (from pexpect->IPython>=4.0.0->neo4jupyter) (0.7.0)\n",
177 | "Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.7/dist-packages (from prettytable->ipython-cypher>=0.2.4->neo4jupyter) (4.10.1)\n",
178 | "Requirement already satisfied: typing-extensions>=3.6.4 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->prettytable->ipython-cypher>=0.2.4->neo4jupyter) (3.10.0.2)\n",
179 | "Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->prettytable->ipython-cypher>=0.2.4->neo4jupyter) (3.7.0)\n",
180 | "Requirement already satisfied: interchange~=2021.0.4 in /usr/local/lib/python3.7/dist-packages (from py2neo->neo4jupyter) (2021.0.4)\n",
181 | "Requirement already satisfied: monotonic in /usr/local/lib/python3.7/dist-packages (from py2neo->neo4jupyter) (1.6)\n",
182 | "Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from py2neo->neo4jupyter) (21.3)\n",
183 | "Requirement already satisfied: pansi>=2020.7.3 in /usr/local/lib/python3.7/dist-packages (from py2neo->neo4jupyter) (2020.7.3)\n",
184 | "Requirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from interchange~=2021.0.4->py2neo->neo4jupyter) (2018.9)\n",
185 | "Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->py2neo->neo4jupyter) (3.0.7)\n",
186 | "Building wheels for collected packages: neo4jupyter, ipython-cypher, neo4jrestclient\n",
187 | " Building wheel for neo4jupyter (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
188 | " Created wheel for neo4jupyter: filename=neo4jupyter-0.2.0-py3-none-any.whl size=3869 sha256=8bd6e4890af8b23ed90abbc49b9e3f5bd012c2449524a9c8de1e069608c25087\n",
189 | " Stored in directory: /root/.cache/pip/wheels/98/e6/6e/04e4ab08495bd0e2bfeb0083436a6040c49f262c17d6345b2b\n",
190 | " Building wheel for ipython-cypher (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
191 | " Created wheel for ipython-cypher: filename=ipython_cypher-0.2.6-py3-none-any.whl size=13272 sha256=380f8d345cfceae16ea74a053367d06ca17bfa9156c755c97ac6b0041a2b1285\n",
192 | " Stored in directory: /root/.cache/pip/wheels/d9/ff/09/e790f902f0013f5479cf2b9288013d2b36f41da1877c7d4df2\n",
193 | " Building wheel for neo4jrestclient (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
194 | " Created wheel for neo4jrestclient: filename=neo4jrestclient-2.1.1-py2.py3-none-any.whl size=78563 sha256=281a3a93f3f7b213af3d1df2e839c26ff5ec79ccd03be5bbdbc9a6282e4a51fa\n",
195 | " Stored in directory: /root/.cache/pip/wheels/4d/39/cd/03fa156cb423361fa55a1f69d711d152eb6f3ce902a324059e\n",
196 | "Successfully built neo4jupyter ipython-cypher neo4jrestclient\n",
197 | "Installing collected packages: neo4jrestclient, ipython-cypher, neo4jupyter\n",
198 | "Successfully installed ipython-cypher-0.2.6 neo4jrestclient-2.1.1 neo4jupyter-0.2.0\n"
199 | ]
200 | }
201 | ],
202 | "source": [
203 | "!pip install neo4jupyter"
204 | ]
205 | },
206 | {
207 | "cell_type": "markdown",
208 | "metadata": {
209 | "id": "t85mjGthFn2k"
210 | },
211 | "source": [
212 | "**Importing Required Libraries**"
213 | ]
214 | },
215 | {
216 | "cell_type": "code",
217 | "execution_count": null,
218 | "metadata": {
219 | "id": "s1hL_XSVqzCc"
220 | },
221 | "outputs": [],
222 | "source": [
223 | "import pandas as pd\n",
224 | "\n",
225 | "from neo4j import GraphDatabase, basic_auth\n",
226 | "from py2neo import Graph\n",
227 | "\n",
228 | "import re\n",
229 | "\n",
230 | "import neo4jupyter"
231 | ]
232 | },
233 | {
234 | "cell_type": "markdown",
235 | "metadata": {
236 | "id": "c6n16laxG0Oz"
237 | },
238 | "source": [
239 | "**Establishing a connection between our Neo4j database and python notebook**"
240 | ]
241 | },
242 | {
243 | "cell_type": "code",
244 | "execution_count": null,
245 | "metadata": {
246 | "id": "gf_XWZyWX4SO"
247 | },
248 | "outputs": [],
249 | "source": [
250 | "g = Graph(\"bolt://34.201.241.51:7687\", password = \"whirls-bullet-boils\")"
251 | ]
252 | },
253 | {
254 | "cell_type": "code",
255 | "execution_count": null,
256 | "metadata": {
257 | "id": "QHubXhyINdaB"
258 | },
259 | "outputs": [],
260 | "source": [
261 | "driver = GraphDatabase.driver(\n",
262 | " \"bolt://34.201.241.51:7687\",\n",
263 | " auth=basic_auth(\"neo4j\", \"whirls-bullet-boils\"))\n",
264 | "\n",
265 | "# The uri \"bolt://34.201.241.51:7687\" needs to be replaced in case of new sandbox creation in neo4j.\n",
266 | "# The credentials \"neo4j\" and \"whirls-bullet-boils\" also need replacement for each use case."
267 | ]
268 | },
269 | {
270 | "cell_type": "code",
271 | "execution_count": null,
272 | "metadata": {
273 | "id": "LmWW4dpMIJSP"
274 | },
275 | "outputs": [],
276 | "source": [
277 | "def execute_transactions(transaction_execution_commands):\n",
278 | " # Establishing connection with database\n",
279 | " data_base_connection = GraphDatabase.driver( \"bolt://34.201.241.51:7687\",\n",
280 | " auth=basic_auth(\"neo4j\", \"whirls-bullet-boils\"))\n",
281 | " # Creating a session\n",
282 | " session = data_base_connection.session() \n",
283 | " for i in transaction_execution_commands:\n",
284 | " session.run(i)"
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "metadata": {
290 | "id": "UV2izztlGMFf"
291 | },
292 | "source": [
293 | "**Loading the datasets**"
294 | ]
295 | },
296 | {
297 | "cell_type": "code",
298 | "execution_count": null,
299 | "metadata": {
300 | "id": "4ibNZ7PxqsEl"
301 | },
302 | "outputs": [],
303 | "source": [
304 | "# This dataset consists of transactions which will be used to establish relationship between the customer and the stock.\n",
305 | "df = pd.read_excel(r'Rec_sys_data-1.xlsx')"
306 | ]
307 | },
308 | {
309 | "cell_type": "code",
310 | "execution_count": null,
311 | "metadata": {
312 | "id": "9ierhqFbzxzW"
313 | },
314 | "outputs": [],
315 | "source": [
316 | "# Little bit of preprocessing so that we can easily run NoSQL queries.\n",
317 | "df['CustomerID'] = df['CustomerID'].apply(str)"
318 | ]
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": null,
323 | "metadata": {
324 | "id": "welDIq7-o5zc"
325 | },
326 | "outputs": [],
327 | "source": [
328 | "# This dataset contains detailed information about each stock which will be used to link stockcodes and their description/title. \n",
329 | "df1 = pd.read_excel('Rec_sys_data-1.xlsx','product')"
330 | ]
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {
336 | "colab": {
337 | "base_uri": "https://localhost:8080/",
338 | "height": 354
339 | },
340 | "id": "7tA-sEOmq7nH",
341 | "outputId": "ab7af65d-5843-49f6-b5c0-6eb667b3146a"
342 | },
343 | "outputs": [
344 | {
345 | "data": {
346 | "text/html": [
347 | "\n",
348 | "
\n",
349 | "
\n",
350 | "
\n",
351 | "\n",
364 | "
\n",
365 | " \n",
366 | " \n",
367 | " | \n",
368 | " StockCode | \n",
369 | " Product Name | \n",
370 | " Description | \n",
371 | " Category | \n",
372 | " Brand | \n",
373 | " Unit Price | \n",
374 | "
\n",
375 | " \n",
376 | " \n",
377 | " \n",
378 | " 0 | \n",
379 | " 22629 | \n",
380 | " Ganma Superheroes Ordinary Life Case For Samsu... | \n",
381 | " New unique design, great gift.High quality pla... | \n",
382 | " Cell Phones|Cellphone Accessories|Cases & Prot... | \n",
383 | " Ganma | \n",
384 | " 13.99 | \n",
385 | "
\n",
386 | " \n",
387 | " 1 | \n",
388 | " 21238 | \n",
389 | " Eye Buy Express Prescription Glasses Mens Wome... | \n",
390 | " Rounded rectangular cat-eye reading glasses. T... | \n",
391 | " Health|Home Health Care|Daily Living Aids | \n",
392 | " Eye Buy Express | \n",
393 | " 19.22 | \n",
394 | "
\n",
395 | " \n",
396 | " 2 | \n",
397 | " 22181 | \n",
398 | " MightySkins Skin Decal Wrap Compatible with Ni... | \n",
399 | " Each Nintendo 2DS kit is printed with super-hi... | \n",
400 | " Video Games|Video Game Accessories|Accessories... | \n",
401 | " Mightyskins | \n",
402 | " 14.99 | \n",
403 | "
\n",
404 | " \n",
405 | " 3 | \n",
406 | " 84879 | \n",
407 | " Mediven Sheer and Soft 15-20 mmHg Thigh w/ Lac... | \n",
408 | " The sheerest compression stocking in its class... | \n",
409 | " Health|Medicine Cabinet|Braces & Supports | \n",
410 | " Medi | \n",
411 | " 62.38 | \n",
412 | "
\n",
413 | " \n",
414 | " 4 | \n",
415 | " 84836 | \n",
416 | " Stupell Industries Chevron Initial Wall D cor | \n",
417 | " Features: -Made in the USA. -Sawtooth hanger o... | \n",
418 | " Home Improvement|Paint|Wall Decals|All Wall De... | \n",
419 | " Stupell Industries | \n",
420 | " 35.99 | \n",
421 | "
\n",
422 | " \n",
423 | "
\n",
424 | "
\n",
425 | "
\n",
435 | " \n",
436 | " \n",
473 | "\n",
474 | " \n",
498 | "
\n",
499 | "
\n",
500 | " "
501 | ],
502 | "text/plain": [
503 | " StockCode ... Unit Price\n",
504 | "0 22629 ... 13.99\n",
505 | "1 21238 ... 19.22\n",
506 | "2 22181 ... 14.99\n",
507 | "3 84879 ... 62.38\n",
508 | "4 84836 ... 35.99\n",
509 | "\n",
510 | "[5 rows x 6 columns]"
511 | ]
512 | },
513 | "execution_count": 18,
514 | "metadata": {},
515 | "output_type": "execute_result"
516 | }
517 | ],
518 | "source": [
519 | "df1.head()"
520 | ]
521 | },
522 | {
523 | "cell_type": "markdown",
524 | "metadata": {
525 | "id": "pUltg57aPzmP"
526 | },
527 | "source": [
528 | "**Uploading the entities in Neo4J Database**"
529 | ]
530 | },
531 | {
532 | "cell_type": "markdown",
533 | "metadata": {
534 | "id": "bmWA9TruQZoV"
535 | },
536 | "source": [
537 | "To implement knowledge graphs in Neo4J we need to convert the dataframe into Relational Database. For this, we need to convert customers and stocks into entities (or nodes of a graph) and build a relation between them."
538 | ]
539 | },
540 | {
541 | "cell_type": "code",
542 | "execution_count": null,
543 | "metadata": {
544 | "id": "dI5S_HhzGiVU"
545 | },
546 | "outputs": [],
547 | "source": [
548 | "# creating a list of all unique customer IDs \n",
549 | "customerids = df['CustomerID'].unique().tolist()\n",
550 | "\n",
551 | "# storing all the create commands to be executed into create_customers list\n",
552 | "create_customers = []\n",
553 | "\n",
554 | "for i in customerids:\n",
555 | " # example of create statement \"create (n:entity {property_key : '12345'})\" \n",
556 | " statement = \"create (c:customer{cid:\"+ '\"' + str(i) + '\"' +\"})\"\n",
557 | " create_customers.append(statement)\n",
558 | "\n",
559 | "# running all the queries into neo4j to create customer entities\n",
560 | "execute_transactions(create_customers)"
561 | ]
562 | },
563 | {
564 | "cell_type": "markdown",
565 | "metadata": {
566 | "id": "b9rkehYfQp9K"
567 | },
568 | "source": [
569 | "Once we are done with customer nodes, we need to create nodes for stocks as well."
570 | ]
571 | },
572 | {
573 | "cell_type": "code",
574 | "execution_count": null,
575 | "metadata": {
576 | "id": "JO10R9GbGiY9"
577 | },
578 | "outputs": [],
579 | "source": [
580 | "# creating a lit of all unique stockcodes\n",
581 | "stockcodes = df['StockCode'].unique().tolist()\n",
582 | "\n",
583 | "# storing all the create commands to be executed into the create_stockcodes list\n",
584 | "create_stockcodes = []\n",
585 | "\n",
586 | "for i in stockcodes:\n",
587 | " # example of create statement \"create (m:entity {property_key : 'XYZ'})\"\n",
588 | " statement = \"create (s:stock{stockcode:\"+ '\"' + str(i) + '\"' +\"})\"\n",
589 | " create_stockcodes.append(statement)\n",
590 | "\n",
591 | "# running all the queries into neo4j to create stock entities\n",
592 | "execute_transactions(create_stockcodes)"
593 | ]
594 | },
595 | {
596 | "cell_type": "markdown",
597 | "metadata": {
598 | "id": "_LIzS0izRPxB"
599 | },
600 | "source": [
601 | "Once we are done creating nodes for customers and stocks, we need to create a link between stockcodes and title which will be needed to recommend items.\n"
602 | ]
603 | },
604 | {
605 | "cell_type": "markdown",
606 | "metadata": {
607 | "id": "jnrkyaPQR1oq"
608 | },
609 | "source": [
610 | "For this we will create another property key called as 'title' into the stock entity already present in our neo4j database."
611 | ]
612 | },
613 | {
614 | "cell_type": "code",
615 | "execution_count": null,
616 | "metadata": {
617 | "id": "AUFPEIlEqxnP"
618 | },
619 | "outputs": [],
620 | "source": [
621 | "# creating a blank dataframe\n",
622 | "df2 = pd.DataFrame(columns = ['StockCode', 'Title'])"
623 | ]
624 | },
625 | {
626 | "cell_type": "code",
627 | "execution_count": null,
628 | "metadata": {
629 | "id": "vdireF1Enj3H"
630 | },
631 | "outputs": [],
632 | "source": [
633 | "# This cell of code will add all the unique stockcodes along with their title in df2\n",
634 | "stockcodes = df['StockCode'].unique().tolist()\n",
635 | "\n",
636 | "for i in range(len(stockcodes)):\n",
637 | " df2['StockCode'][i] = stockcodes[i]\n",
638 | " df2['Title'][i] = df1[df1['StockCode']==stockcodes[i]]['Product Name'].values"
639 | ]
640 | },
641 | {
642 | "cell_type": "code",
643 | "execution_count": null,
644 | "metadata": {
645 | "id": "3dt9dyDHvlaG"
646 | },
647 | "outputs": [],
648 | "source": [
649 | "# Doing some data preprocessing such that these queries can be run in neo4j\n",
650 | "df2['Title'] = df2['Title'].apply(str)\n",
651 | "df2['Title'] = df2['Title'].map(lambda x: re.sub(r'\\W+', ' ', x))\n",
652 | "df2['Title'] = df2['Title'].apply(str)"
653 | ]
654 | },
655 | {
656 | "cell_type": "code",
657 | "execution_count": null,
658 | "metadata": {
659 | "id": "K2tx_F9yr-QD"
660 | },
661 | "outputs": [],
662 | "source": [
663 | "# This query will add the 'title' property key to each stock entity in our neo4j database\n",
664 | "for i in range(len(df2)):\n",
665 | " query = \"\"\"\n",
666 | " MATCH (s:stock {stockcode:\"\"\" + '\"' + str(df2['StockCode'][i]) + '\"' + \"\"\"})\n",
667 | " SET s.title =\"\"\"+ '\"' + str(df2['Title'][i]) + '\"' + \"\"\"\n",
668 | " RETURN s.stockcode, s.title\n",
669 | " \"\"\"\n",
670 | "\n",
671 | " g.run(query)"
672 | ]
673 | },
674 | {
675 | "cell_type": "markdown",
676 | "metadata": {
677 | "id": "zOMos-MFSQuN"
678 | },
679 | "source": [
680 | "**Creating relation between customers and stocks**"
681 | ]
682 | },
683 | {
684 | "cell_type": "markdown",
685 | "metadata": {
686 | "id": "WTV4hhWRSW8N"
687 | },
688 | "source": [
689 | "Since we have all the transactions in our dataset, the relation is already known and present. But since we have to convert it into a RDS, we have to run cypher queries in neo4j to build this relationship."
690 | ]
691 | },
692 | {
693 | "cell_type": "code",
694 | "execution_count": null,
695 | "metadata": {
696 | "id": "iJSZzIO2N25H"
697 | },
698 | "outputs": [],
699 | "source": [
700 | "# Storing transaction values in a list\n",
701 | "transaction_list = df.values.tolist()\n",
702 | "\n",
703 | "# storing all commands to build relationship in an empty list relation\n",
704 | "relation = []\n",
705 | "\n",
706 | "for i in transaction_list:\n",
707 | " # the 9th column in df is customerID and 2nd column is stockcode which we are appending in the statement\n",
708 | " statement = \"\"\"MATCH (a:customer),(b:stock) WHERE a.cid = \"\"\"+'\"' + str(i[8])+ '\"' + \"\"\" AND b.stockcode = \"\"\" + '\"' + str(i[1]) + '\"' + \"\"\" CREATE (a)-[:bought]->(b) \"\"\"\n",
709 | " relation.append(statement)"
710 | ]
711 | },
712 | {
713 | "cell_type": "code",
714 | "execution_count": null,
715 | "metadata": {
716 | "id": "hmeP4aVYN5qW"
717 | },
718 | "outputs": [],
719 | "source": [
720 | "execute_transactions(relation)"
721 | ]
722 | },
723 | {
724 | "cell_type": "markdown",
725 | "metadata": {
726 | "id": "zb0O0P_IS74S"
727 | },
728 | "source": [
729 | "**Finding similarity between users using the relationship created**"
730 | ]
731 | },
732 | {
733 | "cell_type": "code",
734 | "execution_count": null,
735 | "metadata": {
736 | "id": "9sOPOb2_4EoV"
737 | },
738 | "outputs": [],
739 | "source": [
740 | "def similar_users(id) : \n",
741 | " # This query will find users who have bought stocks in common with the customer having id specified by user \n",
742 | " # Later we will find jaccard index for each of them \n",
743 | " # We wil return the neighbors sorted by jaccard index in descending order\n",
744 | " query = \"\"\"\n",
745 | " MATCH (c1:customer)-[:bought]->(s:stock)<-[:bought]-(c2:customer)\n",
746 | " WHERE c1 <> c2 AND c1.cid =\"\"\" + '\"' + str(id) +'\"' \"\"\"\n",
747 | " WITH c1, c2, COUNT(DISTINCT s) as intersection\n",
748 | " MATCH (c:customer)-[:bought]->(s:stock)\n",
749 | " WHERE c in [c1, c2]\n",
750 | " WITH c1, c2, intersection, COUNT(DISTINCT s) as union\n",
751 | " WITH c1, c2, intersection, union, (intersection * 1.0 / union) as jaccard_index\n",
752 | " ORDER BY jaccard_index DESC, c2.cid\n",
753 | " WITH c1, COLLECT([c2.cid, jaccard_index, intersection, union])[0..15] as neighbors\n",
754 | " WHERE SIZE(neighbors) = 15 // return users with enough neighbors\n",
755 | " RETURN c1.cid as customer, neighbors\n",
756 | " \n",
757 | " \"\"\"\n",
758 | " neighbors = pd.DataFrame([['CustomerID','JaccardIndex','Intersection','Union']])\n",
759 | " for i in g.run(query).data():\n",
760 | " neighbors = neighbors.append(i[\"neighbors\"])\n",
761 | " \n",
762 | " print(\"\\n----------- customer's 15 nearest neighbors ---------\\n\")\n",
763 | " print(neighbors)\n",
764 | " "
765 | ]
766 | },
767 | {
768 | "cell_type": "markdown",
769 | "metadata": {
770 | "id": "ZOEu9a4uTcq5"
771 | },
772 | "source": [
773 | "*Sample Outputs*"
774 | ]
775 | },
776 | {
777 | "cell_type": "code",
778 | "execution_count": null,
779 | "metadata": {
780 | "colab": {
781 | "base_uri": "https://localhost:8080/"
782 | },
783 | "id": "OJmygmDo4XJ-",
784 | "outputId": "231a2607-e3df-4179-9414-73bdf8a57c9a"
785 | },
786 | "outputs": [
787 | {
788 | "name": "stdout",
789 | "output_type": "stream",
790 | "text": [
791 | "\n",
792 | "----------- customer's 15 nearest neighbors ---------\n",
793 | "\n",
794 | " 0 1 2 3\n",
795 | "0 CustomerID JaccardIndex Intersection Union\n",
796 | "0 17396 0.111111 10 90\n",
797 | "1 13821 0.108333 13 120\n",
798 | "2 17097 0.107784 18 167\n",
799 | "3 13324 0.103093 10 97\n",
800 | "4 15658 0.099099 11 111\n",
801 | "5 15606 0.097345 11 113\n",
802 | "6 16389 0.09375 9 96\n",
803 | "7 18092 0.092784 9 97\n",
804 | "8 13814 0.091743 10 109\n",
805 | "9 13265 0.08871 11 124\n",
806 | "10 13488 0.087248 26 298\n",
807 | "11 12843 0.086957 12 138\n",
808 | "12 16618 0.086207 10 116\n",
809 | "13 15502 0.084821 19 224\n",
810 | "14 17722 0.08427 15 178\n"
811 | ]
812 | }
813 | ],
814 | "source": [
815 | "similar_users('12347')"
816 | ]
817 | },
818 | {
819 | "cell_type": "code",
820 | "execution_count": null,
821 | "metadata": {
822 | "colab": {
823 | "base_uri": "https://localhost:8080/"
824 | },
825 | "id": "mDXr_a94v1Xa",
826 | "outputId": "3dbc1e8c-f077-439f-9c0a-7f782c11feab"
827 | },
828 | "outputs": [
829 | {
830 | "name": "stdout",
831 | "output_type": "stream",
832 | "text": [
833 | "\n",
834 | "----------- customer's 15 nearest neighbors ---------\n",
835 | "\n",
836 | " 0 1 2 3\n",
837 | "0 CustomerID JaccardIndex Intersection Union\n",
838 | "0 15356 0.131098 43 328\n",
839 | "1 18231 0.126531 31 245\n",
840 | "2 14395 0.125436 36 287\n",
841 | "3 15856 0.124668 47 377\n",
842 | "4 16907 0.124424 27 217\n",
843 | "5 17787 0.123404 29 235\n",
844 | "6 15059 0.11236 30 267\n",
845 | "7 13344 0.11215 24 214\n",
846 | "8 16222 0.111111 29 261\n",
847 | "9 17085 0.108949 28 257\n",
848 | "10 17450 0.10687 28 262\n",
849 | "11 17865 0.106796 33 309\n",
850 | "12 16910 0.106061 35 330\n",
851 | "13 16549 0.105919 34 321\n",
852 | "14 13263 0.105155 51 485\n"
853 | ]
854 | }
855 | ],
856 | "source": [
857 | "similar_users(17975)"
858 | ]
859 | },
860 | {
861 | "cell_type": "code",
862 | "execution_count": null,
863 | "metadata": {
864 | "colab": {
865 | "base_uri": "https://localhost:8080/"
866 | },
867 | "id": "TignS9T_4h2J",
868 | "outputId": "5b9bf097-47a0-40f1-e565-57fdf512a39b"
869 | },
870 | "outputs": [
871 | {
872 | "name": "stdout",
873 | "output_type": "stream",
874 | "text": [
875 | "\n",
876 | "----------- customer's 15 nearest neighbors ---------\n",
877 | "\n",
878 | " 0 1 2 3\n",
879 | "0 CustomerID JaccardIndex Intersection Union\n",
880 | "0 15319 0.148936 7 47\n",
881 | "1 15124 0.146341 6 41\n",
882 | "2 13706 0.137255 7 51\n",
883 | "3 15985 0.135593 8 59\n",
884 | "4 12842 0.130435 6 46\n",
885 | "5 14226 0.130435 9 69\n",
886 | "6 14651 0.127907 11 86\n",
887 | "7 14959 0.126984 8 63\n",
888 | "8 13900 0.126761 9 71\n",
889 | "9 16989 0.125 5 40\n",
890 | "10 14209 0.121951 10 82\n",
891 | "11 16721 0.119403 8 67\n",
892 | "12 15076 0.115385 9 78\n",
893 | "13 15643 0.112903 7 62\n",
894 | "14 15681 0.111111 6 54\n"
895 | ]
896 | }
897 | ],
898 | "source": [
899 | "similar_users(16359)"
900 | ]
901 | },
902 | {
903 | "cell_type": "code",
904 | "execution_count": null,
905 | "metadata": {
906 | "colab": {
907 | "base_uri": "https://localhost:8080/"
908 | },
909 | "id": "zuuLuFr8582q",
910 | "outputId": "f703b679-efae-4ee3-b92c-0de26c2cbad8"
911 | },
912 | "outputs": [
913 | {
914 | "name": "stdout",
915 | "output_type": "stream",
916 | "text": [
917 | "\n",
918 | "----------- customer's 15 nearest neighbors ---------\n",
919 | "\n",
920 | " 0 1 2 3\n",
921 | "0 CustomerID JaccardIndex Intersection Union\n",
922 | "0 13551 0.2 2 10\n",
923 | "1 16566 0.133333 2 15\n",
924 | "2 12917 0.111111 1 9\n",
925 | "3 13967 0.111111 1 9\n",
926 | "4 14332 0.111111 1 9\n",
927 | "5 15442 0.111111 1 9\n",
928 | "6 17483 0.105263 2 19\n",
929 | "7 13217 0.1 1 10\n",
930 | "8 17384 0.1 1 10\n",
931 | "9 16526 0.095238 2 21\n",
932 | "10 17854 0.095238 2 21\n",
933 | "11 15160 0.090909 1 11\n",
934 | "12 13207 0.083333 1 12\n",
935 | "13 18032 0.083333 1 12\n",
936 | "14 13805 0.076923 1 13\n"
937 | ]
938 | }
939 | ],
940 | "source": [
941 | "similar_users(17867)"
942 | ]
943 | },
944 | {
945 | "cell_type": "markdown",
946 | "metadata": {
947 | "id": "pGfezPCeTvWB"
948 | },
949 | "source": [
950 | "**Recommending items based on the similar users**"
951 | ]
952 | },
953 | {
954 | "cell_type": "code",
955 | "execution_count": null,
956 | "metadata": {
957 | "id": "c7j5iDHy6Ate"
958 | },
959 | "outputs": [],
960 | "source": [
961 | "def recommend(id):\n",
962 | " # The query below is same as similar_users function\n",
963 | " # It will return the most similar customers\n",
964 | " query1 = \"\"\"\n",
965 | " MATCH (c1:customer)-[:bought]->(s:stock)<-[:bought]-(c2:customer)\n",
966 | " WHERE c1 <> c2 AND c1.cid =\"\"\" + '\"' + str(id) +'\"' \"\"\"\n",
967 | " WITH c1, c2, COUNT(DISTINCT s) as intersection\n",
968 | " MATCH (c:customer)-[:bought]->(s:stock)\n",
969 | " WHERE c in [c1, c2]\n",
970 | " WITH c1, c2, intersection, COUNT(DISTINCT s) as union\n",
971 | " WITH c1, c2, intersection, union, (intersection * 1.0 / union) as jaccard_index\n",
972 | " ORDER BY jaccard_index DESC, c2.cid\n",
973 | " WITH c1, COLLECT([c2.cid, jaccard_index, intersection, union])[0..15] as neighbors\n",
974 | " WHERE SIZE(neighbors) = 15 // return users with enough neighbors\n",
975 | " RETURN c1.cid as customer, neighbors\n",
976 | " \n",
977 | " \"\"\"\n",
978 | " neighbors = pd.DataFrame([['CustomerID','JaccardIndex','Intersection','Union']])\n",
979 | " neighbors_list = {}\n",
980 | " for i in g.run(query1).data():\n",
981 | " neighbors = neighbors.append(i[\"neighbors\"])\n",
982 | " neighbors_list[i[\"customer\"]] = i[\"neighbors\"]\n",
983 | " print(neighbors_list)\n",
984 | " \n",
985 | " # From the neighbors_list returned, we will fetch the customer ids of those neighbors to recommend items\n",
986 | " nearest_neighbors = [neighbors_list[id][i][0] for i in range(len(neighbors_list[id]))]\n",
987 | "\n",
988 | " # The below query will fetch all the items boughts by nearest neighbors\n",
989 | " # We will remove the items which have been already bought by the target customer\n",
990 | " # Now from the filtered set of items, we will count how many times each item is repeating within the shopping carts of nearest neighbors\n",
991 | " # We will sort that list on count of repititions and return in descending order\n",
992 | " query2 = \"\"\"\n",
993 | " // get top n recommendations for customer from their nearest neighbors\n",
994 | " MATCH (c1:customer),(neighbor:customer)-[:bought]->(s:stock) // all items bought by neighbors\n",
995 | " WHERE c1.cid = \"\"\" + '\"' + str(id) + '\"' \"\"\" \n",
996 | " AND neighbor.cid in $nearest_neighbors\n",
997 | " AND not (c1)-[:bought]->(s) // filter for items that our user hasn't bought before\n",
998 | " \n",
999 | " WITH c1, s, COUNT(DISTINCT neighbor) as countnns // times bought by nearest neighbors\n",
1000 | " ORDER BY c1.cid, countnns DESC \n",
1001 | " RETURN c1.cid as customer, COLLECT([s.title, s.stockcode, countnns])[0..$n] as recommendations \n",
1002 | " \"\"\"\n",
1003 | "\n",
1004 | " recommendations = pd.DataFrame([['Title','StockCode','Number of times bought by neighbors']])\n",
1005 | " for i in g.run(query2, id = id, nearest_neighbors = nearest_neighbors, n = 5).data():\n",
1006 | " #recommendations[i[\"customer\"]] = i[\"recommendations\"]\n",
1007 | " recommendations = recommendations.append(i[\"recommendations\"])\n",
1008 | "\n",
1009 | "\n",
1010 | " # We will also print the items bought earlier by the target customer\n",
1011 | " print(\" \\n---------- Top 8 StockCodes bought by customer \" + str(id) + \" -----------\\n\")\n",
1012 | " \n",
1013 | " print(df[df['CustomerID']==id][['CustomerID','StockCode','Quantity']].nlargest(8,'Quantity'))\n",
1014 | "\n",
1015 | " bought = df[df['CustomerID']==id][['CustomerID','StockCode','Quantity']].nlargest(8,'Quantity')\n",
1016 | "\n",
1017 | " print('\\n-------Product Name of bought StockCodes ------\\n')\n",
1018 | "\n",
1019 | " print((df1[df1.StockCode.isin(bought.StockCode)]['Product Name']).to_string())\n",
1020 | "\n",
1021 | " # Here we will print the recommendations\n",
1022 | " print(\"------------ \\n Recommendations for Customer {} ------- \\n\".format(id))\n",
1023 | " print(recommendations.to_string())\n"
1024 | ]
1025 | },
1026 | {
1027 | "cell_type": "code",
1028 | "execution_count": null,
1029 | "metadata": {
1030 | "colab": {
1031 | "base_uri": "https://localhost:8080/"
1032 | },
1033 | "id": "Utd7CM0JjdR_",
1034 | "outputId": "20a74279-3de8-49c6-cfe2-aa19c88a797f"
1035 | },
1036 | "outputs": [
1037 | {
1038 | "name": "stdout",
1039 | "output_type": "stream",
1040 | "text": [
1041 | "{'17850': [['15497', 0.14814814814814814, 4, 27], ['17169', 0.14705882352941177, 5, 34], ['18170', 0.14285714285714285, 6, 42], ['15636', 0.1388888888888889, 5, 36], ['13187', 0.13725490196078433, 7, 51], ['15722', 0.1276595744680851, 6, 47], ['15482', 0.11764705882352941, 4, 34], ['13161', 0.11538461538461539, 3, 26], ['14035', 0.11428571428571428, 4, 35], ['17866', 0.1111111111111111, 3, 27], ['13884', 0.10714285714285714, 6, 56], ['14440', 0.10638297872340426, 5, 47], ['12747', 0.1, 5, 50], ['17742', 0.0967741935483871, 3, 31], ['14163', 0.09615384615384616, 5, 52]]}\n",
1042 | " \n",
1043 | "---------- Top 8 StockCodes bought by customer 17850 -----------\n",
1044 | "\n",
1045 | " CustomerID StockCode Quantity\n",
1046 | "285 17850 82494L 12\n",
1047 | "2629 17850 85123A 12\n",
1048 | "2634 17850 71053 12\n",
1049 | "2978 17850 71053 12\n",
1050 | "2983 17850 85123A 12\n",
1051 | "3299 17850 71053 12\n",
1052 | "3301 17850 21068 12\n",
1053 | "3302 17850 84029G 12\n",
1054 | "\n",
1055 | "-------Product Name of bought StockCodes ------\n",
1056 | "\n",
1057 | "135 Mediven Sheer and Soft 15-20 mmHg Thigh w/ Lac...\n",
1058 | "162 Heavy Duty Handlebar Motorcycle Mount Holder K...\n",
1059 | "179 AARCO Enclosed Wall Mounted Bulletin Board\n",
1060 | "669 3 1/2\"W x 20\"D x 20\"H Funston Craftsman Smooth...\n",
1061 | "967 Awkward Styles Shamrock Flag St. Patrick's Day...\n",
1062 | "------------ \n",
1063 | " Recommendations for Customer 17850 ------- \n",
1064 | "\n",
1065 | " 0 1 2\n",
1066 | "0 Title StockCode Number of times bought by neighbors\n",
1067 | "0 Puppy Apparel Clothes Clothing Dog Sweatshirt Pullover Coat Hoodie Gift for Pet 21754 5\n",
1068 | "1 Mediven Sheer and Soft 15 20 mmHg Thigh w Lace Silicone Top Band CT Wheat II Ankle 8 8 75 inches 84879 5\n",
1069 | "2 The Holiday Aisle LED C7 Faceted Christmas Light Bulb 22470 5\n",
1070 | "3 Mediven Sheer and Soft 15 20 mmHg Thigh w Lace Silicone Top Band CT Wheat II Ankle 8 8 75 inches 82484 4\n",
1071 | "4 MightySkins Skin Decal Wrap Compatible with Lifeproof Sticker Protective Cover 100 s of Color Options 22469 4\n"
1072 | ]
1073 | }
1074 | ],
1075 | "source": [
1076 | "recommend('17850')"
1077 | ]
1078 | },
1079 | {
1080 | "cell_type": "code",
1081 | "execution_count": null,
1082 | "metadata": {
1083 | "colab": {
1084 | "base_uri": "https://localhost:8080/"
1085 | },
1086 | "id": "DHAzY_8jjfGB",
1087 | "outputId": "294d8c8b-7927-4245-b7e4-d960605df2fd"
1088 | },
1089 | "outputs": [
1090 | {
1091 | "name": "stdout",
1092 | "output_type": "stream",
1093 | "text": [
1094 | "{'16359': [['15319', 0.14893617021276595, 7, 47], ['15124', 0.14634146341463414, 6, 41], ['13706', 0.13725490196078433, 7, 51], ['15985', 0.13559322033898305, 8, 59], ['12842', 0.13043478260869565, 6, 46], ['14226', 0.13043478260869565, 9, 69], ['14651', 0.12790697674418605, 11, 86], ['14959', 0.12698412698412698, 8, 63], ['13900', 0.1267605633802817, 9, 71], ['16989', 0.125, 5, 40], ['14209', 0.12195121951219512, 10, 82], ['16721', 0.11940298507462686, 8, 67], ['15076', 0.11538461538461539, 9, 78], ['15643', 0.11290322580645161, 7, 62], ['15681', 0.1111111111111111, 6, 54]]}\n",
1095 | " \n",
1096 | "---------- Top 8 StockCodes bought by customer 16359 -----------\n",
1097 | "\n",
1098 | " CustomerID StockCode Quantity\n",
1099 | "161089 16359 84836 120\n",
1100 | "232132 16359 84836 72\n",
1101 | "101750 16359 84836 60\n",
1102 | "124252 16359 84836 60\n",
1103 | "53524 16359 16169M 50\n",
1104 | "75394 16359 84836 48\n",
1105 | "33114 16359 84836 36\n",
1106 | "53526 16359 84836 36\n",
1107 | "\n",
1108 | "-------Product Name of bought StockCodes ------\n",
1109 | "\n",
1110 | "4 Stupell Industries Chevron Initial Wall D cor\n",
1111 | "3046 Harriton Ladies' 4.2 oz. Athletic Sport T-Shirt\n",
1112 | "------------ \n",
1113 | " Recommendations for Customer 16359 ------- \n",
1114 | "\n",
1115 | " 0 1 2\n",
1116 | "0 Title StockCode Number of times bought by neighbors\n",
1117 | "0 Men s 1ct Diamond Ring In 14K Rose Gold I J K I1 I2 Size 10 21136 4\n",
1118 | "1 1 30 Carat ctw 14K White Gold Round Diamond Ladies 3 Stone Bridal Engagement Ring Set With Band 22961 4\n",
1119 | "2 Mediven Sheer and Soft 15 20 mmHg Thigh w Lace Silicone Top Band CT Wheat II Ankle 8 8 75 inches 85123A 3\n",
1120 | "3 2019 Minecraft Bilingual FRE Wall Calendar 22855 3\n",
1121 | "4 MightySkins Skin Decal Wrap Compatible with Nintendo Sticker Protective Cover 100 s of Color Options 21755 3\n"
1122 | ]
1123 | }
1124 | ],
1125 | "source": [
1126 | "recommend(\"16359\")"
1127 | ]
1128 | },
1129 | {
1130 | "cell_type": "code",
1131 | "execution_count": null,
1132 | "metadata": {
1133 | "colab": {
1134 | "base_uri": "https://localhost:8080/"
1135 | },
1136 | "id": "T_HIUNBpmgBJ",
1137 | "outputId": "09854097-960c-4a0c-84fa-e7bb3b23b0ff"
1138 | },
1139 | "outputs": [
1140 | {
1141 | "name": "stdout",
1142 | "output_type": "stream",
1143 | "text": [
1144 | "{'17867': [['13551', 0.2, 2, 10], ['16566', 0.13333333333333333, 2, 15], ['12917', 0.1111111111111111, 1, 9], ['13967', 0.1111111111111111, 1, 9], ['14332', 0.1111111111111111, 1, 9], ['15442', 0.1111111111111111, 1, 9], ['17483', 0.10526315789473684, 2, 19], ['13217', 0.1, 1, 10], ['17384', 0.1, 1, 10], ['16526', 0.09523809523809523, 2, 21], ['17854', 0.09523809523809523, 2, 21], ['15160', 0.09090909090909091, 1, 11], ['13207', 0.08333333333333333, 1, 12], ['18032', 0.08333333333333333, 1, 12], ['13805', 0.07692307692307693, 1, 13]]}\n",
1145 | " \n",
1146 | "---------- Top 8 StockCodes bought by customer 17867 -----------\n",
1147 | "\n",
1148 | " CustomerID StockCode Quantity\n",
1149 | "137223 17867 18097C 288\n",
1150 | "188192 17867 23109 42\n",
1151 | "188161 17867 85103 37\n",
1152 | "64167 17867 21633 2\n",
1153 | "188162 17867 15056N 2\n",
1154 | "137222 17867 21631 1\n",
1155 | "137224 17867 72351B 1\n",
1156 | "137225 17867 47599A 1\n",
1157 | "\n",
1158 | "-------Product Name of bought StockCodes ------\n",
1159 | "\n",
1160 | "89 Window Tint Film Chevy (back doors) DIY\n",
1161 | "261 Peanuts Valentine Sign Craft Kit (Pack ...\n",
1162 | "371 Urbane Urbane Classic Crossover Scrub Top Scru...\n",
1163 | "902 \"Soccer\" Vinyl Graphic - Large - Ivory\n",
1164 | "1591 Handcrafted Ercolano Music Box Featuring \"Lunc...\n",
1165 | "2513 Mediven Sheer and Soft 15-20 mmHg Thigh w/ Lac...\n",
1166 | "2739 Edwards Garment Women's Two Pockets Chino Blen...\n",
1167 | "3069 MightySkins Skin Decal Wrap Compatible with HP...\n",
1168 | "------------ \n",
1169 | " Recommendations for Customer 17867 ------- \n",
1170 | "\n",
1171 | " 0 1 2\n",
1172 | "0 Title StockCode Number of times bought by neighbors\n",
1173 | "0 Urbane Urbane Classic Crossover Scrub Top Scrub Top 84946 3\n",
1174 | "1 1 5 Flexo Remix PET Expandable Braided Sleeving Jungle 40FT 47599B 2\n",
1175 | "2 MLS Vancouver Whitecaps Women s Middle Logo Scarf Tee 15056BL 2\n",
1176 | "3 Port Authority K110 Dry Zone UV Micro Mesh Polo Gusty Grey S 47566 2\n",
1177 | "4 Mediven Sheer and Soft 15 20 mmHg Thigh w Lace Silicone Top Band CT Wheat II Ankle 8 8 75 inches 85123A 2\n"
1178 | ]
1179 | }
1180 | ],
1181 | "source": [
1182 | "recommend(\"17867\")"
1183 | ]
1184 | },
1185 | {
1186 | "cell_type": "code",
1187 | "execution_count": null,
1188 | "metadata": {
1189 | "colab": {
1190 | "base_uri": "https://localhost:8080/"
1191 | },
1192 | "id": "Anx7EhN5mhzU",
1193 | "outputId": "a2b3b004-704e-4745-db04-010f76a3448f"
1194 | },
1195 | "outputs": [
1196 | {
1197 | "name": "stdout",
1198 | "output_type": "stream",
1199 | "text": [
1200 | "{'12347': [['17396', 0.1111111111111111, 10, 90], ['13821', 0.10833333333333334, 13, 120], ['17097', 0.10778443113772455, 18, 167], ['13324', 0.10309278350515463, 10, 97], ['15658', 0.0990990990990991, 11, 111], ['15606', 0.09734513274336283, 11, 113], ['16389', 0.09375, 9, 96], ['18092', 0.09278350515463918, 9, 97], ['13814', 0.09174311926605505, 10, 109], ['13265', 0.08870967741935484, 11, 124], ['13488', 0.087248322147651, 26, 298], ['12843', 0.08695652173913043, 12, 138], ['16618', 0.08620689655172414, 10, 116], ['15502', 0.08482142857142858, 19, 224], ['17722', 0.08426966292134831, 15, 178]]}\n",
1201 | " \n",
1202 | "---------- Top 8 StockCodes bought by customer 12347 -----------\n",
1203 | "\n",
1204 | " CustomerID StockCode Quantity\n",
1205 | "99443 12347 23076 240\n",
1206 | "10526 12347 22492 36\n",
1207 | "99444 12347 22492 36\n",
1208 | "153949 12347 17021 36\n",
1209 | "200488 12347 84558A 36\n",
1210 | "10527 12347 85167B 30\n",
1211 | "10534 12347 84558A 24\n",
1212 | "43446 12347 84991 24\n",
1213 | "\n",
1214 | "-------Product Name of bought StockCodes ------\n",
1215 | "\n",
1216 | "33 Rosalind Wheeler Wall Mounted Bulletin Board\n",
1217 | "447 Eye Buy Express Kids Childrens Reading Glasses...\n",
1218 | "782 6pc Boy Formal Necktie Black & White Suit Set ...\n",
1219 | "1607 3 1/2\"W x 32\"D x 36\"H Traditional Arts & Craft...\n",
1220 | "1820 Fruit of the Loom T-Shirts HD Cotton Tank Top\n",
1221 | "2668 Vickerman 14\" Finial Drop Christmas Ornaments,...\n",
1222 | "------------ \n",
1223 | " Recommendations for Customer 12347 ------- \n",
1224 | "\n",
1225 | " 0 1 2\n",
1226 | "0 Title StockCode Number of times bought by neighbors\n",
1227 | "0 Handcrafted Ercolano Music Box Featuring Luncheon of the Boating Party by Renoir Pierre Auguste New YorkNew York 22697 8\n",
1228 | "1 Window Tint Film Mitsubishi all doors DIY 22698 8\n",
1229 | "2 Girls Dress Up Kids Crafts Hair Kit With Hair Makes 10 Unique Hair Accessories Assortment of Kids Fashion Headbands Craft Kit Perfect Beauty Shop Play Date 22427 6\n",
1230 | "3 Elite Series Counter Height Storage Cabinet with Adjustable Shelves 46 W x 24 D x 42 H Charcoal 23245 6\n",
1231 | "4 Port Authority K110 Dry Zone UV Micro Mesh Polo Gusty Grey S 47566 5\n"
1232 | ]
1233 | }
1234 | ],
1235 | "source": [
1236 | "recommend(\"12347\")"
1237 | ]
1238 | }
1239 | ],
1240 | "metadata": {
1241 | "colab": {
1242 | "collapsed_sections": [],
1243 | "name": "Copy_of_neo4j (2).ipynb",
1244 | "provenance": []
1245 | },
1246 | "kernelspec": {
1247 | "display_name": "Python 3 (ipykernel)",
1248 | "language": "python",
1249 | "name": "python3"
1250 | },
1251 | "language_info": {
1252 | "codemirror_mode": {
1253 | "name": "ipython",
1254 | "version": 3
1255 | },
1256 | "file_extension": ".py",
1257 | "mimetype": "text/x-python",
1258 | "name": "python",
1259 | "nbconvert_exporter": "python",
1260 | "pygments_lexer": "ipython3",
1261 | "version": "3.9.7"
1262 | }
1263 | },
1264 | "nbformat": 4,
1265 | "nbformat_minor": 1
1266 | }
1267 |
--------------------------------------------------------------------------------
/Chapter - 4, 5/~$apter5_doc.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/applied-recommender-systems-python/77609995cf4b7c0a672cdf94c4f43c4531ef37ce/Chapter - 4, 5/~$apter5_doc.docx
--------------------------------------------------------------------------------
/Chapter - 9/Deep_Learning_Recommendation_System (Chapter 9).ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "id": "AekEB0E8Msx3"
8 | },
9 | "outputs": [],
10 | "source": [
11 | "#!pip install recommenders[gpu] -f https://download.pytorch.org/whl/cu111/torch_stable.html"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {
18 | "id": "UsLaFbgbNpdF"
19 | },
20 | "outputs": [],
21 | "source": [
22 | "%load_ext autoreload\n",
23 | "%autoreload 2"
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": 1,
29 | "metadata": {
30 | "colab": {
31 | "base_uri": "https://localhost:8080/"
32 | },
33 | "id": "a7MjktOsNxJr",
34 | "outputId": "4c71eca8-1b17-47f0-9e18-aa5a4bfdb3a7"
35 | },
36 | "outputs": [
37 | {
38 | "name": "stdout",
39 | "output_type": "stream",
40 | "text": [
41 | "System version: 3.7.13 (default, Mar 28 2022, 08:03:21) [MSC v.1916 64 bit (AMD64)]\n",
42 | "Pandas version: 1.3.5\n",
43 | "Tensorflow version: 2.7.4\n"
44 | ]
45 | }
46 | ],
47 | "source": [
48 | "import sys\n",
49 | "import pandas as pd\n",
50 | "import tensorflow as tf\n",
51 | "tf.get_logger().setLevel('ERROR') # only show error messages\n",
52 | "\n",
53 | "from recommenders.utils.timer import Timer\n",
54 | "from recommenders.models.ncf.ncf_singlenode import NCF\n",
55 | "from recommenders.models.ncf.dataset import Dataset as NCFDataset\n",
56 | "#from recommenders.datasets import movielens\n",
57 | "from recommenders.utils.notebook_utils import is_jupyter\n",
58 | "from recommenders.datasets.python_splitters import python_chrono_split,python_stratified_split\n",
59 | "from recommenders.evaluation.python_evaluation import (rmse, mae, rsquared, exp_var, map_at_k, ndcg_at_k, precision_at_k, \n",
60 | " recall_at_k, get_top_k_items)\n",
61 | "\n",
62 | "print(\"System version: {}\".format(sys.version))\n",
63 | "print(\"Pandas version: {}\".format(pd.__version__))\n",
64 | "print(\"Tensorflow version: {}\".format(tf.__version__))"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": 2,
70 | "metadata": {
71 | "id": "MGFvEHcnOW7d"
72 | },
73 | "outputs": [],
74 | "source": [
75 | "# top k items to recommend\n",
76 | "TOP_K = 10\n",
77 | "\n",
78 | "# Select MovieLens data size: 100k, 1m, 10m, or 20m\n",
79 | "#MOVIELENS_DATA_SIZE = '100k'\n",
80 | "\n",
81 | "# Model parameters\n",
82 | "EPOCHS = 50\n",
83 | "BATCH_SIZE = 256\n",
84 | "\n",
85 | "SEED = 42"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {
91 | "id": "iFJ6jg3Hkrze"
92 | },
93 | "source": [
94 | "##1. Load dataset"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": 15,
100 | "metadata": {
101 | "colab": {
102 | "base_uri": "https://localhost:8080/"
103 | },
104 | "id": "UKpFFeWoTIOl",
105 | "outputId": "a8c9bc98-3291-412a-886e-6e6c814bcb79"
106 | },
107 | "outputs": [],
108 | "source": [
109 | "df = pd.read_excel('Rec_sys_data.xlsx')"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": 16,
115 | "metadata": {
116 | "id": "_LxvPPL4T54E"
117 | },
118 | "outputs": [],
119 | "source": [
120 | "df= df[['CustomerID','StockCode','Quantity','DeliveryDate']]"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 17,
126 | "metadata": {},
127 | "outputs": [],
128 | "source": [
129 | "df[\"StockCode\"] = df[\"StockCode\"].apply(lambda x: pd.to_numeric(x, errors='coerce')).dropna()"
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": 34,
135 | "metadata": {
136 | "colab": {
137 | "base_uri": "https://localhost:8080/",
138 | "height": 441
139 | },
140 | "id": "1qV4Lqp1Ux8g",
141 | "outputId": "530af003-c52c-4371-bcb6-9387982256aa",
142 | "scrolled": true
143 | },
144 | "outputs": [
145 | {
146 | "name": "stdout",
147 | "output_type": "stream",
148 | "text": [
149 | "(246706, 4)\n"
150 | ]
151 | },
152 | {
153 | "data": {
154 | "text/html": [
155 | "\n",
156 | "\n",
169 | "
\n",
170 | " \n",
171 | " \n",
172 | " | \n",
173 | " userID | \n",
174 | " itemID | \n",
175 | " rating | \n",
176 | " timestamp | \n",
177 | "
\n",
178 | " \n",
179 | " \n",
180 | " \n",
181 | " 1 | \n",
182 | " 17850 | \n",
183 | " 71053.0 | \n",
184 | " 6 | \n",
185 | " 2010-12-02 08:26:00 | \n",
186 | "
\n",
187 | " \n",
188 | " 2 | \n",
189 | " 17850 | \n",
190 | " 21730.0 | \n",
191 | " 6 | \n",
192 | " 2010-12-03 08:26:00 | \n",
193 | "
\n",
194 | " \n",
195 | " 4 | \n",
196 | " 17850 | \n",
197 | " 22752.0 | \n",
198 | " 2 | \n",
199 | " 2010-12-04 08:26:00 | \n",
200 | "
\n",
201 | " \n",
202 | " 7 | \n",
203 | " 17850 | \n",
204 | " 22633.0 | \n",
205 | " 6 | \n",
206 | " 2010-12-04 08:28:00 | \n",
207 | "
\n",
208 | " \n",
209 | " 8 | \n",
210 | " 17850 | \n",
211 | " 22632.0 | \n",
212 | " 6 | \n",
213 | " 2010-12-03 08:28:00 | \n",
214 | "
\n",
215 | " \n",
216 | " ... | \n",
217 | " ... | \n",
218 | " ... | \n",
219 | " ... | \n",
220 | " ... | \n",
221 | "
\n",
222 | " \n",
223 | " 272399 | \n",
224 | " 15249 | \n",
225 | " 23399.0 | \n",
226 | " 12 | \n",
227 | " 2011-10-08 11:37:00 | \n",
228 | "
\n",
229 | " \n",
230 | " 272400 | \n",
231 | " 15249 | \n",
232 | " 22727.0 | \n",
233 | " 4 | \n",
234 | " 2011-10-08 11:37:00 | \n",
235 | "
\n",
236 | " \n",
237 | " 272401 | \n",
238 | " 15249 | \n",
239 | " 23434.0 | \n",
240 | " 12 | \n",
241 | " 2011-10-08 11:37:00 | \n",
242 | "
\n",
243 | " \n",
244 | " 272402 | \n",
245 | " 15249 | \n",
246 | " 23340.0 | \n",
247 | " 12 | \n",
248 | " 2011-10-07 11:37:00 | \n",
249 | "
\n",
250 | " \n",
251 | " 272403 | \n",
252 | " 15249 | \n",
253 | " 23209.0 | \n",
254 | " 10 | \n",
255 | " 2011-10-08 11:37:00 | \n",
256 | "
\n",
257 | " \n",
258 | "
\n",
259 | "
246706 rows × 4 columns
\n",
260 | "
"
261 | ],
262 | "text/plain": [
263 | " userID itemID rating timestamp\n",
264 | "1 17850 71053.0 6 2010-12-02 08:26:00\n",
265 | "2 17850 21730.0 6 2010-12-03 08:26:00\n",
266 | "4 17850 22752.0 2 2010-12-04 08:26:00\n",
267 | "7 17850 22633.0 6 2010-12-04 08:28:00\n",
268 | "8 17850 22632.0 6 2010-12-03 08:28:00\n",
269 | "... ... ... ... ...\n",
270 | "272399 15249 23399.0 12 2011-10-08 11:37:00\n",
271 | "272400 15249 22727.0 4 2011-10-08 11:37:00\n",
272 | "272401 15249 23434.0 12 2011-10-08 11:37:00\n",
273 | "272402 15249 23340.0 12 2011-10-07 11:37:00\n",
274 | "272403 15249 23209.0 10 2011-10-08 11:37:00\n",
275 | "\n",
276 | "[246706 rows x 4 columns]"
277 | ]
278 | },
279 | "execution_count": 34,
280 | "metadata": {},
281 | "output_type": "execute_result"
282 | }
283 | ],
284 | "source": [
285 | "df = df.dropna()\n",
286 | "print(df.shape)\n",
287 | "df"
288 | ]
289 | },
290 | {
291 | "cell_type": "markdown",
292 | "metadata": {
293 | "id": "YqSgGwwdd48o"
294 | },
295 | "source": []
296 | },
297 | {
298 | "cell_type": "code",
299 | "execution_count": 35,
300 | "metadata": {
301 | "id": "C67TctvNd5mu"
302 | },
303 | "outputs": [],
304 | "source": [
305 | "#header=[\"userID\", \"itemID\", \"rating\", \"timestamp\"]\n",
306 | "\n",
307 | "df = df.rename(columns={\n",
308 | " \n",
309 | " 'CustomerID':\"userID\",'StockCode':\"itemID\",'Quantity':\"rating\",'DeliveryDate':\"timestamp\"\n",
310 | " \n",
311 | "})\n",
312 | "\n",
313 | "df[\"userID\"] = df[\"userID\"].astype(int)\n",
314 | "df[\"itemID\"] = df[\"itemID\"].astype(int)"
315 | ]
316 | },
317 | {
318 | "cell_type": "markdown",
319 | "metadata": {
320 | "id": "8OScdDfHkjpk"
321 | },
322 | "source": [
323 | "##2. Split the data using the Spark chronological splitter provided in utilities"
324 | ]
325 | },
326 | {
327 | "cell_type": "code",
328 | "execution_count": 36,
329 | "metadata": {
330 | "id": "aqSnVDYjUjVF"
331 | },
332 | "outputs": [],
333 | "source": [
334 | "train, test = python_chrono_split(df, 0.75)"
335 | ]
336 | },
337 | {
338 | "cell_type": "code",
339 | "execution_count": 37,
340 | "metadata": {},
341 | "outputs": [],
342 | "source": [
343 | "train_file = \"./train.csv\"\n",
344 | "test_file = \"./test.csv\"\n",
345 | "train.to_csv(train_file, index=False)\n",
346 | "test.to_csv(test_file, index=False)"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": 38,
352 | "metadata": {
353 | "scrolled": true
354 | },
355 | "outputs": [
356 | {
357 | "name": "stdout",
358 | "output_type": "stream",
359 | "text": [
360 | "\n",
361 | "Int64Index: 185041 entries, 37126 to 137334\n",
362 | "Data columns (total 4 columns):\n",
363 | " # Column Non-Null Count Dtype \n",
364 | "--- ------ -------------- ----- \n",
365 | " 0 userID 185041 non-null int32 \n",
366 | " 1 itemID 185041 non-null int32 \n",
367 | " 2 rating 185041 non-null int64 \n",
368 | " 3 timestamp 185041 non-null datetime64[ns]\n",
369 | "dtypes: datetime64[ns](1), int32(2), int64(1)\n",
370 | "memory usage: 5.6 MB\n"
371 | ]
372 | }
373 | ],
374 | "source": [
375 | "train.info()"
376 | ]
377 | },
378 | {
379 | "cell_type": "markdown",
380 | "metadata": {
381 | "id": "sMneMQzjkd72"
382 | },
383 | "source": [
384 | "##3. Train the NCF model on the training data, and get the top-k recommendations for our testing data\n",
385 | "NCF accepts implicit feedback and generates prospensity of items to be recommended to users in the scale of 0 to 1. A recommended item list can then be generated based on the scores. Note that this quickstart notebook is using a smaller number of epochs to reduce time for training. As a consequence, the model performance will be slighlty deteriorated."
386 | ]
387 | },
388 | {
389 | "cell_type": "code",
390 | "execution_count": 39,
391 | "metadata": {
392 | "id": "Q64_tRl5emGN"
393 | },
394 | "outputs": [
395 | {
396 | "name": "stderr",
397 | "output_type": "stream",
398 | "text": [
399 | "INFO:recommenders.models.ncf.dataset:Indexing ./train.csv ...\n",
400 | "INFO:recommenders.models.ncf.dataset:Indexing ./test.csv ...\n",
401 | "INFO:recommenders.models.ncf.dataset:Creating full leave-one-out test file ./test_full.csv ...\n",
402 | "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 3498/3498 [01:03<00:00, 54.95it/s]\n",
403 | "INFO:recommenders.models.ncf.dataset:Indexing ./test_full.csv ...\n"
404 | ]
405 | }
406 | ],
407 | "source": [
408 | "data = NCFDataset(train_file=train_file, test_file=test_file, seed=SEED)"
409 | ]
410 | },
411 | {
412 | "cell_type": "code",
413 | "execution_count": 40,
414 | "metadata": {
415 | "id": "7nrT0JFNfUT4"
416 | },
417 | "outputs": [
418 | {
419 | "ename": "ImportError",
420 | "evalue": "DLL load failed: The specified procedure could not be found.",
421 | "output_type": "error",
422 | "traceback": [
423 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
424 | "\u001b[1;31mImportError\u001b[0m Traceback (most recent call last)",
425 | "\u001b[1;32m~\\AppData\\Local\\Temp\\ipykernel_38616\\2530418255.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[0mlearning_rate\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1e-3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m \u001b[0mseed\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mSEED\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 12\u001b[0m )\n",
426 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\recommenders\\models\\ncf\\ncf_singlenode.py\u001b[0m in \u001b[0;36m__init__\u001b[1;34m(self, n_users, n_items, model_type, n_factors, layer_sizes, n_epochs, batch_size, learning_rate, verbose, seed)\u001b[0m\n\u001b[0;32m 81\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mncf_layer_size\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mn_factors\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mlayer_sizes\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 82\u001b[0m \u001b[1;31m# create ncf model\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 83\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_create_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 84\u001b[0m \u001b[1;31m# set GPU use with demand growth\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 85\u001b[0m \u001b[0mgpu_options\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcompat\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mv1\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mGPUOptions\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mallow_growth\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
427 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\recommenders\\models\\ncf\\ncf_singlenode.py\u001b[0m in \u001b[0;36m_create_model\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 196\u001b[0m \u001b[0mnum_outputs\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlayer_size\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 197\u001b[0m \u001b[0mactivation_fn\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnn\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrelu\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 198\u001b[1;33m weights_initializer=tf.compat.v1.keras.initializers.VarianceScaling(\n\u001b[0m\u001b[0;32m 199\u001b[0m \u001b[0mscale\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 200\u001b[0m \u001b[0mmode\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"fan_avg\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
428 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\python\\util\\lazy_loader.py\u001b[0m in \u001b[0;36m__getattr__\u001b[1;34m(self, item)\u001b[0m\n\u001b[0;32m 60\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 61\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__getattr__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mitem\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 62\u001b[1;33m \u001b[0mmodule\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_load\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 63\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmodule\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mitem\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 64\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
429 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\python\\util\\lazy_loader.py\u001b[0m in \u001b[0;36m_load\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 43\u001b[0m \u001b[1;34m\"\"\"Load the module and insert it into the parent's globals.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 44\u001b[0m \u001b[1;31m# Import the target module and insert it into the parent's namespace\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 45\u001b[1;33m \u001b[0mmodule\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mimport_module\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__name__\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 46\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parent_module_globals\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_local_name\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmodule\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 47\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
430 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\__init__.py\u001b[0m in \u001b[0;36mimport_module\u001b[1;34m(name, package)\u001b[0m\n\u001b[0;32m 125\u001b[0m \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 126\u001b[0m \u001b[0mlevel\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 127\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0m_bootstrap\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_gcd_import\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mlevel\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpackage\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlevel\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 128\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 129\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
431 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_gcd_import\u001b[1;34m(name, package, level)\u001b[0m\n",
432 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[1;34m(name, import_)\u001b[0m\n",
433 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load_unlocked\u001b[1;34m(name, import_)\u001b[0m\n",
434 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_call_with_frames_removed\u001b[1;34m(f, *args, **kwds)\u001b[0m\n",
435 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_gcd_import\u001b[1;34m(name, package, level)\u001b[0m\n",
436 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[1;34m(name, import_)\u001b[0m\n",
437 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load_unlocked\u001b[1;34m(name, import_)\u001b[0m\n",
438 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_call_with_frames_removed\u001b[1;34m(f, *args, **kwds)\u001b[0m\n",
439 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_gcd_import\u001b[1;34m(name, package, level)\u001b[0m\n",
440 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[1;34m(name, import_)\u001b[0m\n",
441 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load_unlocked\u001b[1;34m(name, import_)\u001b[0m\n",
442 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_call_with_frames_removed\u001b[1;34m(f, *args, **kwds)\u001b[0m\n",
443 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_gcd_import\u001b[1;34m(name, package, level)\u001b[0m\n",
444 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load\u001b[1;34m(name, import_)\u001b[0m\n",
445 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_find_and_load_unlocked\u001b[1;34m(name, import_)\u001b[0m\n",
446 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_load_unlocked\u001b[1;34m(spec)\u001b[0m\n",
447 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap_external.py\u001b[0m in \u001b[0;36mexec_module\u001b[1;34m(self, module)\u001b[0m\n",
448 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\importlib\\_bootstrap.py\u001b[0m in \u001b[0;36m_call_with_frames_removed\u001b[1;34m(f, *args, **kwds)\u001b[0m\n",
449 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 18\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mio\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhttps\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m//\u001b[0m\u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mio\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m \"\"\"\n\u001b[1;32m---> 20\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mdistribute\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 21\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mmodels\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 22\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mengine\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_layer\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mInput\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
450 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\distribute\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 17\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 18\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdistribute\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0msidecar_evaluator\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
451 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\distribute\\sidecar_evaluator.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplatform\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtf_logging\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mlogging\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mutil\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mdeprecation\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 22\u001b[1;33m from keras.optimizers.optimizer_experimental import (\n\u001b[0m\u001b[0;32m 23\u001b[0m \u001b[0moptimizer\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0moptimizer_experimental\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 24\u001b[0m )\n",
452 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\optimizers\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 24\u001b[0m \u001b[1;31m# Imports needed for deserialization.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 25\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mbackend\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 26\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlegacy\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0madadelta\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0madadelta_legacy\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 27\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlegacy\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0madagrad\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0madagrad_legacy\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 28\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlegacy\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0madam\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0madam_legacy\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
453 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\optimizers\\legacy\\adadelta.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[1;34m\"\"\"Legacy Adadelta optimizer implementation.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 17\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizer_v2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0madadelta\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 18\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[1;31m# isort: off\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
454 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\optimizers\\optimizer_v2\\adadelta.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mbackend_config\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 21\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizer_v2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0moptimizer_v2\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 22\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 23\u001b[0m \u001b[1;31m# isort: off\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
455 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\optimizers\\optimizer_v2\\optimizer_v2.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 24\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 25\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mbackend\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 26\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0minitializers\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 27\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mengine\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mbase_layer_utils\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 28\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizers\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimizer_v2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mutils\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0moptimizer_utils\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
456 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\initializers\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minitializers\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0minitializers_v1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 22\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minitializers\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0minitializers_v2\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 23\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mutils\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mgeneric_utils\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 24\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mutils\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtf_inspect\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0minspect\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
457 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\initializers\\initializers_v2.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 22\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mbackend\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 23\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mutils\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 24\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 25\u001b[0m \u001b[1;31m# isort: off\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
458 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\keras\\dtensor\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;31m# Conditional import the dtensor API, since it is currently broken in OSS.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0m_DTENSOR_API_ENABLED\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 22\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcompat\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mexperimental\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mdtensor\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mdtensor_api\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 23\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 24\u001b[0m \u001b[1;31m# Leave it with a placeholder, so that the import line from other python\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
459 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\_api\\v2\\compat\\v2\\experimental\\dtensor\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0msys\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0m_sys\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mapi\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mcall_with_layout\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 9\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mapi\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mcheck_layout\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mapi\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mclient_id\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
460 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\dtensor\\python\\__init__.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 17\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mgen_dtensor_ops\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mops\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 18\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mmesh_util\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 19\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtpu_util\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
461 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\dtensor\\python\\mesh_util.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 21\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mapi\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 22\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mlayout\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 23\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mmulti_client_util\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
462 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\dtensor\\python\\api.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 20\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtyping\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mAny\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mCallable\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mList\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mOptional\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mSequence\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mUnion\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 22\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mdtensor_device\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 23\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mgen_dtensor_ops\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 24\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mlayout\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mlayout_lib\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
463 | "\u001b[1;32m~\\anaconda3\\envs\\recommenders_env\\lib\\site-packages\\tensorflow\\dtensor\\python\\dtensor_device.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 26\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mgen_dtensor_ops\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 27\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdtensor\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mlayout\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mlayout_lib\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 28\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0m_pywrap_dtensor_device\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 29\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0meager\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mcontext\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 30\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0meager\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mcore\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
464 | "\u001b[1;31mImportError\u001b[0m: DLL load failed: The specified procedure could not be found."
465 | ]
466 | }
467 | ],
468 | "source": [
469 | "model = NCF (\n",
470 | " n_users=data.n_users, \n",
471 | " n_items=data.n_items,\n",
472 | " model_type=\"NeuMF\",\n",
473 | " n_factors=4,\n",
474 | " layer_sizes=[16,8,4],\n",
475 | " n_epochs=EPOCHS,\n",
476 | " batch_size=BATCH_SIZE,\n",
477 | " learning_rate=1e-3,\n",
478 | " verbose=10,\n",
479 | " seed=SEED\n",
480 | ")"
481 | ]
482 | },
483 | {
484 | "cell_type": "code",
485 | "execution_count": null,
486 | "metadata": {
487 | "colab": {
488 | "base_uri": "https://localhost:8080/"
489 | },
490 | "id": "OqQu8zKLfZcM",
491 | "outputId": "a779117a-a070-4f4b-cbcd-1d21047ec1b6"
492 | },
493 | "outputs": [
494 | {
495 | "name": "stdout",
496 | "output_type": "stream",
497 | "text": [
498 | "Took 842.6078 seconds for training.\n"
499 | ]
500 | }
501 | ],
502 | "source": [
503 | "with Timer() as train_time:\n",
504 | " model.fit(data)\n",
505 | "\n",
506 | "print(\"Took {} seconds for training.\".format(train_time))"
507 | ]
508 | },
509 | {
510 | "cell_type": "code",
511 | "execution_count": null,
512 | "metadata": {
513 | "colab": {
514 | "base_uri": "https://localhost:8080/"
515 | },
516 | "id": "w_YS74rmfeK4",
517 | "outputId": "37267df5-2b3b-48b6-f191-a6e67e7adbe9"
518 | },
519 | "outputs": [
520 | {
521 | "name": "stdout",
522 | "output_type": "stream",
523 | "text": [
524 | "Took 24.8943 seconds for prediction.\n"
525 | ]
526 | }
527 | ],
528 | "source": [
529 | "with Timer() as test_time:\n",
530 | " users, items, preds = [], [], []\n",
531 | " item = list(train.itemID.unique())\n",
532 | " for user in train.userID.unique():\n",
533 | " user = [user] * len(item) \n",
534 | " users.extend(user)\n",
535 | " items.extend(item)\n",
536 | " preds.extend(list(model.predict(user, item, is_list=True)))\n",
537 | "\n",
538 | " all_predictions = pd.DataFrame(data={\"userID\": users, \"itemID\":items, \"prediction\":preds})\n",
539 | "\n",
540 | " merged = pd.merge(train, all_predictions, on=[\"userID\", \"itemID\"], how=\"outer\")\n",
541 | " all_predictions = merged[merged.rating.isnull()].drop('rating', axis=1)\n",
542 | "\n",
543 | "print(\"Took {} seconds for prediction.\".format(test_time))"
544 | ]
545 | },
546 | {
547 | "cell_type": "markdown",
548 | "metadata": {
549 | "id": "nL_pYSkPj81T"
550 | },
551 | "source": [
552 | "##4. Evaluate how well NCF performs\n",
553 | "The ranking metrics are used for evaluation."
554 | ]
555 | },
556 | {
557 | "cell_type": "code",
558 | "execution_count": null,
559 | "metadata": {
560 | "colab": {
561 | "base_uri": "https://localhost:8080/"
562 | },
563 | "id": "TzsX97Yufk89",
564 | "outputId": "86ffcb91-443a-48d2-9946-ec9fc62c8314"
565 | },
566 | "outputs": [
567 | {
568 | "name": "stdout",
569 | "output_type": "stream",
570 | "text": [
571 | "MAP:\t0.020692\n",
572 | "NDCG:\t0.064364\n",
573 | "Precision@K:\t0.047777\n",
574 | "Recall@K:\t0.051526\n"
575 | ]
576 | }
577 | ],
578 | "source": [
579 | "eval_map = map_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)\n",
580 | "eval_ndcg = ndcg_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)\n",
581 | "eval_precision = precision_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)\n",
582 | "eval_recall = recall_at_k(test, all_predictions, col_prediction='prediction', k=TOP_K)\n",
583 | "\n",
584 | "print(\"MAP:\\t%f\" % eval_map,\n",
585 | " \"NDCG:\\t%f\" % eval_ndcg,\n",
586 | " \"Precision@K:\\t%f\" % eval_precision,\n",
587 | " \"Recall@K:\\t%f\" % eval_recall, sep='\\n')"
588 | ]
589 | },
590 | {
591 | "cell_type": "code",
592 | "execution_count": null,
593 | "metadata": {
594 | "id": "sdHaSli43ztH"
595 | },
596 | "outputs": [],
597 | "source": [
598 | "df_order = pd.read_excel('/content/drive/My Drive/Rec_sys_data.xlsx', 'order')\n",
599 | "df_customer = pd.read_excel('/content/drive/My Drive/Rec_sys_data.xlsx', 'customer')\n",
600 | "df_product = pd.read_excel('/content/drive/My Drive/Rec_sys_data.xlsx', 'product')"
601 | ]
602 | },
603 | {
604 | "cell_type": "code",
605 | "execution_count": null,
606 | "metadata": {
607 | "colab": {
608 | "base_uri": "https://localhost:8080/",
609 | "height": 206
610 | },
611 | "id": "hrH92rSu3RCD",
612 | "outputId": "fee2cd20-2349-4131-a5f9-2a29818a7c4f"
613 | },
614 | "outputs": [
615 | {
616 | "data": {
617 | "text/html": [
618 | "\n",
619 | " \n",
620 | "
\n",
621 | "
\n",
622 | "\n",
635 | "
\n",
636 | " \n",
637 | " \n",
638 | " | \n",
639 | " userID | \n",
640 | " itemID | \n",
641 | " timestamp | \n",
642 | " prediction | \n",
643 | "
\n",
644 | " \n",
645 | " \n",
646 | " \n",
647 | " 206767 | \n",
648 | " 12346 | \n",
649 | " 22678 | \n",
650 | " NaT | \n",
651 | " 0.973725 | \n",
652 | "
\n",
653 | " \n",
654 | " 204556 | \n",
655 | " 12346 | \n",
656 | " 22193 | \n",
657 | " NaT | \n",
658 | " 0.972970 | \n",
659 | "
\n",
660 | " \n",
661 | " 206766 | \n",
662 | " 12346 | \n",
663 | " 22676 | \n",
664 | " NaT | \n",
665 | " 0.971280 | \n",
666 | "
\n",
667 | " \n",
668 | " 206765 | \n",
669 | " 12346 | \n",
670 | " 22683 | \n",
671 | " NaT | \n",
672 | " 0.962661 | \n",
673 | "
\n",
674 | " \n",
675 | " 206763 | \n",
676 | " 12346 | \n",
677 | " 22680 | \n",
678 | " NaT | \n",
679 | " 0.962542 | \n",
680 | "
\n",
681 | " \n",
682 | "
\n",
683 | "
\n",
684 | "
\n",
694 | " \n",
695 | " \n",
732 | "\n",
733 | " \n",
757 | "
\n",
758 | "
\n",
759 | " "
760 | ],
761 | "text/plain": [
762 | " userID itemID timestamp prediction\n",
763 | "206767 12346 22678 NaT 0.973725\n",
764 | "204556 12346 22193 NaT 0.972970\n",
765 | "206766 12346 22676 NaT 0.971280\n",
766 | "206765 12346 22683 NaT 0.962661\n",
767 | "206763 12346 22680 NaT 0.962542"
768 | ]
769 | },
770 | "execution_count": 16,
771 | "metadata": {},
772 | "output_type": "execute_result"
773 | }
774 | ],
775 | "source": [
776 | "all_predictions[all_predictions['userID']==12346].nlargest(5,'prediction')"
777 | ]
778 | },
779 | {
780 | "cell_type": "code",
781 | "execution_count": null,
782 | "metadata": {
783 | "id": "GE67RjSC75qb"
784 | },
785 | "outputs": [],
786 | "source": [
787 | "all_predictions = all_predictions[['userID','itemID','prediction']]"
788 | ]
789 | },
790 | {
791 | "cell_type": "code",
792 | "execution_count": null,
793 | "metadata": {
794 | "id": "agUv0QI08fpm"
795 | },
796 | "outputs": [],
797 | "source": [
798 | "all_predictions = all_predictions.rename(columns={\n",
799 | " \n",
800 | " \"userID\":'CustomerID',\"itemID\":'StockCode',\"rating\":'Quantity','prediction':'probability'\n",
801 | " \n",
802 | "})"
803 | ]
804 | },
805 | {
806 | "cell_type": "markdown",
807 | "metadata": {
808 | "id": "yjLD9I-C_UAJ"
809 | },
810 | "source": []
811 | },
812 | {
813 | "cell_type": "code",
814 | "execution_count": null,
815 | "metadata": {
816 | "id": "J91Xf9WJ47ZC"
817 | },
818 | "outputs": [],
819 | "source": [
820 | "def recommend_product(customer_id):\n",
821 | "\n",
822 | " print(\" \\n---------- Top 5 Bought StockCodes -----------\\n\")\n",
823 | " \n",
824 | "\n",
825 | " print(df_order[df_order['CustomerID']==customer_id][['CustomerID','StockCode','Quantity']].nlargest(5,'Quantity'))\n",
826 | "\n",
827 | " top_5_bought = df_order[df_order['CustomerID']==customer_id][['CustomerID','StockCode','Quantity']].nlargest(5,'Quantity')\n",
828 | "\n",
829 | " print('\\n-------Product Name of bought StockCodes ------\\n')\n",
830 | "\n",
831 | " print(df_product[df_product.StockCode.isin(top_5_bought.StockCode)]['Product Name'])\n",
832 | "\n",
833 | "\n",
834 | " print(\"\\n --------- Top 5 Recommendations ------------ \\n\")\n",
835 | "\n",
836 | " print(all_predictions[all_predictions['CustomerID']==customer_id].nlargest(5,'probability'))\n",
837 | "\n",
838 | " recommend = all_predictions[all_predictions['CustomerID']==customer_id].nlargest(5,'probability')\n",
839 | "\n",
840 | " print('\\n-------Product Name of Recommendations ------\\n')\n",
841 | "\n",
842 | " print(df_product[df_product.StockCode.isin(recommend.StockCode)]['Product Name'])\n"
843 | ]
844 | },
845 | {
846 | "cell_type": "markdown",
847 | "metadata": {
848 | "id": "zH8aPyEv_Vsa"
849 | },
850 | "source": [
851 | "##5. Recommendation's"
852 | ]
853 | },
854 | {
855 | "cell_type": "code",
856 | "execution_count": null,
857 | "metadata": {
858 | "colab": {
859 | "base_uri": "https://localhost:8080/"
860 | },
861 | "id": "c8gBM4Cr7P_3",
862 | "outputId": "5c590874-f740-4e21-9b7b-c3e2b9cf1017"
863 | },
864 | "outputs": [
865 | {
866 | "name": "stdout",
867 | "output_type": "stream",
868 | "text": [
869 | " \n",
870 | "---------- Top 5 Bought StockCodes -----------\n",
871 | "\n",
872 | " CustomerID StockCode Quantity\n",
873 | "234414 13137 84077 48\n",
874 | "234443 13137 23321 13\n",
875 | "50797 13137 21985 12\n",
876 | "234404 13137 22296 12\n",
877 | "234418 13137 22297 12\n",
878 | "\n",
879 | "-------Product Name of bought StockCodes ------\n",
880 | "\n",
881 | "70 MightySkins Skin Decal Wrap Compatible with Li...\n",
882 | "490 Window Tint Film Mitsubishi (all doors) DIY\n",
883 | "694 Harriton Men's Paradise Short-Sleeve Performan...\n",
884 | "1065 MightySkins Skin For Samsung Galaxy J3 (2016),...\n",
885 | "1339 MightySkins Skin Decal Wrap Compatible with Le...\n",
886 | "Name: Product Name, dtype: object\n",
887 | "\n",
888 | " --------- Top 5 Recommendations ------------ \n",
889 | "\n",
890 | " CustomerID StockCode probability\n",
891 | "1951608 13137 85123A 0.975194\n",
892 | "1952595 13137 21034 0.971388\n",
893 | "1951667 13137 22197 0.960145\n",
894 | "1951758 13137 85099F 0.929778\n",
895 | "1952914 13137 22766 0.917395\n",
896 | "\n",
897 | "-------Product Name of Recommendations ------\n",
898 | "\n",
899 | "63 Tom Ford Lip Color Sheer 0.07Oz/2g New In Box ...\n",
900 | "135 Mediven Sheer and Soft 15-20 mmHg Thigh w/ Lac...\n",
901 | "161 Union 3\" Female Ports Stainless Steel Pipe Fit...\n",
902 | "215 MightySkins Skin Decal Wrap Compatible with Ap...\n",
903 | "236 MightySkins Skin Decal Wrap Compatible with HP...\n",
904 | "Name: Product Name, dtype: object\n"
905 | ]
906 | }
907 | ],
908 | "source": [
909 | "recommend_product(13137)"
910 | ]
911 | },
912 | {
913 | "cell_type": "code",
914 | "execution_count": null,
915 | "metadata": {
916 | "colab": {
917 | "base_uri": "https://localhost:8080/"
918 | },
919 | "id": "8WKR_H9Y9weE",
920 | "outputId": "10968de8-bdc0-4d08-ff68-263153fe9b42"
921 | },
922 | "outputs": [
923 | {
924 | "name": "stdout",
925 | "output_type": "stream",
926 | "text": [
927 | " \n",
928 | "---------- Top 5 Bought StockCodes -----------\n",
929 | "\n",
930 | " CustomerID StockCode Quantity\n",
931 | "272296 15127 23263 48\n",
932 | "272287 15127 23354 24\n",
933 | "272288 15127 22813 24\n",
934 | "272289 15127 23096 24\n",
935 | "272285 15127 21181 12\n",
936 | "\n",
937 | "-------Product Name of bought StockCodes ------\n",
938 | "\n",
939 | "13 billyboards Porcelain School Chalkboard\n",
940 | "374 MightySkins Protective Vinyl Skin Decal for Po...\n",
941 | "923 Zoan Synchrony Duo Sport Electric Snow Helmet ...\n",
942 | "952 MightySkins Skin Decal Wrap Compatible with Sm...\n",
943 | "1576 EMPIRE KLIX Klutch Designer Wallet Case for LG G2\n",
944 | "Name: Product Name, dtype: object\n",
945 | "\n",
946 | " --------- Top 5 Recommendations ------------ \n",
947 | "\n",
948 | " CustomerID StockCode probability\n",
949 | "6135734 15127 84879 0.973742\n",
950 | "6137006 15127 35970 0.935546\n",
951 | "6136832 15127 21034 0.931347\n",
952 | "6137564 15127 23356 0.925915\n",
953 | "6137220 15127 85049A 0.922400\n",
954 | "\n",
955 | "-------Product Name of Recommendations ------\n",
956 | "\n",
957 | "3 Mediven Sheer and Soft 15-20 mmHg Thigh w/ Lac...\n",
958 | "215 MightySkins Skin Decal Wrap Compatible with Ap...\n",
959 | "288 MightySkins Skin Decal Wrap Compatible with Sm...\n",
960 | "1558 Ebe Men Black Rectangle Half Rim Spring Hinge ...\n",
961 | "1713 Ebe Prescription Glasses Mens Womens Burgundy ...\n",
962 | "Name: Product Name, dtype: object\n"
963 | ]
964 | }
965 | ],
966 | "source": [
967 | "recommend_product(15127)\n"
968 | ]
969 | },
970 | {
971 | "cell_type": "markdown",
972 | "metadata": {
973 | "id": "7vhoTZHrOSMj"
974 | },
975 | "source": []
976 | }
977 | ],
978 | "metadata": {
979 | "colab": {
980 | "collapsed_sections": [],
981 | "name": "Deep_Learning_Recommendation_System.ipynb",
982 | "provenance": []
983 | },
984 | "kernelspec": {
985 | "display_name": "Python 3 (ipykernel)",
986 | "language": "python",
987 | "name": "python3"
988 | },
989 | "language_info": {
990 | "codemirror_mode": {
991 | "name": "ipython",
992 | "version": 3
993 | },
994 | "file_extension": ".py",
995 | "mimetype": "text/x-python",
996 | "name": "python",
997 | "nbconvert_exporter": "python",
998 | "pygments_lexer": "ipython3",
999 | "version": "3.9.7"
1000 | }
1001 | },
1002 | "nbformat": 4,
1003 | "nbformat_minor": 1
1004 | }
1005 |
--------------------------------------------------------------------------------
/Contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to Apress Source Code
2 |
3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers.
4 |
5 | ## How to Contribute
6 |
7 | 1. Make sure you have a GitHub account.
8 | 2. Fork the repository for the relevant book.
9 | 3. Create a new branch on which to make your change, e.g.
10 | `git checkout -b my_code_contribution`
11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted.
12 | 5. Submit a pull request.
13 |
14 | Thank you for your contribution!
--------------------------------------------------------------------------------
/Data/Rec_sys_data.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/applied-recommender-systems-python/77609995cf4b7c0a672cdf94c4f43c4531ef37ce/Data/Rec_sys_data.xlsx
--------------------------------------------------------------------------------
/Data/data.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/applied-recommender-systems-python/77609995cf4b7c0a672cdf94c4f43c4531ef37ce/Data/data.csv
--------------------------------------------------------------------------------
/Data/mba_data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/applied-recommender-systems-python/77609995cf4b7c0a672cdf94c4f43c4531ef37ce/Data/mba_data
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Freeware License, some rights reserved
2 |
3 | Copyright (c) 2023 Akshay Kulkarni, Adarsha Shivananda, Anoosh Kulkarni, V Adithya Krishnan
4 |
5 | Permission is hereby granted, free of charge, to anyone obtaining a copy
6 | of this software and associated documentation files (the "Software"),
7 | to work with the Software within the limits of freeware distribution and fair use.
8 | This includes the rights to use, copy, and modify the Software for personal use.
9 | Users are also allowed and encouraged to submit corrections and modifications
10 | to the Software for the benefit of other users.
11 |
12 | It is not allowed to reuse, modify, or redistribute the Software for
13 | commercial use in any way, or for a user’s educational materials such as books
14 | or blog articles without prior permission from the copyright holder.
15 |
16 | The above copyright notice and this permission notice need to be included
17 | in all copies or substantial portions of the software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apress Source Code
2 |
3 | This repository accompanies [*Applied Recommender Systems with Python*](https://link.springer.com/book/10.1007/978-1-4842-8954-9) by Akshay Kulkarni, Adarsha Shivananda, Anoosh Kulkarni, and V Adithya Krishnan (Apress, 2023).
4 |
5 | [comment]: #cover
6 | 
7 |
8 | Download the files as a zip using the green button, or clone the repository to your machine using Git.
9 |
10 | ## Releases
11 |
12 | Release v1.0 corresponds to the code in the published book, without corrections or updates.
13 |
14 | ## Contributions
15 |
16 | See the file Contributing.md for more information on how you can contribute to this repository.
--------------------------------------------------------------------------------
/errata.md:
--------------------------------------------------------------------------------
1 | # Errata for *Applied Recommender Systems with Python*
2 |
3 | On **page xx** [Summary of error]:
4 |
5 | Details of error here. Highlight key pieces in **bold**.
6 |
7 | ***
8 |
9 | On **page xx** [Summary of error]:
10 |
11 | Details of error here. Highlight key pieces in **bold**.
12 |
13 | ***
--------------------------------------------------------------------------------