【自然語言處理】【手把手實現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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章