Anda hanya diwajibkan untuk mengumpulkan file ini saja ke uploader yang disediakan di http://elearning2.uai.ac.id/. Ganti nama file ini saat pengumpulan menjadi tugas5_NIM.ipynb.
Keterlambatan: Pengumpulan tugas yang melebihi tenggat yang telah ditentukan tidak akan diterima. Keterlambatan akan berakibat pada nilai nol untuk tugas ini.
Kolaborasi: Anda diperbolehkan untuk berdiskusi dengan teman Anda, tetapi dilarang keras menyalin kode maupun tulisan dari teman Anda.
Terdapat enam packages yang Anda akan gunakan dalam mengerjakan tugas ini, yaitu:
Anda diperbolehkan (jika dirasa perlu) untuk mengimpor modul tambahan untuk tugas ini, kecuali dijelaskan sebaliknya. Namun, seharusnya modul yang tersedia sudah cukup untuk memenuhi kebutuhan Anda.
Pastikan jawaban Anda singkat, padat, dan jelas. Mayoritas pertanyaan yang diberikan dapat dijawab dalam 3-4 kalimat saja.
NIM:
Nilai akhir: XX/70
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
%matplotlib inline
RANDOM_STATE = 538
plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (15.0, 7.0)
df = pd.read_csv('../dataset/lastfm/user_artists.dat', delimiter='\t')
Dataset yang digunakan dalam tugas ini merupakan data pengguna mendengarkan seorang artis/musisi dari situs Last.fm. Dalam dataset ini, terdapat 92,834 pasang pengguna-artis dari 17,632 artis dan 1,892 pengguna. Terdapat atribut weight yang menggambarkan berapa kali pengguna mendengarkan seorang artis.
Tugas Anda adalah menghasilkan root mean squared error (RMSE) serendah mungkin dengan masing-masing metode yang digunakan. Gunakan pengetahuan yang telah Anda dapatkan dari materi dan tugas-tugas sebelumnya.
Cantador, I., Brusilovsky, P.L. and Kuflik, T., 2011. Second workshop on information heterogeneity and fusion in recommender systems (HetRec2011).
Beberapa konsep yang diterapkan dalam tugas ini dapat Anda lihat dalam buku Mining of Massive Datasets (Leskovec et al., 2014) pada Chapter 9.
Pada bagian ini, Anda diminta untuk melakukan eksplorasi awal dari dataset yang terbatas ini. Anda juga diminta untuk membuat prediksi weight dengan menggunakan beberapa metode sederhana, yaitu dengan pencarian rata-rata dan median.
Kelompokkan data berdasarkan artistID
, lalu jumlahkan weight
-nya. Hal ini dilakukan untuk melihat sebaran artis-artis yang populer untuk didengarkan di last.fm.
Anda dapat mengubah nilai yang telah dijumlahkan di atas dengan transformasi logaritmik terlebih dahulu. Gambarkan kembali histogramnya. Apa yang terjadi?
Apa yang dapat Anda amati dari distribusi di atas? Mengapa hal ini dapat terjadi?
Jawaban Anda di sini
Bagi data menjadi dua variabel: train
dan test
. Pastikan bahwa Anda melakukan pengacakan urutan data sebelum membaginya dan proporsi data train
:test
adalah 70:30.
Catatan: Hanya dua variabel yang perlu dihasilkan, bukan X_train
, X_test
, y_train
, y_test
seperti di tugas-tugas sebelumnya.
from sklearn.model_selection import train_test_split
Buang semua data dalam test
yang artistID
-nya tidak ada dalam train
. Mengapa kita melakukan hal ini?
Jawaban Anda di sini
Salah satu asumsi paling mendasar adalah kita dapat menggunakan rata-rata weight yang diberikan oleh seorang pengguna untuk menebak weight yang akan diberikan untuk artis tertentu. Oleh karena itu, cari nilai rata-rata untuk weight berdasarkan userID
dalam train
. Lalu, gunakan nilai rata-rata tersebut untuk memprediksi weight yang akan diberikan oleh pengguna tersebut pada artis yang akan didengar pada test
. Laporkan nilai RMSE-nya.
from sklearn.metrics import mean_squared_error
Asumsi lain yang dapat digunakan adalah: seorang pengguna akan mendengarkan seorang artis seperti halnya orang-orang lain akan mendengarkan artis tersebut. Jadi, lakukan hal yang sama seperti pada soal 1.3.a, tetapi ambil nilai rata-rata dengan pengelompokan berdasarkan artistID
. Laporkan nilai RMSE-nya.
Lakukan prediksi seperti pada bagian a dan b, tetapi kali ini ganti nilai yang akan diprediksi dengan menggunakan median. Apakah hasilnya menjadi lebih baik?
Berikan kesimpulan sementara dari yang Anda telah temukan sejauh ini.
Jawaban Anda di sini
Sebagai perbandingan, Anda akan membuat prediksi nilai dengan menggunakan metode collaborative filtering.
Perhatian: Berhati-hatilah dengan bagian ini karena ada banyak manipulasi matriks yang mungkin diperlukan. Selalu lakukan sanity check. Do not procrastinate.
Buat X_train
dari hasil pivot train
dengan menjadikan userID
sebagai index, artistID
sebagai kolom, dan weight
menjadi nilai dari cell.
Sanity check: Perintah ini seharusnya menghasilkan sparse matrix.
Prediksi dengan collaborative filtering berdasarkan pengguna dapat dilakukan dengan menghitung cosine similarity. Nilai similarity tersebut kemudian akan dijadikan bobot untuk tiap nilai yang akan dihasilkan alih-alih menggunakan k-rekomendasi terbaik.
Hitung nilai cosine similarity dari X_train
dengan menggunakan fungsi dari scikit-learn
. Lalu, simpanlah nilai cosine similarity tersebut.
Cosine similarity didefinisikan sebagai $$ sim(u, u^{\prime}) = \cos(\theta) = \frac{\mathbf{w}_u \cdot \mathbf{w}_{u^{\prime}}}{\|\mathbf{w}_u\| \|\mathbf{w}_{u^{\prime}}\|} $$ dengan $u$ adalah pengguna dan $w_u$ adalah seberapa sering pengguna $u$ mendengarkan daftar artis dalam bentuk vektor.
Sanity check: Untuk similarity berdasarkan pengguna, pastikan matriks yang dihasilkan berukuran $U \times U$ dengan $U$ adalah jumlah pengguna dalam data.
from sklearn.metrics.pairwise import cosine_similarity
Munculkan nilai minimum, maksimum, dan rata-rata dari seluruh cosine similarity yang dihasilkan.
Hasil prediksi untuk artis yang belum didengar yang kita simpan pada test
dapat dihitung dengan
Namun, nilai ini masih perlu dinormalisasi lagi (mengapa?). Hasil prediksi dengan normalisasi menjadi
$$ \hat{w}_{ui} = \frac{\sum_{u^{\prime}} sim(u,u^{\prime}) w_{u^{\prime} i}}{\sum_{u^{\prime}} |sim(u,u^{\prime})|} $$Dengan menggunakan referensi ini, coba hasilkan prediksi berdasarkan similarity dan X_train
yang telah dibentuk di soal sebelumnya. Lalu, simpan hasilnya ke menjadi DataFrame
sebagai variabel X_pred
. Jangan lupa untuk mengisi parameter index
dengan X_train.index
dan columns
dengan X_train.columns
.
Prediksi nilai di data test
dari X_pred
yang telah dihasilkan. Laporkan RMSE-nya.
Petunjuk: Anda dapat memanfaatkan test.apply()
lalu menerapkan fungsi lambda yang mengambil prediksi untuk userID
dan artistID
tertentu dalam X_pred
. Pastikan bahwa Anda mengambil weight yang benar dari matriks tersebut. Anda mungkin perlu menghapus variabel X_pred
setelah selesai digunakan untuk menghemat memory.
Bandingkan RMSE tersebut dengan hasil pada bagian 1. Apa yang dapat Anda lihat? Apa yang menyebabkan hasilnya seperti itu dibandingkan dengan metode yang telah dicobakan sebelumnya?
Petunjuk: Anda mungkin perlu melihat isi matriks X_pred
.
Jawaban Anda di sini
Apakah hasilnya berbeda jika kita menggunakan fungsi logaritma untuk normalisasi nilai X_train
? Terapkan proses normalisasi ini pada X_train
, lalu simpan sebagai X_normal
. Isi nilai kosong pada X_train
sementara dengan 0.
Hitung nilai cosine similarity dari X_normal
, lalu tampilkan nilai minimum, maksimum, dan rata-rata dari similarity yang dihasilkan.
Prediksi kembali weight yang diberikan pada data test
. Hitung nilai RMSE-nya. Apakah hasilnya kali ini lebih baik?
Berikan kesimpulan yang dapat Anda ambil untuk sistem rekomendasi dengan menggunakan collaborative filtering ini.
Jawaban Anda di sini
Metode lain yang dapat digunakan untuk melakukan prediksi adalah dengan menggunakan proses faktorisasi matriks. Dalam bagian ini, Anda akan melakukan UV-decomposition dengan routine yang telah disediakan oleh scikit-learn.
Dengan menggunakan modul NMF
untuk non-negative matrix factorization dengan n_components=2
. Transformasi X_train
dengan terlebih dahulu mengisi nilai kosong dengan 0, lalu simpan sebagai X_transformed
.
from sklearn.decomposition import NMF
Ide dari UV-decomposition adalah menghasilkan matriks $U$ dan $V$ yang dimensinya jauh lebih kecil dibandingkan $X$. Dari matriks $U$ dan $V$ tersebut, kita akan melakukan inversi dari hasil transformasi untuk mendapatkan aproksimasi untuk nilai yang kosong.
Lakukan transformasi dan inversnya, kemudian simpan matriks ini sebagai X_pred
. Jangan lupa untuk mengisi nilai index
dan columns
dari DataFrame
yang dibentuk dengan X_pred
.
Gunakan matriks X_pred
untuk memprediksi weight pada data test
. Lalu, laporkan RMSE-nya.
Apakah RMSE yang dihasilkan cukup bagus? Kita dapat mengonfirmasi ini dengan melihat nilai error pada aproksimasi yang dihasilkan. Cetak nilai ini dengan menggunakan .reconstruction_err_
. Apa yang dapat Anda simpulkan dari nilai error ini?
Jawaban Anda di sini
Coba hasilkan faktorisasi matriks dengan menggunakan jumlah komponen $n = [2, 4, 8, 16, 32, 64]$, lalu laporkan reconstruction error-nya dalam bentuk line plot.
Anda akan melihat bahwa tren error rekonstruksinya selalu menurun seiring dengan bertambahnya jumlah komponen. Apakah dengan menggunakan $n = u$ errornya bisa mendekati nol? Jika bisa, apakah hasil prediksi untuk data test
akan menjadi lebih baik, lalu apa yang menjadi masalahnya? Jika tidak, jelaskan mengapa hal tersebut tidak mungkin.
Petunjuk: Anda mungkin bisa melihat perubahan hasil prediksi ketika $n$ ditambah.
Jawaban Anda di sini
Apa yang mungkin perlu dilakukan agar hasil prediksi menggunakan UV-decomposition ini bisa lebih baik?
Petunjuk: Anda bisa menggunakan referensi buku Mining of Massive Datasets (Leskovec et al., 2014) pada Section 9.4.
Jawaban Anda di sini
Berikan kesimpulan Anda terkait sistem rekomendasi dengan menggunakan UV-decomposition ini.
Jawaban Anda di sini
Apakah Anda dapat menghasilkan prediksi yang lebih baik dengan metode yang lain atau dengan mengembangkan metode yang ada? Anda juga dapat menggunakan data lain dalam folder dataset/lastfm
.