{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":31254,"databundleVersionId":3103714,"sourceType":"competition"},{"sourceId":6644,"databundleVersionId":44315,"sourceType":"competition"}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:00:07.341319Z","iopub.execute_input":"2024-12-07T01:00:07.342036Z","iopub.status.idle":"2024-12-07T01:02:31.742212Z","shell.execute_reply.started":"2024-12-07T01:00:07.341994Z","shell.execute_reply":"2024-12-07T01:02:31.740656Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom matplotlib import pyplot as plt\nimport networkx as nx\nfrom gensim.models import Word2Vec\nfrom sklearn.metrics.pairwise import cosine_similarity\nimport matplotlib.image as mpimg\nimport random","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:03:18.142318Z","iopub.execute_input":"2024-12-07T01:03:18.142886Z","iopub.status.idle":"2024-12-07T01:03:18.150275Z","shell.execute_reply.started":"2024-12-07T01:03:18.142848Z","shell.execute_reply":"2024-12-07T01:03:18.148562Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport os\nos.getcwd()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:03:39.181251Z","iopub.execute_input":"2024-12-07T01:03:39.181748Z","iopub.status.idle":"2024-12-07T01:03:39.190214Z","shell.execute_reply.started":"2024-12-07T01:03:39.181698Z","shell.execute_reply":"2024-12-07T01:03:39.188659Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import zipfile","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:03:52.820567Z","iopub.execute_input":"2024-12-07T01:03:52.820986Z","iopub.status.idle":"2024-12-07T01:03:52.826281Z","shell.execute_reply.started":"2024-12-07T01:03:52.820951Z","shell.execute_reply":"2024-12-07T01:03:52.825023Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile(\"/kaggle/input/instacart-market-basket-analysis/orders.csv.zip\",\"r\") as z:\n z.extractall(\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:04:05.832062Z","iopub.execute_input":"2024-12-07T01:04:05.832437Z","iopub.status.idle":"2024-12-07T01:04:07.015128Z","shell.execute_reply.started":"2024-12-07T01:04:05.832406Z","shell.execute_reply":"2024-12-07T01:04:07.014028Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#每個使用者的購物紀錄\norders=pd.read_csv('/kaggle/working/orders.csv')\norders.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:04:21.381370Z","iopub.execute_input":"2024-12-07T01:04:21.382383Z","iopub.status.idle":"2024-12-07T01:04:23.508474Z","shell.execute_reply.started":"2024-12-07T01:04:21.382328Z","shell.execute_reply":"2024-12-07T01:04:23.507251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile(\"/kaggle/input/instacart-market-basket-analysis/order_products__prior.csv.zip\",\"r\") as z:\n z.extractall(\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:04:46.244472Z","iopub.execute_input":"2024-12-07T01:04:46.244887Z","iopub.status.idle":"2024-12-07T01:04:52.275682Z","shell.execute_reply.started":"2024-12-07T01:04:46.244852Z","shell.execute_reply":"2024-12-07T01:04:52.274506Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#每個使用者再次購買紀錄\nprior = pd.read_csv('/kaggle/working/order_products__prior.csv')\nprior.head()\nmovies = prior\nmovies","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:05:53.786849Z","iopub.execute_input":"2024-12-07T01:05:53.787249Z","iopub.status.idle":"2024-12-07T01:06:02.837465Z","shell.execute_reply.started":"2024-12-07T01:05:53.787212Z","shell.execute_reply":"2024-12-07T01:06:02.836199Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile(\"/kaggle/input/instacart-market-basket-analysis/order_products__train.csv.zip\",\"r\") as z:\n z.extractall(\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:06:07.359294Z","iopub.execute_input":"2024-12-07T01:06:07.360166Z","iopub.status.idle":"2024-12-07T01:06:07.660259Z","shell.execute_reply.started":"2024-12-07T01:06:07.360111Z","shell.execute_reply":"2024-12-07T01:06:07.658741Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train=pd.read_csv('/kaggle/working/order_products__train.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:06:20.163053Z","iopub.execute_input":"2024-12-07T01:06:20.163476Z","iopub.status.idle":"2024-12-07T01:06:20.566037Z","shell.execute_reply.started":"2024-12-07T01:06:20.163427Z","shell.execute_reply":"2024-12-07T01:06:20.564685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.head()\ndf = train\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:06:34.165665Z","iopub.execute_input":"2024-12-07T01:06:34.166089Z","iopub.status.idle":"2024-12-07T01:06:34.178855Z","shell.execute_reply.started":"2024-12-07T01:06:34.166052Z","shell.execute_reply":"2024-12-07T01:06:34.177705Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"prior.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:06:49.347819Z","iopub.execute_input":"2024-12-07T01:06:49.348327Z","iopub.status.idle":"2024-12-07T01:06:49.356519Z","shell.execute_reply.started":"2024-12-07T01:06:49.348278Z","shell.execute_reply":"2024-12-07T01:06:49.355321Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"prior=prior[0:300000]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:07:04.335772Z","iopub.execute_input":"2024-12-07T01:07:04.336145Z","iopub.status.idle":"2024-12-07T01:07:04.341838Z","shell.execute_reply.started":"2024-12-07T01:07:04.336111Z","shell.execute_reply":"2024-12-07T01:07:04.340426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#使用者一起合併到購物紀錄\norder_prior=pd.merge(prior,orders,on=['order_id','order_id'])\norder_prior=order_prior.sort_values(by=['user_id','order_id'])\norder_prior.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:07:23.382789Z","iopub.execute_input":"2024-12-07T01:07:23.383752Z","iopub.status.idle":"2024-12-07T01:07:25.736389Z","shell.execute_reply.started":"2024-12-07T01:07:23.383702Z","shell.execute_reply":"2024-12-07T01:07:25.734984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile(\"/kaggle/input/instacart-market-basket-analysis/products.csv.zip\",\"r\") as z:\n z.extractall(\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:07:45.569397Z","iopub.execute_input":"2024-12-07T01:07:45.569780Z","iopub.status.idle":"2024-12-07T01:07:45.614961Z","shell.execute_reply.started":"2024-12-07T01:07:45.569746Z","shell.execute_reply":"2024-12-07T01:07:45.613687Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#產品的名稱跟哪一個銷售區域\nproducts = pd.read_csv('/kaggle/working/products.csv')\nproducts.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:08:02.598681Z","iopub.execute_input":"2024-12-07T01:08:02.599091Z","iopub.status.idle":"2024-12-07T01:08:02.673390Z","shell.execute_reply.started":"2024-12-07T01:08:02.599055Z","shell.execute_reply":"2024-12-07T01:08:02.671973Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile(\"/kaggle/input/instacart-market-basket-analysis/aisles.csv.zip\",\"r\") as z:\n z.extractall(\".\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:08:15.510877Z","iopub.execute_input":"2024-12-07T01:08:15.511542Z","iopub.status.idle":"2024-12-07T01:08:15.532095Z","shell.execute_reply.started":"2024-12-07T01:08:15.511490Z","shell.execute_reply":"2024-12-07T01:08:15.530918Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"aisles = pd.read_csv('/kaggle/working/aisles.csv')\naisles.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:08:28.291709Z","iopub.execute_input":"2024-12-07T01:08:28.292084Z","iopub.status.idle":"2024-12-07T01:08:28.305974Z","shell.execute_reply.started":"2024-12-07T01:08:28.292052Z","shell.execute_reply":"2024-12-07T01:08:28.304707Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"_mt = pd.merge(prior,products, on = ['product_id','product_id'])\n_mt = pd.merge(_mt,orders,on=['order_id','order_id'])\nmt = pd.merge(_mt,aisles,on=['aisle_id','aisle_id'])\nmt.head(3)\n#合併購物的使用者跟名稱","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:09:01.013464Z","iopub.execute_input":"2024-12-07T01:09:01.014509Z","iopub.status.idle":"2024-12-07T01:09:03.396209Z","shell.execute_reply.started":"2024-12-07T01:09:01.014467Z","shell.execute_reply":"2024-12-07T01:09:03.394779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mt = mt.rename(columns={'order_id': 't_dat','user_id': 'customer_id', 'product_id': 'article_id', 'add_to_cart_order': 'frequency'})\nGraphTravel_HM = mt\nGraphTravel_HM","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:13:25.167930Z","iopub.execute_input":"2024-12-07T01:13:25.168480Z","iopub.status.idle":"2024-12-07T01:13:25.210868Z","shell.execute_reply.started":"2024-12-07T01:13:25.168428Z","shell.execute_reply":"2024-12-07T01:13:25.209684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sns.distplot(GraphTravel_HM['frequency'], kde=True, bins=30)\n\nplt.title('Distribution of frequency')\nplt.xlabel('Frequency')\nplt.ylabel('Density')\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:13:45.481034Z","iopub.execute_input":"2024-12-07T01:13:45.481398Z","iopub.status.idle":"2024-12-07T01:13:47.066166Z","shell.execute_reply.started":"2024-12-07T01:13:45.481367Z","shell.execute_reply":"2024-12-07T01:13:47.065076Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#在GraphTravel_HM 裡找每一個 customer_id 還有item_name_mappin 到products資料庫裡找對應的產品名稱\nunique_customer_ids = GraphTravel_HM['customer_id'].unique()\ncustomer_id_mapping = {id: i for i, id in enumerate(unique_customer_ids)}\nGraphTravel_HM['customer_id'] = GraphTravel_HM['customer_id'].map(customer_id_mapping)\n\nitem_name_mapping = dict(zip(products['product_id'], products['product_name'])) # prod_name","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:17:31.646686Z","iopub.execute_input":"2024-12-07T01:17:31.647125Z","iopub.status.idle":"2024-12-07T01:17:31.740830Z","shell.execute_reply.started":"2024-12-07T01:17:31.647087Z","shell.execute_reply":"2024-12-07T01:17:31.739624Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# customer_id_mapping","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"G = nx.Graph()\n\nfor index, row in GraphTravel_HM.iterrows():\n    G.add_node(row['customer_id'], type='user')\n    G.add_node(row['article_id'], type='item')\n    G.add_edge(row['customer_id'], row['article_id'], weight=row['frequency'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:19:03.231222Z","iopub.execute_input":"2024-12-07T01:19:03.231681Z","iopub.status.idle":"2024-12-07T01:19:23.326862Z","shell.execute_reply.started":"2024-12-07T01:19:03.231636Z","shell.execute_reply":"2024-12-07T01:19:23.325679Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# biased random walk  \ndef biased_random_walk(G, start_node, walk_length, p=1, q=1):\n    walk = [start_node]\n\n    while len(walk) < walk_length:\n        cur_node = walk[-1]\n        cur_neighbors = list(G.neighbors(cur_node))\n\n        if len(cur_neighbors) > 0:\n            if len(walk) == 1:\n                walk.append(random.choice(cur_neighbors))\n            else:\n                prev_node = walk[-2]\n\n                probability = []\n                for neighbor in cur_neighbors:\n                    if neighbor == prev_node:\n                        # Return parameter \n                        probability.append(1/p)\n                    elif G.has_edge(neighbor, prev_node):\n                        # Stay parameter \n                        probability.append(1)\n                    else:\n                        # In-out parameter \n                        probability.append(1/q)\n\n                probability = np.array(probability)\n                probability = probability / probability.sum()  # normalize\n\n                next_node = np.random.choice(cur_neighbors, p=probability)\n                walk.append(next_node)\n        else:\n            break\n\n    return walk","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:19:28.158668Z","iopub.execute_input":"2024-12-07T01:19:28.159155Z","iopub.status.idle":"2024-12-07T01:19:28.167983Z","shell.execute_reply.started":"2024-12-07T01:19:28.159118Z","shell.execute_reply":"2024-12-07T01:19:28.166728Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def generate_walks(G, num_walks, walk_length, p=1, q=1):\n    walks = []\n    nodes = list(G.nodes())\n    for _ in range(num_walks):\n        random.shuffle(nodes)  # to ensure randomness\n        for node in nodes:\n            walk_from_node = biased_random_walk(G, node, walk_length, p, q)\n            walks.append(walk_from_node)\n    return walks","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:19:43.567872Z","iopub.execute_input":"2024-12-07T01:19:43.568273Z","iopub.status.idle":"2024-12-07T01:19:43.574336Z","shell.execute_reply.started":"2024-12-07T01:19:43.568237Z","shell.execute_reply":"2024-12-07T01:19:43.573198Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#generate_walks(G, 2, 8, p=0.5, q=0.5)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Random Walk \nwalks = generate_walks(G, num_walks=10, walk_length=20, p=9, q=1)\nfiltered_walks = [walk for walk in walks if len(walk) >= 5]\n\n# to String  (for Word2Vec input)\nwalks = [[str(node) for node in walk] for walk in walks]\n\n# Word2Vec train\nmodel = Word2Vec(walks, vector_size=128, window=5, min_count=0,  hs=1, sg=1, workers=4, epochs=10)\n\n# node embedding extract\nembeddings = {node_id: model.wv[node_id] for node_id in model.wv.index_to_key}\n","metadata":{"execution":{"iopub.status.busy":"2024-12-07T01:43:41.481050Z","iopub.execute_input":"2024-12-07T01:43:41.481469Z","iopub.status.idle":"2024-12-07T02:00:36.580848Z","shell.execute_reply.started":"2024-12-07T01:43:41.481426Z","shell.execute_reply":"2024-12-07T02:00:36.579172Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#get_user_embedding","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_user_embedding(user_id, embeddings):\n    return embeddings[str(user_id)]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:42:51.701973Z","iopub.execute_input":"2024-12-07T01:42:51.702391Z","iopub.status.idle":"2024-12-07T01:42:51.708439Z","shell.execute_reply.started":"2024-12-07T01:42:51.702354Z","shell.execute_reply":"2024-12-07T01:42:51.706700Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_rated_items(user_id, df):\n    return set(df[df['customer_id'] == user_id]['article_id'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:41:22.298418Z","iopub.execute_input":"2024-12-07T01:41:22.298959Z","iopub.status.idle":"2024-12-07T01:41:22.305051Z","shell.execute_reply.started":"2024-12-07T01:41:22.298897Z","shell.execute_reply":"2024-12-07T01:41:22.303900Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def calculate_similarities(user_id, df, embeddings):\n    rated_items = get_rated_items(user_id, df)\n    user_embedding = get_user_embedding(user_id, embeddings)\n\n    item_similarities = []\n    for item_id in set(df['article_id']):\n        if item_id not in rated_items:  \n            item_embedding = embeddings[str(item_id)]\n            similarity = cosine_similarity([user_embedding], [item_embedding])[0][0]\n            item_similarities.append((item_id, similarity))\n\n    return item_similarities","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:42:30.746738Z","iopub.execute_input":"2024-12-07T01:42:30.747110Z","iopub.status.idle":"2024-12-07T01:42:30.753417Z","shell.execute_reply.started":"2024-12-07T01:42:30.747078Z","shell.execute_reply":"2024-12-07T01:42:30.752265Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_images(items, item_name_mapping, num_items, show_similarity=False):\n    f, ax = plt.subplots(1, num_items, figsize=(20,10))\n    if num_items == 1:\n        ax = [ax]\n    for i, item in enumerate(items):\n        item_id, similarity = item\n        print(f\"- Item {item_id}: {item_name_mapping[item_id]}\", end='')\n        if show_similarity:\n            print(f\" with similarity score: {similarity}\")\n        else:\n            print()\n        img_path = f\"../input/h-and-m-personalized-fashion-recommendations/images/0{str(item_id)[:2]}/0{int(item_id)}.jpg\"\n        try:\n            img = mpimg.imread(img_path)\n            ax[i].imshow(img)\n            ax[i].set_title(f'Item {item_id}')\n            ax[i].set_xticks([], [])\n            ax[i].set_yticks([], [])\n            ax[i].grid(False)\n        except FileNotFoundError:\n            print(f\"Image for item {item_id} not found.\")\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:42:34.762844Z","iopub.execute_input":"2024-12-07T01:42:34.763248Z","iopub.status.idle":"2024-12-07T01:42:34.771890Z","shell.execute_reply.started":"2024-12-07T01:42:34.763214Z","shell.execute_reply":"2024-12-07T01:42:34.770574Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def recommend_items(user_id, df, embeddings, item_name_mapping, num_items=5):\n    rated_items = get_rated_items(user_id, df)\n    \n    print(f\"User {user_id} has purchased:\")\n    show_images([(item_id, 0) for item_id in list(rated_items)[:5]], item_name_mapping, min(len(rated_items), 5))\n    \n    item_similarities = calculate_similarities(user_id, df, embeddings)\n\n    recommended_items = sorted(item_similarities, key=lambda x: x[1], reverse=True)[:num_items]\n\n    print(f\"\\nRecommended items for user {user_id}:\")\n    show_images(recommended_items, item_name_mapping, num_items, show_similarity=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:42:37.317242Z","iopub.execute_input":"2024-12-07T01:42:37.317686Z","iopub.status.idle":"2024-12-07T01:42:37.325443Z","shell.execute_reply.started":"2024-12-07T01:42:37.317632Z","shell.execute_reply":"2024-12-07T01:42:37.323955Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# costomer 45's top 5 \nrecommend_items(45, GraphTravel_HM, embeddings, item_name_mapping, num_items=5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-07T01:42:58.856556Z","iopub.execute_input":"2024-12-07T01:42:58.857003Z","iopub.status.idle":"2024-12-07T01:42:59.577226Z","shell.execute_reply.started":"2024-12-07T01:42:58.856962Z","shell.execute_reply":"2024-12-07T01:42:59.575705Z"}},"outputs":[],"execution_count":null}]}