最详细NER实战讲解-bilstm+crf(4)提取词边界和词性特征

提取词性和词边界信息

word_bounds = ['M' for item in tag_list]  # 和tag list长度一样的 全部都是M构成的
word_flags = []
for text in texts:  # 遍历里面每一句话
    for word, flag in psg.cut(text):  # 对每一句话进行切词
        if len(word) == 1:
            start = len(word_flages)                          # B 开头 E 结束  S 是单独的词                         
            word_bounds[start] = 'S'                           M是中间的                               
            word_flags.append(flag)
        else:
            start = len(word_flags)
            word_bounds[start] = 'B'
            word_flags += [flag] * len(word)
            end = len(word_flags) - 1
            word_bounds[end] = 'E' 


# -------------------统一截断---------------------------------------
tags = []
bounds = []
flags = []
start = 0
end = 0
for s in texts:
    l = len(s)
    end += 1
    bounds.append(word_bounds[start:end])
    flags.append(word_flags[start:end])
    start += 1
data['bound'] = bounds           
data['flag'] = flags
data['label'] = tags



         

这样就得到分词标记(B M E S) 和词性 (ns, n, eng....)

然后再获取拼音特征

我们要安装一个包

from cnradical import 

pip install cnradical  写一个test 熟悉一下这个库

from cnradical import Radical, RunOption

radical = Radical(RunOption.Radical)  #获取偏旁部首

pinyin = Radical(RunOption.Pinyin)  # 获取拼音

input = '大撒大青蛙大全'
radical_out = [radical.trans_ch(ele) for ele in input]  # 对每一个字进行处理
pinyin_out = [pinyin.trans_ch(ele) for ele in input]
print(radical_out)
print(pinyin_out)

radical_out = radical.trans_str(input)
pinyin_out = pinyin.trans_str(input)

输出结果为

————————————————获取拼音特征————————————————————

radical = Radical(RunOption.Radical)  # 提取偏旁部首
pinyin = Radical(RunOption.Pinyin) # 提取拼音

data['radical'] = [[radical.trans_ch(x) if radical.trans_ch(x) is not None else 'PAD' for x in s] for s in texts]  # 如果不是空 把None 改成PAD PAD后续自己再设置
data['pinyin'] = [[pinyin.trans_str(x) if pinyin.trans_ch(x) is not None else 'PAD'for x in s] for s in texts]
#  这里就有一个问题 None 我们要用一个特殊的符号代替


return texts[0] , tags[0],bounds[0], flags[0], data['radical'][0], data['pinyin'][0]

输出 第一句话的texts tags:标签 O B-Disease。。  I-。。  bounds:第一句话的分词边界 B E M S

flags:第一句话的词性  data[’radical‘]:第一句话的偏旁部首 data['pinyin']:第一句话的拼音

然后我们要把数据存起来 后面统一的做数据读取

num_samples=len(texts)  # 统计有多少个样本
num_col = len(data.keys) # 统计有多少列 要写成每一行一个字 字 标记 等等特征
dataset = []
for i in range(num_samples):  # 用zip压缩
    records = list(zip(*[list(v[i] for v in data.value()]))
    dataset += records + [['sep'] * num_col] # 加个*解压  第一句话存完之后 要和第二句话隔开
dataset = dataset[:-1]  # 不要最后一组隔开符 sep
# 然后再把这个列表变成 dataframe
dataset = pd.DataFrame(dataset, columns=data.keys())  
save_path = f'data/prepare/{split_name}/{idx}.csv'   # 

def clean_word(w):
    if w == '\n':
        return 'LB'
    if w in [' ', '\t', '\u2003']:  # '\u2003中文的空格'
        return 'SPACE'
    if w.isdigit(): # 将所有的数字都变成一种符号    #这样可以提高泛化能力
        return 'num'
    return w
dataset['word'] = dataset['word'].apply(clean_word)  # 对dataset 应用clean_word这个函数
dataset.to_csv(save_path, index=False, encoding='utf-8')

然后将所有的数据全部处理掉  获取训练集和测试集的下标

train_dir = 'ruijin_round1_train2_20181022'
def multi_process(split_method=None, train_ratio=0.8):
    if os.path.exists('data/prepare/'):
        shutil.rmtree('data/prepare/')  # 如果这个目录存在就删掉
    if not os.path.exists('data/prepare/train/'):
        os.mkdirs('data/prepare/train'): #如果这个文件夹不存在就创建一个文件夹
        os.mkdirs('data/prepare/test'): # 注意 这里是mkdirs 因为创建的多层文件夹
    idxs = list(set([file.split('.')[0] for file in os.listdir('datas/') + train_dir])) # 获取所有文件的名字 (下标)
    shuffle(idxs)  # 打乱下标
    index = int(len(idxs) * train_ratio)   # 这个就是训练集的下标
    
    # 取 训练集和测试集的下标
    train_ids = idxs[:index]  
    test_ids = idxs[index:]

如果一个文件一个文件处理的话会很慢 所以这里引入多进程

import multiprocessing as mp
num_cpus = mp.cpu_count() # 获取机器cpu的个数

# 线程池
pool = mp.Pool(num_cpus) 
train_results = []
test_results = []
for idx in train_ids:
    result = pool.apply_async(process_text(), args=(idx, split_method,'train'))                
                                                     #apply_async 不用等待当前进程执行完毕
                                                      #apply 就是需要等待当前进程执行完毕
    results.append(result)

for idx in test_ids:
    result = pool.apply_async(process_text(), args=(idx, split_method,'test'))
    results.append(result)
pool.close()  # 进程池关掉
pool.join()
[r.get() for r in results]

到此数据集和测试集就做好了 在开始构建模型之前 我们还需要做一个映射字典(embedding)然后做一个数据增强 下章讲!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyttonkeepgoing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值