文本相似度、文本匹配、文本聚类

1 1在Keras的Embedding层中使用预训练的word2vec词向量:https://blog.csdn.net/u012052268/article/details/90238282

import numpy as np
import pandas as pd

#1准备工作

# graph LR
# 文本-->分词
# 分词-->训练词向量
# 训练词向量-->保存词向量

import gensim
#训练自己的词向量,并保存

def trainWord2Vec(filePath):
    sentences = gensim.models.word2vec.LineSentence(filePath)#读取分词后的文本
    model = gensim.models.Word2Vec(sentences, size=100, window=5, min_count=1, workers=4)#训练模型

    model.save('./CarComment_vord2vec_100')

def testMyWord2Vec():
    #读取自己的词向量,并简单测试一下效果
    inp = './CarCommennt_vord2vec_100' #读取词向量
    model = gensim.models.Word2Vec.load(inp)

    print('空间的词向量(100维):', model['空间'])
    print('打印与空间最相近的5个词语:', model.most_similar('空间', topn=5))

if __name__ == '__main__':
    testMyWord2Vec()
    pass

#通过上述,我们就拥有了预训练的词向量文件CarCommennt_vord2vec_100


# 转化词向量为keras所需格式
#keras中使用的embedding层,embedding层所需要的格式为一个巨大的“矩阵”:第i列表示词索引为i的词的词向量
#思路:embedding层,提供一个【word:word_vector]的词典来初始化embedding层中所需要的的大矩阵,并且标记为不可训练

# 获取所有词语word和词向量
#首先导入预训练的词向量
myPath = './CarCommennt_vord2vec_100' #本地词向量的位置
Word2VecModel = gensim.models.Word2Vec.load(myPath) # 读取词向量
vector = Word2VecModel.wv['空间']  #词语的向量,是numpy格式

#gensim的word2vec模型 把所有的单词和 词向量 都存储在了Word2VecModel.wv里面,讲道理直接使用这个.wv即可

print(type(Word2VecModel.wv)) #结果为Word2VecKeyedVectors

for i,j in Word2VecModel.wv.vocab.items():
    print(i) #此时i 代表每个单词
    print(j) #j代表封装了词频等信息的gensim“Vocab”对象,例子:Vocab(count:1481, index:38, sample_int:3701260191)
    break


#2.2 构造“词语——词向量”字典

#构造一个list存储所有的单词:vocab——list存储所有词语
#构造一个字典word_index:{word:index}, key是每个词语,value是单词在字典中的序号。
#在后期tokenize(序号化)训练集的时候就是用该词典

#构造一个大向量矩阵embedding_matrix(按照embedding层的要求):行数为所有单词数,比如10000;列数为词向量维度,比如100.

#构造包含所有词语的list,以及初始化“词语-序号”字典和“词向量”矩阵

vocab_list = [word for word, Vocab in Word2VecModel.wv.vocab.items()]#存储所有的词语
word_index = {" ": 0}#初始化‘[word:token]',后期tokenize语料库就是用该词典
word_vector = {} #初始化’[word:vector]'字典

#初始化存储所有向量的大矩阵,留意其中多一位(首行),词向量全为0,用于padding补零
#行数为所有单词+1,比如10001;列数为词向量维度,比如100

embedding_matrix = np.zeros((len(vocab_list)+1),Word2VecModel.vector_size)

#2.3 填充字典和矩阵
#填充上述步骤中的字典和大矩阵

for i in range(len(vocab_list)):
    word = vocab_list[i] #每个词语
    word_index[word] = i+1 #词语:序号
    word_vector[word] = Word2VecModel.wv[word]#词语:词向量
    embedding_matrix[i+1] = Word2VecModel.wv[word] #词向量矩阵

#2.4在keras的embedding层中使用与驯良词向量

from keras.layers import Embedding

from keras.utils.np_utils import *

#from…import *:是把一个模块中所有函数都导入进来; 注:相当于:相当于导入的是一个文件夹中所有文件,所有函数都是绝对路径。
EMBEDDING_DIM = 100 #词向量维度

embedding_layer = Embedding(input_dim=len(embedding_matrix),#字典长度
                            EMBEDDING_DIM, #词向量长度100
                            weights= [embedding_matrix],#重点:预训练的词向量系数
                            input_length=MAX_SEQUENCE_LENGTH,#每句话的最大长度(必须padding
                            trainable=False) #是否在训练的过程中更新词向量

#此时输入EMbedding层的数据的维度是,形如(samples,sequence_length)的2D张量
#3D张量:(samples,sequence_length,embeding_matrix)

#*2.5不使用“预训练”而直接生成词向量模型
#我们也可以直接使用KERAS自带的Embedding层训练词向量,而不用预训练的word2vec词向量。
embedding_layer = Embedding(len(word_index)+1,#由于没有预训练,设置 +1
                            EMBEDDING_DIM,
                            input_length = MAX_SEQUENCE_LENGTH)

#一般来说,在自然语言处理任务中,当样本数量非常少时,使用预训练的词向量是可行的。(实际上,预训练的词向量引入了外部语义信息


# 3整体代码:在Keras模型中使用预训练的词向量
#文本数据预处理,将每个文本样本转换为一个数字矩阵,矩阵的每一行表示一个词向量。

