<p>The fundamental difficulty when it comes to adding new users in your system is that you need retraining to be able to give meaningful predictions to new users. Even if you were able to dynamically resize the embedding matrices, what values would you use for the parameters describing the new user?</p>

<p>Taking this into account, you have a couple of options.</p>

<ol>
<li>Save the weights of the graph, then create a new graph with adjusted dimensions and retrain it on data that includes information on the new user. As you say, this may be too costly to be in your critical path.</li>
<li>Use some sort of fold-in approach. For example, you could initialise the new user's embedding using the average of embeddings of users that have interacted with similar items.</li>
<li>Use a model that doesn't have this problem and that can incorporate new users in a more natural manner.</li>
</ol>

<p>My recommendation would be the third option. There are classes of models that take the sequence (or set) of user interactions directly when making predictions, and do not rely on you declaring the number of users ahead of time. For example, you could use on of the following:</p>

<ol>
<li>The <a href="https://pdfs.semanticscholar.org/6c02/053805434162e0fed26e1d5e035eb1071249.pdf" rel="nofollow noreferrer">AutoRec</a> model: a simple autoencoder model that takes the set of items the user has interacted with as the input.</li>
<li><a href="https://arxiv.org/pdf/1511.06939.pdf" rel="nofollow noreferrer">Session-based Recommendations with Recurrent Neural Networks</a>: a recurrent model that takes as input the sequence of user interactions at prediction time.</li>
</ol>

<p>Both models naturally handle new users without changes to the computation graph; adding new items will require re-training.</p>

<p>One implementation for the first class of models is <a href="https://github.com/mesuvash/NNRec" rel="nofollow noreferrer">here</a>; for the second class, check out my recommender system package <a href="https://maciejkula.github.io/spotlight/sequence/implicit.html" rel="nofollow noreferrer">Spotlight</a>.</p>
Changing size of embedding TensorFlow (e.g. creating a new user in Recommendation Engine)
<p>I have a TensorFlow recommendation system based off <a href="https://github.com/songgc/TF-recomm" rel="nofollow noreferrer"><code>TF-recomm</code></a>. Each user has <code>1+numFactors</code> numbers associated with her: a vector of <code>numFactors</code>, and an offset of a single number. Each task also has a bias and a vector of <code>numFactors</code> assigned. The TF-recomm code is</p>

<pre><code>def inference_svd(user_batch, item_batch, user_num, item_num, dim=5):
    bias_global = tf.get_variable("bias_global", shape=[])
    w_bias_user = tf.get_variable("embd_bias_user", shape=[user_num])
    w_bias_item = tf.get_variable("embd_bias_item", shape=[item_num])
    bias_user = tf.nn.embedding_lookup(w_bias_user, user_batch, name="bias_user")
    bias_item = tf.nn.embedding_lookup(w_bias_item, item_batch, name="bias_item")
    w_user = tf.get_variable("embd_user", shape=[user_num, dim], initializer=tf.truncated_normal_initializer(stddev=0.02))
    w_item = tf.get_variable("embd_item", shape=[item_num, dim], initializer=tf.truncated_normal_initializer(stddev=0.02))
    embd_user = tf.nn.embedding_lookup(w_user, user_batch, name="embedding_user")
    embd_item = tf.nn.embedding_lookup(w_item, item_batch, name="embedding_item")
    infer = tf.reduce_sum(tf.multiply(embd_user, embd_item), 1)
    infer = tf.add(infer, bias_global)
    infer = tf.add(infer, bias_user)
    infer = tf.add(infer, bias_item, name="svd_inference")
    regularizer = tf.add(tf.nn.l2_loss(embd_user), tf.nn.l2_loss(embd_item), name="svd_regularizer")
    return infer, regularizer
</code></pre>

<p>I have been able to get this code to work, and have been able to link it up with a REST-API. </p>

<p>The problem that I encounter is when I get new users. I know what I want to do:</p>

<ul>
<li>Add a row to the <code>bias_user</code>, initialized to 0</li>
<li>Add a row to the <code>embd_user</code>, initialized to 0</li>
<li>When users rate new items, we use the same graph but <code>freeze</code> the weights on the items (which I can do with <code>var_list</code> on <code>optimizer.minimize</code>)</li>
</ul>

<p>However, the weights and biases have their shapes declared ahead of time. All the material I have seen on tensorflow (running or deploying) allows the weights to change, but doesn't seem to allow the network to grow.</p>

<p>If I implemented this in <code>numpy</code> I would simply add new rows to the appropriate matrices. There are a couple of ways of doing this, such as creating new graphs and variables, but it seems best to reuse the graph used to train the model in the first place (to ensure consistency). </p>

<p>I am looking for a system of "best practices" for dealing with changing the size of embedding tensors, especially for a system that is online where it will have to serve predictions quickly (which prevents expensive operations).</p>