From e74e6b017deb12f70068a7a8ecddb04d2ccb08d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=95=8A=E5=91=80=E5=91=80=E5=91=80=E5=91=80=E5=91=80?= <8298132+csuznhyq@user.noreply.gitee.com> Date: Sun, 17 Nov 2024 14:04:20 +0000 Subject: [PATCH 1/3] add end4rec model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 啊呀呀呀呀呀 <8298132+csuznhyq@user.noreply.gitee.com> --- research/recommend/END4Rec/README.md | 2 + .../__pycache__/datasets.cpython-39.pyc | Bin 0 -> 1824 bytes .../END4Rec/__pycache__/models.cpython-39.pyc | Bin 0 -> 2415 bytes .../__pycache__/modules.cpython-39.pyc | Bin 0 -> 4408 bytes .../__pycache__/trainers.cpython-39.pyc | Bin 0 -> 7106 bytes .../END4Rec/__pycache__/utils.cpython-39.pyc | Bin 0 -> 7156 bytes research/recommend/END4Rec/data/Beauty.txt | 22363 ++++++++++++++++ research/recommend/END4Rec/data/genesample.py | 77 + research/recommend/END4Rec/datasets.py | 113 + research/recommend/END4Rec/main.py | 95 + research/recommend/END4Rec/models.py | 61 + research/recommend/END4Rec/modules.py | 99 + .../recommend/END4Rec/output/extrafilter.py | 12 + research/recommend/END4Rec/trainers.py | 214 + research/recommend/END4Rec/utils.py | 223 + 15 files changed, 23259 insertions(+) create mode 100644 research/recommend/END4Rec/README.md create mode 100644 research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/models.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/utils.cpython-39.pyc create mode 100644 research/recommend/END4Rec/data/Beauty.txt create mode 100644 research/recommend/END4Rec/data/genesample.py create mode 100644 research/recommend/END4Rec/datasets.py create mode 100644 research/recommend/END4Rec/main.py create mode 100644 research/recommend/END4Rec/models.py create mode 100644 research/recommend/END4Rec/modules.py create mode 100644 research/recommend/END4Rec/output/extrafilter.py create mode 100644 research/recommend/END4Rec/trainers.py create mode 100644 research/recommend/END4Rec/utils.py diff --git a/research/recommend/END4Rec/README.md b/research/recommend/END4Rec/README.md new file mode 100644 index 000000000..17ad6a79e --- /dev/null +++ b/research/recommend/END4Rec/README.md @@ -0,0 +1,2 @@ +# END4Rec +The source code for our WWW 2024 Paper diff --git a/research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ac889bc31719625a9f55e28da23c48d7b21eb40 GIT binary patch literal 1824 zcmbVMOK&4Z5bnpk>^#VZ4M_kkds;CF*_V|-Vuhk52nmTCKwK=L*2vv)#<9nCcYE1H zJr}&35J>!k-6IkwehSCFa>`!-M5yYCO`IcbO?6edx~jYCt17m(+62}QzdauOoDuQ| z3b$7T!V!GtLm-k!IwHMhr#%WX8?iC(aY{ZTlFR4?k&)sH-iu@`lNY2HOZpYb(-BvYBK+_wGJr%%85QuS|~p7_}6 zqOAHc_*kwMFz_<+34G>PAdWgB$bbN)jt&{@+(nX}GkxmVG5O|c9lO|(A(w2QY{0v| zXNROtY-D4XEa-xQ&D(Vf7W8G}5=mStqkV!_uP7z6NL& zGrv79o+Behsv6icpP~%Bk9AQEl;_AN#dNAF>9?&iR#a*rN~^}kwKCF9z~;{nx?jVUO!us)E+*ArRzmdd zu`=g&GVPAbN}B0JtFE2s{#h5p0x(Qxdf_u6%Br+NB;dw8077U2zl>!xqxb0!eE@q# z4_LxbfBD854m!)@eN5JJA&+ScK)@$ifWQ#S32CM$In%F!E<7`*`gP>-5e+#6&Zh#C zD8ySJ81zKw<=)-E!J;4jMGIIMY6ZYuxCKN75CWu_W7tvwUL1JTMV30Ypml6n1Hxgn zV08j#Vw*U=pa-N*B^ywe-Y1UllbR!VhA{v&K(OYG9qP`R(Vvs=0Pw?9k~!7CBNt+4 zHXF7a1=^PUM;0W$CPiyfvL@l_aPBm&Th$Yg{+F-QsBXCy5z z8VEJ(+lWw8jHe?N@CeugxC&EVD!qkAL-i1!Fa!`#KC!AY6YZlBU@vcnlKL1>r=G)x zSl4@Ko)ne&R_R`f9kUA6D1ACDBv!q*8QP?|faz`Y=UO!W&0Uym2r*DL+)f~LO$P{} zZMqroyUn)gHXwMHw`rRrAAWx&tsCy|D7`$q3#*mKoHY|6Pq0g>VyuMlZ6U@JIUgav zDa34EjGBM+n-E$fVD-C5{zG)&5Y`$eFAhwD&6d&jUdDrN4a7^M&^-7cOI}h5^HTyK zUonKTBhQF_@2-Bf;}{eeZk@uZocRQ1kerNtihEhvocpXPrLy`Ru<;R!x2_s)iJ3ft z&tNMN$X`ZxsYY#{=!dZB_ksAGQ2Wl@mLt=_k)p8`!+V19Ew`%-`0PoOy^j%oApj1S IO}6vVzrsqUDF6Tf literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/models.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24948364fbcb3f189488ee63670fa78cae85b950 GIT binary patch literal 2415 zcmZuzJ#QRE7@pbh+dDgU9GsZXBm$(1MBD@+A-)8O5E600N3+dpeKS7qYku*7-7_PF4}c^oBf8zb?A zFM`J`@kJ;i{02{$$C427I<|Z7)B9h^!F|LU51b|M)b>#*h&HGUGrVRe&dixJ&T6z% z*LWkp=A!@w2N2Gwi_yq`|)aK{}Sj(Cpid zs?@p3%OZVlr09NZcvqEGIW@_~!l7vUX{E|t8!mc^?$q|$FbjD7tg6O`7^Dq9l=*Pq zXu$7jIo?wp*gxgAlcs}lrgfS=Wq-fB{jHWtZ|`TtVOb0h@~jwc-9I0Pww?vj%*}`obJm(gs3)mk(r1i7qaQF!Yi zATzv20Kf?b0DyNZJhT81F5cU7kA35gJOiL=e-2yWpE`gbfRDvm>NVZ~%qSRzYJ`3S z??LU>!4*a@k2)p>Y~49K;iH}iP7zClwR??;sIg$Pl?M0_K2~eYh>nOsk*JP@x5bV- zbq7#)+jp*B!7gJW%)xlI`>7Xn`^TMr1ee0Og zdWC#sY+Qj~6KUYG*@t?Yd~KlW$1Qm}c|ltMN0Qad7+Ew*G0F6Ui93`}$a>ZzwsPc})*GxUvJ&2ux2zP!GW(A)9##n zU*?6(ltP+Er*&sNk(tbf1+s89P8-G~>m=E2WR*7B)8+ziH_x>7kEAM7>+j{DWZ!8i z5LrAF4@HwSG50dR20`cnpG|&rZ5fFRNg|>=SAdhqb8(usuF>wL>A^G` zw=<3Iw_K%v5}HtUWsy$?5_?ORc5{_XNWPjpO4_0+Z$!M;jaH(qX0#u*FDPnc_jXaV m*A}+%b(7=TiwN$wrzM^&1$nNK(Fg6Kk4WV;WhX@9YtDbyQgpBY literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d814a7c08d93e4eae2252879ade6cae2dd2feddd GIT binary patch literal 4408 zcmb_f&5s;M6|d^=`P>gL{)mGZqzD*^>=Gv!35*l4;}FSN0^SH12(9*X?M#nnx@W6; zV|$oELTf2-un-awLds$HxEBujbLvEt12QL$h>Q8X>YkZhd#zkjqk2>Is=BM{z2EQE z>!{JFGL-**`bO{1O~yW_&dK7S^A@W56e4CZAF@vI&pX`ot&U~>?UB=QcroUV9E))_ z@;W{=R%}0Fogj8%7ylIz2!Bu&mDu~l?$q94u^$JISR4pvP(QFc4QMKH6`E?PX+l$r z>(JCo%?dP)xCu?O)T~0Y60btDT58r}euuT!o?zc>yUXdXEYuEAZ=k9c#1!Y+z&>+! z$fqo~4(-@J;+NSGzrZ#a-r{WcFb(COZaSMQ1|j|yfsSFSdB9&w#=KhMp?W+6l!z) zP&+*_-1qSYWzi0}B!@kB9`chp51fee6el^tsqV02zTLJYJ*<6|^hQ|{OAkG>twL02 z&{g*n)u*@5S8AZ$w#|atk=TYLO&9f4p|z=~Z$Jn}xBw=+kJ&CazOQub()Z5C%wZiD z7WH-IcJxrl?M#mTwf65<|M2&}?ftN8oA(rg+Ab>nt7{NB%i)~^>(Dv^wsQN>$=yS5 z%8&4yvd}Lz!9r7+TF_Sw4y?&9Ze*#-<$gDBMXe#Nonq})Vd++qw(`Dc?c8dq{NYfv zz9q&g8D=R4R1ym_sP^_FDOxhi^7dx6RhI2`4W`>43n^EyOC5w^k|uc=YAa23<^4!T zBavg&c)-b0p|p2jB)xvF-HDKy($3u^QhN2HNCFgH5teJWZNNwjcXh3w#IZ<2l}rRc zHdX*uB@Da6NU1Pfx=^lT1FK{&LL9T3d>y~Z`ohwi^SyNqmS_?R`Hw7p166H9O!)we zAm2T>Qoc+l8LkGPS2{;9LM-F0&bYF>t3q9{#-x#2$D1$y1b_HrM_= zA;xhsdP3_11kOlAskX=2ePbR;+mM$?oF{RSW;yaDY7+%C-`89{3tWFUllLPT)9m8p zyvZ-(H(6VryqweKk_>e0k)Kj{27aoBVSxg)>tP5l4~r3FPf4iOjndp*F&xfKPDYkr zB|-c#-X{bovS+}Xfzfo)IaLVHRMaaFbG8_+z~YYra0P5ZoLq9n)wNs65D+q_IpsPs zBP~uZRlkKeizEXt=5VPWTQ9+_7s$N7GN&S#UqzFC--%a>_%MXu4zZ<8Qg%5x+(NEjx# zGD_oAH%HNfP>H>8DAHcumzOa?`@6#|%3r^to84?Q9*PHHNf`g8%*NS%uFsW}h>LzW zmf2lh!$??ajPZ{xgB|TevZo4H8K)V4(WY9c3&?B&Hj|ALraqf4^f1LwLzlZ~z)tKp z_RN~uGbiT*YXEAL^s#4d&JP`;#1Wr)Q+MiZFw$Wb^=vcGdF;&mDLeG1K4t}I1yh7E zA{2Uop^$tPD`_{Ac|U7g+6IZVLlF#7f~WHP7?nSOXjc%8`VqpBv9i6pnTec%p!WO7^G5*c)w`{)_K0lCto>f^s`Aw z0gsMrNJ!uZX<#o926jdkXO%5$(XtmU2YEq3E{xt`vWCaou6!4N@;wrC2g;w4FpRK^ z3+TtBc$NR>%af8(Bk~Cimj@`5G4l*NE zle#?%;3+?#djV-y+42Zzg}M9!Tkqr90$apEUE4MH)R3|(vv-X!vgFSTp+Kfr9t1-O zuJTFK>~`sS+Ty&BZK!_(Rne8d@H{pP&l3iak<2%0$)914{5ixtlOP}JW|Skg zuBhw3q_>l~JZ?Rmyi%TVfr`y*!>k(()pa!HkKpz)S;r2ZDsX8KO8eB+_smDtZOqk_ zeDp+TE!`i5WwbLJQL;l%E<@I@sJloPK0r^I4`$#LDIO1=PFA1Y*G`xAJTHW5>KnL{ z7kX?)`2f4gK74uRA_qXQI&Wbqfp J*DtKs{|_h#v~U0b literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5db4051559ab6f621564274f069c54c6e650ddc7 GIT binary patch literal 7106 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 JkN7!% 0).astype(ms.int32) + expand_dims = ops.ExpandDims() + extended_attention_mask = expand_dims(attention_mask, 1) + extended_attention_mask = expand_dims(extended_attention_mask, 2) # torch.int64 + max_len = attention_mask.shape[-1] + attn_shape = (1, max_len, max_len) + subsequent_mask = Tensor(np.triu(np.ones(attn_shape), k=1), ms.int32) # torch.uint8 + subsequent_mask = (subsequent_mask == 0).astype(ms.int32) + subsequent_mask = expand_dims(subsequent_mask, 1) + subsequent_mask = expand_dims(subsequent_mask, 1) + subsequent_mask = subsequent_mask.astype(ms.int32) + # item_encoded_layers = self.item_encoder(sequence_emb, extended_attention_mask, output_all_encoded_layers=True) + if self.cuda_condition: + subsequent_mask = subsequent_mask.cuda() + extended_attention_mask = extended_attention_mask * subsequent_mask + first_param_dtype = next(self.get_parameters())[0].dtype + extended_attention_mask = extended_attention_mask.astype(first_param_dtype) # fp16 compatibility + extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0 + sequence_emb = self.add_position_embedding(input_ids) + + sequence_output = sequence_emb + + return sequence_output \ No newline at end of file diff --git a/research/recommend/END4Rec/modules.py b/research/recommend/END4Rec/modules.py new file mode 100644 index 000000000..58a9fa0cb --- /dev/null +++ b/research/recommend/END4Rec/modules.py @@ -0,0 +1,99 @@ +import copy +import math +import torch +import torch.nn as nn +import torch.nn.functional as F + +def gelu(x): + return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0))) + +def swish(x): + return x * torch.sigmoid(x) + +ACT2FN = {"gelu": gelu, "relu": F.relu, "swish": swish} + +class LayerNorm(nn.Module): + def __init__(self, hidden_size, eps=1e-12): + """Construct a layernorm module in the TF style (epsilon inside the square root). + """ + super(LayerNorm, self).__init__() + self.weight = nn.Parameter(torch.ones(hidden_size)) + self.bias = nn.Parameter(torch.zeros(hidden_size)) + self.variance_epsilon = eps + + def forward(self, x): + u = x.mean(-1, keepdim=True) + s = (x - u).pow(2).mean(-1, keepdim=True) + x = (x - u) / torch.sqrt(s + self.variance_epsilon) + return self.weight * x + self.bias + + +class FilterLayer(nn.Module): + def __init__(self, args): + super(FilterLayer, self).__init__() + self.complex_weight = nn.Parameter(torch.randn(1, args.max_seq_length//2 + 1, args.hidden_size, 2, dtype=torch.float32) * 0.02) + self.out_dropout = nn.Dropout(args.hidden_dropout_prob) + self.LayerNorm = LayerNorm(args.hidden_size, eps=1e-12) + + def forward(self, input_tensor): + batch, seq_len, hidden = input_tensor.shape + x = torch.fft.rfft(input_tensor, dim=1, norm='ortho') + weight = torch.view_as_complex(self.complex_weight) + x = x * weight + sequence_emb_fft = torch.fft.irfft(x, n=seq_len, dim=1, norm='ortho') + hidden_states = self.out_dropout(sequence_emb_fft) + hidden_states = self.LayerNorm(hidden_states + input_tensor) + + return hidden_states + +class Intermediate(nn.Module): + def __init__(self, args): + super(Intermediate, self).__init__() + self.dense_1 = nn.Linear(args.hidden_size, args.hidden_size * 4) + if isinstance(args.hidden_act, str): + self.intermediate_act_fn = ACT2FN[args.hidden_act] + else: + self.intermediate_act_fn = args.hidden_act + + self.dense_2 = nn.Linear(4 * args.hidden_size, args.hidden_size) + self.LayerNorm = LayerNorm(args.hidden_size, eps=1e-12) + self.dropout = nn.Dropout(args.hidden_dropout_prob) + + def forward(self, input_tensor): + hidden_states = self.dense_1(input_tensor) + hidden_states = self.intermediate_act_fn(hidden_states) + + hidden_states = self.dense_2(hidden_states) + hidden_states = self.dropout(hidden_states) + hidden_states = self.LayerNorm(hidden_states + input_tensor) + + return hidden_states + +class Layer(nn.Module): + def __init__(self, args): + super(Layer, self).__init__() + self.filterlayer = FilterLayer(args) + self.intermediate = Intermediate(args) + + def forward(self, hidden_states, attention_mask): + + hidden_states = self.filterlayer(hidden_states) + intermediate_output = self.intermediate(hidden_states) + return intermediate_output + +class Encoder(nn.Module): + def __init__(self, args): + super(Encoder, self).__init__() + layer = Layer(args) + self.layer = nn.ModuleList([copy.deepcopy(layer) + for _ in range(args.num_hidden_layers)]) + + def forward(self, hidden_states, attention_mask, output_all_encoded_layers=True): + all_encoder_layers = [] + for layer_module in self.layer: + hidden_states = layer_module(hidden_states, attention_mask) + if output_all_encoded_layers: + all_encoder_layers.append(hidden_states) + if not output_all_encoded_layers: + all_encoder_layers.append(hidden_states) + return all_encoder_layers diff --git a/research/recommend/END4Rec/output/extrafilter.py b/research/recommend/END4Rec/output/extrafilter.py new file mode 100644 index 000000000..1e0dd7f01 --- /dev/null +++ b/research/recommend/END4Rec/output/extrafilter.py @@ -0,0 +1,12 @@ +import torch +import pickle as pkl + +model_lists=['EBMRec-Beauty------.pt'] +model2list={} +for model_path in model_lists: + data=torch.load(model_path) + filters = data['item_encoder.layer.0.filterlayer.complex_weight'] + filter_mean = torch.mean(filters, 2)[0] + model2list[model_path]=filter_mean.cpu().numpy().tolist() + +pkl.dump(model2list, open('filter.pkl', 'wb')) \ No newline at end of file diff --git a/research/recommend/END4Rec/trainers.py b/research/recommend/END4Rec/trainers.py new file mode 100644 index 000000000..491f20bd0 --- /dev/null +++ b/research/recommend/END4Rec/trainers.py @@ -0,0 +1,214 @@ +import os +import numpy as np +import mindspore as ms +from mindspore import nn, ops, Tensor, Parameter +from mindspore.common.initializer import Normal +from mindspore.train.callback import Callback +from mindspore.dataset import GeneratorDataset +from tqdm import tqdm +import warnings +warnings.filterwarnings('ignore') +from utils import recall_at_k, ndcg_k, get_metric + +class CustomWithLossCell(nn.Cell): + def __init__(self, backbone, loss_fn): + super(CustomWithLossCell, self).__init__() + self.backbone = backbone + self.loss_fn = loss_fn + + def construct(self, input_ids, pos_ids, neg_ids): + out = self.backbone(input_ids) + return self.loss_fn(out, pos_ids, neg_ids) + +class Trainer: + def __init__(self, model, train_dataloader, + eval_dataloader, + test_dataloader, args): + + self.args = args + self.cuda_condition = not self.args.no_cuda and ms.context.get_context('device_target') == 'GPU' + self.device = ms.context.get_context('device_target') + + self.model = model + if self.cuda_condition: + self.model.set_train(True) + + self.train_dataloader = train_dataloader + self.eval_dataloader = eval_dataloader + self.test_dataloader = test_dataloader + + betas = (self.args.adam_beta1, self.args.adam_beta2) + self.optim = nn.Adam(self.model.trainable_params(), learning_rate=self.args.lr, beta1=betas[0], beta2=betas[1], weight_decay=self.args.weight_decay) + + self.net_with_criterion = CustomWithLossCell(self.model, self.cross_entropy) + self.train_one_step = nn.TrainOneStepCell(self.net_with_criterion, self.optim) + + print("Total Parameters:", sum([np.prod(p.shape) for p in self.model.trainable_params()])) + + def train(self, epoch): + self.iteration(epoch, self.train_dataloader) + + def valid(self, epoch): + return self.iteration(epoch, self.eval_dataloader, train=False) + + def test(self, epoch): + return self.iteration(epoch, self.test_dataloader, train=False) + + def iteration(self, epoch, dataloader, train=True): + str_code = "train" if train else "test" + rec_data_iter = tqdm(enumerate(dataloader.create_tuple_iterator()), + desc="Recommendation EP_%s:%d" % (str_code, epoch), + total=dataloader.get_dataset_size(), + bar_format="{l_bar}{r_bar}") + + if train: + self.model.set_train(True) + rec_loss = 0.0 + + for i, (index, input_ids, answer, neg_answer) in rec_data_iter: + input_ids, answer, neg_answer = map(lambda x: Tensor(x, ms.int32), [input_ids, answer, neg_answer]) + loss = self.train_one_step(input_ids, answer, neg_answer) + rec_loss += loss.asnumpy().item() + + post_fix = { + "epoch": epoch, + "rec_loss": '{:.4f}'.format(rec_loss / len(rec_data_iter)), + } + + if (epoch + 1) % self.args.log_freq == 0: + print(str(post_fix)) + + with open(self.args.log_file, 'a') as f: + f.write(str(post_fix) + '\n') + + else: + self.model.set_train(False) + pred_list = None + for i, (index, input_ids, answers, _, sample_negs) in rec_data_iter: + input_ids, answers, sample_negs = map(lambda x: Tensor(x, ms.int32), [input_ids, answers, sample_negs]) + recommend_output = self.model(input_ids) + expand_dims = ops.ExpandDims() + test_neg_items = ops.Concat(-1)((expand_dims(answers, -1), sample_negs)) + recommend_output = recommend_output[:, -1, :] + + test_logits = self.predict_sample(recommend_output, test_neg_items) + test_logits = test_logits.asnumpy().copy() + if i == 0: + pred_list = test_logits + else: + pred_list = np.append(pred_list, test_logits, axis=0) + + return self.get_sample_scores(epoch, pred_list) + + def get_sample_scores(self, epoch, pred_list): + pred_list = (-pred_list).argsort().argsort()[:, 0] + HIT_1, NDCG_1, MRR = get_metric(pred_list, 1) + HIT_5, NDCG_5, MRR = get_metric(pred_list, 5) + HIT_10, NDCG_10, MRR = get_metric(pred_list, 10) + post_fix = { + "Epoch": epoch, + "HIT@1": '{:.4f}'.format(HIT_1), "NDCG@1": '{:.4f}'.format(NDCG_1), + "HIT@5": '{:.4f}'.format(HIT_5), "NDCG@5": '{:.4f}'.format(NDCG_5), + "HIT@10": '{:.4f}'.format(HIT_10), "NDCG@10": '{:.4f}'.format(NDCG_10), + "MRR": '{:.4f}'.format(MRR), + } + print(post_fix) + with open(self.args.log_file, 'a') as f: + f.write(str(post_fix) + '\n') + return [HIT_1, NDCG_1, HIT_5, NDCG_5, HIT_10, NDCG_10, MRR], str(post_fix) + + def save(self, file_name): + ms.save_checkpoint(self.model, file_name) + + def load(self, file_name): + param_dict = ms.load_checkpoint(file_name) + ms.load_param_into_net(self.model, param_dict) + + def cross_entropy(self, seq_out, pos_ids, neg_ids): + pos_emb = self.model.item_embeddings(pos_ids) + neg_emb = self.model.item_embeddings(neg_ids) + + seq_emb = seq_out[:, -1, :] + pos_logits = ops.reduce_sum(pos_emb * seq_emb, -1) + neg_logits = ops.reduce_sum(neg_emb * seq_emb, -1) + + loss = ops.reduce_mean( + - ops.log(self.sigmoid(pos_logits) + 1e-24) - + ops.log(1 - self.sigmoid(neg_logits) + 1e-24) + ) + + return loss + + def sigmoid(self, x): + return 1 / (1 + ops.exp(-x)) + + def predict_sample(self, seq_out, test_neg_sample): + test_item_emb = self.model.item_embeddings(test_neg_sample) + batch_matmul = ops.BatchMatMul() + test_logits = batch_matmul(test_item_emb, seq_out.expand_dims(-1)).squeeze(-1) + return test_logits + + def predict_full(self, seq_out): + test_item_emb = self.model.item_embeddings.weight + rating_pred = ops.matmul(seq_out, test_item_emb.T) + return rating_pred + +class EBMRecTrainer(Trainer): + + def __init__(self, model, + train_dataloader, + eval_dataloader, + test_dataloader, args): + super(EBMRecTrainer, self).__init__( + model, + train_dataloader, + eval_dataloader, + test_dataloader, args + ) + + def iteration(self, epoch, dataloader, train=True): + + str_code = "train" if train else "test" + rec_data_iter = tqdm(enumerate(dataloader.create_tuple_iterator()), + desc="Recommendation EP_%s:%d" % (str_code, epoch), + total=dataloader.get_dataset_size(), + bar_format="{l_bar}{r_bar}") + + if train: + self.model.set_train(True) + rec_loss = 0.0 + + for i, (index, input_ids, answer, neg_answer) in rec_data_iter: + input_ids, answer, neg_answer = map(lambda x: Tensor(x, ms.int32), [input_ids, answer, neg_answer]) + loss = self.train_one_step(input_ids, answer, neg_answer) + rec_loss += loss.asnumpy().item() + + post_fix = { + "epoch": epoch, + "rec_loss": '{:.4f}'.format(rec_loss / len(rec_data_iter)), + } + + if (epoch + 1) % self.args.log_freq == 0: + print(str(post_fix)) + + with open(self.args.log_file, 'a') as f: + f.write(str(post_fix) + '\n') + + else: + self.model.set_train(False) + pred_list = None + for i, (index, input_ids, answers, _, sample_negs) in rec_data_iter: + input_ids, answers, sample_negs = map(lambda x: Tensor(x, ms.int32), [input_ids, answers, sample_negs]) + recommend_output = self.model(input_ids) + expand_dims = ops.ExpandDims() + test_neg_items = ops.Concat(-1)((expand_dims(answers, -1), sample_negs)) + recommend_output = recommend_output[:, -1, :] + + test_logits = self.predict_sample(recommend_output, test_neg_items) + test_logits = test_logits.asnumpy().copy() + if i == 0: + pred_list = test_logits + else: + pred_list = np.append(pred_list, test_logits, axis=0) + + return self.get_sample_scores(epoch, pred_list) \ No newline at end of file diff --git a/research/recommend/END4Rec/utils.py b/research/recommend/END4Rec/utils.py new file mode 100644 index 000000000..bdce9285f --- /dev/null +++ b/research/recommend/END4Rec/utils.py @@ -0,0 +1,223 @@ +import os +import math +import random +import torch +import datetime +import numpy as np + +from scipy.sparse import csr_matrix +from torch.utils.data import DataLoader, RandomSampler, SequentialSampler +from datasets import EBMRecDataset + +sequential_data_list = ['Beauty'] + +def set_seed(seed): + random.seed(seed) + os.environ['PYTHONHASHSEED'] = str(seed) + np.random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + torch.backends.cudnn.deterministic = True + +def check_path(path): + if not os.path.exists(path): + os.makedirs(path) + print(f'{path} created') + +def get_local_time(): + cur = datetime.datetime.now() + cur = cur.strftime('%b-%d-%Y_%H-%M-%S') + return cur + +class EarlyStopping: + def __init__(self, checkpoint_path, patience=10, verbose=False, delta=0): + self.checkpoint_path = checkpoint_path + self.patience = patience + self.verbose = verbose + self.counter = 0 + self.best_score = None + self.early_stop = False + self.delta = delta + + def compare(self, score): + for i in range(len(score)): + if score[i] > self.best_score[i]+self.delta: + return False + return True + + def __call__(self, score, model): + # score HIT@10 NDCG@10 + if self.best_score is None: + self.best_score = score + self.score_min = np.array([0]*len(score)) + self.save_checkpoint(score, model) + elif self.compare(score): + self.counter += 1 + print(f'EarlyStopping counter: {self.counter} out of {self.patience}') + if self.counter >= self.patience: + self.early_stop = True + else: + self.best_score = score + self.save_checkpoint(score, model) + self.counter = 0 + + def save_checkpoint(self, score, model): + '''Saves model when validation loss decrease.''' + if self.verbose: + print(f'Validation score increased. Saving model ...') + torch.save(model.state_dict(), self.checkpoint_path) + self.score_min = score + +def generate_rating_matrix_valid(user_seq, num_users, num_items): + + row = [] + col = [] + data = [] + for user_id, item_list in enumerate(user_seq): + for item in item_list[:-2]: # + row.append(user_id) + col.append(item) + data.append(1) + + row = np.array(row) + col = np.array(col) + data = np.array(data) + rating_matrix = csr_matrix((data, (row, col)), shape=(num_users, num_items)) + + return rating_matrix + +def generate_rating_matrix_test(user_seq, num_users, num_items): + row = [] + col = [] + data = [] + for user_id, item_list in enumerate(user_seq): + for item in item_list[:-1]: # + row.append(user_id) + col.append(item) + data.append(1) + + row = np.array(row) + col = np.array(col) + data = np.array(data) + rating_matrix = csr_matrix((data, (row, col)), shape=(num_users, num_items)) + + return rating_matrix + +def get_rating_matrix(data_name, seq_dic, max_item): + num_items = max_item + 1 + if data_name in sequential_data_list: + valid_rating_matrix = generate_rating_matrix_valid(seq_dic['user_seq'], seq_dic['num_users'], num_items) + test_rating_matrix = generate_rating_matrix_test(seq_dic['user_seq'], seq_dic['num_users'], num_items) + + return valid_rating_matrix, test_rating_matrix + +def get_user_seqs_and_max_item(data_file): + lines = open(data_file).readlines() + lines = lines[1:] + user_seq = [] + item_set = set() + for line in lines: + user, items = line.strip().split(' ', 1) + items = items.split() + items = [int(item) for item in items] + user_seq.append(items) + item_set = item_set | set(items) + max_item = max(item_set) + return user_seq, max_item + +def get_user_seqs_and_sample(data_file, sample_file): + lines = open(data_file).readlines() + user_seq = [] + item_set = set() + for line in lines: + user, items = line.strip().split(' ', 1) + items = items.split(' ') + items = [int(item) for item in items] + user_seq.append(items) + item_set = item_set | set(items) + max_item = max(item_set) + num_users = len(lines) + lines = open(sample_file).readlines() + sample_seq = [] + for line in lines: + user, items = line.strip().split(' ', 1) + items = items.split(' ') + items = [int(item) for item in items] + sample_seq.append(items) + + assert len(user_seq) == len(sample_seq) + + return user_seq, max_item, num_users, sample_seq + + + +def get_metric(pred_list, topk=10): + NDCG = 0.0 + HIT = 0.0 + MRR = 0.0 + # [batch] the answer's rank + for rank in pred_list: + MRR += 1.0 / (rank + 1.0) + if rank < topk: + NDCG += 1.0 / np.log2(rank + 2.0) + HIT += 1.0 + return HIT /len(pred_list), NDCG /len(pred_list), MRR /len(pred_list) + +def recall_at_k(actual, predicted, topk): + sum_recall = 0.0 + num_users = len(predicted) + true_users = 0 + for i in range(num_users): + act_set = set([actual[i]]) + pred_set = set(predicted[i][:topk]) + if len(act_set) != 0: + sum_recall += len(act_set & pred_set) / float(len(act_set)) + true_users += 1 + return sum_recall / true_users + +def ndcg_k(actual, predicted, topk): + res = 0 + for user_id in range(len(actual)): + k = min(topk, len([actual[user_id]])) + idcg = idcg_k(k) + dcg_k = sum([int(predicted[user_id][j] in + set([actual[user_id]])) / math.log(j+2, 2) for j in range(topk)]) + res += dcg_k / idcg + return res / float(len(actual)) + + +def idcg_k(k): + res = sum([1.0/math.log(i+2, 2) for i in range(k)]) + if not res: + return 1.0 + else: + return res + +def get_seq_dic(args): + + if args.data_name in sequential_data_list: + args.data_file = args.data_dir + args.data_name + '.txt' + args.sample_file = args.data_dir + args.data_name + '_sample.txt' + user_seq, max_item, num_users, sample_seq = \ + get_user_seqs_and_sample(args.data_file, args.sample_file) + seq_dic = {'user_seq':user_seq, 'num_users':num_users, 'sample_seq':sample_seq} + + return seq_dic, max_item + +def get_dataloder(args,seq_dic): + + if args.data_name in sequential_data_list: + train_dataset = EBMRecDataset(args, seq_dic['user_seq'], data_type='train') + train_sampler = RandomSampler(train_dataset) + train_dataloader = DataLoader(train_dataset, sampler=train_sampler, batch_size=args.batch_size) + + eval_dataset = EBMRecDataset(args, seq_dic['user_seq'], test_neg_items=seq_dic['sample_seq'], data_type='valid') + eval_sampler = SequentialSampler(eval_dataset) + eval_dataloader = DataLoader(eval_dataset, sampler=eval_sampler, batch_size=args.batch_size) + + test_dataset = EBMRecDataset(args, seq_dic['user_seq'], test_neg_items=seq_dic['sample_seq'], data_type='test') + test_sampler = SequentialSampler(test_dataset) + test_dataloader = DataLoader(test_dataset, sampler=test_sampler, batch_size=args.batch_size) + + return train_dataloader, eval_dataloader, test_dataloader -- Gitee From 530aa8f297dc238c3a23260a6456b74dcc778dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=95=8A=E5=91=80=E5=91=80=E5=91=80=E5=91=80=E5=91=80?= <8298132+csuznhyq@user.noreply.gitee.com> Date: Sat, 23 Nov 2024 07:18:43 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20rese?= =?UTF-8?q?arch/recommend/END4Rec?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- research/recommend/END4Rec/README.md | 2 - .../__pycache__/datasets.cpython-39.pyc | Bin 1824 -> 0 bytes .../END4Rec/__pycache__/models.cpython-39.pyc | Bin 2415 -> 0 bytes .../__pycache__/modules.cpython-39.pyc | Bin 4408 -> 0 bytes .../__pycache__/trainers.cpython-39.pyc | Bin 7106 -> 0 bytes .../END4Rec/__pycache__/utils.cpython-39.pyc | Bin 7156 -> 0 bytes research/recommend/END4Rec/data/Beauty.txt | 22363 ---------------- research/recommend/END4Rec/data/genesample.py | 77 - research/recommend/END4Rec/datasets.py | 113 - research/recommend/END4Rec/main.py | 95 - research/recommend/END4Rec/models.py | 61 - research/recommend/END4Rec/modules.py | 99 - .../recommend/END4Rec/output/extrafilter.py | 12 - research/recommend/END4Rec/trainers.py | 214 - research/recommend/END4Rec/utils.py | 223 - 15 files changed, 23259 deletions(-) delete mode 100644 research/recommend/END4Rec/README.md delete mode 100644 research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc delete mode 100644 research/recommend/END4Rec/__pycache__/models.cpython-39.pyc delete mode 100644 research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc delete mode 100644 research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc delete mode 100644 research/recommend/END4Rec/__pycache__/utils.cpython-39.pyc delete mode 100644 research/recommend/END4Rec/data/Beauty.txt delete mode 100644 research/recommend/END4Rec/data/genesample.py delete mode 100644 research/recommend/END4Rec/datasets.py delete mode 100644 research/recommend/END4Rec/main.py delete mode 100644 research/recommend/END4Rec/models.py delete mode 100644 research/recommend/END4Rec/modules.py delete mode 100644 research/recommend/END4Rec/output/extrafilter.py delete mode 100644 research/recommend/END4Rec/trainers.py delete mode 100644 research/recommend/END4Rec/utils.py diff --git a/research/recommend/END4Rec/README.md b/research/recommend/END4Rec/README.md deleted file mode 100644 index 17ad6a79e..000000000 --- a/research/recommend/END4Rec/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# END4Rec -The source code for our WWW 2024 Paper diff --git a/research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc deleted file mode 100644 index 8ac889bc31719625a9f55e28da23c48d7b21eb40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1824 zcmbVMOK&4Z5bnpk>^#VZ4M_kkds;CF*_V|-Vuhk52nmTCKwK=L*2vv)#<9nCcYE1H zJr}&35J>!k-6IkwehSCFa>`!-M5yYCO`IcbO?6edx~jYCt17m(+62}QzdauOoDuQ| z3b$7T!V!GtLm-k!IwHMhr#%WX8?iC(aY{ZTlFR4?k&)sH-iu@`lNY2HOZpYb(-BvYBK+_wGJr%%85QuS|~p7_}6 zqOAHc_*kwMFz_<+34G>PAdWgB$bbN)jt&{@+(nX}GkxmVG5O|c9lO|(A(w2QY{0v| zXNROtY-D4XEa-xQ&D(Vf7W8G}5=mStqkV!_uP7z6NL& zGrv79o+Behsv6icpP~%Bk9AQEl;_AN#dNAF>9?&iR#a*rN~^}kwKCF9z~;{nx?jVUO!us)E+*ArRzmdd zu`=g&GVPAbN}B0JtFE2s{#h5p0x(Qxdf_u6%Br+NB;dw8077U2zl>!xqxb0!eE@q# z4_LxbfBD854m!)@eN5JJA&+ScK)@$ifWQ#S32CM$In%F!E<7`*`gP>-5e+#6&Zh#C zD8ySJ81zKw<=)-E!J;4jMGIIMY6ZYuxCKN75CWu_W7tvwUL1JTMV30Ypml6n1Hxgn zV08j#Vw*U=pa-N*B^ywe-Y1UllbR!VhA{v&K(OYG9qP`R(Vvs=0Pw?9k~!7CBNt+4 zHXF7a1=^PUM;0W$CPiyfvL@l_aPBm&Th$Yg{+F-QsBXCy5z z8VEJ(+lWw8jHe?N@CeugxC&EVD!qkAL-i1!Fa!`#KC!AY6YZlBU@vcnlKL1>r=G)x zSl4@Ko)ne&R_R`f9kUA6D1ACDBv!q*8QP?|faz`Y=UO!W&0Uym2r*DL+)f~LO$P{} zZMqroyUn)gHXwMHw`rRrAAWx&tsCy|D7`$q3#*mKoHY|6Pq0g>VyuMlZ6U@JIUgav zDa34EjGBM+n-E$fVD-C5{zG)&5Y`$eFAhwD&6d&jUdDrN4a7^M&^-7cOI}h5^HTyK zUonKTBhQF_@2-Bf;}{eeZk@uZocRQ1kerNtihEhvocpXPrLy`Ru<;R!x2_s)iJ3ft z&tNMN$X`ZxsYY#{=!dZB_ksAGQ2Wl@mLt=_k)p8`!+V19Ew`%-`0PoOy^j%oApj1S IO}6vVzrsqUDF6Tf diff --git a/research/recommend/END4Rec/__pycache__/models.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/models.cpython-39.pyc deleted file mode 100644 index 24948364fbcb3f189488ee63670fa78cae85b950..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2415 zcmZuzJ#QRE7@pbh+dDgU9GsZXBm$(1MBD@+A-)8O5E600N3+dpeKS7qYku*7-7_PF4}c^oBf8zb?A zFM`J`@kJ;i{02{$$C427I<|Z7)B9h^!F|LU51b|M)b>#*h&HGUGrVRe&dixJ&T6z% z*LWkp=A!@w2N2Gwi_yq`|)aK{}Sj(Cpid zs?@p3%OZVlr09NZcvqEGIW@_~!l7vUX{E|t8!mc^?$q|$FbjD7tg6O`7^Dq9l=*Pq zXu$7jIo?wp*gxgAlcs}lrgfS=Wq-fB{jHWtZ|`TtVOb0h@~jwc-9I0Pww?vj%*}`obJm(gs3)mk(r1i7qaQF!Yi zATzv20Kf?b0DyNZJhT81F5cU7kA35gJOiL=e-2yWpE`gbfRDvm>NVZ~%qSRzYJ`3S z??LU>!4*a@k2)p>Y~49K;iH}iP7zClwR??;sIg$Pl?M0_K2~eYh>nOsk*JP@x5bV- zbq7#)+jp*B!7gJW%)xlI`>7Xn`^TMr1ee0Og zdWC#sY+Qj~6KUYG*@t?Yd~KlW$1Qm}c|ltMN0Qad7+Ew*G0F6Ui93`}$a>ZzwsPc})*GxUvJ&2ux2zP!GW(A)9##n zU*?6(ltP+Er*&sNk(tbf1+s89P8-G~>m=E2WR*7B)8+ziH_x>7kEAM7>+j{DWZ!8i z5LrAF4@HwSG50dR20`cnpG|&rZ5fFRNg|>=SAdhqb8(usuF>wL>A^G` zw=<3Iw_K%v5}HtUWsy$?5_?ORc5{_XNWPjpO4_0+Z$!M;jaH(qX0#u*FDPnc_jXaV m*A}+%b(7=TiwN$wrzM^&1$nNK(Fg6Kk4WV;WhX@9YtDbyQgpBY diff --git a/research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc deleted file mode 100644 index d814a7c08d93e4eae2252879ade6cae2dd2feddd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4408 zcmb_f&5s;M6|d^=`P>gL{)mGZqzD*^>=Gv!35*l4;}FSN0^SH12(9*X?M#nnx@W6; zV|$oELTf2-un-awLds$HxEBujbLvEt12QL$h>Q8X>YkZhd#zkjqk2>Is=BM{z2EQE z>!{JFGL-**`bO{1O~yW_&dK7S^A@W56e4CZAF@vI&pX`ot&U~>?UB=QcroUV9E))_ z@;W{=R%}0Fogj8%7ylIz2!Bu&mDu~l?$q94u^$JISR4pvP(QFc4QMKH6`E?PX+l$r z>(JCo%?dP)xCu?O)T~0Y60btDT58r}euuT!o?zc>yUXdXEYuEAZ=k9c#1!Y+z&>+! z$fqo~4(-@J;+NSGzrZ#a-r{WcFb(COZaSMQ1|j|yfsSFSdB9&w#=KhMp?W+6l!z) zP&+*_-1qSYWzi0}B!@kB9`chp51fee6el^tsqV02zTLJYJ*<6|^hQ|{OAkG>twL02 z&{g*n)u*@5S8AZ$w#|atk=TYLO&9f4p|z=~Z$Jn}xBw=+kJ&CazOQub()Z5C%wZiD z7WH-IcJxrl?M#mTwf65<|M2&}?ftN8oA(rg+Ab>nt7{NB%i)~^>(Dv^wsQN>$=yS5 z%8&4yvd}Lz!9r7+TF_Sw4y?&9Ze*#-<$gDBMXe#Nonq})Vd++qw(`Dc?c8dq{NYfv zz9q&g8D=R4R1ym_sP^_FDOxhi^7dx6RhI2`4W`>43n^EyOC5w^k|uc=YAa23<^4!T zBavg&c)-b0p|p2jB)xvF-HDKy($3u^QhN2HNCFgH5teJWZNNwjcXh3w#IZ<2l}rRc zHdX*uB@Da6NU1Pfx=^lT1FK{&LL9T3d>y~Z`ohwi^SyNqmS_?R`Hw7p166H9O!)we zAm2T>Qoc+l8LkGPS2{;9LM-F0&bYF>t3q9{#-x#2$D1$y1b_HrM_= zA;xhsdP3_11kOlAskX=2ePbR;+mM$?oF{RSW;yaDY7+%C-`89{3tWFUllLPT)9m8p zyvZ-(H(6VryqweKk_>e0k)Kj{27aoBVSxg)>tP5l4~r3FPf4iOjndp*F&xfKPDYkr zB|-c#-X{bovS+}Xfzfo)IaLVHRMaaFbG8_+z~YYra0P5ZoLq9n)wNs65D+q_IpsPs zBP~uZRlkKeizEXt=5VPWTQ9+_7s$N7GN&S#UqzFC--%a>_%MXu4zZ<8Qg%5x+(NEjx# zGD_oAH%HNfP>H>8DAHcumzOa?`@6#|%3r^to84?Q9*PHHNf`g8%*NS%uFsW}h>LzW zmf2lh!$??ajPZ{xgB|TevZo4H8K)V4(WY9c3&?B&Hj|ALraqf4^f1LwLzlZ~z)tKp z_RN~uGbiT*YXEAL^s#4d&JP`;#1Wr)Q+MiZFw$Wb^=vcGdF;&mDLeG1K4t}I1yh7E zA{2Uop^$tPD`_{Ac|U7g+6IZVLlF#7f~WHP7?nSOXjc%8`VqpBv9i6pnTec%p!WO7^G5*c)w`{)_K0lCto>f^s`Aw z0gsMrNJ!uZX<#o926jdkXO%5$(XtmU2YEq3E{xt`vWCaou6!4N@;wrC2g;w4FpRK^ z3+TtBc$NR>%af8(Bk~Cimj@`5G4l*NE zle#?%;3+?#djV-y+42Zzg}M9!Tkqr90$apEUE4MH)R3|(vv-X!vgFSTp+Kfr9t1-O zuJTFK>~`sS+Ty&BZK!_(Rne8d@H{pP&l3iak<2%0$)914{5ixtlOP}JW|Skg zuBhw3q_>l~JZ?Rmyi%TVfr`y*!>k(()pa!HkKpz)S;r2ZDsX8KO8eB+_smDtZOqk_ zeDp+TE!`i5WwbLJQL;l%E<@I@sJloPK0r^I4`$#LDIO1=PFA1Y*G`xAJTHW5>KnL{ z7kX?)`2f4gK74uRA_qXQI&Wbqfp J*DtKs{|_h#v~U0b diff --git a/research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc deleted file mode 100644 index 5db4051559ab6f621564274f069c54c6e650ddc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7106 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 JkN7!% 0).astype(ms.int32) - expand_dims = ops.ExpandDims() - extended_attention_mask = expand_dims(attention_mask, 1) - extended_attention_mask = expand_dims(extended_attention_mask, 2) # torch.int64 - max_len = attention_mask.shape[-1] - attn_shape = (1, max_len, max_len) - subsequent_mask = Tensor(np.triu(np.ones(attn_shape), k=1), ms.int32) # torch.uint8 - subsequent_mask = (subsequent_mask == 0).astype(ms.int32) - subsequent_mask = expand_dims(subsequent_mask, 1) - subsequent_mask = expand_dims(subsequent_mask, 1) - subsequent_mask = subsequent_mask.astype(ms.int32) - # item_encoded_layers = self.item_encoder(sequence_emb, extended_attention_mask, output_all_encoded_layers=True) - if self.cuda_condition: - subsequent_mask = subsequent_mask.cuda() - extended_attention_mask = extended_attention_mask * subsequent_mask - first_param_dtype = next(self.get_parameters())[0].dtype - extended_attention_mask = extended_attention_mask.astype(first_param_dtype) # fp16 compatibility - extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0 - sequence_emb = self.add_position_embedding(input_ids) - - sequence_output = sequence_emb - - return sequence_output \ No newline at end of file diff --git a/research/recommend/END4Rec/modules.py b/research/recommend/END4Rec/modules.py deleted file mode 100644 index 58a9fa0cb..000000000 --- a/research/recommend/END4Rec/modules.py +++ /dev/null @@ -1,99 +0,0 @@ -import copy -import math -import torch -import torch.nn as nn -import torch.nn.functional as F - -def gelu(x): - return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0))) - -def swish(x): - return x * torch.sigmoid(x) - -ACT2FN = {"gelu": gelu, "relu": F.relu, "swish": swish} - -class LayerNorm(nn.Module): - def __init__(self, hidden_size, eps=1e-12): - """Construct a layernorm module in the TF style (epsilon inside the square root). - """ - super(LayerNorm, self).__init__() - self.weight = nn.Parameter(torch.ones(hidden_size)) - self.bias = nn.Parameter(torch.zeros(hidden_size)) - self.variance_epsilon = eps - - def forward(self, x): - u = x.mean(-1, keepdim=True) - s = (x - u).pow(2).mean(-1, keepdim=True) - x = (x - u) / torch.sqrt(s + self.variance_epsilon) - return self.weight * x + self.bias - - -class FilterLayer(nn.Module): - def __init__(self, args): - super(FilterLayer, self).__init__() - self.complex_weight = nn.Parameter(torch.randn(1, args.max_seq_length//2 + 1, args.hidden_size, 2, dtype=torch.float32) * 0.02) - self.out_dropout = nn.Dropout(args.hidden_dropout_prob) - self.LayerNorm = LayerNorm(args.hidden_size, eps=1e-12) - - def forward(self, input_tensor): - batch, seq_len, hidden = input_tensor.shape - x = torch.fft.rfft(input_tensor, dim=1, norm='ortho') - weight = torch.view_as_complex(self.complex_weight) - x = x * weight - sequence_emb_fft = torch.fft.irfft(x, n=seq_len, dim=1, norm='ortho') - hidden_states = self.out_dropout(sequence_emb_fft) - hidden_states = self.LayerNorm(hidden_states + input_tensor) - - return hidden_states - -class Intermediate(nn.Module): - def __init__(self, args): - super(Intermediate, self).__init__() - self.dense_1 = nn.Linear(args.hidden_size, args.hidden_size * 4) - if isinstance(args.hidden_act, str): - self.intermediate_act_fn = ACT2FN[args.hidden_act] - else: - self.intermediate_act_fn = args.hidden_act - - self.dense_2 = nn.Linear(4 * args.hidden_size, args.hidden_size) - self.LayerNorm = LayerNorm(args.hidden_size, eps=1e-12) - self.dropout = nn.Dropout(args.hidden_dropout_prob) - - def forward(self, input_tensor): - hidden_states = self.dense_1(input_tensor) - hidden_states = self.intermediate_act_fn(hidden_states) - - hidden_states = self.dense_2(hidden_states) - hidden_states = self.dropout(hidden_states) - hidden_states = self.LayerNorm(hidden_states + input_tensor) - - return hidden_states - -class Layer(nn.Module): - def __init__(self, args): - super(Layer, self).__init__() - self.filterlayer = FilterLayer(args) - self.intermediate = Intermediate(args) - - def forward(self, hidden_states, attention_mask): - - hidden_states = self.filterlayer(hidden_states) - intermediate_output = self.intermediate(hidden_states) - return intermediate_output - -class Encoder(nn.Module): - def __init__(self, args): - super(Encoder, self).__init__() - layer = Layer(args) - self.layer = nn.ModuleList([copy.deepcopy(layer) - for _ in range(args.num_hidden_layers)]) - - def forward(self, hidden_states, attention_mask, output_all_encoded_layers=True): - all_encoder_layers = [] - for layer_module in self.layer: - hidden_states = layer_module(hidden_states, attention_mask) - if output_all_encoded_layers: - all_encoder_layers.append(hidden_states) - if not output_all_encoded_layers: - all_encoder_layers.append(hidden_states) - return all_encoder_layers diff --git a/research/recommend/END4Rec/output/extrafilter.py b/research/recommend/END4Rec/output/extrafilter.py deleted file mode 100644 index 1e0dd7f01..000000000 --- a/research/recommend/END4Rec/output/extrafilter.py +++ /dev/null @@ -1,12 +0,0 @@ -import torch -import pickle as pkl - -model_lists=['EBMRec-Beauty------.pt'] -model2list={} -for model_path in model_lists: - data=torch.load(model_path) - filters = data['item_encoder.layer.0.filterlayer.complex_weight'] - filter_mean = torch.mean(filters, 2)[0] - model2list[model_path]=filter_mean.cpu().numpy().tolist() - -pkl.dump(model2list, open('filter.pkl', 'wb')) \ No newline at end of file diff --git a/research/recommend/END4Rec/trainers.py b/research/recommend/END4Rec/trainers.py deleted file mode 100644 index 491f20bd0..000000000 --- a/research/recommend/END4Rec/trainers.py +++ /dev/null @@ -1,214 +0,0 @@ -import os -import numpy as np -import mindspore as ms -from mindspore import nn, ops, Tensor, Parameter -from mindspore.common.initializer import Normal -from mindspore.train.callback import Callback -from mindspore.dataset import GeneratorDataset -from tqdm import tqdm -import warnings -warnings.filterwarnings('ignore') -from utils import recall_at_k, ndcg_k, get_metric - -class CustomWithLossCell(nn.Cell): - def __init__(self, backbone, loss_fn): - super(CustomWithLossCell, self).__init__() - self.backbone = backbone - self.loss_fn = loss_fn - - def construct(self, input_ids, pos_ids, neg_ids): - out = self.backbone(input_ids) - return self.loss_fn(out, pos_ids, neg_ids) - -class Trainer: - def __init__(self, model, train_dataloader, - eval_dataloader, - test_dataloader, args): - - self.args = args - self.cuda_condition = not self.args.no_cuda and ms.context.get_context('device_target') == 'GPU' - self.device = ms.context.get_context('device_target') - - self.model = model - if self.cuda_condition: - self.model.set_train(True) - - self.train_dataloader = train_dataloader - self.eval_dataloader = eval_dataloader - self.test_dataloader = test_dataloader - - betas = (self.args.adam_beta1, self.args.adam_beta2) - self.optim = nn.Adam(self.model.trainable_params(), learning_rate=self.args.lr, beta1=betas[0], beta2=betas[1], weight_decay=self.args.weight_decay) - - self.net_with_criterion = CustomWithLossCell(self.model, self.cross_entropy) - self.train_one_step = nn.TrainOneStepCell(self.net_with_criterion, self.optim) - - print("Total Parameters:", sum([np.prod(p.shape) for p in self.model.trainable_params()])) - - def train(self, epoch): - self.iteration(epoch, self.train_dataloader) - - def valid(self, epoch): - return self.iteration(epoch, self.eval_dataloader, train=False) - - def test(self, epoch): - return self.iteration(epoch, self.test_dataloader, train=False) - - def iteration(self, epoch, dataloader, train=True): - str_code = "train" if train else "test" - rec_data_iter = tqdm(enumerate(dataloader.create_tuple_iterator()), - desc="Recommendation EP_%s:%d" % (str_code, epoch), - total=dataloader.get_dataset_size(), - bar_format="{l_bar}{r_bar}") - - if train: - self.model.set_train(True) - rec_loss = 0.0 - - for i, (index, input_ids, answer, neg_answer) in rec_data_iter: - input_ids, answer, neg_answer = map(lambda x: Tensor(x, ms.int32), [input_ids, answer, neg_answer]) - loss = self.train_one_step(input_ids, answer, neg_answer) - rec_loss += loss.asnumpy().item() - - post_fix = { - "epoch": epoch, - "rec_loss": '{:.4f}'.format(rec_loss / len(rec_data_iter)), - } - - if (epoch + 1) % self.args.log_freq == 0: - print(str(post_fix)) - - with open(self.args.log_file, 'a') as f: - f.write(str(post_fix) + '\n') - - else: - self.model.set_train(False) - pred_list = None - for i, (index, input_ids, answers, _, sample_negs) in rec_data_iter: - input_ids, answers, sample_negs = map(lambda x: Tensor(x, ms.int32), [input_ids, answers, sample_negs]) - recommend_output = self.model(input_ids) - expand_dims = ops.ExpandDims() - test_neg_items = ops.Concat(-1)((expand_dims(answers, -1), sample_negs)) - recommend_output = recommend_output[:, -1, :] - - test_logits = self.predict_sample(recommend_output, test_neg_items) - test_logits = test_logits.asnumpy().copy() - if i == 0: - pred_list = test_logits - else: - pred_list = np.append(pred_list, test_logits, axis=0) - - return self.get_sample_scores(epoch, pred_list) - - def get_sample_scores(self, epoch, pred_list): - pred_list = (-pred_list).argsort().argsort()[:, 0] - HIT_1, NDCG_1, MRR = get_metric(pred_list, 1) - HIT_5, NDCG_5, MRR = get_metric(pred_list, 5) - HIT_10, NDCG_10, MRR = get_metric(pred_list, 10) - post_fix = { - "Epoch": epoch, - "HIT@1": '{:.4f}'.format(HIT_1), "NDCG@1": '{:.4f}'.format(NDCG_1), - "HIT@5": '{:.4f}'.format(HIT_5), "NDCG@5": '{:.4f}'.format(NDCG_5), - "HIT@10": '{:.4f}'.format(HIT_10), "NDCG@10": '{:.4f}'.format(NDCG_10), - "MRR": '{:.4f}'.format(MRR), - } - print(post_fix) - with open(self.args.log_file, 'a') as f: - f.write(str(post_fix) + '\n') - return [HIT_1, NDCG_1, HIT_5, NDCG_5, HIT_10, NDCG_10, MRR], str(post_fix) - - def save(self, file_name): - ms.save_checkpoint(self.model, file_name) - - def load(self, file_name): - param_dict = ms.load_checkpoint(file_name) - ms.load_param_into_net(self.model, param_dict) - - def cross_entropy(self, seq_out, pos_ids, neg_ids): - pos_emb = self.model.item_embeddings(pos_ids) - neg_emb = self.model.item_embeddings(neg_ids) - - seq_emb = seq_out[:, -1, :] - pos_logits = ops.reduce_sum(pos_emb * seq_emb, -1) - neg_logits = ops.reduce_sum(neg_emb * seq_emb, -1) - - loss = ops.reduce_mean( - - ops.log(self.sigmoid(pos_logits) + 1e-24) - - ops.log(1 - self.sigmoid(neg_logits) + 1e-24) - ) - - return loss - - def sigmoid(self, x): - return 1 / (1 + ops.exp(-x)) - - def predict_sample(self, seq_out, test_neg_sample): - test_item_emb = self.model.item_embeddings(test_neg_sample) - batch_matmul = ops.BatchMatMul() - test_logits = batch_matmul(test_item_emb, seq_out.expand_dims(-1)).squeeze(-1) - return test_logits - - def predict_full(self, seq_out): - test_item_emb = self.model.item_embeddings.weight - rating_pred = ops.matmul(seq_out, test_item_emb.T) - return rating_pred - -class EBMRecTrainer(Trainer): - - def __init__(self, model, - train_dataloader, - eval_dataloader, - test_dataloader, args): - super(EBMRecTrainer, self).__init__( - model, - train_dataloader, - eval_dataloader, - test_dataloader, args - ) - - def iteration(self, epoch, dataloader, train=True): - - str_code = "train" if train else "test" - rec_data_iter = tqdm(enumerate(dataloader.create_tuple_iterator()), - desc="Recommendation EP_%s:%d" % (str_code, epoch), - total=dataloader.get_dataset_size(), - bar_format="{l_bar}{r_bar}") - - if train: - self.model.set_train(True) - rec_loss = 0.0 - - for i, (index, input_ids, answer, neg_answer) in rec_data_iter: - input_ids, answer, neg_answer = map(lambda x: Tensor(x, ms.int32), [input_ids, answer, neg_answer]) - loss = self.train_one_step(input_ids, answer, neg_answer) - rec_loss += loss.asnumpy().item() - - post_fix = { - "epoch": epoch, - "rec_loss": '{:.4f}'.format(rec_loss / len(rec_data_iter)), - } - - if (epoch + 1) % self.args.log_freq == 0: - print(str(post_fix)) - - with open(self.args.log_file, 'a') as f: - f.write(str(post_fix) + '\n') - - else: - self.model.set_train(False) - pred_list = None - for i, (index, input_ids, answers, _, sample_negs) in rec_data_iter: - input_ids, answers, sample_negs = map(lambda x: Tensor(x, ms.int32), [input_ids, answers, sample_negs]) - recommend_output = self.model(input_ids) - expand_dims = ops.ExpandDims() - test_neg_items = ops.Concat(-1)((expand_dims(answers, -1), sample_negs)) - recommend_output = recommend_output[:, -1, :] - - test_logits = self.predict_sample(recommend_output, test_neg_items) - test_logits = test_logits.asnumpy().copy() - if i == 0: - pred_list = test_logits - else: - pred_list = np.append(pred_list, test_logits, axis=0) - - return self.get_sample_scores(epoch, pred_list) \ No newline at end of file diff --git a/research/recommend/END4Rec/utils.py b/research/recommend/END4Rec/utils.py deleted file mode 100644 index bdce9285f..000000000 --- a/research/recommend/END4Rec/utils.py +++ /dev/null @@ -1,223 +0,0 @@ -import os -import math -import random -import torch -import datetime -import numpy as np - -from scipy.sparse import csr_matrix -from torch.utils.data import DataLoader, RandomSampler, SequentialSampler -from datasets import EBMRecDataset - -sequential_data_list = ['Beauty'] - -def set_seed(seed): - random.seed(seed) - os.environ['PYTHONHASHSEED'] = str(seed) - np.random.seed(seed) - torch.manual_seed(seed) - torch.cuda.manual_seed(seed) - torch.cuda.manual_seed_all(seed) - torch.backends.cudnn.deterministic = True - -def check_path(path): - if not os.path.exists(path): - os.makedirs(path) - print(f'{path} created') - -def get_local_time(): - cur = datetime.datetime.now() - cur = cur.strftime('%b-%d-%Y_%H-%M-%S') - return cur - -class EarlyStopping: - def __init__(self, checkpoint_path, patience=10, verbose=False, delta=0): - self.checkpoint_path = checkpoint_path - self.patience = patience - self.verbose = verbose - self.counter = 0 - self.best_score = None - self.early_stop = False - self.delta = delta - - def compare(self, score): - for i in range(len(score)): - if score[i] > self.best_score[i]+self.delta: - return False - return True - - def __call__(self, score, model): - # score HIT@10 NDCG@10 - if self.best_score is None: - self.best_score = score - self.score_min = np.array([0]*len(score)) - self.save_checkpoint(score, model) - elif self.compare(score): - self.counter += 1 - print(f'EarlyStopping counter: {self.counter} out of {self.patience}') - if self.counter >= self.patience: - self.early_stop = True - else: - self.best_score = score - self.save_checkpoint(score, model) - self.counter = 0 - - def save_checkpoint(self, score, model): - '''Saves model when validation loss decrease.''' - if self.verbose: - print(f'Validation score increased. Saving model ...') - torch.save(model.state_dict(), self.checkpoint_path) - self.score_min = score - -def generate_rating_matrix_valid(user_seq, num_users, num_items): - - row = [] - col = [] - data = [] - for user_id, item_list in enumerate(user_seq): - for item in item_list[:-2]: # - row.append(user_id) - col.append(item) - data.append(1) - - row = np.array(row) - col = np.array(col) - data = np.array(data) - rating_matrix = csr_matrix((data, (row, col)), shape=(num_users, num_items)) - - return rating_matrix - -def generate_rating_matrix_test(user_seq, num_users, num_items): - row = [] - col = [] - data = [] - for user_id, item_list in enumerate(user_seq): - for item in item_list[:-1]: # - row.append(user_id) - col.append(item) - data.append(1) - - row = np.array(row) - col = np.array(col) - data = np.array(data) - rating_matrix = csr_matrix((data, (row, col)), shape=(num_users, num_items)) - - return rating_matrix - -def get_rating_matrix(data_name, seq_dic, max_item): - num_items = max_item + 1 - if data_name in sequential_data_list: - valid_rating_matrix = generate_rating_matrix_valid(seq_dic['user_seq'], seq_dic['num_users'], num_items) - test_rating_matrix = generate_rating_matrix_test(seq_dic['user_seq'], seq_dic['num_users'], num_items) - - return valid_rating_matrix, test_rating_matrix - -def get_user_seqs_and_max_item(data_file): - lines = open(data_file).readlines() - lines = lines[1:] - user_seq = [] - item_set = set() - for line in lines: - user, items = line.strip().split(' ', 1) - items = items.split() - items = [int(item) for item in items] - user_seq.append(items) - item_set = item_set | set(items) - max_item = max(item_set) - return user_seq, max_item - -def get_user_seqs_and_sample(data_file, sample_file): - lines = open(data_file).readlines() - user_seq = [] - item_set = set() - for line in lines: - user, items = line.strip().split(' ', 1) - items = items.split(' ') - items = [int(item) for item in items] - user_seq.append(items) - item_set = item_set | set(items) - max_item = max(item_set) - num_users = len(lines) - lines = open(sample_file).readlines() - sample_seq = [] - for line in lines: - user, items = line.strip().split(' ', 1) - items = items.split(' ') - items = [int(item) for item in items] - sample_seq.append(items) - - assert len(user_seq) == len(sample_seq) - - return user_seq, max_item, num_users, sample_seq - - - -def get_metric(pred_list, topk=10): - NDCG = 0.0 - HIT = 0.0 - MRR = 0.0 - # [batch] the answer's rank - for rank in pred_list: - MRR += 1.0 / (rank + 1.0) - if rank < topk: - NDCG += 1.0 / np.log2(rank + 2.0) - HIT += 1.0 - return HIT /len(pred_list), NDCG /len(pred_list), MRR /len(pred_list) - -def recall_at_k(actual, predicted, topk): - sum_recall = 0.0 - num_users = len(predicted) - true_users = 0 - for i in range(num_users): - act_set = set([actual[i]]) - pred_set = set(predicted[i][:topk]) - if len(act_set) != 0: - sum_recall += len(act_set & pred_set) / float(len(act_set)) - true_users += 1 - return sum_recall / true_users - -def ndcg_k(actual, predicted, topk): - res = 0 - for user_id in range(len(actual)): - k = min(topk, len([actual[user_id]])) - idcg = idcg_k(k) - dcg_k = sum([int(predicted[user_id][j] in - set([actual[user_id]])) / math.log(j+2, 2) for j in range(topk)]) - res += dcg_k / idcg - return res / float(len(actual)) - - -def idcg_k(k): - res = sum([1.0/math.log(i+2, 2) for i in range(k)]) - if not res: - return 1.0 - else: - return res - -def get_seq_dic(args): - - if args.data_name in sequential_data_list: - args.data_file = args.data_dir + args.data_name + '.txt' - args.sample_file = args.data_dir + args.data_name + '_sample.txt' - user_seq, max_item, num_users, sample_seq = \ - get_user_seqs_and_sample(args.data_file, args.sample_file) - seq_dic = {'user_seq':user_seq, 'num_users':num_users, 'sample_seq':sample_seq} - - return seq_dic, max_item - -def get_dataloder(args,seq_dic): - - if args.data_name in sequential_data_list: - train_dataset = EBMRecDataset(args, seq_dic['user_seq'], data_type='train') - train_sampler = RandomSampler(train_dataset) - train_dataloader = DataLoader(train_dataset, sampler=train_sampler, batch_size=args.batch_size) - - eval_dataset = EBMRecDataset(args, seq_dic['user_seq'], test_neg_items=seq_dic['sample_seq'], data_type='valid') - eval_sampler = SequentialSampler(eval_dataset) - eval_dataloader = DataLoader(eval_dataset, sampler=eval_sampler, batch_size=args.batch_size) - - test_dataset = EBMRecDataset(args, seq_dic['user_seq'], test_neg_items=seq_dic['sample_seq'], data_type='test') - test_sampler = SequentialSampler(test_dataset) - test_dataloader = DataLoader(test_dataset, sampler=test_sampler, batch_size=args.batch_size) - - return train_dataloader, eval_dataloader, test_dataloader -- Gitee From 8ea0cd8a3768854135680ce552f99ecb640d4a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=95=8A=E5=91=80=E5=91=80=E5=91=80=E5=91=80=E5=91=80?= <8298132+csuznhyq@user.noreply.gitee.com> Date: Sat, 23 Nov 2024 07:19:07 +0000 Subject: [PATCH 3/3] add end4rec model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 啊呀呀呀呀呀 <8298132+csuznhyq@user.noreply.gitee.com> --- research/recommend/END4Rec/README.md | 1 + .../__pycache__/datasets.cpython-39.pyc | Bin 0 -> 3481 bytes .../END4Rec/__pycache__/models.cpython-39.pyc | Bin 0 -> 2394 bytes .../__pycache__/modules.cpython-39.pyc | Bin 0 -> 4378 bytes .../__pycache__/trainers.cpython-39.pyc | Bin 0 -> 5687 bytes .../END4Rec/__pycache__/utils.cpython-39.pyc | Bin 0 -> 4489 bytes research/recommend/END4Rec/data/Beauty.txt | 22363 ++++++++++++++++ research/recommend/END4Rec/data/genesample.py | 93 + research/recommend/END4Rec/datasets.py | 128 + research/recommend/END4Rec/main.py | 112 + research/recommend/END4Rec/models.py | 202 + research/recommend/END4Rec/modules.py | 136 + research/recommend/END4Rec/requirements.txt | 5 + research/recommend/END4Rec/trainers.py | 229 + research/recommend/END4Rec/utils.py | 163 + 15 files changed, 23432 insertions(+) create mode 100644 research/recommend/END4Rec/README.md create mode 100644 research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/models.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc create mode 100644 research/recommend/END4Rec/__pycache__/utils.cpython-39.pyc create mode 100644 research/recommend/END4Rec/data/Beauty.txt create mode 100644 research/recommend/END4Rec/data/genesample.py create mode 100644 research/recommend/END4Rec/datasets.py create mode 100644 research/recommend/END4Rec/main.py create mode 100644 research/recommend/END4Rec/models.py create mode 100644 research/recommend/END4Rec/modules.py create mode 100644 research/recommend/END4Rec/requirements.txt create mode 100644 research/recommend/END4Rec/trainers.py create mode 100644 research/recommend/END4Rec/utils.py diff --git a/research/recommend/END4Rec/README.md b/research/recommend/END4Rec/README.md new file mode 100644 index 000000000..0bfdf82f7 --- /dev/null +++ b/research/recommend/END4Rec/README.md @@ -0,0 +1 @@ +The source code of end4rec. \ No newline at end of file diff --git a/research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/datasets.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0b6b6f93e23aacb618b15660a0c04197e8bd365 GIT binary patch literal 3481 zcmbVO&5t8T6|buPZhK}Y%OpD!g=j+%p#$=O5N`grx~Rn`0Wy_aom z#SFhYfB#|sPdkkLjV9NBE++5b(-Mtjk`Gw7>3Nr9E(T)gbRAAK2V=ME4!y27^t(Q2 zuJoR?q+TILxX{=T+jE zn1;U`WinT0>tR;P(eP0=91k#k;ZZ)B=4Dl6g9WK4NW$XRLhs@G89x12G!?7aoS*S? zHWPg|b1E@sGq)Cp?4x&QUhSPZ=j_atT#9q?p_uuzpblt$&S!yir2CB3!677o?womb zaLzfa-AdHKoIil1$;*{ryI2papcd#OoXD@87~8Y%eC1i*+F9}PtjTX6*O_y)@tl7w z^k06#KIOGjhjmoP$1YUpAAP}ZUvNCON6qp_Y9V_*!l!r9^r4E6+B4o<@ONT@&Cl6$ zZk(d5o(m&7-!pDe4`2IE|{sSL7{cb<6(kXCkFLn|L7)>e;xx+52z03-B8KZ8VIxxyyYX@?9SDZTp3o5p_vxi(R3<3EnmB`XG?I z*vL7;pk^oZ@mqj_TNtI{8bw%&Q@NlK-IK>iC zo$5(-+FIHhlf+T4;3)MCYFAiEmGcM?KZaPHX6on@|&W48H+Yo3FbW_UjI3myn|1F3r)@l2D?H=78`ii zk)HGcX08lmh~BfH7Mrb~KY0IP-Xk1??T?ICsjMh_1Wn5y`6vaNRrntvV)+?$09?huIXuQ*ld*K|G^lBGcnGpFJ5P7;uk1V`#Sxbp>}%*DSh zFE17Opz%J*28F!9{4$Bu8z5O5nQiiPQa-|`Up+Pf%`rBf0;1%~#^g&RVY|w8m6mzm z28LcZLG^T;Cy{Y=J~+M-tKOmm-llDc+lh&aay+flLTbYc6M}?P(aSeIAxzVvEUGjm zgX>q(FoX<(Mo_5i@*Vyv`jGDlUl9HDr8R4ImfP3jhoF~~Va-WdmNL%?i~?oxqeL`M zByUf+`T@GlTLmd8Bu(#QO_LW z5=b`X>d&AC_Uy0AE{weAI1vbbHG=IZ;j)jBA-8$x-cdXJ4?<)t1ez&i3` z5?hl3*Gri{QMYNwkBHgNO8x6xbuB1S7O)33L=%iNNjC4ctu#$zRcRw#Z#qdU zO#x%}Zs|{PfbO7Sfcdud-fgiB(BI)VotVcCjqU$SKU$3b=?16!n@+Won208-fv<=W z0^T$=aheWCayp=KJ549kY|yNzJ2+b1rRH5~R#ihYvibH+EKpw3lwLv}zZg1-XlpJ^ z5W6bc=s^`b;}RGs;g08m9JywnF!kmpeX>(iYQe1ud=g=Npb3ga6Ht$;2KnXdSWy&H zYKxkyOWOPW7_=TfO>_p$g-8g>Qf&wl6+bE^=mj>oe~$qLH{EX^H8C9AnTbVUp}@p# zDP&MQg6>{%g5Lu_s^ibynTOQrpNOsi*~ncN=p|7-*UP(fJ4bF=zwL2*c}_*ooQ7JbcduUa)d?^Rwbke sTZPzqq0tpNj1_h5F4oh?$xL{!384FgKbk7frX<^S!u>GZxf=%m23hqc`~Uy| literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/models.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa2e6bf4782a38556a080cc1bcd536a0c74ed10f GIT binary patch literal 2394 zcmZuz%WfP+6s_v_^o*UvHcrAbi2!LLk!%nM#7mF}Ate^#vFS~#GgThHeMrkGt2w}DJ{^7HP;7d8RP$ z+fJGe#+lY>`jq|s!R_z0RQmQ#R_vF>a5vA2;q5z8KQv`^dy*GISEZ8679pr_Rr@MJ zxB#!dh=%c19`H@R#xL@i$IijV65zK^i**k95UU9JFYxLIXlgzKrRV(6F?{6I)Vjda zBfJmY+MW5ro%0!303R@57B-d#E2=Sb=+|EDUuK5^MmlwX5whZi6##2*>!iWjvA!_- zm9&A7KjZ`1GN6k>5oEq8)nLa4nL;(B^~R`-dJQ|YooS(Wr&7YHBloJT5NW2>Dy9@w zp+QQm!Rm)95i=j@1& zdLlSRE)mx56(*v_gUwbN;6ub%tuZ4yA_hgGIuhPhcG#&qfV$frYxN2~LBEgn(pV+c|R7O%j8VKLVeCd^n0A47l@(Hyh6m zJhtEwk9^_|T^-~->k(V|Su}W6>{*;n8JqaQ)g>5YIdtLkX^#9eHgbqqpK~ zi>KuYc1X%Pky&9~ZG^gsk*)rUjdPtB+GIHND#n-%?&XEdl){aUP8-g8A~Tr{3tYI_ zIBgh{Tq4uz32YIHge;`$vT7NqSCHqcGkzi7a=~%vil6ncL-p8v+nwY!B zuRsubz-N;mTvNq zmv(cRTu8o}Ym>A^)4dV#UN>5at~R6ns69bZBfGbXqAgq4=GVl8y V=NcJ()GqpjR9@5VgiQRR^B;d=ZFK+u literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/modules.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab03b0484c3b839f51ebbc2a72d4cc862807ad0f GIT binary patch literal 4378 zcmb_fO^+N$8LsN@`PkXr@#2p-h=~*dBat<6z!H&h60PG9;VdEE2pEW3?djT?9?x{o zR`tgAFmpg_DRA%s2?-%_*gg8ffuB<+5QoT|a^_;5x4P$J?X_}AjjE>l?dqz~DSnS8aBNhk38Pt#L&KfM0xC%?Pv@~F; z#dTQfrDYwKwYULGqqJ zcFd0Zrjmrp2==s+d}SZXB6dq?WhBp zKjE4`c)}!2_P@8Ue5!<0SNc)v={b7SeZQmNbITD%?WmPhdtrDZA;R_+E+<$lqIqBaAlTOG!?q( zs{4uR)7$4Wt)btx&4k*KScW7^7xh%3xv8k{q7jU^0bY1tuzhauuXOAZf9DJ4u#O9_ z`nqyEdMM;>CP!ax{`ZYP{Ozv?KkeG)Jw-!(7nT0ibu>B4fzXk4Y@L8#xqa;9?y)!J zC-_ZS=$DpYVW~_l*sF#M*5p?^S*mh**v(r}Ye;jan7cJHo^B;+EANZe-mR9(9}Y$9 z`(mt;VV2^CN@8Jds)NHwik8f>yuDp*m1VbGgX<2*LdtclQU_s}q)8rz+DcPh`8bl% zNaVO{5OA_oDDB-BNw1%4cOqn_v~xF!l-~F}k|0J`gyr0A8&nd*eO>D(aV*kMB@+Rn zjTOjM3B&F%QYs9W5XvSNutEMJ)-k)moA^zd3r}y)*VZ*$qCqHxA9;EQRqdjg@&Qyq z*gdvp)|5}Ji%>`GoUGdI!cK~r+EX@gEF%x=4(Bc>C(CbB zL;5l369W|aGvJNDSh~14Rfx}2)az*GYB5@Y#~%gI3eP}JUQHp#6Gif)I zc|U7g+J;uNLxBpxfT!{&xGUdA)2<-s^dm$a<4}8lKSzkBcK!22+z%ramhO{pnKveM zQ~sEqCz7@+h0E$mI)*oMk*Z8;_imJT`yIc;M0-WxG1@bV>}=rHp)f&ebT_2=*5<(} zk8<(6HjQ{lK#EkycpdSm&I7&$3>wzt+$svCLgn``a7E%vff1d)gIWr#?iqr8BLb^` zm_lD85hvKh3kq8tLleyYqQXE71iXPuiNp!%#mjxtPhL5)y`8(oZRmc9hioAe^uS-|UcNtSPfzV6v41G$l^Nz9(-?UWx;)JGCk_B`TP;V!?R z)i3aDK`WA;uI-ysXh^w}S-VE`SjtAej0zvp5-5~1oXd#44YS%M^0dTxA>YvT4yvL9 zeStg{3*?Cd$T#K-wdBVbBY%lzo+l87x)J3FX?c>R;V4q~I;Uxk^8-QeETD-N#ZnE( zleJ>0UyChyiWoM>)|F)GqMj=Aou0~+Po4dq$&~rZ>F;a*{j{6KLcTmMkwnhI_fIT$ zj@{)1Inw2Uf5dOHqatYzOkA-~ef5d6^XY0TL0;Ca~ zQBF6*XG#zwv!fm?*7grI50Rw01y>eg($(w3MCEic-S{=Vo#6Jk^=$HbxyJ=7wyzJf zZZuRk(3wAiL(Ak9ckoofOT$oFr>=fv68YO0t0}$ciOyzvI10-^XBML5Z|KP-PiYNB z@iNRAOa6EW6*?4|kdtF-dyb!DD+R&9y=&>240qiFG?A4izqaVTQ$U;(# z�+W5SX)r>eN=(me*5qrwLS+S)%r$@mQpB+be<-aaw+YMqetp8%9V&aSVeNaaioF z(_Gr*+*UXD%JlXu!v7X8EyJ`!v5h+j)zq7;&v(AaocCUSG!r6w^eS=&Vw)$)(r!vJ zN-`FCN?<;gx6{;Qgq?Hq%kBNcv`cc0hPt}a=eNw)r}^%b^l2-9jz)V0*u{B7vB`uZ qqd7D2%1)Qu3$7Pg{te1vO>7B(G8W65R$vEq!)k6co6QT&`u_nhBdPEJ literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/trainers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8b10c7c0c54b86479148a33cc84d2a63f5791ae GIT binary patch literal 5687 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 literal 0 HcmV?d00001 diff --git a/research/recommend/END4Rec/__pycache__/utils.cpython-39.pyc b/research/recommend/END4Rec/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24b3b03092b155e5becd1c6ac0a8e8cb21cd35bc GIT binary patch literal 4489 zcmdT{-*4Pl6~6cS$9N`_G-=Z&X{secr0M`omkQCUloGL_`vYwRO?Lrni`Vt_Oq_T; zlWR|DB9DZWtXc#-@P@QPN*?iC2A(`YU^Q$xWxw#g;FlWoR%-QyBb9Q_eXOY&r zp6_ucEomPxzy3axj&u*0boYhdkTvOHbVAl;1LvlkkWHK?<)oa#c}mX9X*qMi{R{G< zyo8ZyIV&&YJR`5jIh-#_zQI}xuVEcqZ*kp-ausyLLM6{58avrI6#AC;aOCq41>0hW z{D=)%$qt3&N1QaQCD!+5mY?2SmN%DwA1r@xbNS<&%Ns3AdonEIBI(B3%6fm)US6m+ zUE-xyG*GXYs$to$@80?(k5ztaGt72-S!X8+v(BxxINvUM{af86lX<_V;xpQyNYZ?z zzpJM@aS^1wC`)NweJ?-UCqTV1YVx=2T zYOx2Ez(;{p++Ro#&t(ve%O_G=*aghXhpb{Q5?FB)SB}EWiz*SDu z7fCA}F0JA*K-?kIXmW%PGQdlR!pBljxGND5bz{~mADJ=ctlIhH1! zI`$6-K?{i0jR; zAHQ;RJkemUa3hDcXMqikgpZ> zQf-5fLtQiT6Y1CKevl@4p>0zANxTU3HmU|^a5mglUFgnLd9V6R#b=} z$55dPc1oXjaZ!S7<`AifP(&MulS>QI+P4s2Al7qZR8gEZQK-Fc0!n=!i>Mz!v??bk zdM9$PPVr#UPuCDXflMOpb;IWYMT7bwCi$0)cgH>MU!-pvA3KlA43*}wIQb2h8&R>x zXZfs9^lcH*+Q~+Ep5`YJZ7egKt)_e&a^$Nh#6B=7sidq8ZRDhN#12tY(U=Hi zurqW^_s~YW;#Q4R>8>HaF)BdPRURWxOLw3D0_*HtFI*tXk@upk8T6bAy{~zF%t*>Q za?b`1Lw_9*$CKuelY930-^Gr-Q3VP0Ibhe8&|>9X^&`wbk5c14Wgpd`2cP5ie{it9 z6@u<0r}H4pBoean$;y4x?c@)joIHqT!R~<>bX~=vOp`1|%I9$b5$o z;ya6DiZ}sh^&u@trC_Xgpx~zjGqpE^BKZ(59a=b0JK^kmLj*WlCr64ow#e>)zCo;f zo2h9eiYU;d;vPDRBW~`B(xN&H7f+Yua0J03QtDI#MOR~O%cRV|@lvyml&^l?84awW zb`kpmo?hp+sj8GjeHF_Qi=ye;_U-kx_ulud4?cXXt&bl)(l$Dn?eowz2)b?z4@H|; zGN)#Y0VeFi19f`*3V>3SG-KpIJuP8m@Och}u&E+%2vksJc!}NuIDI;F>B~xYfprj< z!y2woz!uQSl!DR-V;-KY?SnwJEj15xa8-J%xKkLNIyQr$MTi1JX9u%NXOWs!kjqDS zzv);F&9rO-iMmXqs}S00r@gRf)ls{m0_D8IDv63%s&!288#xM=im5d){Ny(ZHHfPc zrsioz4Ns!B6~1R+hISswiR$?vEQ0Li{OHdVD1t^_0x|+}Ux0N{#{nN|`V01gzYuMNn6wTEPC?Jn(_k8_bP24} z;Dd9jl}`XPe-LLGkjRCsqV6`o2VuzNHj&FqP8O7W0nPLqYo3v_sP6zb&cU@uVv$u8 z)Z(vcHF$;AsT^YCKW`JgbgzR-@KX$HzV*sdL}ltRiFZkm0gAX--G}%BM^3*EE*Hnh z+r}F0R`2{122S&3+K|dLcaJ?W#ntDy_g1zx`Enh13piPd1NtKYbR$=xxa99h z 0).astype(ms.int32) + expand_dims = ops.ExpandDims() + extended_attention_mask = expand_dims(attention_mask, 1) + extended_attention_mask = expand_dims(extended_attention_mask, 2) # torch.int64 + max_len = attention_mask.shape[-1] + attn_shape = (1, max_len, max_len) + subsequent_mask = Tensor(np.triu(np.ones(attn_shape), k=1), ms.int32) # torch.uint8 + subsequent_mask = (subsequent_mask == 0).astype(ms.int32) + subsequent_mask = expand_dims(subsequent_mask, 1) + subsequent_mask = expand_dims(subsequent_mask, 1) + subsequent_mask = subsequent_mask.astype(ms.int32) + # item_encoded_layers = self.item_encoder(sequence_emb, extended_attention_mask, output_all_encoded_layers=True) + if self.cuda_condition: + subsequent_mask = subsequent_mask.cuda() + extended_attention_mask = extended_attention_mask * subsequent_mask + first_param_dtype = next(self.get_parameters())[0].dtype + extended_attention_mask = extended_attention_mask.astype(first_param_dtype) # fp16 compatibility + extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0 + sequence_emb = self.add_position_embedding(input_ids) + + sequence_output = sequence_emb + + return sequence_output \ No newline at end of file diff --git a/research/recommend/END4Rec/modules.py b/research/recommend/END4Rec/modules.py new file mode 100644 index 000000000..f6ba85576 --- /dev/null +++ b/research/recommend/END4Rec/modules.py @@ -0,0 +1,136 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + + +import numpy as np +import mindspore as ms +from mindspore import nn, ops, Tensor, Parameter +from copy import deepcopy + +# Activation functions +def gelu(x): + return x * 0.5 * (1.0 + ops.Erf()(x / np.sqrt(2.0))) + +def swish(x): + return x * ops.Sigmoid()(x) + +ACT2FN = {"gelu": gelu, "relu": ops.ReLU(), "swish": swish} + +class LayerNorm(nn.Cell): + def __init__(self, hidden_size, eps=1e-12): + super(LayerNorm, self).__init__() + self.weight = Parameter(Tensor(np.ones(hidden_size), ms.float32)) + self.bias = Parameter(Tensor(np.zeros(hidden_size), ms.float32)) + self.variance_epsilon = eps + + def construct(self, x): + u = x.mean(axis=-1, keep_dims=True) + s = ((x - u) ** 2).mean(axis=-1, keep_dims=True) + x = (x - u) / ops.Sqrt()(s + self.variance_epsilon) + return self.weight * x + self.bias + +def dft_matrix(N): + i, j = np.meshgrid(np.arange(N), np.arange(N)) + omega = np.exp(-2j * np.pi * i * j / N) + return omega + +def idft_matrix(N): + i, j = np.meshgrid(np.arange(N), np.arange(N)) + omega = np.exp(2j * np.pi * i * j / N) / N + return omega + +class FilterLayer(nn.Cell): + def __init__(self, hidden_size, max_seq_length): + super(FilterLayer, self).__init__() + self.complex_weight = Parameter(Tensor(np.random.randn(1, max_seq_length // 2 + 1, hidden_size, 2) * 0.02, ms.float32)) + self.out_dropout = nn.Dropout() + self.LayerNorm = LayerNorm(hidden_size, eps=1e-12) + + self.dft_matrix = Tensor(dft_matrix(max_seq_length), dtype=ms.complex64) + self.idft_matrix = Tensor(idft_matrix(max_seq_length), dtype=ms.complex64) + + def construct(self, input_tensor): + batch, seq_len, hidden = input_tensor.shape + input_tensor_complex = ops.Cast()(input_tensor, ms.complex64) + + # Perform DFT + x = ops.MatMul()(input_tensor_complex, self.dft_matrix[:seq_len, :seq_len]) + + # Apply weights (complex multiplication) + weight = ops.Complex()(self.complex_weight[..., 0], self.complex_weight[..., 1]) + weight = weight[:, :seq_len // 2 + 1, :] + x = x * weight + + # Perform IDFT + sequence_emb_fft = ops.MatMul()(x, self.idft_matrix[:seq_len, :seq_len]) + + # Take real part of the result + sequence_emb_fft = ops.Real()(sequence_emb_fft) + + hidden_states = self.out_dropout(sequence_emb_fft) + hidden_states = self.LayerNorm(hidden_states + input_tensor) + + return hidden_states + +class Intermediate(nn.Cell): + def __init__(self, hidden_size, hidden_act): + super(Intermediate, self).__init__() + self.dense_1 = nn.Dense(hidden_size, hidden_size * 4) + if isinstance(hidden_act, str): + self.intermediate_act_fn = ACT2FN[hidden_act] + else: + self.intermediate_act_fn = hidden_act + + self.dense_2 = nn.Dense(4 * hidden_size, hidden_size) + self.LayerNorm = LayerNorm(hidden_size, eps=1e-12) + self.dropout = nn.Dropout() + + def construct(self, input_tensor): + hidden_states = self.dense_1(input_tensor) + hidden_states = self.intermediate_act_fn(hidden_states) + + hidden_states = self.dense_2(hidden_states) + hidden_states = self.dropout(hidden_states) + hidden_states = self.LayerNorm(hidden_states + input_tensor) + + return hidden_states + +class Layer(nn.Cell): + def __init__(self, hidden_size, max_seq_length, hidden_act): + super(Layer, self).__init__() + self.filterlayer = FilterLayer(hidden_size, max_seq_length) + self.intermediate = Intermediate(hidden_size, hidden_act) + + def construct(self, hidden_states, attention_mask): + hidden_states = self.filterlayer(hidden_states) + intermediate_output = self.intermediate(hidden_states) + return intermediate_output + +class Encoder(nn.Cell): + def __init__(self, hidden_size, max_seq_length, hidden_act, num_hidden_layers): + super(Encoder, self).__init__() + layer = Layer(hidden_size, max_seq_length, hidden_act) + self.layer = nn.CellList([deepcopy(layer) for _ in range(num_hidden_layers)]) + + def construct(self, hidden_states, attention_mask, output_all_encoded_layers=True): + all_encoder_layers = [] + for layer_module in self.layer: + hidden_states = layer_module(hidden_states, attention_mask) + if output_all_encoded_layers: + all_encoder_layers.append(hidden_states) + if not output_all_encoded_layers: + all_encoder_layers.append(hidden_states) + return all_encoder_layers + diff --git a/research/recommend/END4Rec/requirements.txt b/research/recommend/END4Rec/requirements.txt new file mode 100644 index 000000000..96e055a16 --- /dev/null +++ b/research/recommend/END4Rec/requirements.txt @@ -0,0 +1,5 @@ +numpy==1.21.2 +pandas==1.3.3 +scikit-learn==0.24.2 +python==3.7 +mindspore==1.7.0 \ No newline at end of file diff --git a/research/recommend/END4Rec/trainers.py b/research/recommend/END4Rec/trainers.py new file mode 100644 index 000000000..74ed97435 --- /dev/null +++ b/research/recommend/END4Rec/trainers.py @@ -0,0 +1,229 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +import os +import numpy as np +import mindspore as ms +from mindspore import nn, ops, Tensor, Parameter +from mindspore.common.initializer import Normal +from mindspore.train.callback import Callback +from mindspore.dataset import GeneratorDataset +from tqdm import tqdm +import warnings +warnings.filterwarnings('ignore') +from utils import recall_at_k, ndcg_k, get_metric + +class CustomWithLossCell(nn.Cell): + def __init__(self, backbone, loss_fn): + super(CustomWithLossCell, self).__init__() + self.backbone = backbone + self.loss_fn = loss_fn + + def construct(self, input_ids, pos_ids, neg_ids): + out = self.backbone(input_ids) + return self.loss_fn(out, pos_ids, neg_ids) + +class Trainer: + def __init__(self, model, train_dataloader, + eval_dataloader, + test_dataloader, args): + + self.args = args + self.cuda_condition = not self.args.no_cuda and ms.context.get_context('device_target') == 'GPU' + self.device = ms.context.get_context('device_target') + + self.model = model + if self.cuda_condition: + self.model.set_train(True) + + self.train_dataloader = train_dataloader + self.eval_dataloader = eval_dataloader + self.test_dataloader = test_dataloader + + betas = (self.args.adam_beta1, self.args.adam_beta2) + self.optim = nn.Adam(self.model.trainable_params(), learning_rate=self.args.lr, beta1=betas[0], beta2=betas[1], weight_decay=self.args.weight_decay) + + self.net_with_criterion = CustomWithLossCell(self.model, self.cross_entropy) + self.train_one_step = nn.TrainOneStepCell(self.net_with_criterion, self.optim) + + print("Total Parameters:", sum([np.prod(p.shape) for p in self.model.trainable_params()])) + + def train(self, epoch): + self.iteration(epoch, self.train_dataloader) + + def valid(self, epoch): + return self.iteration(epoch, self.eval_dataloader, train=False) + + def test(self, epoch): + return self.iteration(epoch, self.test_dataloader, train=False) + + def iteration(self, epoch, dataloader, train=True): + str_code = "train" if train else "test" + rec_data_iter = tqdm(enumerate(dataloader.create_tuple_iterator()), + desc="Recommendation EP_%s:%d" % (str_code, epoch), + total=dataloader.get_dataset_size(), + bar_format="{l_bar}{r_bar}") + + if train: + self.model.set_train(True) + rec_loss = 0.0 + + for i, (index, input_ids, answer, neg_answer) in rec_data_iter: + input_ids, answer, neg_answer = map(lambda x: Tensor(x, ms.int32), [input_ids, answer, neg_answer]) + loss = self.train_one_step(input_ids, answer, neg_answer) + rec_loss += loss.asnumpy().item() + + post_fix = { + "epoch": epoch, + "rec_loss": '{:.4f}'.format(rec_loss / len(rec_data_iter)), + } + + if (epoch + 1) % self.args.log_freq == 0: + print(str(post_fix)) + + with open(self.args.log_file, 'a') as f: + f.write(str(post_fix) + '\n') + + else: + self.model.set_train(False) + pred_list = None + for i, (index, input_ids, answers, _, sample_negs) in rec_data_iter: + input_ids, answers, sample_negs = map(lambda x: Tensor(x, ms.int32), [input_ids, answers, sample_negs]) + recommend_output = self.model(input_ids) + expand_dims = ops.ExpandDims() + test_neg_items = ops.Concat(-1)((expand_dims(answers, -1), sample_negs)) + recommend_output = recommend_output[:, -1, :] + + test_logits = self.predict_sample(recommend_output, test_neg_items) + test_logits = test_logits.asnumpy().copy() + if i == 0: + pred_list = test_logits + else: + pred_list = np.append(pred_list, test_logits, axis=0) + + return self.get_sample_scores(epoch, pred_list) + + def get_sample_scores(self, epoch, pred_list): + pred_list = (-pred_list).argsort().argsort()[:, 0] + HIT_1, NDCG_1, MRR = get_metric(pred_list, 1) + HIT_5, NDCG_5, MRR = get_metric(pred_list, 5) + HIT_10, NDCG_10, MRR = get_metric(pred_list, 10) + post_fix = { + "Epoch": epoch, + "HIT@1": '{:.4f}'.format(HIT_1), "NDCG@1": '{:.4f}'.format(NDCG_1), + "HIT@5": '{:.4f}'.format(HIT_5), "NDCG@5": '{:.4f}'.format(NDCG_5), + "HIT@10": '{:.4f}'.format(HIT_10), "NDCG@10": '{:.4f}'.format(NDCG_10), + "MRR": '{:.4f}'.format(MRR), + } + print(post_fix) + with open(self.args.log_file, 'a') as f: + f.write(str(post_fix) + '\n') + return [HIT_1, NDCG_1, HIT_5, NDCG_5, HIT_10, NDCG_10, MRR], str(post_fix) + + def save(self, file_name): + ms.save_checkpoint(self.model, file_name) + + def load(self, file_name): + param_dict = ms.load_checkpoint(file_name) + ms.load_param_into_net(self.model, param_dict) + + def cross_entropy(self, seq_out, pos_ids, neg_ids): + pos_emb = self.model.item_embeddings(pos_ids) + neg_emb = self.model.item_embeddings(neg_ids) + + seq_emb = seq_out[:, -1, :] + pos_logits = ops.reduce_sum(pos_emb * seq_emb, -1) + neg_logits = ops.reduce_sum(neg_emb * seq_emb, -1) + + loss = ops.reduce_mean( + - ops.log(self.sigmoid(pos_logits) + 1e-24) - + ops.log(1 - self.sigmoid(neg_logits) + 1e-24) + ) + + return loss + + def sigmoid(self, x): + return 1 / (1 + ops.exp(-x)) + + def predict_sample(self, seq_out, test_neg_sample): + test_item_emb = self.model.item_embeddings(test_neg_sample) + batch_matmul = ops.BatchMatMul() + test_logits = batch_matmul(test_item_emb, seq_out.expand_dims(-1)).squeeze(-1) + return test_logits + + def predict_full(self, seq_out): + test_item_emb = self.model.item_embeddings.weight + rating_pred = ops.matmul(seq_out, test_item_emb.T) + return rating_pred + +class EBMRecTrainer(Trainer): + + def __init__(self, model, + train_dataloader, + eval_dataloader, + test_dataloader, args): + super(EBMRecTrainer, self).__init__( + model, + train_dataloader, + eval_dataloader, + test_dataloader, args + ) + + def iteration(self, epoch, dataloader, train=True): + + str_code = "train" if train else "test" + rec_data_iter = tqdm(enumerate(dataloader.create_tuple_iterator()), + desc="Recommendation EP_%s:%d" % (str_code, epoch), + total=dataloader.get_dataset_size(), + bar_format="{l_bar}{r_bar}") + + if train: + self.model.set_train(True) + rec_loss = 0.0 + + for i, (index, input_ids, answer, neg_answer) in rec_data_iter: + input_ids, answer, neg_answer = map(lambda x: Tensor(x, ms.int32), [input_ids, answer, neg_answer]) + loss = self.train_one_step(input_ids, answer, neg_answer) + rec_loss += loss.asnumpy().item() + + post_fix = { + "epoch": epoch, + "rec_loss": '{:.4f}'.format(rec_loss / len(rec_data_iter)), + } + + if (epoch + 1) % self.args.log_freq == 0: + print(str(post_fix)) + + with open(self.args.log_file, 'a') as f: + f.write(str(post_fix) + '\n') + + else: + self.model.set_train(False) + pred_list = None + for i, (index, input_ids, answers, _, sample_negs) in rec_data_iter: + input_ids, answers, sample_negs = map(lambda x: Tensor(x, ms.int32), [input_ids, answers, sample_negs]) + recommend_output = self.model(input_ids) + expand_dims = ops.ExpandDims() + test_neg_items = ops.Concat(-1)((expand_dims(answers, -1), sample_negs)) + recommend_output = recommend_output[:, -1, :] + + test_logits = self.predict_sample(recommend_output, test_neg_items) + test_logits = test_logits.asnumpy().copy() + if i == 0: + pred_list = test_logits + else: + pred_list = np.append(pred_list, test_logits, axis=0) + + return self.get_sample_scores(epoch, pred_list) \ No newline at end of file diff --git a/research/recommend/END4Rec/utils.py b/research/recommend/END4Rec/utils.py new file mode 100644 index 000000000..8abbba998 --- /dev/null +++ b/research/recommend/END4Rec/utils.py @@ -0,0 +1,163 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + + +import os +import math +import random +import datetime +import numpy as np +from scipy.sparse import csr_matrix + +def get_local_time(): + cur = datetime.datetime.now() + cur = cur.strftime('%b-%d-%Y_%H-%M-%S') + return cur + +class EarlyStopping: + def __init__(self, checkpoint_path, patience=10, verbose=False, delta=0): + self.checkpoint_path = checkpoint_path + self.patience = patience + self.verbose = verbose + self.counter = 0 + self.best_score = None + self.early_stop = False + self.delta = delta + + def compare(self, score): + for i in range(len(score)): + if score[i] > self.best_score[i]+self.delta: + return False + return True + + def __call__(self, score, model): + # score HIT@10 NDCG@10 + if self.best_score is None: + self.best_score = score + self.score_min = np.array([0]*len(score)) + elif self.compare(score): + self.counter += 1 + print(f'EarlyStopping counter: {self.counter} out of {self.patience}') + if self.counter >= self.patience: + self.early_stop = True + else: + self.best_score = score + self.counter = 0 + + + +def generate_rating_matrix_valid(user_seq, num_users, num_items): + + row = [] + col = [] + data = [] + for user_id, item_list in enumerate(user_seq): + for item in item_list[:-2]: # + row.append(user_id) + col.append(item) + data.append(1) + + row = np.array(row) + col = np.array(col) + data = np.array(data) + rating_matrix = csr_matrix((data, (row, col)), shape=(num_users, num_items)) + + return rating_matrix + +def generate_rating_matrix_test(user_seq, num_users, num_items): + row = [] + col = [] + data = [] + for user_id, item_list in enumerate(user_seq): + for item in item_list[:-1]: # + row.append(user_id) + col.append(item) + data.append(1) + + row = np.array(row) + col = np.array(col) + data = np.array(data) + rating_matrix = csr_matrix((data, (row, col)), shape=(num_users, num_items)) + + return rating_matrix + +def get_rating_matrix(data_name, seq_dic, max_item): + num_items = max_item + 1 + valid_rating_matrix = generate_rating_matrix_valid(seq_dic['user_seq'], seq_dic['num_users'], num_items) + test_rating_matrix = generate_rating_matrix_test(seq_dic['user_seq'], seq_dic['num_users'], num_items) + + return valid_rating_matrix, test_rating_matrix + +def get_user_seqs_and_max_item(data_file): + lines = open(data_file).readlines() + lines = lines[1:] + user_seq = [] + item_set = set() + for line in lines: + user, items = line.strip().split(' ', 1) + items = items.split() + items = [int(item) for item in items] + user_seq.append(items) + item_set = item_set | set(items) + max_item = max(item_set) + return user_seq, max_item + + + +def get_metric(pred_list, topk=10): + NDCG = 0.0 + HIT = 0.0 + MRR = 0.0 + # [batch] the answer's rank + for rank in pred_list: + MRR += 1.0 / (rank + 1.0) + if rank < topk: + NDCG += 1.0 / np.log2(rank + 2.0) + HIT += 1.0 + return HIT /len(pred_list), NDCG /len(pred_list), MRR /len(pred_list) + +def recall_at_k(actual, predicted, topk): + sum_recall = 0.0 + num_users = len(predicted) + true_users = 0 + for i in range(num_users): + act_set = set([actual[i]]) + pred_set = set(predicted[i][:topk]) + if len(act_set) != 0: + sum_recall += len(act_set & pred_set) / float(len(act_set)) + true_users += 1 + return sum_recall / true_users + +def ndcg_k(actual, predicted, topk): + res = 0 + for user_id in range(len(actual)): + k = min(topk, len([actual[user_id]])) + idcg = idcg_k(k) + dcg_k = sum([int(predicted[user_id][j] in + set([actual[user_id]])) / math.log(j+2, 2) for j in range(topk)]) + res += dcg_k / idcg + return res / float(len(actual)) + + +def idcg_k(k): + res = sum([1.0/math.log(i+2, 2) for i in range(k)]) + if not res: + return 1.0 + else: + return res + + + + -- Gitee