代码下载
1 准备工作
1.1 什么是词向量?
1.2 获取词向量
步骤:
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 = './CarComment_vord2vec_100' # 读取词向量
model = gensim.models.Word2Vec.load(inp)
print('空间的词向量(100维):',model['空间'])
print('打印与空间最相近的5个词语:',model.most_similar('空间', topn=5))
if __name__ == '__main__':
#trainWord2Vec('./CarCommentAll_cut.csv')
testMyWord2Vec()
pass
2 转化词向量为keras所需格式
2.1 获取所有词语word和词向量
## 1 导入 预训练的词向量
myPath = './CarComment_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
<class 'gensim.models.keyedvectors.Word2VecKeyedVectors'>
2.2 构造“词语-词向量”字典
代码:
## 2 构造包含所有词语的 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 比如 10000+1 ; 列数为 词向量“维度”比如100。
embeddings_matrix = np.zeros((len(vocab_list) + 1, Word2VecModel.vector_size))
2.3 填充字典和矩阵
## 3 填充 上述 的字典 和 大矩阵
for i in range(len(vocab_list)):
# print(i)
word = vocab_list[i] # 每个词语
word_index[word] = i + 1 # 词语:序号
word_vector[word] = Word2VecModel.wv[word] # 词语:词向量
embeddings_matrix[i + 1] = Word2VecModel.wv[word] # 词向量矩阵
2.4 在 keras的Embedding层中使用 预训练词向量
from keras.layers import Embedding
EMBEDDING_DIM = 100 #词向量维度
embedding_layer = Embedding(input_dim = len(embeddings_matrix), # 字典长度
EMBEDDING_DIM, # 词向量 长度(100)
weights=[embeddings_matrix], # 重点:预训练的词向量系数
input_length=MAX_SEQUENCE_LENGTH, # 每句话的 最大长度(必须padding)
trainable=False # 是否在 训练的过程中 更新词向量
)
- Embedding层的输入shape
- Embedding层的输出shape
*2.5 不使用“预训练”而直接生成词向量
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_kbqa_traindata_zong_right.csv',encoding='utf-8')
print(dataFrame_2016.columns) # 打印列的名称
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] 的形式
## 把类别从int 3 转换为(0,0,0,1,0,0)的形式
labels = to_categorical(np.asarray(labels)) # keras的处理方法,一定要学会# 此时为[[0. 0. 1. 0. 0. 0. 0.]....] 的形式
return texts, labels # 总文本,总标签
3.2 句子分词
## 2. cut_sentence2word 句子分词
def cut_sentence2word(texts):
texts = [jieba.lcut(Sentence.replace('\n', '')) for Sentence in texts] # 句子分词
return texts
3.3 *构造词向量字典
## 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_LEN, 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
# 序号化 文本,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.pad_sequences(data, maxlen = MAX_SEQUENCE_LENGTH) # 使用kears的内置函数padding对齐句子,好处是输出numpy数组,不用自己转化了
return texts
3.5 切分数据
## 5.切分数据
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
3.6 使用Embedding层将每个词编码转换为词向量
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'
)