tensorflow / tensorflow/recommenders

[Question] can `Scann` be used inside the model during training?

Open
#538 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
2k
Forks
300
PR merge metrics
No merged PRs in 30d

Description

I have the following model using sequences to predict the next item:

class Model(tfrs.models.Model):
    def __init__(self):
        super().__init__()

        self.query_model = tf.keras.Sequential([
            QueryModel(),
            tf.keras.layers.Dense(64),
            L2NormalizationLayer(axis=1)

        ])
        
        self.candidate_model = tf.keras.Sequential([
            CandidateModel(),
            tf.keras.layers.Dense(64),
            L2NormalizationLayer(axis=1)
        ])
        
        scann = tfrs.layers.factorized_top_k.ScaNN(num_reordering_candidates=100)
        scann.index_from_dataset(
            candidates_ds.map(
                lambda x: (x['id'], self.candidate_model({ 'url': x['url'] }))
            )
        )
        
        self.task = tfrs.tasks.Retrieval(
            # Normal approach commented out, using the candidate model to map over a dataset of unique candidates.
             metrics=tfrs.metrics.FactorizedTopK(
                  # candidates=candidates_ds.map( lambda x: (x['id'], self.candidate_model({ 'url': x['url'] })))
                  # Instead we use the SCANN layer
                  candidates=scann
            )
            remove_accidental_hits=True
        )
        
    def call(self, features):
        candidate_embeddings = self.candidate_model({
            'url': features['url'],
        })

        query_embeddings = self.query_model({
            'advertiser_name': features['advertiser_name']        
        })
                
        return (
            query_embeddings,
            candidate_embeddings,
        )
    
    def compute_loss(self, features, training=False):
        query_embeddings, candidate_embeddings = self(features)

        return self.task(
            query_embeddings, 
            candidate_embeddings,
            candidate_ids=features['id'],
            compute_metrics=not training
        )

This runs fine and much quicker! The evaluation step sees 100x speed ups!

However this model does not improve on the metric, my first thought it that the model is not updating the embeddings each epoch as they are run only once. However, in the normal approach we also pass a dataset of already mapped candidate embeddings...

At which point in the training does the model update the embeddings it is learning to use for new evaluation runs?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the ScaNN setup in the model constructor, the candidate_model calls, and compute_loss with compute_metrics. Check when FactorizedTopK and ScaNN receive candidate embeddings during training versus evaluation. Done means documenting whether the index is refreshed and why the metric differs from the normal mapped-dataset approach.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, tensorflow
Domain
machine-learning
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.