项目文件夹

文件
KounianhuaDu 60426278bf [Example] TAHIN (#2864)
* tahin

* readme

* readme

* readme

* readme

* readme

* readme

* main

* main

* new_line

* update

Co-authored-by: zhjwy9343 <6593865@qq.com>
2021-06-03 16:03:55 +08:00

321 行
12 KiB
Python

import torch
from torch.utils.data import Dataset, DataLoader
import dgl
import os
import pickle as pkl
import numpy as np
import random
# Split data into train/eval/test
def split_data(hg, etype_name):
src, dst = hg.edges(etype=etype_name)
user_item_src = src.numpy().tolist()
user_item_dst = dst.numpy().tolist()
num_link = len(user_item_src)
pos_label=[1]*num_link
pos_data=list(zip(user_item_src,user_item_dst,pos_label))
ui_adj = np.array(hg.adj(etype=etype_name).to_dense())
full_idx = np.where(ui_adj==0)
sample = random.sample(range(0, len(full_idx[0])), num_link)
neg_label = [0]*num_link
neg_data = list(zip(full_idx[0][sample],full_idx[1][sample],neg_label))
full_data = pos_data + neg_data
random.shuffle(full_data)
train_size = int(len(full_data) * 0.6)
eval_size = int(len(full_data) * 0.2)
test_size = len(full_data) - train_size - eval_size
train_data = full_data[:train_size]
eval_data = full_data[train_size : train_size+eval_size]
test_data = full_data[train_size+eval_size : train_size+eval_size+test_size]
train_data = np.array(train_data)
eval_data = np.array(eval_data)
test_data = np.array(test_data)
return train_data, eval_data, test_data
def process_amazon(root_path):
# User-Item 3584 2753 50903 UIUI
# Item-View 2753 3857 5694 UIVI
# Item-Brand 2753 334 2753 UIBI
# Item-Category 2753 22 5508 UICI
#Construct graph from raw data.
# load data of amazon
data_path = os.path.join(root_path, 'Amazon')
if not (os.path.exists(data_path)):
print('Can not find amazon in {}, please download the dataset first.'.format(data_path))
# item_view
item_view_src=[]
item_view_dst=[]
with open(os.path.join(data_path, 'item_view.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split(',')
item, view= int(_line[0]), int(_line[1])
item_view_src.append(item)
item_view_dst.append(view)
# user_item
user_item_src=[]
user_item_dst=[]
with open(os.path.join(data_path, 'user_item.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split('\t')
user, item, rate = int(_line[0]), int(_line[1]), int(_line[2])
if rate > 3:
user_item_src.append(user)
user_item_dst.append(item)
# item_brand
item_brand_src=[]
item_brand_dst=[]
with open(os.path.join(data_path, 'item_brand.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split(',')
item, brand= int(_line[0]), int(_line[1])
item_brand_src.append(item)
item_brand_dst.append(brand)
# item_category
item_category_src=[]
item_category_dst=[]
with open(os.path.join(data_path, 'item_category.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split(',')
item, category= int(_line[0]), int(_line[1])
item_category_src.append(item)
item_category_dst.append(category)
#build graph
hg = dgl.heterograph({
('item', 'iv', 'view') : (item_view_src, item_view_dst),
('view', 'vi', 'item') : (item_view_dst, item_view_src),
('user', 'ui', 'item') : (user_item_src, user_item_dst),
('item', 'iu', 'user') : (user_item_dst, user_item_src),
('item', 'ib', 'brand') : (item_brand_src, item_brand_dst),
('brand', 'bi', 'item') : (item_brand_dst, item_brand_src),
('item', 'ic', 'category') : (item_category_src, item_category_dst),
('category', 'ci', 'item') : (item_category_dst, item_category_src)})
print("Graph constructed.")
# Split data into train/eval/test
train_data, eval_data, test_data = split_data(hg, 'ui')
#delete the positive edges in eval/test data in the original graph
train_pos = np.nonzero(train_data[:,2])
train_pos_idx = train_pos[0]
user_item_src_processed = train_data[train_pos_idx, 0]
user_item_dst_processed = train_data[train_pos_idx, 1]
edges_dict = {
('item', 'iv', 'view') : (item_view_src, item_view_dst),
('view', 'vi', 'item') : (item_view_dst, item_view_src),
('user', 'ui', 'item') : (user_item_src_processed, user_item_dst_processed),
('item', 'iu', 'user') : (user_item_dst_processed, user_item_src_processed),
('item', 'ib', 'brand') : (item_brand_src, item_brand_dst),
('brand', 'bi', 'item') : (item_brand_dst, item_brand_src),
('item', 'ic', 'category') : (item_category_src, item_category_dst),
('category', 'ci', 'item') : (item_category_dst, item_category_src)
}
nodes_dict = {
'user': hg.num_nodes('user'),
'item': hg.num_nodes('item'),
'view': hg.num_nodes('view'),
'brand': hg.num_nodes('brand'),
'category': hg.num_nodes('category'),
}
hg_processed = dgl.heterograph(data_dict = edges_dict, num_nodes_dict = nodes_dict)
print("Graph processed.")
#save the processed data
with open(os.path.join(root_path, 'amazon_hg.pkl'), 'wb') as file:
pkl.dump(hg_processed, file)
with open(os.path.join(root_path, 'amazon_train.pkl'), 'wb') as file:
pkl.dump(train_data, file)
with open(os.path.join(root_path, 'amazon_test.pkl'), 'wb') as file:
pkl.dump(test_data, file)
with open(os.path.join(root_path, 'amazon_eval.pkl'), 'wb') as file:
pkl.dump(eval_data, file)
return hg_processed, train_data, eval_data, test_data
def process_movielens(root_path):
# User-Movie 943 1682 100000 UMUM
# User-Age 943 8 943 UAUM
# User-Occupation 943 21 943 UOUM
# Movie-Genre 1682 18 2861 UMGM
data_path = os.path.join(root_path, 'Movielens')
if not (os.path.exists(data_path)):
print('Can not find movielens in {}, please download the dataset first.'.format(data_path))
#Construct graph from raw data.
# movie_genre
movie_genre_src=[]
movie_genre_dst=[]
with open(os.path.join(data_path, 'movie_genre.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split('\t')
movie, genre = int(_line[0]), int(_line[1])
movie_genre_src.append(movie)
movie_genre_dst.append(genre)
# user_movie
user_movie_src=[]
user_movie_dst=[]
with open(os.path.join(data_path, 'user_movie.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split('\t')
user, item, rate = int(_line[0]), int(_line[1]), int(_line[2])
if rate > 3:
user_movie_src.append(user)
user_movie_dst.append(item)
# user_occupation
user_occupation_src=[]
user_occupation_dst=[]
with open(os.path.join(data_path, 'user_occupation.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split('\t')
user, occupation = int(_line[0]), int(_line[1])
user_occupation_src.append(user)
user_occupation_dst.append(occupation)
# user_age
user_age_src=[]
user_age_dst=[]
with open(os.path.join(data_path, 'user_age.dat')) as fin:
for line in fin.readlines():
_line = line.strip().split('\t')
user, age = int(_line[0]), int(_line[1])
user_age_src.append(user)
user_age_dst.append(age)
#build graph
hg = dgl.heterograph({
('movie', 'mg', 'genre') : (movie_genre_src, movie_genre_dst),
('genre', 'gm', 'movie') : (movie_genre_dst, movie_genre_src),
('user', 'um', 'movie') : (user_movie_src, user_movie_dst),
('movie', 'mu', 'user') : (user_movie_dst, user_movie_src),
('user', 'uo', 'occupation') : (user_occupation_src, user_occupation_dst),
('occupation', 'ou', 'user') : (user_occupation_dst, user_occupation_src),
('user', 'ua', 'age') : (user_age_src, user_age_dst),
('age', 'au', 'user') : (user_age_dst, user_age_src)})
print("Graph constructed.")
# Split data into train/eval/test
train_data, eval_data, test_data = split_data(hg, 'um')
#delete the positive edges in eval/test data in the original graph
train_pos = np.nonzero(train_data[:,2])
train_pos_idx = train_pos[0]
user_movie_src_processed = train_data[train_pos_idx, 0]
user_movie_dst_processed = train_data[train_pos_idx, 1]
edges_dict = {
('movie', 'mg', 'genre') : (movie_genre_src, movie_genre_dst),
('genre', 'gm', 'movie') : (movie_genre_dst, movie_genre_src),
('user', 'um', 'movie') : (user_movie_src_processed, user_movie_dst_processed),
('movie', 'mu', 'user') : (user_movie_dst_processed, user_movie_src_processed),
('user', 'uo', 'occupation') : (user_occupation_src, user_occupation_dst),
('occupation', 'ou', 'user') : (user_occupation_dst, user_occupation_src),
('user', 'ua', 'age') : (user_age_src, user_age_dst),
('age', 'au', 'user') : (user_age_dst, user_age_src)
}
nodes_dict = {
'user': hg.num_nodes('user'),
'movie': hg.num_nodes('movie'),
'genre': hg.num_nodes('genre'),
'occupation': hg.num_nodes('occupation'),
'age': hg.num_nodes('age'),
}
hg_processed = dgl.heterograph(data_dict = edges_dict, num_nodes_dict = nodes_dict)
print("Graph processed.")
#save the processed data
with open(os.path.join(root_path, 'movielens_hg.pkl'), 'wb') as file:
pkl.dump(hg_processed, file)
with open(os.path.join(root_path, 'movielens_train.pkl'), 'wb') as file:
pkl.dump(train_data, file)
with open(os.path.join(root_path, 'movielens_test.pkl'), 'wb') as file:
pkl.dump(test_data, file)
with open(os.path.join(root_path, 'movielens_eval.pkl'), 'wb') as file:
pkl.dump(eval_data, file)
return hg_processed, train_data, eval_data, test_data
class MyDataset(Dataset):
def __init__(self, triple):
self.triple = triple
self.len = self.triple.shape[0]
def __getitem__(self, index):
return self.triple[index, 0], self.triple[index, 1], self.triple[index, 2].float()
def __len__(self):
return self.len
def load_data(dataset, batch_size=128, num_workers = 10, root_path = './data'):
if (os.path.exists(os.path.join(root_path, dataset+'_train.pkl'))):
g_file = open(os.path.join(root_path, dataset+'_hg.pkl'), 'rb')
hg = pkl.load(g_file)
g_file.close()
train_set_file = open(os.path.join(root_path, dataset+'_train.pkl'), 'rb')
train_set = pkl.load(train_set_file)
train_set_file.close()
test_set_file = open(os.path.join(root_path, dataset+'_test.pkl'), 'rb')
test_set = pkl.load(test_set_file)
test_set_file.close()
eval_set_file = open(os.path.join(root_path, dataset+'_eval.pkl'), 'rb')
eval_set = pkl.load(eval_set_file)
eval_set_file.close()
else:
if dataset == 'movielens':
hg, train_set, eval_set, test_set = process_movielens(root_path)
elif dataset == 'amazon':
hg, train_set, eval_set, test_set = process_amazon(root_path)
else:
print('Available datasets: movielens, amazon.')
raise NotImplementedError
if dataset == 'movielens':
meta_paths = {
'user': [['um', 'mu']],
'movie': [['mu', 'um'], ['mg', 'gm']]
}
user_key = 'user'
item_key = 'movie'
elif dataset == 'amazon':
meta_paths = {
'user': [['ui', 'iu']],
'item': [['iu', 'ui'], ['ic', 'ci'], ['ib', 'bi'], ['iv', 'vi']]
}
user_key = 'user'
item_key = 'item'
else:
print('Available datasets: movielens, amazon.')
raise NotImplementedError
train_set = torch.Tensor(train_set).long()
eval_set = torch.Tensor(eval_set).long()
test_set = torch.Tensor(test_set).long()
train_set = MyDataset(train_set)
train_loader= DataLoader(dataset=train_set, batch_size = batch_size, shuffle=True, num_workers = num_workers)
eval_set = MyDataset(eval_set)
eval_loader= DataLoader(dataset=eval_set, batch_size = batch_size, shuffle=True, num_workers = num_workers)
test_set = MyDataset(test_set)
test_loader= DataLoader(dataset=test_set, batch_size = batch_size, shuffle=True, num_workers = num_workers)
return hg, train_loader, eval_loader, test_loader, meta_paths, user_key, item_key