一. 训练词向量
具体参数参考gensim实现word2vec
def train_W2V(w2vCorpus, size=100):
w2vModel = Word2Vec(sentences=w2vCorpus, hs=0, negative=5, min_count=5, window=8, iter=1, size=size)
w2vModel.save(inPath+‘w2vModel.model‘)
return w2vModel
二. 加载自己训练的词向量或网上训练好的词向量
def load_W2V(W2V_path, loader_mySelf=1):
if loader_mySelf:
print(‘use my w2vModel‘)
w2vModel = Word2Vec.load(W2V_path+‘w2vModel.model‘) #使用自己训练的词向量
else: #加载腾讯训练的词向量
print(‘use other w2vModel‘)
w2vModel = gensim.models.KeyedVectors.load_word2vec_format(W2V_path+‘w2v_embedding_tengxun‘, binary=False)
return w2vModel
三. 使用训练好的词向量,来获得初始化的词嵌入矩阵和数字化训练文本:
方法一:
Wordidx:{单词:数字},用于将训练数据中的单词变为数字
embedMatrix:嵌入矩阵,用于Embedding的初始化
def build_word2idx_embedMatrix(w2vModel):
word2idx = {"_stopWord": 0} # 这里加了一行是用来过滤停用词的,也可以不加。
vocab_list = [(w, w2vModel.wv[w]) for w, v in w2vModel.wv.vocab.items()]
# 存储所有 word2vec 中所有向量的数组,留意其中多一位,词向量全为 0, 用于 padding
embedMatrix = np.zeros((len(w2vModel.wv.vocab.items()) + 1, w2vModel.vector_size))
for i in range(0, len(vocab_list)):
word = vocab_list[i][0]
word2idx[word] = i + 1
embedMatrix[i + 1] = vocab_list[i][1]
return word2idx, embedMatrix
将用于训练的文本数字化(这里不能使用keras里面的tokenizer),因为必须与word2idx字典里的对应
def make_deepLearn_data(sentenList, word2idx):
X_train_idx = [[word2idx.get(w, 0) for w in sen] for sen in sentenList]
X_train_idx = np.array(sequence.pad_sequences(X_train_idx, maxlen) # 必须是np.array()类型
return X_train_idx
方法二:
embeddings_index:{单词:向量}
词向量为文本格式
def build_embeddings_index()
embeddings_index = dict()
f = open('../glove_data/glove.6B/glove.6B.100d.txt')
for line in f:
values = line.split()
word = values[0]
coefs = asarray(values[1:], dtype='float32')
embeddings_index[word] = coefs
f.close()
return embeddings_index
词向量为gensim保存的二进制格式
def build_embeddings_index(model)
embeddings_index = {}
word_vectors = model.wv
for word, vocab_obj in model.wv.vocab.items():
embeddings_index[word] = word_vectors[word]
return embeddings_index
使用tokenzier将要训练的文本数字化
def make_deepLearn_data():
max_features = 20000
maxlen = 1000
tokenizer = Tokenizer(num_words=max_features, lower=True) # 建立一个max_features个词的字典
# 使用一系列文档来生成token词典。可以将输入的文本中的每个词编号,编号是根据词频的,词频越大,编号越小。
tokenizer.fit_on_texts(train_data)
# 对每个词编码之后,每个文本中的每个词就可以用对应的编码表示,即每条文本已经转变成一个向量了
sequences = tokenizer.texts_to_sequences(train_data)
# 将每条文本的长度设置一个固定值。
x_train = sequence.pad_sequences(sequences, maxlen)
return x_train
embeddings_matrix:嵌入矩阵,用于Embedding的初始化
def build_embeddings_Matrix(embeddings_index, word_index, max_features,embedding_dims):
embeddings_matrix = np.zeros((max_features,embedding_dims)) # 对比词向量字典中包含词的个数与文本数据所有词的个数,取小
for word,i in word_index.items(): # 从索引为1的词语开始,用词向量填充矩阵
if i < max_features:
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None:
#文本数据中的词在词向量字典中没有,向量为取0;如果有则取词向量中该词的向量
embeddings_matrix[i] = embedding_vector # 词向量矩阵,第一行是0向量(没有索引为0的词语,未被填充
return embeddings_matrix
以上两种方法都可以,但我更喜欢第二种方法,因为第二种方法可以使用tokenzier过滤低频词,比如按出现频率,只要前2000个词,而第一种方法需要我们自己来操作,大家也可以看看有没有将上文的word2idx字典用在tokenzier上的方法。其实我们还发现了一个问题就是第一种方法的词嵌入矩阵更大,因为它里面的单词数目等于我们训练好的词向量的单词数目,比如我们在网上下载一个拥有很多单词的词向量,那么得到的词嵌入矩阵也就更大,这样很耗内存,当然我们也可以通过其他的方法来把这个词嵌入矩阵减小到我们规定的最大词的数目,这里就不再实现了。
四. 在模型的Embedding层中加入初始化词嵌入矩阵的设置
Embedding(
len(embeddings_matrix), #表示文本数据中词汇的取值可能数,从语料库之中保留多少个单词。
embedding_dims, # 嵌入单词的向量空间的大小。它为每个单词定义了这个层的输出向量的大小
weights=[embeddings_matrix], #构建一个[num_words, EMBEDDING_DIM]的矩阵,然后遍历word_index,将word在W2V模型之中对应vector复制过来。换个方式说:embedding_matrix 是原始W2V的子集,排列顺序按照Tokenizer在fit之后的词顺序。作为权重喂给Embedding Layer
input_length=maxlen, # 输入序列的长度,也就是一次输入带有的词汇个数
trainable=False # 我们设置 trainable = False,代表词向量不作为参数进行更新,如果为True代表依此为初始,参与参数更新
)