電影數據集

電影數據集

The MovieLens Dataset

有許多數據集可用於推薦研究。其中,MovieLens數據集可能是最受歡迎的數據集之一。MovieLens是一個基於web的非商業電影推薦系統。創建於1997年,由明尼蘇達大學的一個研究實驗室GroupLens管理,目的是爲了研究目的收集電影分級數據。MovieLens的數據對於包括個性化推薦和社會心理學在內的一些研究都是至關重要的。

  1. Getting the Data

MovieLens數據集由GroupLens網站託管。有幾個版本可用。將使用MovieLens 100K數據集。此數據集包括10萬收視率,從1星到5星,從1682部電影的943名用戶。已經被清理,這樣每個用戶至少有20部電影。一些簡單的人口統計信息,如年齡、性別、用戶的類型和項目也可用。可以下載ml-100k.zip並提取u.data文件,其中包含所有10萬csv格式的評分。文件夾中還有許多其文件,每個文件的詳細說明可以在數據集的自述文件中找到。首先,讓導入運行本節實驗所需的包。

from d2l import mxnet as d2l

from mxnet import gluon, np

import os

import pandas as pd

然後,下載MovieLens
100k數據集並將交互作爲DataFrame加載。

#@save

d2l.DATA_HUB[‘ml-100k’] = (

'http://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

  1. Statistics
    of the Dataset

讓裝載數據並手動檢查前五個記錄。這是學習數據結構並驗證是否已正確加載的有效方法。

data, num_users, num_items = read_data_ml100k()

sparsity = 1 - len(data) / (num_users * num_items)

print(‘number of users: %d, number of
items: %d.’ % (num_users, num_items))

print(‘matrix sparsity: %f’ % sparsity)

print(data.head(5))

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

可以看到,每行由四列組成,包括“userid”1-943、“item
id”1-1682、“rating”1-5和“timestamp”。可以構造一個尺寸的相互作用矩陣牛×米牛×米,其中nn和米米分別是用戶數和項目數。這個數據集只記錄現有的評級,所以也可以稱之爲評級矩陣,如果這個矩陣的值代表確切的評級,將互換使用交互矩陣和評級矩陣。評級矩陣中的大多數值是未知的,因爲用戶沒有對大多數電影進行評級。還展示了這個數據集的稀疏性。稀疏性定義爲The sparsity is defined
as 1 - number of nonzero entries / ( number of users * number of items).。顯然,相互作用矩陣非常稀疏(即稀疏度=93.695%)。現實世界中的數據集可能會受到更大程度的稀疏性的影響,並且一直是構建推薦系統的長期挑戰。一個可行的解決方案是使用附加的附加信息,例如用戶/項目特性來緩解稀疏性。然後,繪製不同評級的計數分佈圖。正如預期的那樣,這似乎是一個正態分佈,大多數評級集中在3-4。

d2l.plt.hist(data[‘rating’], bins=5, ec=‘black’)

d2l.plt.xlabel(‘Rating’)

d2l.plt.ylabel(‘Count’)

d2l.plt.title(‘Distribution of Ratings in MovieLens 100K’)

d2l.plt.show()
在這裏插入圖片描述
3. Splitting the dataset

將數據集分成訓練集和測試集。以下函數提供兩種分割模式,包括隨機和序列感知。在隨機模式下,該函數在不考慮時間戳的情況下隨機分割100k個交互,默認使用90%的數據作爲訓練樣本,其餘10%作爲測試樣本。在seq-aware模式中,將用戶最近評估的項目和用戶的歷史交互作爲訓練集。用戶歷史交互根據時間戳從最舊到最新排序。此模式將在序列感知推薦部分中使用。

#@save

def split_data_ml100k(data, num_users, num_items,

                  split_mode='random', test_ratio=0.1):

"""Split the dataset in random mode or seq-aware

mode."""

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

請注意,除了測試集之外,在實踐中使用驗證集是一個很好的實踐。然而,爲了簡潔起見,省略了這一點。在這種情況下,測試集可以被視爲保留驗證集。

  1. Loading the data

數據集拆分後,爲了方便起見,將訓練集和測試集轉換成列表和字典/矩陣。以下函數逐行讀取數據幀並從零開始枚舉用戶/項的索引。然後,該函數返回用戶、項目、評分和記錄交互的字典/矩陣的列表。可以將反饋的類型指定爲顯式或隱式。

#@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

之後,將上述步驟放在一起,並將在下一節中使用。結果用Dataset和DataLoader包裝。注意,訓練數據的最後一批DataLoader被設置爲rollover模式(剩餘的樣本被滾動到下一個epoch),並且順序被無序排列。

#@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
  1. Summary
    MovieLens datasets are widely used for recommendation research. It is public available and free to use.
    We define functions to download and preprocess the MovieLens 100k dataset for further use in later sections.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章