How to optimise nn.Embedding in backpropagation?

yuanqi_chau: <p>Hi, I am writing a PyTorch program on cross-domain recommendations.<br>
I would like to summarise my model as<br>
input: users and items interacted, retrieve embeddings, pass it through the model, and get the output.</p>
<pre><code class="lang-auto">#Initialisation 
self.U = nn.Embedding(self.nUser, self.edim_u)
</code></pre>
<pre><code class="lang-auto">self.param = [self.U + other params]
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(self.params, lr=self.learning_rate)

</code></pre>
<p>And this is the error message<br>
“optimizer can only optimize Tensors, but one of the params is torch.nn.modules.sparse.Embedding”.</p>
<p>Help please…</p>

albanD: <p>Hi,</p>
<p>You need to give your Module’s parameters to the optimizer, not the Module itself. In particular you can use <code>self.U.parameters()</code> here.<br>
Or if <code>self</code> is already a Module itself, <code>self.parameters()</code>.</p>

yuanqi_chau: <p>Hi alban,</p>
<p>self is not a module in my case, I have tried using self.U.parameters() and the error is now<br>
“optimizer can only optimize Tensors, but one of the params is Module.parameters”<br>
Do you have any idea why is this so?</p>
<p>I was trying to write a customisable program so I didn’t inherit nn.Module, thank you!</p>

albanD: <p>Hi,</p>
<p><code>Module.parameters()</code> is a function that you need to call to get the parameters <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

yuanqi_chau: <p>Yes, I have called the function self.U.parameters() but it still has this error:<br>
“optimizer can only optimize Tensors, but one of the params is Module.parameters”</p>
<p>Can you explain more please?</p>

albanD: <p>Can you share the full error message please? Because <code>Module.parameters</code> is a function <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

pascal_notsawo: <p>Here is a little piece of code that works without any problem for me.</p>
<pre><code class="lang-auto">import torch
from torch import nn
class Model(nn.Module) :
    def __init__(self, nUser, edim_u):
        super(Model, self).__init__()
        self.U = nn.Embedding(nUser, edim_u)
        #criterion = nn.CrossEntropyLoss()
        #optimizer = torch.optim.SGD(self.parameters(), lr = 3e-4)
        
model = Model(2, 1)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 3e-4)
</code></pre>

yuanqi_chau: <p>I think the problem I am having is not inheriting nn.Module in my class. Therefore, the method .parameters() is not available to me.</p>
<p>Is there any other way that I could change nn.Embedding into something that the optimizer can understand? So that I can add it into the parameter list manually?</p>
<p>Thank you</p>

yuanqi_chau: <p>Hello, that’s the only error message I got.<br>
so basically instead of using model.parameters(), I send it my own parameter list, parameter = [] into the optimizer.<br>
I tried adding self.U.parameters() into the list and optimize it, the error was “optimizer can only optimize Tensors, but one of the params is Module.parameters”…</p>

pascal_notsawo: <p>It seems that I have found the cause of your problem.<br>
self.U.parameters() is not a parameter, but a list of parameters (see comments below).</p>
<pre><code class="lang-auto">import torch
from torch import nn
from torch.autograd import Variable

class Model(nn.Module) :
    def __init__(self, nUser, edim_u, lr = 3e-4):
        super(Model, self).__init__()
        self.U = nn.Embedding(nUser, edim_u)
        self.other_parameters = Variable(torch.zeros(nUser, edim_u))
        self.lr = lr
        
        # This will generate an error ([1]) because self.U.parameters() is not a parameter.
        #self.params = [self.U.parameters(), self.other_parameters]
        
        # To correct the problem.
        self.params = [*self.U.parameters(), self.other_parameters] # = list(self.U.parameters()) + [self.other_parameters]

        # Then  
        optimizer = torch.optim.SGD(self.params, lr = self.lr)
        
model = Model(2, 1)

# [1] TypeError: optimizer can only optimize Tensors, but one of the params is Module.parameters
</code></pre>
<p>I advise you to take a look at the <a href="https://pytorch.org/docs/stable/optim.html" rel="noopener nofollow ugc">documentation</a>.<br>
For example, it is requested in the documentation that the parameters should be Variables (see section Constructing it)</p>

yuanqi_chau: <p>Hi brother, this actually works but I have one question.<br>
What does the * in *self.U.parameters() mean?<br>
I really appreciate your help!</p>

pascal_notsawo: <p>Let’s say * is the unpacking operator.</p>
<pre><code class="lang-auto">*[a, b, c] = a, b, c
Then [*[a, b, c], d] = [a, b, c, d] # = [a, b, c] + [d]
</code></pre>
<p>Also, a function f can be called up in this way:<br>
<code>result = f(p1, p2), you can make result = f(*[p1, p2])</code></p>
<p>Also,<br>
<code>x, *y = 1, 2, 3 implique x=1 et y = [2, 3]</code><br>
<a href="https://stackoverflow.com/questions/57814195/what-does-for-x-y-in-list-mean-in-python" rel="noopener nofollow ugc">stackoverflow</a></p>

yuanqi_chau: <p>I see, thank you very much for the help!</p>