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);
}