zoukankan      html  css  js  c++  java
  • Python之利用 gensim的word2vec进行酒店评论+wiki百科语料联合词向量训练

    1.word2vec词向量原理解析

    word2vec,即词向量,就是一个词用一个向量来表示。是2013年Google提出的。word2vec工具主要包含两个模型:跳字模型(skip-gram)和连续词袋模型(continuous bag of words,简称CBOW),以及两种高效训练的方法:负采样(negative sampling)和层序softmax(hierarchical softmax)。word2vec词向量可以较好地表达不同词之间的相似和类比关系。word2vec是一个NLP工具,它可以将所有的词向量化,这样词与词之间就可以定量的去度量他们之间的关系,挖掘词之间的联系。

    NLP(自然语言处理)里面,最细粒度的是词语,词语组成句子,句子再组成段落、篇章、文档。所以处理 NLP 的问题,首先要先处理词语。词语,是人类的抽象总结,是符号形式的(比如中文、英文、拉丁文等等),所以需要把他们转换成数值形式,或者说——嵌入到一个数学空间里,这种嵌入方式,就叫词嵌入(word embedding),而 Word2vec,就是词嵌入( word embedding) 的一种。简单点来说就是把一个词语转换成对应向量的表达形式,来让机器读取数据。

    2.gensim训练中文词向量

    如果在以词为基本单元输入的自然语言处理任务中,都避免不了使用词的表示,词的表示有很多种,这里主要介绍的就是词向量,word2vec是目前比较通用的训练词向量的工具,使用Gensim模块,可以使词向量的训练变的简单,那么我们知道对于word2vec来说,不论的Skip-Gram models还是CBOW models,他们的输入以及输出都是以单词为基本单位的,只是他们对应的输入以及输出不一样:

    1. Skip-Gram models:输入为单个词,输出目标为多个上下文单词;
    2. CBOW models:输入为多个上下文单词,输出目标为一个单词;

    我们从上面可以看出,无论是Skip-Gram models还是CBOW models基本的单元都是词,那么我们获取到的语料,必须要经过分词处理以后才能用于词向量的训练语料。

    对于词向量的训练,语料越大训练出来的结果越好(非常重要)

    3.word2vec类

    参数表这一列,等号右边的值表示默认值

    sentences (iterable of iterables, optional) – 供训练的句子,可以使用简单的列表,但是对于大语料库,建议直接从磁盘/网络流迭代传输句子。参阅word2vec模块中的BrownCorpus,Text8Corpus或LineSentence
    corpus_file (str, optional) – LineSentence格式的语料库文件路径。
    size (int, optional) – word向量的维度。
    window (int, optional) – 一个句子中当前单词和被预测单词的最大距离。
    min_count (int, optional) – 忽略词频小于此值的单词。
    workers (int, optional) – 训练模型时使用的线程数。
    sg ({0, 1}, optional) – 模型的训练算法: 1: skip-gram; 0: CBOW.
    hs ({0, 1}, optional) – 1: 采用hierarchical softmax训练模型; 0: 使用负采样。
    negative (int, optional) – > 0: 使用负采样,设置多个负采样(通常在5-20之间)。
    ns_exponent (float, optional) – 负采样分布指数。1.0样本值与频率成正比,0.0样本所有单词均等,负值更多地采样低频词。
    cbow_mean ({0, 1}, optional) – 0: 使用上下文单词向量的总和; 1: 使用均值,适用于使用CBOW。
    alpha (float, optional) – 初始学习率。
    min_alpha (float, optional) – 随着训练的进行,学习率线性下降到min_alpha。
    seed (int, optional) – 随机数发生器种子。
    max_vocab_size (int, optional) – 词汇构建期间RAM的限制; 如果有更多的独特单词,则修剪不常见的单词。 每1000万个类型的字需要大约1GB的RAM。
    max_final_vocab (int, optional) – 自动选择匹配的min_count将词汇限制为目标词汇大小。
    sample (float, optional) – 高频词随机下采样的配置阈值,范围是(0,1e-5)。
    hashfxn (function, optional) – 哈希函数用于随机初始化权重,以提高训练的可重复性。
    iter (int, optional) – 迭代次数。
    trim_rule (function, optional) – 词汇修剪规则,指定某些词语是否应保留在词汇表中,修剪掉或使用默认值处理。
    sorted_vocab ({0, 1}, optional) – 如果为1,则在分配单词索引前按降序对词汇表进行排序。
    batch_words (int, optional) – 每一个batch传递给线程单词的数量。
    compute_loss (bool, optional) – 如果为True,则计算并存储可使用get_latest_training_loss()检索的损失值。
    callbacks (iterable of CallbackAny2Vec, optional) – 在训练中特定阶段执行回调序列。

    4.开始训练

    只需要给Word2Vec类赋上参数,就可以直接训练了。其中common_texts是一段内置的语料

    [[‘human’, ‘interface’, ‘computer’], [‘survey’, ‘user’, ‘computer’, ‘system’, ‘response’, ‘time’], [‘eps’, ‘user’, ‘interface’, ‘system’], [‘system’, ‘human’, ‘system’, ‘eps’], [‘user’, ‘response’, ‘time’], [‘trees’], [‘graph’, ‘trees’], [‘graph’, ‘minors’, ‘trees’], [‘graph’, ‘minors’, ‘survey’]]

    可以看到整体格式是[['A','B'],['C','D','E']],其中这个list表示所有的文本(此处表示2个文本,里面的A,B等表示单词,如果是中文则表示分词的结果

    在示例1中,第8行和第10行都是用来保存训练模型的(简称save和format_save),而两者之间的相同点就是:都可以复用,即载入之后可以得到对应单词的词向量;不同点是:save保存的模型,载入之后可以继续在此基础上接着训练(后文会介绍),而format_save保存的模型不能,但有个好处就是如果s设置binary=False则保存后的结果可以直接打开查看(一共有12个词向量,每个词向量100维)

    (1)查看词表相关信息

    model = Word2Vec.load('./MyModel')
    # 对于训练好的模型,我们可以通过下面这前三行代码来查看词表中的词,频度,以及索引位置,
    # 最关键的是可以通过第四行代码判断模型中是否存在这个词
    for key in model.wv.vocab:
        print(key)
        print(model.wv.vocab[key])
    print('human' in model.wv.vocab)
    print(len(model.wv.vocab)) #获取词表中的总词数

    控制台输出:

    human
    Vocab(count:2, index:4, sample_int:579459575)
    interface
    Vocab(count:2, index:5, sample_int:579459575)
    computer
    Vocab(count:2, index:6, sample_int:579459575)
    survey
    Vocab(count:2, index:7, sample_int:579459575)
    user
    Vocab(count:3, index:1, sample_int:463795800)
    system
    Vocab(count:4, index:0, sample_int:396841800)
    response
    Vocab(count:2, index:8, sample_int:579459575)
    time
    Vocab(count:2, index:9, sample_int:579459575)
    eps
    Vocab(count:2, index:10, sample_int:579459575)
    trees
    Vocab(count:3, index:2, sample_int:463795800)
    graph
    Vocab(count:3, index:3, sample_int:463795800)
    minors
    Vocab(count:2, index:11, sample_int:579459575)
    True
    12

    (2)获取对应的词向量及维度

    # 示例3  获取对应的词向量及维度
    model = Word2Vec.load('./MyModel')
    print(model.wv.vector_size) #输出词向量的维度
    print(model['human'])  #输出human这个词的词向量
    print(model['good'])

    (3)wiki+hotel语料训练词向量

    from gensim.models import word2vec
    import gensim
    #分词结果split_result_txt包下多个txt合并,将分割符由/替换成空格
    def review_corpus_merge():
        for i in range(1, 10):
            review_split_txt_path = 'split_result_txt/split_txt_' + str(i) + '.txt'
            fenci_result_corpus_path = 'fenci_result_corpus/hotel_review_corpus.txt'
            #读取文件
            f = open(review_split_txt_path, 'r', encoding='utf-8')
            for line in f.readlines():
                review = line.split("/")
                review_kongge = " ".join(review)
                if (len(review_kongge.strip()) != 0):  # strip()函数删除空格与换行符,删除空行
                    #向文件中追加写入
                    f = open(fenci_result_corpus_path, 'a', encoding='utf-8')
                    f.write('
    ' + review_kongge.strip())
                    f.close()
    
    #review_corpus_merge() 这个函数运行一次即可
    
    def train_word2vec(filename):
        text = gensim.models.word2vec.LineSentence(filename)
        #参数说明:text训练语料,size设置训练的词向量为300维,min_count表示词频小于10的词汇不训练,sg=1表示使用skip-gram
        #hs=1表示使用hierarchical softmax训练模型,workers训练模型使用的线程数
        word2vec = gensim.models.word2vec.Word2Vec(text, size=300, window=10, min_count=10, sg=1, hs=1, iter=8,
                                                   workers=25)
        word2vec.save('../word2vec_model/word2vec_hotel')
        word2vec.wv.save_word2vec_format('../word2vec_model/word2vec_hotel.txt', binary=False)
        print('语料数:', word2vec.corpus_count)
        print('词表长度:', len(word2vec.wv.vocab))
    
    #首先先单独训练酒店语料库
    train_word2vec('../fenci_result_corpus/hotel_review_corpus.txt')
    
    # 在原有的酒店语料库中添加wiki百科语料库,进行进一步训练
    loaded_model = gensim.models.word2vec.Word2Vec.load('../word2vec_model/word2vec_hotel')  # 加载模型
    text_add = gensim.models.word2vec.LineSentence('../fenci_result_corpus/wiki_corpus')
    loaded_model.build_vocab(sentences=text_add, update=True)
    loaded_model.train(sentences=text_add, total_examples=loaded_model.corpus_count, epochs=loaded_model.iter)
    loaded_model.save('../word2vec_model/word2vec_hotel_wiki')
    loaded_model.wv.save_word2vec_format('../word2vec_model/word2vec_hotel_wiki.txt', binary=False)
    print('语料数:', loaded_model.corpus_count)
    print('词表长度:', len(loaded_model.wv.vocab))

    训练结果:

    5.追加训练

    FileNotFoundError: [Errno 2] No such file or directory: 'word2vec_model/word2vec_hotel_3.wv.vectors.npy'

    这是文件保存的路径有问题,应该检查文件的路径地址,考虑目录的层级结构,是否少了../等

    最终训练模型保存为4个文件:

    word2vec_hotel_wiki,
    word2vec_hotel_wiki.trainables.syn1.npy,
    word2vec_hotel_wiki.trainables.syn1neg.npy,
    word2vec_hotel_wiki.wv.vectors.npy
    import gensim
    #加载已训练好的模型
    loaded_model = gensim.models.word2vec.Word2Vec.load('../word2vec_model/word2vec_hotel_wiki')  # 加载模型
    #获取要追加训练的语料
    text_add = gensim.models.word2vec.LineSentence('../fenci_result_corpus/hotel_review_corpus_add02.txt')
    loaded_model.build_vocab(sentences=text_add, update=True)
    loaded_model.train(sentences=text_add, total_examples=loaded_model.corpus_count, epochs=loaded_model.iter)
    #训练好的模型重新保存
    loaded_model.save('../word2vec_model/word2vec_hotel_3')
    loaded_model.wv.save_word2vec_format('../word2vec_model/word2vec_hotel_3.txt', binary=False)
    print('语料数:', loaded_model.corpus_count)
    print('词表长度:', len(loaded_model.wv.vocab))

    参考文献:

    https://blog.csdn.net/liuchenbaidu/article/details/106289334

    https://www.jianshu.com/p/3c6c53ec1512 推荐

    https://blog.csdn.net/The_lastest/article/details/81734980 必看

  • 相关阅读:
    spring中的bean
    在Eclipse上使用Maven
    类加载机制
    jstack简单使用,定位死循环、线程阻塞、死锁等问题
    “心若冰清,天塌不惊”,道家文化原文欣赏,你值得收藏研读!
    【干货分享】可能是东半球最全的.NET Core跨平台微服务学习资源
    Oracle 查询两个时间段内的所有日期列表
    SQL Server中获取指定时间段内的所有月份
    天气预报接口
    pixel和nexus设备安卓9.0/8.1/7.1.x/6.x WiFi和信号图标出现叉x号或者感叹号的消除办 法
  • 原文地址:https://www.cnblogs.com/luckyplj/p/13202698.html
Copyright © 2011-2022 走看看