【自然语言处理】【手把手实现BILSTM-CRF命名实体识别模型并部署(一)】预训练词向量的裁剪与保存

import numpy as np
import pandas as pd

一、介绍

1. 预训练词向量

预训练词向量是一种词的分布式表征,常见的词向量有word2vec、fasttext及Glove等。在这些预训练词向量中,每个词都会对应一个浮点型的向量,这个向量就是该词的向量表示。

2. 词向量裁剪

预训练词向量往往包含一个很大的词表以及这个词表所对应的向量。但是在应用中,往往并不需要将所有词的向量均加载到内存中,而是只将那些语料中用到的词对应的向量加载到内存中即可。该文使用的词向量来源于Chinese-Word-Vectors中人名日报的Word+Character+Ngram的300维词向量,云盘下载链接。用于构造词表的数据使用的是来自msra的命名实体识别数据集。该数据集在本项目的github上https://github.com/bqw18744018044/BILSTM-CRF

二、实现

1. 加载预训练词向量

EMBEDDING_FILE = '../data/sgns.renmin.bigram-char'
def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')
embeddings_index = dict(get_coefs(*o.strip().split(" ")) for o in open(EMBEDDING_FILE,encoding='utf-8'))
print(len(embeddings_index))
356038

2. 加载并处理数据

import codecs
train_file = '../data/train.txt'
dev_file = '../data/dev.txt'
def load_data(file):
    with codecs.open(file,encoding='utf-8') as f:
        texts = []
        text = []
        labels = []
        label = []
        for line in f:
            line = line.strip()
            if len(line)==0: # 空白行,表示一句话已经结束
                texts.append(text)
                labels.append(label)
                text = []
                label = []
            else:
                line = line.split()
                text.append(line[0])
                label.append(line[-1])
    return {'texts':texts,'labels':labels}
train_data = load_data(train_file)
dev_data = load_data(dev_file)

3.构造词表

from keras_preprocessing.text import Tokenizer
all_texts = []
all_texts.extend(train_data['texts'])
all_texts.extend(dev_data['texts'])
tokenizer = Tokenizer(num_words=None,lower=False)
tokenizer.fit_on_texts(all_texts)
print(len(tokenizer.word_counts))
4411

4.构造embedding矩阵(也就是裁剪词向量)

from tqdm import tqdm
def build_matrix(embeddings_index,word_index):
    embedding_matrix = np.zeros((len(word_index), 300))
    for word, i in tqdm(word_index.items()):
        if i >= len(word_index): continue
        try:
            # word对应的vector
            embedding_vector = embeddings_index[word]
        except:
            # word不存在则使用unknown的vector
            embedding_vector = embeddings_index["未知"]
        if embedding_vector is not None:
            # 保证embedding_matrix行的向量与word_index中序号一致
            embedding_matrix[i] = embedding_vector
    return embedding_matrix
# 与词表对应的embedding矩阵
embedding_matrix = build_matrix(embeddings_index,tokenizer.word_index)
print(embedding_matrix.shape)
100%|██████████████████████████████████████████████████████████████████████████| 4411/4411 [00:00<00:00, 402372.23it/s]


(4411, 300)

5. 持久化

np.save("../data/sgn_renmin", embedding_matrix)  # 持久化embedding矩阵
words = [word+'\n' for word in list(tokenizer.word_index.keys())]  # 持久化词表
with open('../data/vocab.txt', 'w', encoding='utf-8') as f:
    f.writelines(words)

6. 加载持久化的embedding矩阵

embedding_matrix = np.load("../data/sgn_renmin.npy")
print(embedding_matrix.shape)
(4411, 300)

你可能感兴趣的:(自然语言处理)