MovieLens Veri Kümesi ===================== Tavsiye araştırmaları için kullanılabilen bir dizi veri kümesi vardır. Bunların arasında, `MovieLens `__ veri kümesi muhtemelen en popüler olanlardan biridir. MovieLens ticari olmayan web tabanlı bir film tavsiye sistemidir. 1997 yılında, Minnesota Üniversitesi'nde bir araştırma laboratuvarı olan GroupLens tarafından araştırma amacıyla film derecelendirme verilerini toplamak için oluşturulmuştur ve işletilmektedir. MovieLens verileri, kişiselleştirilmiş tavsiye ve sosyal psikoloji de dahil olmak üzere çeşitli araştırma çalışmaları için kritik öneme sahiptir. Verileri Alma ------------- MovieLens veri kümesi, `GroupLens `__ web sitesinde konuşlandırılmaktadır. Birçok sürümü mevcuttur. MovieLens 100K veri kümesini kullanacağız :cite:`Herlocker.Konstan.Borchers.ea.1999`. Bu veri kümesi, 1682 filmdeki 943 kullanıcıdan 1 ile 5 yıldız arasında değişen :math:`100000` derecelendirmeden oluşmaktadır. Veri her kullanıcıdan en az 20 film derecelendirmesi içerecek şekilde temizlendi. Yaş, cinsiyet, kullanıcılar ve öğeler için türler gibi bazı basit demografik bilgiler de mevcuttur. `ml-100k.zip `__'i indirebilir ve csv formatındaki bütün :math:`100000` derecelendirmeyi içeren ``u.data`` dosyasını ayıklayabiliriz. Klasörde başka birçok dosya bulunur, her dosya için ayrıntılı bir açıklama veri kümesinin `README `__ dosyasında bulunabilir. Başlangıç olarak, bu bölümün deneylerini çalıştırmak için gereken paketleri içe aktaralım. .. raw:: latex \diilbookstyleinputcell .. code:: python import os import pandas as pd from d2l import mxnet as d2l from mxnet import gluon, np Ardından, MovieLens 100k veri kümesini indirir ve etkileşimleri ``DataFrame`` olarak yükleriz. .. raw:: latex \diilbookstyleinputcell .. code:: python #@save d2l.DATA_HUB['ml-100k'] = ( 'https://files.grouplens.org/datasets/movielens/ml-100k.zip', 'cd4dcac4241c8a4ad7badc7ca635da8a69dddb83') #@save def read_data_ml100k(): data_dir = d2l.download_extract('ml-100k') names = ['user_id', 'item_id', 'rating', 'timestamp'] data = pd.read_csv(os.path.join(data_dir, 'u.data'), '\t', names=names, engine='python') num_users = data.user_id.unique().shape[0] num_items = data.item_id.unique().shape[0] return data, num_users, num_items Veri Kümesinin İstatistikleri ----------------------------- Verileri yükleyelim ve ilk beş kaydı elden inceleyelim. Bu, veri yapısını öğrenmek ve düzgün yüklendiklerini doğrulamak için etkili bir yoldur. .. raw:: latex \diilbookstyleinputcell .. code:: python data, num_users, num_items = read_data_ml100k() sparsity = 1 - len(data) / (num_users * num_items) print(f'number of users: {num_users}, number of items: {num_items}') print(f'matrix sparsity: {sparsity:f}') print(data.head(5)) .. raw:: latex \diilbookstyleoutputcell .. parsed-literal:: :class: output number of users: 943, number of items: 1682 matrix sparsity: 0.936953 user_id item_id rating timestamp 0 196 242 3 881250949 1 186 302 3 891717742 2 22 377 1 878887116 3 244 51 2 880606923 4 166 346 1 886397596 Her satırın “user id” (kullanıcı kimliği) 1-943, “item id” (öğe kimliği) 1-1682, “rating” (derecelendirme) 1-5 ve “timestamp” (zaman damgası) dahil olmak üzere dört sütundan oluştuğunu görebiliriz. :math:`n \times m` boyutlarında bir etkileşim matrisi oluşturabiliriz, burada :math:`n` ve :math:`m` sırasıyla kullanıcı sayısı ve öğe sayısıdır. Bu veri kümesi yalnızca mevcut derecelendirmeleri kaydeder, bu nedenle buna derecelendirme matrisi diyebiliriz ve bu matrisin değerlerinin tam derecelendirmeleri temsil etmesi durumunda etkileşim matrisi ve derecelendirme matrisini birbirinin yerine kullanacağız. Kullanıcılar filmlerin çoğunu derecelendirmediğinden derecelendirme matrisindeki değerlerin çoğu bilinmemektedir. Ayrıca bu veri kümesinin seyrek olduğunu da gösteriyoruz. Seyreklik ``1 - number of nonzero entries / ( number of users * number of items)`` ( 1 - sıfır olmayan girdiler / (kullanıcı sayısı \* öğe sayısı)) olarak tanımlanır. Açıkçası, etkileşim matrisi son derece seyrektir (yani, seyreklik = 93.695%). Gerçek dünya veri kümeleri, daha büyük ölçüde seyreklik yaşayabilir ve tavsiye sistemlerinin oluşturulmasında uzun süredir devam eden bir zorluk olmuştur. Kullanıcı/öğe öznitelikleri gibi ek yan bilgileri kullanmak için uygulanabilir bir çözüm, seyrekliği hafifletmektir. Daha sonra farklı derecelendirme sayımlarının dağılımını çizdiriyoruz. Beklendiği gibi, normal bir dağılım gibi görünüyor ve çoğu derecelendirme 3-4 olarak ortalanmıştır. .. raw:: latex \diilbookstyleinputcell .. code:: python d2l.plt.hist(data['rating'], bins=5, ec='black') d2l.plt.xlabel('Değerlendirme') d2l.plt.ylabel('Sayım') d2l.plt.title('MovieLens 100Kda değerlendirmelerin dağılımı') d2l.plt.show() .. figure:: output_movielens_140487_7_0.png Veri Kümesini Bölme ------------------- Veri kümesini eğitim ve test kümelerine ayırdık. Aşağıdaki işlev ``random`` ve ``seq-aware`` dahil olmak üzere iki bölünmüş mod sağlar. ``random`` modunda, fonksiyon 100 bin etkileşimi zaman damgası dikkate almadan rastgele böler ve varsayılan olarak verilerin %90'ını eğitim örnekleri, geri kalanın %10'unu test örnekleri olarak kullanır. ``seq-aware`` modunda, bir kullanıcının test için en son puan aldığı öğeyi ve kullanıcıların eğitim kümesi olarak tarihsel etkileşimlerini bırakıyoruz. Kullanıcı geçmişi etkileşimleri, zaman damgasına göre en eskisinden en yeniye sıralanır. Bu mod, sıraya duyarlı tavsiye bölümünde kullanılır. .. raw:: latex \diilbookstyleinputcell .. code:: python #@save def split_data_ml100k(data, num_users, num_items, split_mode='random', test_ratio=0.1): """Veri kümesini rastgele modda veya sıraya duyarlı modda böl.""" if split_mode == 'seq-aware': train_items, test_items, train_list = {}, {}, [] for line in data.itertuples(): u, i, rating, time = line[1], line[2], line[3], line[4] train_items.setdefault(u, []).append((u, i, rating, time)) if u not in test_items or test_items[u][-1] < time: test_items[u] = (i, rating, time) for u in range(1, num_users + 1): train_list.extend(sorted(train_items[u], key=lambda k: k[3])) test_data = [(key, *value) for key, value in test_items.items()] train_data = [item for item in train_list if item not in test_data] train_data = pd.DataFrame(train_data) test_data = pd.DataFrame(test_data) else: mask = [True if x == 1 else False for x in np.random.uniform( 0, 1, (len(data))) < 1 - test_ratio] neg_mask = [not x for x in mask] train_data, test_data = data[mask], data[neg_mask] return train_data, test_data Yalnızca bir test kümesi dışında, pratikte bir geçerleme kümesi kullanmanın iyi bir uygulama olduğunu unutmayın. Ancak, kısalık uğruna bunu burada atlıyoruz. Bu durumda, test kümemiz dışarıda tutulan geçerleme kümemiz olarak kabul edilebilir. Veriyi Yükleme -------------- Veri kümesinin bölünmesinden sonra, eğitim kümesini ve test kümesini kolaylık sağlamak için listelere ve sözlüklere/matrise dönüştüreceğiz. Aşağıdaki işlev, veri çerçevesini satır satır okur ve kullanıcıların/öğelerin dizinini sıfırdan başlatır. İşlev daha sonra kullanıcılar, öğeler, derecelendirmeler listelerini ve etkileşimleri kaydeden bir sözlük/matris döndürür. Geri bildirim türünü ``explicit`` (açık) veya ``implicit`` (örtük) diye belirtebiliriz. .. raw:: latex \diilbookstyleinputcell .. code:: python #@save def load_data_ml100k(data, num_users, num_items, feedback='explicit'): users, items, scores = [], [], [] inter = np.zeros((num_items, num_users)) if feedback == 'explicit' else {} for line in data.itertuples(): user_index, item_index = int(line[1] - 1), int(line[2] - 1) score = int(line[3]) if feedback == 'explicit' else 1 users.append(user_index) items.append(item_index) scores.append(score) if feedback == 'implicit': inter.setdefault(user_index, []).append(item_index) else: inter[item_index, user_index] = score return users, items, scores, inter Daha sonra yukarıdaki adımları bir araya getiriyoruz ve bir sonraki bölümde kullanacağız. Sonuçlar ``Dataset`` ve ``DataLoader`` ile sarmalanır. Eğitim verileri için ``DataLoader``'ın (VeriYineleyici) ``last_batch``'inin (son toplu iş) ``rollover`` (çevirme) moduna ayarlandığını (kalan örnekler bir sonraki döneme aktarılır) ve sıraların karıştırıldığını unutmayın. .. raw:: latex \diilbookstyleinputcell .. code:: python #@save def split_and_load_ml100k(split_mode='seq-aware', feedback='explicit', test_ratio=0.1, batch_size=256): data, num_users, num_items = read_data_ml100k() train_data, test_data = split_data_ml100k( data, num_users, num_items, split_mode, test_ratio) train_u, train_i, train_r, _ = load_data_ml100k( train_data, num_users, num_items, feedback) test_u, test_i, test_r, _ = load_data_ml100k( test_data, num_users, num_items, feedback) train_set = gluon.data.ArrayDataset( np.array(train_u), np.array(train_i), np.array(train_r)) test_set = gluon.data.ArrayDataset( np.array(test_u), np.array(test_i), np.array(test_r)) train_iter = gluon.data.DataLoader( train_set, shuffle=True, last_batch='rollover', batch_size=batch_size) test_iter = gluon.data.DataLoader( test_set, batch_size=batch_size) return num_users, num_items, train_iter, test_iter Özet ---- - MovieLens veri kümeleri, tavsiye araştırmaları için yaygın olarak kullanılmaktadır. Kamuya açıktır ve kullanımı ücretsizdir. - MovieLens 100k veri kümesini daha sonraki bölümlerde kullanmak üzere indirmek ve ön işlemek için işlevler tanımlıyoruz. Alıştırmalar ------------ - Başka hangi benzer tavsiye veri kümelerini bulabilirsiniz? - MovieLens hakkında daha fazla bilgi için https://movielens.org/ sitesini ziyaret edin. `Tartışmalar `__