1. 数据预处理

首先说的就是分词,对英语来说每个词与词之间是通过空格辨别的,例如I love natural language processing,每个词之间都是有空格的,所以很容划分为[i, love, natural, language, processing]但是中文的词并没有分开,而是全部连在一起的,例如我爱自然语言处理,我们可以通过分词工具进行切分,我这里使用的jieba分词

import jieba

res = jieba.cut("我爱自然语言处理",cut_all=False)
print(list(res)) # ['我', '爱', '自然语言', '处理']

首先我们需要准备一段预料,一般情况下通常是一个非常大的语料库,这样才能覆盖更多的词语,训练的词向量也会更加准确,但是这里只是为了演示,所以随便搞一点就行。正好最近在看仙逆,截取前两章节作为训练语料。我们将其保存到一个txt中

NLP比赛数据清洗 nlp数据预处理_字符串

首先我们需要对去除每一行的换行符,然后将每一行拼接在一起,送到jieba分词中

import jieba

def read_text_and_cut_word(cropus_path):
    data = []
    with open(cropus_path, 'r', encoding='utf-8') as f:
        lines = f.readlines()
        for line in lines:
            line = line.strip()
            if line != '': # 过滤掉空白行
                data.append(line)


    sentences = "\n".join(data) # 将文本拼接成一个字符串
    words = jieba.cut(sentences,cut_all=False) 
    with open("p_input.txt", "w") as f: # 将分词的结果保存到txt中
        f.write(' '.join(words))

read_text_and_cut_word('news.txt')

NLP比赛数据清洗 nlp数据预处理_自然语言处理_02

原始的文本已经分好词保存下来了,可以看到分的词里面有很多中文的停用词和标点符号,。?、\n等等,通常情况下,分词的时候需要加载我们自定义的停用词,例如啊,的,是等等,不过为了简单,这里只去除标点和数字,

def handle_stopwords_and_whitesapce():
    # 标点符号集
    stopwords = '''~!@#$%^&*()_+`1234567890-={}[]::";'<>,.?/|\、·!()¥“”‘’《》,。?/—-【】….'''
    stopwords_set = set([i for i in stopwords])
    stopwords_set.add("br") # 异常词也加入此集,方便去除
    with open("temp.txt", "r", encoding="utf-8") as f:
        lines = f.readlines()

    data = []
    for line in lines:
        line = line.strip()
        for s in stopwords_set:
            line = line.strip().replace(s, "")
        line = line.replace("   "," ").replace("  "," ")
        if line != "" and line != " ":
            data.append(line)
    
    all_text = " ".join(data)
    with open("train.txt", "w") as f:
        f.write(all_text)

handle_stopwords_and_whitesapce()

NLP比赛数据清洗 nlp数据预处理_人工智能_03


很好,语聊基本就处理好了,现在每个词之间使用空格进行分割,我们就可以将切好的词输入到我们的网络中训练了。但是由于计算机只认识01,所以我们需要对词进行编码。

  1. 首先统计语料中有多少个词,每个词出现的次数是多少
  2. 给每个词进行id编码,为了扩展性,这里留出几个未定义的词
  3. 同时也将每个id编码重新映射为词
from collections import Counter

word2idx = {}
idx2word = {}
max_idx = 0
def build_vocab(cropus,unused_cnt=100):

    with open(cropus, "r", encoding="utf-8") as f:
            all_text = f.readline()
    vocabs = all_text.split(" ") # 读出所有的词

    vocab_dict = dict(Counter(vocabs).most_common()) # 统计每个词出现的频率
    for i,w in enumerate(vocab_dict.keys()): 
        word2idx[w] = i + unused_cnt # 为每个词进行id编码
        idx2word[i + unused_cnt] = w # id重新映射为词

build_vocab('train.txt')


words = ["铁柱", "坐在", "村内", "的", "小", "路边", "望", "着", "蔚蓝", "的", "天空"]

token_id = [word2idx.get(w, 0) for w in words]
print(' '.join(words)) # 铁柱 坐在 村内 的 小 路边 望 着 蔚蓝 的 天空
print(token_id) # [101, 317, 318, 100, 456, 457, 124, 107, 458, 100, 459]

newwords = [idx2word.get(i, '<UNK>') for i in token_id]
print(newwords) # ['铁柱', '坐在', '村内', '的', '小', '路边', '望', '着', '蔚蓝', '的', '天空']