如何在mxnet gluon中使用预训练的embedding
我们复现别人的论文的时候,往往发现nlp任务中大量使用预训练的word2vec作为word embedding的初始权值,如何对gluon.nn.Embedding()进行初始化也就成为了一个小问题。
gluon中没有像tensorflow中专门为embedding层设计了一个传参的方法,也就是说我们需要调用 mx.init 方法来对Embedding层进行初始化。
总体来说,一共有两种方法来实现使用预训练的word2vec进行初始化。
1.自定义init方法
#定义init方法
class MyInit(init.Initializer):
def __init__(self):
super(MyInit, self).__init__()
self._verbose = True
def _init_weight(self, _, arr):
#word2vec是你初始化的embedding矩阵
nd.array(word2vec)
注意到你的实现的init方法仅仅可以对embedding层进行初始化,如果直接在net.initialize()中使用该方法会引起其余层的出错。
#定义网络
def get_net():
net = nn.Sequential()
with net.name_scope():
net.add(nn.Embedding(3000,400)
net.add(nn.Dense(2))
return net
#找到embedding层的权重名称
params = net.collect_params()
print(params)
#发现名称为sequential0_embedding0_weight,这一项一般不会改便
#对该参数使用改写的init方法进行初始化
params['sequential0_embedding0_weight'].initialize(MyInit())
2.暴力使用set_data
方法进行参数改写
w = net[0].weight
w.set_data(nd.array(word2vec))
其实理论上来说使用mx.init.Load()可以完美解决这个问题,但是不知道用的时候为啥老是报错,总之两种方法都有点危险,尤其是第二种,coding的时候最好检查以下究竟是不是真正的初始化为了想要的矩阵。
Reference
1.gluon文档
初始化模型参数 - 动手学深度学习 0.6 documentation
2.如何使用gensim训练word2vec
3.如何把训练得到的word2vec变成一个Emedding矩阵
https://github.com/MarkWuNLP/MultiTurnResponseSelection/blob/master/src/PreProcess.py
第78-98行
注:gensim处理的时候高频和低频词都会删去,没有对应的word2vec,应该是这样的
希望mxnet发展越来越好哦~
import gensim.downloader as api
model = api.load('glove-wiki-gigaword-100')
emb = np.zeros((13516+5,100))
count = 1
no_foung = 0
for line in sword2wid:
try:
emb[int(sword2wid[line])] = model[line]
except:
no_foung = no_foung + 1
print(line)
count = count + 1
print(no_foung)
np.savetxt('glove.txt',emb)