“Please integrate the two codes and modify it to use the dataset and model for the second algorithm, not the dataset for the first algorithm.”
Here are the steps to integrate the two codes:

first code:
from operator import ne
import os
import torch
import argparse
import random
import numpy as np
from model import SASRec
from SASRec_utils import
from UFN_utils import
from torch_ema import ExponentialMovingAverage

def str2bool(s):
if s not in {‘false’, ‘true’}:
raise ValueError(‘Not a valid boolean string’)
return s == ‘true’

parser = argparse.ArgumentParser()
parser.add_argument(‘–dataset’, default=“Beauty”)
parser.add_argument(‘–name’, required=True)
parser.add_argument(‘–batch_size’, default=128, type=int)
parser.add_argument(‘–lr’, default=0.001, type=float)
parser.add_argument(‘–maxlen’, default=50, type=int)
parser.add_argument(‘–hidden_units’, default=50, type=int)
parser.add_argument(‘–num_blocks’, default=2, type=int)
parser.add_argument(‘–num_epochs’, default=201, type=int)
parser.add_argument(‘–num_heads’, default=1, type=int)
parser.add_argument(‘–dropout_rate’, default=0.5, type=float)
parser.add_argument(‘–l2_emb’, default=0.0, type=float)
parser.add_argument(‘–device’, default=‘cuda’, type=str)
parser.add_argument(‘–neg_nums’, default=100, type=int)
parser.add_argument(‘–gpu’, default=“0”, type=str)
parser.add_argument(‘–reverse’,default=5,type=int)
parser.add_argument(‘–lbd’,default=0.3,type=float)
parser.add_argument(‘–decay’,default=0.999,type=float)

