Can we use pre-trained word embeddings for weight initialization in nn.Embedding?

wasiahmad: <p>I want to use pre-trained word embeddings as initial weight vectors for embedding layer in a encoder model? How can I achieve this? For example, in Keras, we can pass a weight matrix as parameter to the embedding layer. Is there any similar way in PyTorch to do this?</p>

ruotianluo: <p>you can just assign the weight to the embedding layer. Like:</p>
<pre><code>embed = nn.Embedding(num_embeddings, embedding_dim)
# pretrained_weight is a numpy matrix of shape (num_embeddings, embedding_dim)
embed.weight.data.copy_(torch.from_numpy(pretrained_weight))</code></pre>

ShawnGuo: <p>I usually use the following way, which is better?</p>
<pre><code class="lang-auto">#embeddings is a torch tensor.
embedding = nn.Embedding(embeddings.size(0), embeddings.size(1))
embedding.weight = nn.Parameter(embeddings)
</code></pre>

apaszke: <p>I’d say they’re both ok.</p>

xinyadu: <p>And how can we keep the embedding matrix fixed during training? I didn’t find that in the doc.</p>

cyyyyc123: <p>For <a class="mention" href="/u/ruotianluo">@ruotianluo</a>’s answer, you can try</p>
<pre><code class="lang-auto">embed.weight.requires_grad = False
</code></pre>
<p>to freeze the parameter of it.</p>

xinyadu: <p>But when I initialize optimizer, i got “ValueError: optimizing a parameter that doesn’t require gradients”</p>

xwgeng: <p>You can use <code>filter</code> to remove the parameters that doesn’t require gradients</p>
<blockquote>
<p>parameters = filter(lambda p: p.requires_grad, net.parameters())</p>
</blockquote>

Navneet_M_Kumar: <p>How can we specifically use glove vectors and mainly in the encoder - decoder model ? Not able to understand.</p>

tushargupta14: <p><a class="mention" href="/u/navneet_m_kumar">@Navneet_M_Kumar</a> try intialising the vectors which you need. More, specifically create a corpus vocabulary and retrieve your pre-trained embeddings to a numpy matrix mapped with an id. This matrix can be passed on to the nn.Embedding layer mentioned above.</p>

sritvik: <p>What if I want to use sentence embedding as a whole and not word vectors. Suppose I have the sentence embeddings ready, do I create a (number of sentences X sentence embedding dimension) matrix and map it to each sentence id? And pass this matrix to the embedding layer and call the sentence ids in the forward function?</p>
<p>Is this approach right? I’m trying to perform a type of sentence classification.</p>

mfa: <p>Regarding the use of pre-trained word embeddings, the indexes of words that are passed to the Embedding layer should be equivalent to their index in the pre-trained embedding (the numpy matrix), right?</p>

shirdu: <p>I know I’m missing something.<br>
embed = nn.Embedding(num_embeddings, embedding_dim) # this creates a layer<br>
embed.weight.data.copy_(torch.from_numpy(pretrained_weight)) # this provides the values</p>
<p>I don’t understand how the last operation inserts a dict from which you can, given a word, retrieve its vector. It seems like we provide a matrix with out what each vector is mapped to. Is this the case or that this matrix’s first column is of the word the following raw vector belongs to (or alternatively, columns)?<br>
How does it know the mappings?</p>

colesbury: <p>Yes, it’s a matrix. Each row is the embedding for a word. You’ll also want a dictionary: mapping of words (strings) to integers 0, 1, …, N</p>

shirdu: <p>Thanks for replying colesbury! <img src="//discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=5" title=":slight_smile:" class="emoji" alt=":slight_smile:"><br>
That makes a lot of sense now, so the layer would know that row number 0 is associated with the word that is mapped to 0. Now the puzzle is solved.<br>
How do I let the embedding know about the dict?<br>
I wasn’t sure what is the code for that?</p>

shirdu: <p>I’ve created this:<br>
def loadEmbd():<br>
upload a glove embedding dict file to generate the input output.<br>
glovefname = '…/glove/glove.6B.50d.txt’<br>
gmat = []<br>
gdict2 = OrderedDict()<br>
for h, line in enumerate(open(glovefname, ‘r’).readlines()):<br>
line = line.strip()<br>
line = line.split()<br>
word = line[0]<br>
gdict2[word] = h<br>
vector = [float(item) for item in line[1:]]<br>
gmat.append(vector)<br>
return gmat, gdict2</p>
<p>And after constructing the model with the embedding mat (gmat)<br>
I tried to load the dict with:<br>
model.load_state_dict(gdict2)</p>
<p>but it said:<br>
KeyError: ‘unexpected key “the” in state_dict’</p>

tushargupta14: <p>Yes, the indexes of the words in your vocabulary should be same as your indexes in your embedding numpy matrix. This helps the embedding layer to map the word tokens to vectors.</p>

austin: <p>I wrote up a simple working code example for loading glove vectors while working on a related project. Notebook is <a href="https://github.com/A-Jacobson/CNN_Sentence_Classification/blob/master/WordVectors.ipynb" rel="nofollow noopener">here</a>. It’s living in my project repo at the moment but I would be happy to split it off if people find it helpful.</p>

sidedishes: <p>Sorry for the bump - what might be the easiest way to have only parts of the embedding matrix frozen? For example, if I wanted to use pre-trained embeddings but for certain words assign a special custom token whose embedding I want to train?</p>

jlquinn: <p>Two ways I’d see doing it:</p>
<p>First to have two separate embeddings.  One embedding learns, the other uses pre-trained weights.  Select the embedding to use depending on the value of the input.</p>
<p>The other approach would be to overwrite the pretrained parts of the embedding at the beginning of each batch to undo the results of the previous optimizer step.</p>