void ItemSimilarityRecommender::finish()

in mlmodel/src/transforms/ItemSimilarityRecommender.cpp [124:323]


  void ItemSimilarityRecommender::finish() {
    
    // Are we using string items?
    bool string_items = (m_isr_data->string_id_values.size() != 0);
    
    // Deal with the input items column.
    {
      Specification::FeatureDescription* fd = new Specification::FeatureDescription;
      std::string name = m_isr_data->item_data_input_column;
      if(name.empty()) {
        name = "items";
      }
      
      fd->set_name(m_isr_data->item_data_input_column);
      fd->set_shortdescription("The list of items used to generate the recommendations. ");
      
      Specification::FeatureType* type = new Specification::FeatureType;
      
      if(use_dictionary_input) {
        if(string_items) {
          type->mutable_dictionarytype()->mutable_stringkeytype();
        } else {
          type->mutable_dictionarytype()->mutable_int64keytype();
        }
      } else {
        if(string_items) {
          type->mutable_sequencetype()->mutable_stringtype();
        } else {
          type->mutable_sequencetype()->mutable_int64type();
        }
      }
      
      fd->set_allocated_type(type);
      m_spec->mutable_description()->mutable_input()->AddAllocated(fd);
      m_spec->mutable_itemsimilarityrecommender()->set_iteminputfeaturename(
                                                                            m_isr_data->item_data_input_column);
    }
    
    // Deal with the number of recommendations as input
    {
      std::string name = m_isr_data->num_recommendations_input_column;
      if(name.empty()) {
        name = "k";
      }

      if(!name.empty()) {
        Specification::FeatureDescription* fd = new Specification::FeatureDescription;
        fd->set_name(name);
        fd->set_shortdescription("The number of items to return on a recommendation.");
        
        Specification::FeatureType* type = new Specification::FeatureType;
        
        type->mutable_int64type();
        
        fd->set_allocated_type(type);
        m_spec->mutable_description()->mutable_input()->AddAllocated(fd);
        m_spec->mutable_itemsimilarityrecommender()->set_numrecommendationsinputfeaturename(name);
      }
    }
    
    // Item restriction list
    {
      const std::string& name = m_isr_data->item_restriction_input_column;
      if(!name.empty()) {
        Specification::FeatureDescription* fd = new Specification::FeatureDescription;
        fd->set_name(name);
        fd->set_shortdescription("A sequence of items from which to generate recommendations.");
        
        Specification::FeatureType* type = new Specification::FeatureType;
        
        if(string_items) {
          type->mutable_sequencetype()->mutable_stringtype();
        } else {
          type->mutable_sequencetype()->mutable_int64type();
        }
        
        type->set_isoptional(true);

        fd->set_allocated_type(type);

        m_spec->mutable_description()->mutable_input()->AddAllocated(fd);
        m_spec->mutable_itemsimilarityrecommender()->set_itemrestrictioninputfeaturename(name);
      }
    }
    
    // Item exclusion list
    {
      const std::string& name = m_isr_data->item_exclusion_input_column;
      if(!name.empty()) {
        Specification::FeatureDescription* fd = new Specification::FeatureDescription;
        fd->set_name(name);
        fd->set_shortdescription("A sequence of items to exclude from recommendations.  Defaults to the input item list if not given.");
        
        Specification::FeatureType* type = new Specification::FeatureType;
        
        if(string_items) {
          type->mutable_sequencetype()->mutable_stringtype();
        } else {
          type->mutable_sequencetype()->mutable_int64type();
        }
        type->set_isoptional(true);

        fd->set_allocated_type(type);
        m_spec->mutable_description()->mutable_input()->AddAllocated(fd);
        m_spec->mutable_itemsimilarityrecommender()->set_itemexclusioninputfeaturename(name);
      }
    }
    
    // Sequence of recommended items
    {
      std::string name = m_isr_data->item_list_output_column;
      
      if(name.empty()) {
        name = "recommendations";
      }
      
      auto* output = m_spec->mutable_description()->mutable_output();
      
      Specification::FeatureDescription* fd = new Specification::FeatureDescription;
      fd->set_name(name);
      fd->set_shortdescription("The recommended items in order from most relevant to least relevant.");
      
      Specification::FeatureType* outputType = new Specification::FeatureType;
      if(string_items) {
        outputType->mutable_sequencetype()->mutable_stringtype();
      } else {
        outputType->mutable_sequencetype()->mutable_int64type();
      }
      m_spec->mutable_itemsimilarityrecommender()->set_recommendeditemlistoutputfeaturename(name);
      
      fd->set_allocated_type(outputType);
      output->AddAllocated(fd);
    }
    
    {
      const std::string& name = m_isr_data->item_score_output_column;
      
      if(!name.empty()) {
        auto* output = m_spec->mutable_description()->mutable_output();
        
        Specification::FeatureDescription* fd = new Specification::FeatureDescription;
        
        fd->set_name(name);
        fd->set_shortdescription("The scores for the recommended items, given as a "
                                 "dictionary of items and the corresponding scores.");
        
        Specification::FeatureType* outputType = new Specification::FeatureType;
        if(string_items) {
          outputType->mutable_dictionarytype()->mutable_stringkeytype();
        } else {
          outputType->mutable_dictionarytype()->mutable_int64keytype();
        }
        
        m_spec->mutable_itemsimilarityrecommender()->set_recommendeditemscoreoutputfeaturename(name);
        
        fd->set_allocated_type(outputType);
        output->AddAllocated(fd);
      }
    }
    
    // Dump all this into the protobuf spec.
    for(const auto& item_p : m_isr_data->item_interactions) {
      auto* interactions = m_isr->add_itemitemsimilarities();
      
      uint64_t item = item_p.first;
      
      interactions->set_itemid(item);
      if(m_isr_data->item_shift_values.count(item)) {
        interactions->set_itemscoreadjustment(m_isr_data->item_shift_values[item]);
      } else {
        interactions->set_itemscoreadjustment(0);
      }
      
      auto* item_list = interactions->mutable_similaritemlist();
      item_list->Clear();
      
      for(const auto& inter_p : item_p.second) {
        auto* item_inter = item_list->Add();
        item_inter->set_itemid(inter_p.first);
        item_inter->set_similarityscore(inter_p.second);
      }
    }
    
    if(!m_isr_data->integer_id_values.empty()) {
      auto* integer_vector = m_isr->mutable_itemint64ids()->mutable_vector();
      
      for(int64_t item_id : m_isr_data->integer_id_values) {
        integer_vector->Add(item_id);
      }
    } else if(!m_isr_data->string_id_values.empty()) {
      auto* string_vector = m_isr->mutable_itemstringids()->mutable_vector();
      
      for(std::string item_id : m_isr_data->string_id_values) {
        string_vector->Add(std::move(item_id));
      }
    }
    
    // Finally, construct and validate the model from the generated spec.
    Recommender::constructAndValidateItemSimilarityRecommenderFromSpec(*m_spec);
  }