# 3.1 读取数据
def load_file():
    dataFrame_2016 = pd.read_csv('data\\nlpcc2016_traindata_zong_right.csv', encoding='utf-8')

    print(dataFrame_2016.coloumns) #打印列的名称

    texts = [] #存储读取的x
    labels = [] #存储读取的y
    #遍历获取数据

    for i in range(len(dataFrame_2016)):
        texts.append(dataFrame_2016.iloc[i].q_text)
        ##每个元素为一句话“《机械设计基础》这本书的作者是谁?”
        labels.append(dataFrame_2016.iloc[i].q_type)
        #每个元素为一个int 代表类别 # [2, 6, ... 3] 的形式


    #把类别从int3转换为(0,0,0,1,0,0)的形式
    labels = to_categorical(np.assarray(labels))## keras的处理方法,一定要学会# 此时为[[0. 0. 1. 0. 0. 0. 0.]....] 的形式
    return texts,labels

#3.2句子分词
import jieba
#jieba.lcut生成为一个列表
def cut_sentence2word(texts):
    texts = [jieba.lcut(Sentence.repalce('\n','')) for Sentence in texts]
    #句子分词
    return texts

#构造词向量字典

#获取word2vec模型,并构造,词语index字典,词向量字典
import os
## 3.获取word2vec模型, 并构造,词语index字典,词向量字典
def get_word2vec_dictionaries(texts):
    def get_word2vec_model(texts=None): # 获取 预训练的词向量 模型,如果没有就重新训练一个。
        if os.path.exists('data_word2vec/Word2vec_model_embedding_25'): # 如果训练好了 就加载一下不用反复训练
            model = Word2Vec.load('data_word2vec/Word2vec_model_embedding_25')
            # print(model['作者'])
            return model
        else:
            model = Word2Vec(texts, size = EMBEDDING_DIM, window=7, min_count=10, workers=4)
            model.save('data_word2vec/Word2vec_model_embedding_25') # 保存模型
            return model

    Word2VecModel = get_word2vec_model(texts) #  获取 预训练的词向量 模型,如果没有就重新训练一个。

    vocab_list = [word for word, Vocab in Word2VecModel.wv.vocab.items()]  # 存储 所有的 词语


    word_index = {" ": 0}# 初始化 `[word : token]` ,后期 tokenize 语料库就是用该词典。
    word_vector = {} # 初始化`[word : vector]`字典

    # 初始化存储所有向量的大矩阵,留意其中多一位(首行),词向量全为 0,用于 padding补零。
    # 行数 为 所有单词数+1 比如 10000+1 ; 列数为 词向量“维度”比如100。
    embeddings_matrix = np.zeros((len(vocab_list) + 1, Word2VecModel.vector_size))

    ## 填充 上述 的字典 和 大矩阵
    for i in range(len(vocab_list)):
        word = vocab_list[i]  # 每个词语
        word_index[word] = i + 1  # 词语:序号
        word_vector[word] = Word2VecModel.wv[word] # 词语:词向量
        embeddings_matrix[i + 1] = Word2VecModel.wv[word]  # 词向量矩阵

    return word_index, word_vector, embeddings_matrix
#3.4文本序号化Tokenizer
#英文文本不用切词,因为默认会将空格将词切开,就需要切词,且每个词用空格隔开
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(num_words = 2000) #建一个2000个单词的字典
tokenizer.fit_on_texts(train_texts)

#当然我们也可以使用之前构建的word——index字典。手动构建tokenizer句子(推荐这种方法,这样序号下标与预训练词向量一致。

from keras.preprocessing import  sequence
#序号化文本,tokenizer句子,并返回每个句子所对应的词语索引
def tokenizer(texts,word_index):
    data = []
    for sentence in texts:
        new_txt = []
        for word in sentence:
            try:
                new_txt.append(word_index[word]) #把句子中的词语转化为index

            except:
                new_txt.append(0)

        data.append(new_txt)
    texts = sequence

#3.5 切分数据
from sklearn.model_selection import train_test_split
def split_data(texts,labels):
    x_train, x_test, y_train, y_test = train_test_split(texts,labels,test_size=0.2)
    return x_train,x_test,y_train,y_test

embedding_layer = Embedding(input_dim=len(embeddings_matrix),  # 字典长度
                                output_dim = EMBEDDING_LEN,  # 词向量 长度(25)
                                weights=[embeddings_matrix],  # 重点:预训练的词向量系数
                                input_length=MAX_SEQUENCE_LENGTH,  # 每句话的 最大长度(必须padding) 10
                                trainable=False,  # 是否在 训练的过程中 更新词向量
                                name= 'embedding_layer')

本文的部分工作、代码、数据共享到gethub网站《使用多层级注意力机制和keras实现问题分类》:https://github.com/xqtbox/question-classification-with-multi-level-attention-mechanism-and-keras

2 QA match/文本匹配/文本分类/文本embedding/文本聚类/文本检索:https://github.com/MachineLP/TextMatch

3 文本相似度计算/文本匹配
https://github.com/JepsonWong/Text_Matching

猜你喜欢

转载自blog.csdn.net/stay_foolish12/article/details/107464263