args = parser.parse_args()
os.environ[“CUDA_VISIBLE_DEVICES”] = args.gpu
args.name = “./” + args.name
if not os.path.isdir(args.dataset + ‘’ + args.name):
os.makedirs(args.dataset + '’ + args.name)
with open(os.path.join(args.dataset + ‘’ + args.name, ‘args.txt’), ‘w’) as f:
f.write(‘\n’.join([str(k) + ‘,’ + str(v) for k, v in sorted(vars(args).items(), key=lambda x: x[0])]))
f.close()

if name == ‘main’:
# global dataset
dataset = data_partition(args.dataset)
[user_train, user_valid, user_test, usernum, itemnum] = dataset
num_batch = len(user_train) // args.batch_size # tail? + ((len(user_train) % args.batch_size) != 0)
cc = 0.0
for u in user_train:
cc += len(user_train[u])
print(‘average sequence length: %.2f’ % (cc / len(user_train)))

f = open(os.path.join(args.dataset + ‘’ + args.name, ‘log.txt’), ‘w’)

sampler = WarpSampler(user_train, usernum, itemnum, batch_size=args.batch_size, maxlen=args.maxlen, n_workers=3,
neg_nums=args.neg_nums)
model = SASRec(usernum, itemnum, args).to(args.device) # no ReLU activation in original SASRec implementation?

for name, param in model.named_parameters():
try:
torch.nn.init.xavier_normal_(param.data)
except:
pass # just ignore those failed init layers

model.train() # enable model training
epoch_start_idx = 1

adam_optimizer = torch.optim.Adam(model.parameters(), lr=args.lr, betas=(0.9, 0.98))

loss_lst = []

flag = False # flag used to decide whether to do negative sampling

hard_items = {} # record the user’s fixed ordinal position’s hard negs in in the last training.
# key:(user_id, position) values:[hard_negs,…]

cnt_items = {} # record frequency of the user’s fixed ordinal position’s hard negs
# key:(user_id, position, hard_neg_id) values:The number of occurrences of hard_neg_id, int

ema = None

for epoch in range(epoch_start_idx, args.num_epochs + 1):
sum_loss = 0
for step in range(num_batch): # tqdm(range(num_batch), total=num_batch, ncols=70, leave=False, unit=‘b’):
u, seq, pos, neg = sampler.next_batch() # tuples to ndarray
u, seq, pos, neg = np.array(u), np.array(seq), np.array(pos), np.array(neg)

reverse = hard_neg_sample(u, seq, pos, neg, hard_items, cnt_items, args)

pos_ = np.expand_dims(pos, 2)
all_samples = np.concatenate((pos_, neg), axis=2)
all_logits = model(u, seq, all_samples)

teacher_logits = None
if flag:
if ema == None:
ema = ExponentialMovingAverage(model.parameters(), decay=args.decay)
ema.to(device = args.device)
else:
with ema.average_parameters():
teacher_logits = model(u, seq, all_samples)
teacher_logits = teacher_logits.detach()

pos_labels, neg_labels = torch.ones(all_logits.shape[0], all_logits.shape[1], 1), torch.zeros(
all_logits.shape[0], all_logits.shape[1], all_logits.shape[2] - 1)

dim0, dim1, dim2 = [],[],[]
cnt = 0
for i in reverse:
neg_labels[i[0]][i[1]][i[2]] = 1
dim0.append(i[0])
dim1.append(i[1])
dim2.append(i[2] + 1)
cnt += 1
reverse_indices = (np.array(dim0), np.array(dim1), np.array(dim2))

if (step == 0):
print("num of labels reversed: ",cnt)

all_labels = torch.cat((pos_labels, neg_labels), dim=2)
all_labels = all_labels.to(device = args.device)

indices = np.where(all_samples != 0)

bce_criterion = torch.nn.BCEWithLogitsLoss()
loss = bce_criterion(all_logits[indices], all_labels[indices])

loss = loss * 2
for param in model.item_emb.parameters(): loss += args.l2_emb * torch.norm(param)

if teacher_logits != None and len(reverse_indices[0]):
loss += args.lbd * bce_criterion(all_logits[reverse_indices], torch.sigmoid(teacher_logits[reverse_indices]))

adam_optimizer.zero_grad()
loss.backward()
adam_optimizer.step()
sum_loss += loss.item()
if flag:
ema.update()

if ((not flag) and len(loss_lst) > 7 and loss_lst[epoch - 3] - loss_lst[epoch - 2] < (loss_lst[0] - loss_lst[5])/200):
flag = True

if flag:
update_hard_negs(u, pos, hard_items, all_logits, all_labels, all_samples, args)

# print(“loss in epoch {} iteration {}: {}”.format(epoch, step, loss.item()))

loss_lst.append(sum_loss)

print(“loss in epoch {} : {}”.format(epoch + 1, sum_loss / num_batch))

if (epoch % 4 == 0):
f.write(str(sum_loss) + ’ ‘)
model.eval()

if flag:
with ema.average_parameters():
print(‘Evaluating’, end=’‘)
t_test = evaluate(model, dataset, args)
t_valid = evaluate_valid(model, dataset, args)
else:
print(‘Evaluating’, end=’‘)
t_test = evaluate(model, dataset, args)
t_valid = evaluate_valid(model, dataset, args)

print(’\n epoch:%d, valid (NDCG@1: %.4f, NDCG@5: %.4f, NDCG@10: %.4f, HR@1: %.4f, HR@5: %.4f, HR@10: %.4f), test (NDCG@1: %.4f, NDCG@5: %.4f, NDCG@10: %.4f, HR@1: %.4f, HR@5: %.4f, HR@10: %.4f)’
% (epoch, t_valid[0], t_valid[1], t_valid[2], t_valid[3], t_valid[4], t_valid[5], t_test[0], t_test[1], t_test[2], t_test[3], t_test[4], t_test[5]))

f.write(str(t_valid) + ’ ’ + str(t_test) + ‘\n’)
f.flush()
model.train()

f.close()
sampler.close()
print(“Done”)
1.
First, load the second code with the necessary libraries and updated false negative detection algorithm.

second code:
# – coding: utf-8 –
“”“
Created on Tue Nov 17 15:33:01 2020

@author: Liwei Huang
”“”
import time
import torch
import numpy as np
import random
from torch.utils.data import DataLoader

from data_prepare import data_partition,NeighborFinder
from model import PTGCN
from modules import TimeEncode,MergeLayer,time_encoding

class Config(object):
“”“config.”“”
data = ‘Moivelens’
batch_size = 64
n_degree = [20,50] #‘Number of neighbors to sample’
n_head = 4 #‘Number of heads used in attention layer’
n_epoch = 50 #‘Number of epochs’
n_layer = 2 #‘Number of network layers’
lr = 0.0001 #‘Learning rate’
patience = 25 #‘Patience for early stopping’
drop_out = 0.1 #‘Dropout probability’
gpu = 0, #‘Idx for the gpu to use’
node_dim = 160 #‘Dimensions of the node embedding’
time_dim = 160 #‘Dimensions of the time embedding’
embed_dim = 160 #‘Dimensions of the hidden embedding’
is_GPU = True
temperature = 0.07


def evaluate(model, ratings, items, dl, adj_user_edge, adj_item_edge, adj_user_time, adj_item_time, device):

torch.cuda.empty_cache()
NDCG5 = 0.0
NDCG10 = 0.0
recall5 = 0.0
recall10 =0.0
num_sample = 0

with torch.no_grad():
model = model.eval()

for ix,batch in enumerate(dl):
#if ix%100==0:
# print(‘batch:’,ix)
count = len(batch)
num_sample = num_sample + count
b_user_edge = find_latest_1D(np.array(ratings.iloc[batch][‘user_id’]), adj_user_edge, adj_user_time, ratings.iloc[batch][‘timestamp’].tolist())
b_user_edge = torch.from_numpy(b_user_edge).to(device)
b_users = torch.from_numpy(np.array(ratings.iloc[batch][‘user_id’])).to(device)

b_item_edge = find_latest_1D(np.array(ratings.iloc[batch][‘item_id’]), adj_item_edge, adj_item_time, ratings.iloc[batch][‘timestamp’].tolist())
b_item_edge = torch.from_numpy(b_item_edge).to(device)
b_items = torch.from_numpy(np.array(ratings.iloc[batch][‘item_id’])).to(device)
timestamps = torch.from_numpy(np.array(ratings.iloc[batch][‘timestamp’])).to(device)

negative_samples = sampler(items, adj_user, ratings.iloc[batch][‘user_id’].tolist() ,100)
neg_edge = find_latest(negative_samples, adj_item_edge, adj_item_time, ratings.iloc[batch][‘timestamp’].tolist())
negative_samples = torch.from_numpy(np.array(negative_samples)).to(device)
item_set = torch.cat([b_items.view(-1,1),negative_samples], dim=1) #batch, 101
timestamps_set = timestamps.unsqueeze(1).repeat(1,101)
neg_edge = torch.from_numpy(neg_edge).to(device)
edge_set = torch.cat([b_item_edge.view(-1,1),neg_edge], dim=1) #batch, 101

user_embeddings = model(b_users, b_user_edge,timestamps, config.n_layer, nodetype=‘user’)
itemset_embeddings = model(item_set.flatten(), edge_set.flatten(), timestamps_set.flatten(), config.n_layer, nodetype=‘item’)
itemset_embeddings = itemset_embeddings.view(count, 101, -1)

logits = torch.bmm(user_embeddings.unsqueeze(1), itemset_embeddings.permute(0,2,1)).squeeze(1) # [count,101]
logits = -logits.cpu().numpy()
rank = logits.argsort().argsort()[:,0]

recall5 += np.array(rank<5).astype(float).sum()
recall10 += np.array(rank<10).astype(float).sum()
NDCG5 += (1 / np.log2(rank + 2))[rank<5].sum()
NDCG10 += (1 / np.log2(rank + 2))[rank<10].sum()

recall5 = recall5/num_sample
recall10 = recall10/num_sample
NDCG5 = NDCG5/num_sample
NDCG10 = NDCG10/num_sample

print(“===> recall_5: {:.10f}, recall_10: {:.10f}, NDCG_5: {:.10f}, NDCG_10: {:.10f}, time:{}”.format(recall5, recall10, NDCG5, NDCG10, time.strftime(‘%Y-%m-%d %H:%M:%S’,time.localtime(time.time()))))

return recall5, recall10, NDCG5, NDCG10

def sampler(items, adj_user, b_users, size):
negs = []
for user in b_users:
houxuan = list(set(items)-set(adj_user[user]))
src_index = random.sample(list(range(len(houxuan))), size)
negs.append(np.array(houxuan)[src_index])
negs = np.array(negs)
return negs

def find_latest(nodes, adj, adj_time, timestamps):
#negative_samples, [b,size]
edge = np.zeros_like(nodes)
for ix in range(nodes.shape[0]):
for iy in range(nodes.shape[1]):
node = nodes[ix, iy]
edge_idx = np.searchsorted(adj_time[node], timestamps[ix])-1
edge[ix, iy] = np.array(adj[node])[edge_idx]
return edge

def find_latest_1D(nodes, adj, adj_time, timestamps):
#negative_samples, [b,size]
edge = np.zeros_like(nodes)
for ix in range(nodes.shape[0]):
node = nodes[ix]
edge_idx = np.searchsorted(adj_time[node], timestamps[ix])-1
edge[ix] = np.array(adj[node])[edge_idx]
return edge


if name==‘main’:

config = Config()
checkpoint_dir=‘/models’
min_NDCG10 = 1000.0
max_itrs = 0

device_string = ‘cuda:0’ if torch.cuda.is_available() else ‘cpu’
device = torch.device(device_string)

print(“loading the dataset…”)
ratings, train_data, valid_data, test_data = data_partition(‘data/movielens/ml-1m’)

users = ratings[‘user_id’].unique()
items = ratings[‘item_id’].unique()
items_in_data = ratings.iloc[train_data+valid_data+test_data][‘item_id’].unique()

adj_user = {user: ratings[ratings.user_id == user][‘item_id’].tolist() for user in users}
adj_user_edge = {user:ratings[ratings.user_id == user].index.tolist() for user in users}
adj_user_time = {user:ratings[ratings.user_id == user][‘timestamp’].tolist() for user in users}

adj_item_edge = {item:ratings[ratings.item_id == item].index.tolist() for item in items}
adj_item_time = {item:ratings[ratings.item_id == item][‘timestamp’].tolist() for item in items}

num_users = len(users)
num_items = len(items)
neighor_finder = NeighborFinder(ratings)
time_encoder = time_encoding(config.time_dim)
MLPLayer = MergeLayer(config.embed_dim, config.embed_dim, config.embed_dim, 1)

a_users = np.array(ratings[‘user_id’])
a_items = np.array(ratings[‘item_id’])
edge_idx = np.arange(0, len(a_users))

user_neig50 = neighor_finder.get_user_neighbor_ind(a_users, edge_idx, max(config.n_degree), device)
item_neig50 = neighor_finder.get_item_neighbor_ind(a_items, edge_idx, max(config.n_degree), device)

criterion = torch.nn.CrossEntropyLoss(reduction=‘sum’)

model = PTGCN(user_neig50, item_neig50, num_users, num_items,
time_encoder, config.n_layer, config.n_degree, config.node_dim, config.time_dim,
config.embed_dim, device, config.n_head, config.drop_out
).to(device)

optim = torch.optim.Adam(model.parameters(),lr=config.lr)

num_params = 0
for param in model.parameters():
num_params += param.numel()
print(num_params)

# 训练集分为不同batch
dl = DataLoader(train_data, config.batch_size, shuffle=True, pin_memory=True)

itrs = 0
sum_loss=0
for epoch in range(config.n_epoch):
time1 = 0.0
x=0.0
for id,batch in enumerate(dl):
#print(‘epoch:’,epoch,’ batch:‘,id)
x=x+1
optim.zero_grad()

count = len(batch)

b_user_edge = find_latest_1D(np.array(ratings.iloc[batch][‘user_id’]), adj_user_edge, adj_user_time, ratings.iloc[batch][‘timestamp’].tolist())
b_user_edge = torch.from_numpy(b_user_edge).to(device)
b_users = torch.from_numpy(np.array(ratings.iloc[batch][‘user_id’])).to(device)

b_item_edge = find_latest_1D(np.array(ratings.iloc[batch][‘item_id’]), adj_item_edge, adj_item_time, ratings.iloc[batch][‘timestamp’].tolist())
b_item_edge = torch.from_numpy(b_item_edge).to(device)
b_items = torch.from_numpy(np.array(ratings.iloc[batch][‘item_id’])).to(device)
timestamps = torch.from_numpy(np.array(ratings.iloc[batch][‘timestamp’])).to(device)

negative_samples = sampler(items_in_data, adj_user, ratings.iloc[batch][‘user_id’].tolist() ,1)
neg_edge = find_latest(negative_samples, adj_item_edge, adj_item_time, ratings.iloc[batch][‘timestamp’].tolist())
negative_samples = torch.from_numpy(np.array(negative_samples)).to(device)
negative_samples = negative_samples.squeeze()
neg_edge = torch.from_numpy(neg_edge).to(device)
neg_edge = neg_edge.squeeze()

time0 = time.time()

user_embeddings = model(b_users, b_user_edge, timestamps, config.n_layer, nodetype=‘user’)
item_embeddings = model(b_items, b_item_edge, timestamps, config.n_layer, nodetype=‘item’)
negs_embeddings = model(negative_samples, neg_edge, timestamps, config.n_layer, nodetype=‘item’)

with torch.no_grad():
labels = torch.zeros(count, dtype=torch.long).to(device)
l_pos = torch.bmm(user_embeddings.view(count, 1, -1), item_embeddings.view(count, -1, 1)).view(count, 1) # [count,1]

l_u = torch.bmm(user_embeddings.view(count, 1, -1), negs_embeddings.view(count, -1, 1)).view(count, 1) # [count,n_negs]
logits = torch.cat([l_pos, l_u], dim=1) # [count, 2]
loss = criterion(logits/config.temperature, labels)

loss.backward()
optim.step()
itrs += 1
#time1 = time1 + (time.time() - time0)
#print(‘time:’+str(time1 / x))

sum_loss = sum_loss + loss.item()
avg_loss = sum_loss / itrs

if id%10==0:
print(“===>({}/{}, {}): loss: {:.10f}, avg_loss: {:.10f}, time:{}”.format(id, len(dl), epoch, loss.item(), avg_loss, time.strftime(’%Y-%m-%d %H:%M:%S’,time.localtime(time.time()))))

print(“===>({}): loss: {:.10f}, avg_loss: {:.10f}, time:{}”.format(epoch, loss.item(), avg_loss, time.strftime(‘%Y-%m-%d %H:%M:%S’,time.localtime(time.time()))))


### Validation
if epoch%3==0:
val_bl = DataLoader(valid_data, 5, shuffle=True, pin_memory=True)
recall5, recall10, NDCG5, NDCG10 = evaluate(model, ratings, items, val_bl, adj_user_edge, adj_item_edge, adj_user_time, adj_item_time, device)

if min_NDCG10>NDCG10:
min_NDCG10 = NDCG10
max_itrs = 0
else:
max_itrs += 1
if max_itrs>config.patience:
break

print(‘Epoch %d test’ % epoch)
test_bl1 = DataLoader(test_data, 5, shuffle=True, pin_memory=True)
recall5, recall10, NDCG5, NDCG10 = evaluate(model, ratings, items, test_bl1, adj_user_edge, adj_item_edge, adj_user_time, adj_item_time, device)
2.Load the new data containing false negative samples into the code based on the first algorithm.
3.Use the false negative detection algorithm from the first code to identify the false negative samples.

4.Using the teacher-student learning technique from the first code, change the label of the false negative samples to positive and add the new data to the training data.
5.Finally, train the model with the new data and evaluate its performance on the test data.

By following these steps,
"Please integrate the two codes and modify it to use the dataset and model for the second algorithm, not the dataset for the first algorithm and use the false negative detection algorithm and teacher-student learning technique from the first algorithm to correct false negative samples in the first algorithm.