【问题标题】:Wor2vec fine-tuningWor2vec 微调
【发布时间】:2019-10-03 14:04:22
【问题描述】:

我需要微调我的 word2vec 模型。我有两个数据集,data1data2

到目前为止我所做的是:

model = gensim.models.Word2Vec(
        data1,
        size=size_v,
        window=size_w,
        min_count=min_c,
        workers=work)
model.train(data1, total_examples=len(data1), epochs=epochs)

model.train(data2, total_examples=len(data2), epochs=epochs)

这是正确的吗?我需要在某处存储学习到的权重吗?

我检查了this answerthis one,但我无法理解它是如何完成的。

有人可以向我解释要遵循的步骤吗?

【问题讨论】:

    标签: python machine-learning data-science word2vec


    【解决方案1】:

    请注意,如果您在模型实例化时已经提供了data1,则不需要使用data1 调用train()。如果您没有在实例化中指定一个,则该模型将使用默认编号 epochs (5) 在提供的语料库上完成自己的内部 build_vocab()train()

    “微调”不是一个简单的过程,需要确保改进模型的可靠步骤。它非常容易出错。

    特别是,如果模型不知道data2 中的单词,它们将被忽略。 (可以选择使用参数update=True 调用build_vocab() 来扩展已知词汇表,但这些词与之前的词并不完全平等。)

    如果 data2 包含一些词,但不包含其他词,则只有 data2 中的那些词会通过额外的训练得到更新——这实际上可能会将这些词从其他词中提取出来出现在data1。 (只有一起训练的单词,在交错的共享训练课程中,才会经历“推拉”,最终将它们留在有用的排列中。)

    增量训练最安全的方法是将data1data2 洗牌,并对所有数据进行持续训练:让所有单词一起得到新的交错训练。

    【讨论】:

      【解决方案2】:

      这是正确的吗?

      是的,是的。您需要确保data1提供的词汇表中data2的单词。如果不是单词 - 不在词汇表中呈现 - 就会丢失。

      请注意,将通过以下方式计算的权重

      model.train(data1, total_examples=len(data1), epochs=epochs)

      model.train(data2, total_examples=len(data2), epochs=epochs)

      不等于

      model.train(data1+data2, total_examples=len(data1+data2), epochs=epochs)

      我需要将学习到的权重存储在某个地方吗?

      不,你不需要。

      但是,如果您愿意,可以将权重保存为文件,以便以后使用。

      model.save("word2vec.model")
      

      然后你加载它们

      model = Word2Vec.load("word2vec.model")
      

      (source)

      我需要微调我的 word2vec 模型。

      请注意,“Word2vec 训练是一项无监督的任务,没有好的方法可以客观地评估结果。评估取决于您的最终应用程序 。” (source) 但是有一些评估可以查找here“如何测量词向量的质量”部分)

      希望有帮助!

      【讨论】:

        【解决方案3】:

        当您使用 gensim 训练 w2v 模型时,它会存储每个单词的 vocabindex
        gensim 使用此信息将单词映射到其向量。

        如果您要微调现有的 w2v 模型,您需要确保您的词汇一致。

        见附件代码。

        import os
        import pickle
        import numpy as np
        import gensim
        from gensim.models import Word2Vec, KeyedVectors
        from gensim.models.callbacks import CallbackAny2Vec
        import operator
        
        os.mkdir("model_dir")
        
        # class EpochSaver(CallbackAny2Vec):
        #     '''Callback to save model after each epoch.'''
        #     def __init__(self, path_prefix):
        #         self.path_prefix = path_prefix
        #         self.epoch = 0
        
        #     def on_epoch_end(self, model):
        #         list_of_existing_files = os.listdir(".")
        #         output_path = 'model_dir/{}_epoch{}.model'.format(self.path_prefix, self.epoch)
        #         try:
        #             model.save(output_path)
        #         except:
        #             model.wv.save_word2vec_format('model_dir/model_{}.bin'.format(self.epoch), binary=True)
        #         print("number of epochs completed = {}".format(self.epoch))
        #         self.epoch += 1
        #         list_of_total_files = os.listdir(".")
        
        # saver = EpochSaver("my_finetuned")
        
        
        
        
        
        # function to load vectors from existing model.
        # I am loading glove vectors from a text file, benefit of doing this is that I get complete vocab of glove as well.
        # If you are using a previous word2vec model I would recommed save that in txt format.
        # In case you decide not to do it, you can tweak the function to get vectors for words in your vocab only.
        def load_vectors(token2id, path,  limit=None):
            embed_shape = (len(token2id), 300)
            freqs = np.zeros((len(token2id)), dtype='f')
        
            vectors = np.zeros(embed_shape, dtype='f')
            i = 0
            with open(path, encoding="utf8", errors='ignore') as f:
                for o in f:
                    token, *vector = o.split(' ')
                    token = str.lower(token)
                    if len(o) <= 100:
                        continue
                    if limit is not None and i > limit:
                        break
                    vectors[token2id[token]] = np.array(vector, 'f')
                    i += 1
        
            return vectors
        
        
        embedding_name = "glove.840B.300d.txt"
        data = "<training data(new line separated tect file)>"
        
        # Dictionary to store a unique id for each token in vocab( in my case vocab contains both my vocab and glove vocab)
        token2id = {}
        
        # This dictionary will contain all the words and their frequencies.
        vocab_freq_dict = {}
        
        # Populating vocab_freq_dict and token2id from my data.
        id_ = 0
        training_examples = []
        file = open("{}".format(data),'r', encoding="utf-8")
        for line in file.readlines():
            words = line.strip().split(" ")
            training_examples.append(words)
            for word in words:
                if word not in vocab_freq_dict:
                    vocab_freq_dict.update({word:0})
                vocab_freq_dict[word] += 1
                if word not in token2id:
                    token2id.update({word:id_})
                    id_ += 1
        
        # Populating vocab_freq_dict and token2id from glove vocab.
        max_id = max(token2id.items(), key=operator.itemgetter(1))[0]
        max_token_id = token2id[max_id]
        with open(embedding_name, encoding="utf8", errors='ignore') as f:
            for o in f:
                token, *vector = o.split(' ')
                token = str.lower(token)
                if len(o) <= 100:
                    continue
                if token not in token2id:
                    max_token_id += 1
                    token2id.update({token:max_token_id})
                    vocab_freq_dict.update({token:1})
        
        with open("vocab_freq_dict","wb") as vocab_file:
            pickle.dump(vocab_freq_dict, vocab_file)
        with open("token2id", "wb") as token2id_file:
            pickle.dump(token2id, token2id_file)
        
        
        
        # converting vectors to keyedvectors format for gensim
        vectors = load_vectors(token2id, embedding_name)
        vec = KeyedVectors(300)
        vec.add(list(token2id.keys()), vectors, replace=True)
        
        # setting vectors(numpy_array) to None to release memory
        vectors = None
        
        params = dict(min_count=1,workers=14,iter=6,size=300)
        
        model = Word2Vec(**params)
        
        # using build from vocab to build the vocab
        model.build_vocab_from_freq(vocab_freq_dict)
        
        # using token2id to create idxmap
        idxmap = np.array([token2id[w] for w in model.wv.index2entity])
        
        # Setting hidden weights(syn0 = between input layer and hidden layer) = your vectors arranged accoring to ids
        model.wv.vectors[:] = vec.vectors[idxmap]
        
        # Setting hidden weights(syn0 = between hidden layer and output layer) = your vectors arranged accoring to ids
        model.trainables.syn1neg[:] = vec.vectors[idxmap]
        
        
        model.train(training_examples, total_examples=len(training_examples), epochs=model.epochs)
        output_path = 'model_dir/final_model.model'
        model.save(output_path)
        
        

        如果您有任何疑问,请发表评论。

        【讨论】:

          猜你喜欢
          • 2023-01-19
          • 2018-05-21
          • 2020-06-10
          • 2020-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多