{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"authorship_tag":"ABX9TyPX+xE181f8IKzMjsVahwg0"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["## Jenis-Jenis Model Recommender Systems\n","Ada beberapa pendekatan yang umum digunakan dalam sistem rekomendasi:\n","\n","* Collaborative Filtering (CF): Mengandalkan interaksi pengguna dan item untuk memberikan rekomendasi.\n","* Content-Based Filtering (CBF): Menggunakan fitur dari item atau pengguna.\n","* Hybrid Models: Menggabungkan CF dan CBF.\n","\n","Untuk memulai, kita akan fokus pada Collaborative Filtering, khususnya Matrix Factorization."],"metadata":{"id":"oQ7NulcJBhII"}},{"cell_type":"markdown","source":["## Implementasi Matrix Factorization\n","Matrix Factorization adalah teknik di mana kita memfaktorkan matriks besar yang berisi data rating pengguna ke dalam dua matriks lebih kecil: satu untuk pengguna dan satu untuk item.\n","\n","Rumus Dasar:\n","\n","Jika kita punya matriks rating \\( R \\) dengan dimensi \\( m * n \\) (di mana \\( m \\) adalah jumlah pengguna dan \\( n \\) adalah jumlah item), maka kita faktorkan matriks ini menjadi dua matriks:\n","- \\( P \\): Matriks pengguna dengan dimensi \\( m * k \\).\n","- \\( Q \\): Matriks item dengan dimensi \\( k * n \\).\n","\n","Model ini mencoba meminimalkan selisih antara \\( R \\) dan perkalian \\( P * Q \\)."],"metadata":{"id":"Gbg2sUaaBzGT"}},{"cell_type":"markdown","source":["## Membangun Model dengan PyTorch\n"],"metadata":{"id":"Pxi5fyTzCPxB"}},{"cell_type":"code","execution_count":1,"metadata":{"id":"Ye2sQ-_EBUmj","executionInfo":{"status":"ok","timestamp":1724028356158,"user_tz":-420,"elapsed":8672,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}}},"outputs":[],"source":["import torch\n","import torch.nn as nn\n","import torch.optim as optim\n","import numpy as np"]},{"cell_type":"code","source":["class MFModel(nn.Module):\n"," def __init__(self, num_users, num_items, embedding_size):\n"," super(MFModel, self).__init__()\n"," self.user_embedding = nn.Embedding(num_users, embedding_size)\n"," self.item_embedding = nn.Embedding(num_items, embedding_size)\n","\n"," def forward(self, user_id, item_id):\n"," user_vec = self.user_embedding(user_id)\n"," item_vec = self.item_embedding(item_id)\n"," dot_product = torch.sum(user_vec * item_vec, dim=1)\n"," return dot_product"],"metadata":{"id":"wjj9iidpCYG5","executionInfo":{"status":"ok","timestamp":1724027645001,"user_tz":-420,"elapsed":3,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}}},"execution_count":7,"outputs":[]},{"cell_type":"code","source":["# Data dummy: user_ids, item_ids, dan ratings\n","user_ids = torch.tensor([0, 1, 2, 0, 1, 2], dtype=torch.long)\n","item_ids = torch.tensor([0, 1, 2, 1, 2, 0], dtype=torch.long)\n","ratings = torch.tensor([5, 4, 3, 4, 5, 2], dtype=torch.float32)"],"metadata":{"id":"EAUFvL3eDX63","executionInfo":{"status":"ok","timestamp":1724028364023,"user_tz":-420,"elapsed":358,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}}},"execution_count":2,"outputs":[]},{"cell_type":"code","source":["# Jumlah pengguna dan item\n","num_users = 3\n","num_items = 3\n","embedding_size = 2"],"metadata":{"id":"itw-Yyq4Cbmt","executionInfo":{"status":"ok","timestamp":1724028366568,"user_tz":-420,"elapsed":3,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}}},"execution_count":3,"outputs":[]},{"cell_type":"markdown","source":["## Training\n","Sekarang, mari kita bicara tentang cara melatih model ini menggunakan data rating nyata. Kamu akan membutuhkan:\n","- **Loss Function**: Biasanya menggunakan Mean Squared Error (MSE).\n","- **Optimizer**: Menggunakan Adam atau SGD."],"metadata":{"id":"4JuPuzF5Ciut"}},{"cell_type":"code","source":["# Membuat model dan loss function\n","model = MFModel(num_users, num_items, embedding_size)\n","criterion = nn.MSELoss()\n","optimizer = optim.Adam(model.parameters(), lr=0.01)\n","\n","# Melatih model\n","for epoch in range(100):\n"," model.train()\n"," optimizer.zero_grad()\n"," predictions = model(user_ids, item_ids)\n"," loss = criterion(predictions, ratings)\n"," loss.backward()\n"," optimizer.step()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"pi-IXtbTCpEK","executionInfo":{"status":"ok","timestamp":1724027799617,"user_tz":-420,"elapsed":849,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}},"outputId":"22bb1702-0b08-458f-8bd1-ee8b5bd25bcc"},"execution_count":13,"outputs":[{"output_type":"stream","name":"stdout","text":["tensor([0.1248, 3.2503, 1.1823, 1.2675, 2.3347, 0.5206],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.1386, 3.2986, 1.2122, 1.3016, 2.3800, 0.5333],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.1528, 3.3474, 1.2425, 1.3361, 2.4256, 0.5464],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.1674, 3.3964, 1.2732, 1.3710, 2.4717, 0.5599],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.1825, 3.4458, 1.3042, 1.4063, 2.5180, 0.5738],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.1979, 3.4955, 1.3357, 1.4419, 2.5648, 0.5881],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.2138, 3.5455, 1.3675, 1.4780, 2.6118, 0.6028],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.2301, 3.5956, 1.3998, 1.5144, 2.6592, 0.6179],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.2468, 3.6460, 1.4324, 1.5512, 2.7068, 0.6334],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.2640, 3.6965, 1.4654, 1.5884, 2.7547, 0.6494],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.2816, 3.7471, 1.4987, 1.6259, 2.8028, 0.6657],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.2996, 3.7978, 1.5324, 1.6637, 2.8511, 0.6825],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.3181, 3.8484, 1.5665, 1.7019, 2.8996, 0.6997],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.3370, 3.8990, 1.6009, 1.7404, 2.9483, 0.7172],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.3564, 3.9494, 1.6356, 1.7792, 2.9970, 0.7352],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.3763, 3.9997, 1.6706, 1.8182, 3.0458, 0.7537],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.3965, 4.0496, 1.7059, 1.8575, 3.0946, 0.7725],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.4173, 4.0992, 1.7415, 1.8970, 3.1434, 0.7917],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.4385, 4.1483, 1.7774, 1.9367, 3.1921, 0.8114],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.4602, 4.1968, 1.8135, 1.9766, 3.2407, 0.8314],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.4823, 4.2448, 1.8498, 2.0166, 3.2892, 0.8518],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.5049, 4.2919, 1.8864, 2.0567, 3.3374, 0.8727],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.5279, 4.3383, 1.9231, 2.0969, 3.3853, 0.8939],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.5514, 4.3836, 1.9600, 2.1370, 3.4328, 0.9155],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.5754, 4.4279, 1.9970, 2.1772, 3.4799, 0.9375],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.5999, 4.4710, 2.0341, 2.2173, 3.5266, 0.9598],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.6248, 4.5127, 2.0713, 2.2573, 3.5727, 0.9825],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.6502, 4.5531, 2.1085, 2.2972, 3.6182, 1.0056],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.6760, 4.5918, 2.1458, 2.3368, 3.6630, 1.0290],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.7023, 4.6289, 2.1830, 2.3762, 3.7070, 1.0527],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.7290, 4.6642, 2.2201, 2.4153, 3.7503, 1.0768],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.7562, 4.6977, 2.2572, 2.4541, 3.7926, 1.1011],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.7838, 4.7291, 2.2942, 2.4925, 3.8340, 1.1258],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.8119, 4.7584, 2.3309, 2.5304, 3.8744, 1.1507],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.8404, 4.7856, 2.3675, 2.5678, 3.9137, 1.1759],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.8693, 4.8105, 2.4038, 2.6047, 3.9518, 1.2013],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.8987, 4.8331, 2.4398, 2.6410, 3.9888, 1.2269],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.9285, 4.8533, 2.4755, 2.6767, 4.0246, 1.2528],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.9587, 4.8712, 2.5108, 2.7118, 4.0591, 1.2788],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([0.9893, 4.8866, 2.5456, 2.7462, 4.0923, 1.3050],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.0203, 4.8997, 2.5800, 2.7798, 4.1241, 1.3313],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.0517, 4.9103, 2.6139, 2.8128, 4.1546, 1.3577],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.0835, 4.9186, 2.6472, 2.8449, 4.1838, 1.3842],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.1157, 4.9246, 2.6799, 2.8764, 4.2116, 1.4108],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.1482, 4.9283, 2.7119, 2.9070, 4.2380, 1.4374],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.1812, 4.9299, 2.7433, 2.9369, 4.2631, 1.4640],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.2144, 4.9293, 2.7739, 2.9660, 4.2868, 1.4906],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.2480, 4.9268, 2.8037, 2.9944, 4.3091, 1.5171],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.2820, 4.9223, 2.8326, 3.0220, 4.3302, 1.5436],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.3162, 4.9161, 2.8607, 3.0489, 4.3500, 1.5699],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.3508, 4.9081, 2.8879, 3.0750, 4.3686, 1.5962],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.3857, 4.8987, 2.9142, 3.1005, 4.3860, 1.6222],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.4209, 4.8878, 2.9395, 3.1253, 4.4022, 1.6480],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.4564, 4.8756, 2.9637, 3.1495, 4.4174, 1.6736],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.4922, 4.8622, 2.9869, 3.1730, 4.4314, 1.6989],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.5282, 4.8478, 3.0091, 3.1960, 4.4445, 1.7240],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.5645, 4.8325, 3.0301, 3.2184, 4.4567, 1.7487],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.6010, 4.8164, 3.0500, 3.2402, 4.4679, 1.7730],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.6378, 4.7996, 3.0688, 3.2616, 4.4784, 1.7970],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.6748, 4.7823, 3.0865, 3.2826, 4.4880, 1.8205],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.7120, 4.7645, 3.1029, 3.3031, 4.4970, 1.8436],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.7495, 4.7463, 3.1182, 3.3232, 4.5053, 1.8663],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.7871, 4.7280, 3.1323, 3.3430, 4.5130, 1.8885],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.8249, 4.7094, 3.1453, 3.3625, 4.5201, 1.9101],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.8629, 4.6909, 3.1570, 3.3816, 4.5268, 1.9312],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.9010, 4.6723, 3.1676, 3.4005, 4.5331, 1.9518],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.9393, 4.6538, 3.1771, 3.4191, 4.5390, 1.9718],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([1.9778, 4.6355, 3.1853, 3.4375, 4.5445, 1.9912],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.0163, 4.6174, 3.1925, 3.4557, 4.5498, 2.0101],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.0550, 4.5996, 3.1985, 3.4737, 4.5548, 2.0283],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.0938, 4.5821, 3.2035, 3.4915, 4.5597, 2.0459],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.1327, 4.5650, 3.2074, 3.5092, 4.5644, 2.0628],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.1717, 4.5482, 3.2103, 3.5267, 4.5691, 2.0792],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.2107, 4.5319, 3.2121, 3.5440, 4.5736, 2.0949],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.2498, 4.5160, 3.2130, 3.5613, 4.5781, 2.1100],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.2890, 4.5006, 3.2130, 3.5784, 4.5826, 2.1244],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.3282, 4.4856, 3.2121, 3.5954, 4.5871, 2.1382],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.3674, 4.4711, 3.2103, 3.6122, 4.5917, 2.1514],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.4066, 4.4571, 3.2077, 3.6289, 4.5963, 2.1640],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.4459, 4.4435, 3.2043, 3.6454, 4.6010, 2.1760],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.4851, 4.4304, 3.2002, 3.6618, 4.6059, 2.1873],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.5243, 4.4177, 3.1954, 3.6781, 4.6108, 2.1981],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.5634, 4.4055, 3.1899, 3.6941, 4.6159, 2.2083],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.6025, 4.3937, 3.1839, 3.7100, 4.6211, 2.2179],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.6416, 4.3822, 3.1773, 3.7256, 4.6264, 2.2270],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.6805, 4.3712, 3.1702, 3.7411, 4.6319, 2.2355],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.7194, 4.3605, 3.1626, 3.7563, 4.6376, 2.2435],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.7582, 4.3501, 3.1546, 3.7712, 4.6435, 2.2511],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.7969, 4.3400, 3.1462, 3.7859, 4.6495, 2.2581],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.8354, 4.3302, 3.1374, 3.8003, 4.6556, 2.2647],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.8738, 4.3206, 3.1284, 3.8145, 4.6619, 2.2708],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.9121, 4.3113, 3.1190, 3.8282, 4.6684, 2.2765],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.9502, 4.3022, 3.1095, 3.8417, 4.6750, 2.2818],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([2.9882, 4.2932, 3.0998, 3.8548, 4.6818, 2.2867],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([3.0259, 4.2844, 3.0899, 3.8676, 4.6887, 2.2913],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([3.0635, 4.2757, 3.0798, 3.8800, 4.6958, 2.2955],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([3.1008, 4.2671, 3.0697, 3.8920, 4.7030, 2.2994],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([3.1379, 4.2587, 3.0596, 3.9036, 4.7103, 2.3030],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([3.1748, 4.2503, 3.0494, 3.9148, 4.7177, 2.3063],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n","tensor([3.2114, 4.2419, 3.0392, 3.9256, 4.7252, 2.3093],\n"," grad_fn=) tensor([5., 4., 3., 4., 5., 2.])\n"]}]},{"cell_type":"markdown","source":["## Evaluasi dan Pengujian\n","Setelah model dilatih, kita bisa mengevaluasi performa dengan metrik seperti RMSE (Root Mean Squared Error) atau MAE (Mean Absolute Error)."],"metadata":{"id":"TnkLwD9HC9PR"}},{"cell_type":"code","source":["model.eval()\n","with torch.no_grad():\n"," predicted_rating = model(torch.tensor([0]), torch.tensor([2]))\n"," print(f\"Predicted rating for user 0 on item 2: {predicted_rating.item():.2f}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"O504toWdC5f1","executionInfo":{"status":"ok","timestamp":1724027844222,"user_tz":-420,"elapsed":348,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}},"outputId":"dcd8a93a-483f-4022-bc14-4cbcfc8e9b6a"},"execution_count":14,"outputs":[{"output_type":"stream","name":"stdout","text":["Predicted rating for user 0 on item 2: 4.58\n"]}]},{"cell_type":"markdown","source":["## Peningkatan Model dengan Bias Term\n","Pada tahap awal, kita hanya menggunakan dot product dari vektor pengguna dan item. Sekarang kita tambahkan bias term untuk pengguna dan item. Ini sering digunakan untuk memperhitungkan preferensi umum dari pengguna atau popularitas item."],"metadata":{"id":"ZgIYgmuEFd2Q"}},{"cell_type":"code","source":["class MFModel(nn.Module):\n"," def __init__(self, num_users, num_items, embedding_size):\n"," super(MFModel, self).__init__()\n"," self.user_embedding = nn.Embedding(num_users, embedding_size)\n"," self.item_embedding = nn.Embedding(num_items, embedding_size)\n"," self.user_bias = nn.Embedding(num_users, 1)\n"," self.item_bias = nn.Embedding(num_items, 1)\n","\n"," def forward(self, user_id, item_id):\n"," user_vec = self.user_embedding(user_id)\n"," item_vec = self.item_embedding(item_id)\n"," user_bias = self.user_bias(user_id).squeeze()\n"," item_bias = self.item_bias(item_id).squeeze()\n"," dot_product = torch.sum(user_vec * item_vec, dim=1)\n"," return dot_product + user_bias + item_bias"],"metadata":{"id":"N4PVmIFvFdCx"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["## Regularisasi untuk Mencegah Overfitting\n","Agar model tidak overfit terhadap data, kita tambahkan regularisasi L2 pada embedding."],"metadata":{"id":"pjSxLOcIFwgR"}},{"cell_type":"code","source":["class MFModel(nn.Module):\n"," def __init__(self, num_users, num_items, embedding_size, reg_factor):\n"," super(MFModel, self).__init__()\n"," self.user_embedding = nn.Embedding(num_users, embedding_size)\n"," self.item_embedding = nn.Embedding(num_items, embedding_size)\n"," self.user_bias = nn.Embedding(num_users, 1)\n"," self.item_bias = nn.Embedding(num_items, 1)\n"," self.reg_factor = reg_factor\n","\n"," def forward(self, user_id, item_id):\n"," user_vec = self.user_embedding(user_id)\n"," item_vec = self.item_embedding(item_id)\n"," user_bias = self.user_bias(user_id).squeeze()\n"," item_bias = self.item_bias(item_id).squeeze()\n"," dot_product = torch.sum(user_vec * item_vec, dim=1)\n"," return dot_product + user_bias + item_bias\n","\n"," def regularization_loss(self):\n"," return self.reg_factor * (torch.norm(self.user_embedding.weight) + torch.norm(self.item_embedding.weight))\n","\n","# Melatih model dengan regularisasi\n","model = MFModel(num_users, num_items, embedding_size, reg_factor=0.01)\n","optimizer = optim.Adam(model.parameters(), lr=0.01)\n","criterion = nn.MSELoss()\n","\n","for epoch in range(100):\n"," model.train()\n"," optimizer.zero_grad()\n"," predictions = model(user_ids, item_ids)\n"," loss = criterion(predictions, ratings)\n"," loss += model.regularization_loss() # Menambahkan regularisasi L2\n"," loss.backward()\n"," optimizer.step()"],"metadata":{"id":"LrjkVie5Ft6Q","executionInfo":{"status":"ok","timestamp":1724028663649,"user_tz":-420,"elapsed":459,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}}},"execution_count":11,"outputs":[]},{"cell_type":"code","source":["from sklearn.metrics import mean_squared_error\n","import numpy as np\n","\n","# Prediksi untuk semua data\n","model.eval()\n","with torch.no_grad():\n"," predictions = model(user_ids, item_ids).numpy()\n"," rmse = np.sqrt(mean_squared_error(ratings.numpy(), predictions))\n"," print(f\"RMSE: {rmse:.4f}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"nrAdqqsOG8oz","executionInfo":{"status":"ok","timestamp":1724028573185,"user_tz":-420,"elapsed":401,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}},"outputId":"ee341d5a-1592-450a-f740-d4116bee8883"},"execution_count":7,"outputs":[{"output_type":"stream","name":"stdout","text":["RMSE: 2.9928\n"]}]},{"cell_type":"code","source":["# Memprediksi rating untuk user 0 terhadap item 2\n","model.eval()\n","with torch.no_grad():\n"," predicted_rating = model(torch.tensor([0]), torch.tensor([2]))\n"," print(f\"Predicted rating for user 0 on item 2: {predicted_rating.item():.2f}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"TzQUJkF_HWA8","executionInfo":{"status":"ok","timestamp":1724028669624,"user_tz":-420,"elapsed":448,"user":{"displayName":"Andys Collection","userId":"04951959771200949138"}},"outputId":"fc7c70d3-6ae9-4f8c-82bf-c2619f0a3462"},"execution_count":12,"outputs":[{"output_type":"stream","name":"stdout","text":["Predicted rating for user 0 on item 2: 4.07\n"]}]}]}