class_docstr: KGNN-LS is a knowledge-based recommendation model.
  KGNN-LS transforms the knowledge graph into a user-specific weighted graph and then apply a graph neural network to
  compute personalized item embeddings. To provide better inductive bias, KGNN-LS relies on label smoothness
  assumption, which posits that adjacent items in the knowledge graph are likely to have similar user relevance
  labels/scores. Label smoothness provides regularization over the edge weights and it is equivalent  to a label
  propagation scheme on a graph.
docstr: Predict the label of items by label smoothness.
  
  Args:
      user_embeddings(torch.FloatTensor): The embeddings of users, shape: [batch_size*2, embedding_size],
      user(torch.FloatTensor): the index of users, shape: [batch_size*2]
      entities(list): entities is a list of i-iter (i = 0, 1, ..., n_iter) neighbors for the batch of items.
                      dimensions of entities: {[batch_size*2, 1],
                      [batch_size*2, n_neighbor],
                      [batch_size*2, n_neighbor^2],
                      ...,
                      [batch_size*2, n_neighbor^n_iter]}
      relations(list): relations is a list of i-iter (i = 0, 1, ..., n_iter) corresponding relations for entities.
                       relations have the same shape as entities.
  
  Returns:
      predicted_labels(torch.FloatTensor): The predicted label of items, shape: [batch_size*2]
docstr_tok: ["Predict","the","label","of","items","by","label","smoothness",".","Args",":","user_embeddings","(","torch.FloatTensor",")",":","The","embeddings","of","users",",","shape",":","[","batch_size","*","2",",","embedding_size","]",",","user","(","torch.FloatTensor",")",":","the","index","of","users",",","shape",":","[","batch_size","*","2","]","entities","(","list",")",":","entities","is","a","list","of","i-iter","(","i","=","0",",","1",",","...",",","n_iter",")","neighbors","for","the","batch","of","items",".","dimensions","of","entities",":","{","[","batch_size","*","2",",","1","]",",","[","batch_size","*","2",",","n_neighbor","]",",","[","batch_size","*","2",",","n_neighbor^2","]",",","...",",","[","batch_size","*","2",",","n_neighbor^n_iter","]","}","relations","(","list",")",":","relations","is","a","list","of","i-iter","(","i","=","0",",","1",",","...",",","n_iter",")","corresponding","relations","for","entities",".","relations","have","the","same","shape","as","entities",".","Returns",":","predicted_labels","(","torch.FloatTensor",")",":","The","predicted","label","of","items",",","shape",":","[","batch_size","*","2","]"]
code: def label_smoothness_predict(
      self, user_embeddings, user, entities, relations
  ):
      r"""Predict the label of items by label smoothness.
  
      Args:
          user_embeddings(torch.FloatTensor): The embeddings of users, shape: [batch_size*2, embedding_size],
          user(torch.FloatTensor): the index of users, shape: [batch_size*2]
          entities(list): entities is a list of i-iter (i = 0, 1, ..., n_iter) neighbors for the batch of items.
                          dimensions of entities: {[batch_size*2, 1],
                          [batch_size*2, n_neighbor],
                          [batch_size*2, n_neighbor^2],
                          ...,
                          [batch_size*2, n_neighbor^n_iter]}
          relations(list): relations is a list of i-iter (i = 0, 1, ..., n_iter) corresponding relations for entities.
                           relations have the same shape as entities.
  
      Returns:
          predicted_labels(torch.FloatTensor): The predicted label of items, shape: [batch_size*2]
      """
      # calculate initial labels; calculate updating masks for label propagation
      entity_labels = []
      # True means the label of this item is reset to initial value during label propagation
      reset_masks = []
      holdout_item_for_user = None
  
      for entities_per_iter in entities:
          users = torch.unsqueeze(user, dim=1)  # [batch_size, 1]
          user_entity_concat = (
              users * self.offset + entities_per_iter
          )  # [batch_size, n_neighbor^i]
  
          # the first one in entities is the items to be held out
          if holdout_item_for_user is None:
              holdout_item_for_user = user_entity_concat
  
          def lookup_interaction_table(x, _):
              x = int(x)
              label = self.interaction_table.setdefault(x, 0.5)
              return label
  
          initial_label = user_entity_concat.clone().cpu().double()
          initial_label.map_(initial_label, lookup_interaction_table)
          initial_label = initial_label.float().to(self.device)
  
          # False if the item is held out
          holdout_mask = (
              holdout_item_for_user - user_entity_concat
          ).bool()
          # True if the entity is a labeled item
          reset_mask = (initial_label - 0.5).bool()
          reset_mask = torch.logical_and(
              reset_mask, holdout_mask
          )  # remove held-out items
          initial_label = (
              holdout_mask.float() * initial_label
              + torch.logical_not(holdout_mask).float() * 0.5
          )  # label initialization
  
          reset_masks.append(reset_mask)
          entity_labels.append(initial_label)
      # we do not need the reset_mask for the last iteration
      reset_masks = reset_masks[:-1]
  
      # label propagation
      relation_vectors = [self.relation_embedding(i) for i in relations]
      for i in range(self.n_iter):
          entity_labels_next_iter = []
          for hop in range(self.n_iter - i):
              masks = reset_masks[hop]
              self_labels = entity_labels[hop]
              neighbor_labels = entity_labels[hop + 1].reshape(
                  self.batch_size, -1, self.neighbor_sample_size
              )
              neighbor_relations = relation_vectors[hop].reshape(
                  self.batch_size,
                  -1,
                  self.neighbor_sample_size,
                  self.embedding_size,
              )
  
              # mix_neighbor_labels
              user_embeddings = user_embeddings.reshape(
                  self.batch_size, 1, 1, self.embedding_size
              )  # [batch_size, 1, 1, dim]
              user_relation_scores = torch.mean(
                  user_embeddings * neighbor_relations, dim=-1
              )  # [batch_size, -1, n_neighbor]
              user_relation_scores_normalized = self.softmax(
                  user_relation_scores
              )  # [batch_size, -1, n_neighbor]
  
              neighbors_aggregated_label = torch.mean(
                  user_relation_scores_normalized * neighbor_labels,
                  dim=2,
              )  # [batch_size, -1, dim] # [batch_size, -1]
              output = (
                  masks.float() * self_labels
                  + torch.logical_not(masks).float()
                  * neighbors_aggregated_label
              )
  
              entity_labels_next_iter.append(output)
          entity_labels = entity_labels_next_iter
  
      predicted_labels = entity_labels[0].squeeze(-1)
      return predicted_labels
  
imports: import random
  import numpy
  import torch
  import torch.nn
  from recbole.model.abstract_recommender import KnowledgeRecommender
  from recbole.model.init import xavier_normal_initialization
  from recbole.model.loss import EmbLoss
  from recbole.utils import InputType
label_desc: Use image node_id 7 for calling the KGNNLS obj's underlying member method code with example usage: obj.label_smoothness_predict(user_embeddings, user, entities, relations) and returns: predicted_labels, label