BILSTM-CRF项目源码

  • boson数据集分析
    • 数据处理
    • BILSTM-CRF
    • train
    • 模型能力
  • 迁移MSRA数据集
    • 数据处理
    • BILSTM-CRF&&resuleCal
    • 训练
    • 模型能力
  • 处理brat标注后的数据
    • ann数据处理

boson数据集分析

数据处理

oragindata

{{product_name:浙江在线杭州}}{{time:4月25日}}讯(记者{{person_name: 施宇翔}} 通讯员 {{person_name:方英}})毒贩很“时髦”,用{{product_name:微信}}交易毒品。没料想警方也很“潮”,将计就计,一举将其擒获。记者从{{org_name:杭州江干区公安分局}}了解到,经过一个多月的侦查工作,{{org_name:江干区禁毒专案组}}抓获吸贩毒人员5名,缴获“冰毒”400余克,毒资30000余元,扣押汽车一辆。{{location:黑龙江}}籍男子{{person_name:钱某}}长期落脚于宾馆、单身公寓,经常变换住址。他有一辆车,经常半夜驾车来往于{{location:杭州主城区}}的各大宾馆和单身公寓,并且常要活动到{{time:凌晨6、7点钟}},{{time:白天}}则在家里呼呼大睡。{{person_name:钱某}}不寻常的特征,引起了警方注意。禁毒大队通过侦查,发现{{person_name:钱某}}实际上是在向落脚于宾馆和单身公寓的吸毒人员贩送“冰毒”。

第一层处理:实现对单个字打标签,具体实现:按照括号配对," : "左边的是tag,右边的是word。再将标签分为开始,中间,结束,分别给word中的每个字打tag。给没有“{{ }}”的每个字打上/o。将处理后的文件输入wordtag中。

def origin2tag():input_data = codecs.open('./origindata.txt','r','utf-8')output_data = codecs.open('./wordtag.txt','w','utf-8')# 一个line是一个待分析的实例for line in input_data.readlines():# 将line中的词组分出来line=line.strip()i=0 #读取词的时候计数while i <len(line):if line[i] == '{':i+=2temp=""while line[i]!='}':temp+=line[i]i+=1i+=2# ":"左边是标签,右边是实体word=temp.split(':')sen = word[1]# 给词组打开始,中间和结束output_data.write(sen[0]+"/B_"+word[0]+" ")for j in sen[1:len(sen)-1]:output_data.write(j+"/M_"+word[0]+" ")output_data.write(sen[-1]+"/E_"+word[0]+" ")else:output_data.write(line[i]+"/O ")i+=1output_data.write('\n')input_data.close()output_data.close()

wordtag

浙/B_product_name 江/M_product_name 在/M_product_name 线/M_product_name 杭/M_product_name 州/E_product_name 4/B_time 月/M_time 2/M_time 5/M_time 日/E_time 讯/O (/O 记/O 者/O  /B_person_name 施/M_person_name 宇/M_person_name 翔/E_person_name  /O 通/O 讯/O 员/O  /O 方/B_person_name 英/E_person_name )/O 毒/O 贩/O 很/O “/O 时/O 髦/O ”/O ,/O 用/O 微/B_product_name 信/E_product_name 交/O 易/O 毒/O 品/O 。/O 没/O 料/O 想/O 警/O 方/O 也/O 很/O “/O 潮/O ”/O ,/O 将/O 计/O 就/O 计/O ,/O 一/O 举/O 将/O 其/O 擒/O 获/O 。/O 记/O 者/O 从/O 杭/B_org_name 州/M_org_name 江/M_org_name 干/M_org_name 区/M_org_name 公/M_org_name 安/M_org_name 分/M_org_name 局/E_org_name 了/O 解/O 到/O ,/O 经/O 过/O 一/O 个/O 多/O 月/O 的/O 侦/O 查/O 工/O 作/O ,/O 江/B_org_name 干/M_org_name 区/M_org_name 禁/M_org_name 毒/M_org_name 专/M_org_name 案/M_org_name 组/E_org_name 抓/O 获/O 吸/O 贩/O 毒/O 人/O 员/O 5/O 名/O ,/O 缴/O 获/O “/O 冰/O 毒/O ”/O 4/O 0/O 0/O 余/O 克/O ,/O 毒/O 资/O 3/O 0/O 0/O 0/O 0/O 余/O 元/O ,/O 扣/O 押/O 汽/O 车/O 一/O 辆/O 。/O 黑/B_location 龙/M_location 江/E_location 籍/O 男/O 子/O 钱/B_person_name 某/E_person_name 长/O 期/O 落/O 脚/O 于/O 宾/O 馆/O 、/O 单/O 身/O 公/O 寓/O ,/O 经/O 常/O 变/O 换/O 住/O 址/O 。/O 他/O 有/O 一/O 辆/O 车/O ,/O 经/O 常/O 半/O 夜/O 驾/O 车/O 来/O 往/O 于/O 杭/B_location 州/M_location 主/M_location 城/M_location 区/E_location 的/O 各/O 大/O 宾/O 馆/O 和/O 单/O 身/O 公/O 寓/O ,/O 并/O 且/O 常/O 要/O 活/O 动/O 到/O 凌/B_time 晨/M_time 6/M_time 、/M_time 7/M_time 点/M_time 钟/E_time ,/O 白/B_time 天/E_time 则/O 在/O 家/O 里/O 呼/O 呼/O 大/O 睡/O 。/O 钱/B_person_name 某/E_person_name 不/O 寻/O 常/O 的/O 特/O 征/O ,/O 引/O 起/O 了/O 警/O 方/O 注/O 意/O 。/O 禁/O 毒/O 大/O 队/O 通/O 过/O 侦/O 查/O ,/O 发/O 现/O 钱/B_person_name 某/E_person_name 实/O 际/O 上/O 是/O 在/O 向/O 落/O 脚/O 于/O 宾/O 馆/O 和/O 单/O 身/O 公/O 寓/O 的/O 吸/O 毒/O 人/O 员/O 贩/O 送/O “/O 冰/O 毒/O ”/O 。/O 

第二层处理:# 按照标点符号进行分段

# 文本处理阶段二
# 逻辑分段(标点符号)
def tagsplit():with open('./wordtag.txt','rb') as inp:texts = inp.read().decode('utf-8')sentences = re.split('[,。!?、‘’“”()]/[O]', texts)output_data = codecs.open('./wordtagsplit.txt','w','utf-8')for sentence in sentences:if sentence != " ":output_data.write(sentence.strip()+'\n')output_data.close()
浙/B_product_name 江/M_product_name 在/M_product_name 线/M_product_name 杭/M_product_name 州/E_product_name 4/B_time 月/M_time 2/M_time 5/M_time 日/E_time 讯/O

第三层处理:制作对应数据,单个字对应的id,tag对应的id,tag对应的字,训练用的数据集

def data2pkl():datas = list()labels = list()linedata=list()linelabel=list()tags = set()# 将标注的文本进行数据处理(获取实体文本以及标签,分别存入两个list datas labels,且一一对应,用集合tag统计存在多少种类型的标签)input_data = codecs.open('./wordtagsplit.txt','r','utf-8')  #处理已经打好标签的文本for line in input_data.readlines():line = line.split()linedata=[]linelabel=[]numNotO=0for word in line:word = word.split('/') #数据中每个词对用空格隔开,每个词和对应的标签使用“/”分隔符隔开的linedata.append(word[0])linelabel.append(word[1])tags.add(word[1])if word[1]!='O':  #o不是我们所需要识别的内容的标签numNotO+=1if numNotO!=0:datas.append(linedata)labels.append(linelabel)input_data.close()print(len(datas),tags)print(len(labels))# 实体打id
#    from compiler.ast import flattenall_words = flatten(datas)sr_allwords = pd.Series(all_words) #给words打对应的idsr_allwords = sr_allwords.value_counts() #统计各word出现的次数,且按照由高到低排列set_words = sr_allwords.indexset_ids = list(range(1, len(set_words)+1))# 标签打idtags = [i for i in tags]tag_ids = list(range(len(tags)))# 四种二元关系word2id = pd.Series(set_ids, index=set_words)id2word = pd.Series(set_words, index=set_ids)tag2id = pd.Series(tag_ids, index=tags)id2tag = pd.Series(tags, index=tag_ids)# 给找不到的实体单独打一个idword2id["unknow"] = len(word2id)+1print(word2id)# 每60个词打包在一起,不足的就截断到60个词max_len = 60def X_padding(words):ids = list(word2id[words])if len(ids) >= max_len:  return ids[:max_len]ids.extend([0]*(max_len-len(ids))) return idsdef y_padding(tags):ids = list(tag2id[tags])if len(ids) >= max_len: return ids[:max_len]ids.extend([0]*(max_len-len(ids))) return ids#建立word和tag的一一对应的二维表,行名是顺序数字df_data = pd.DataFrame({'words': datas, 'tags': labels}, index=list(range(len(datas))))# 填充数据df_data['x'] = df_data['words'].apply(X_padding)df_data['y'] = df_data['tags'].apply(y_padding)# 数据结构化x = np.asarray(list(df_data['x'].values))y = np.asarray(list(df_data['y'].values))# 划分数据集(训练:验证:测试 =0.66 : 0.16 : 0.2)from sklearn.model_selection import train_test_splitx_train,x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=43)x_train, x_valid, y_train, y_valid = train_test_split(x_train, y_train,  test_size=0.2, random_state=43)# 将结构化后的数据送入pkl中存储import pickleimport oswith open('../Bosondata.pkl', 'wb') as outp:pickle.dump(word2id, outp)pickle.dump(id2word, outp)pickle.dump(tag2id, outp)pickle.dump(id2tag, outp)pickle.dump(x_train, outp)pickle.dump(y_train, outp)pickle.dump(x_test, outp)pickle.dump(y_test, outp)pickle.dump(x_valid, outp)pickle.dump(y_valid, outp)print('** Finished saving the data.')
import collections
# 数据拉成一维的
def flatten(x):result = []for el in x:if isinstance(x, collections.Iterable) and not isinstance(el, str):result.extend(flatten(el))else:result.append(el)return result

BILSTM-CRF

具体解析
数据在BISTM-CRF层中的整个流程:



Created with Raphaël 2.2.0












数据进入





lstm训练得到每个词的标签分数





crf层对lstm层输出的标签序列进行路程打分

实现:

  • 初始化模型
  • 前馈
  • 损失函数
  • 反馈
    (具体解析详见链接)

train

加载处理过的数据

with open('../data/Bosondata.pkl', 'rb') as inp:word2id = pickle.load(inp)id2word = pickle.load(inp)tag2id = pickle.load(inp)id2tag = pickle.load(inp)x_train = pickle.load(inp)y_train = pickle.load(inp)x_test = pickle.load(inp)y_test = pickle.load(inp)x_valid = pickle.load(inp)y_valid = pickle.load(inp)

设置初始值

START_TAG = "<START>"
STOP_TAG = "<STOP>"
EMBEDDING_DIM = 100
HIDDEN_DIM = 200
EPOCHS = 5tag2id[START_TAG]=len(tag2id)
tag2id[STOP_TAG]=len(tag2id)

模型

model = BiLSTM_CRF(len(word2id)+1, tag2id, EMBEDDING_DIM, HIDDEN_DIM)

优化器

optimizer = optim.SGD(model.parameters(), lr=0.005, weight_decay=1e-4)

训练

    for sentence, tags in zip(x_train,y_train):index+=1model.zero_grad()# 数据处理的时候已将word转换成id进行存储# sentence = torch.tensor([word2id[w] for w in sentence], dtype=torch.long)# 数据处理的时候已将tag转换成id进行存储# tags = torch.tensor([tag2id[t] for t in tags], dtype=torch.long)sentence = torch.tensor(sentence)tags = torch.tensor(tags)loss = model.neg_log_likelihood(sentence, tags)loss.backward()optimizer.step()if index%30==0:print("epoch", epoch, "index", index)

测试

 entityres=[]entityall=[]for sentence, tags in zip(x_test,y_test):sentence=torch.tensor(sentence, dtype=torch.long)score,predict = model(sentence)sentence = sentence.numpy().tolist()tags = tags.tolist()entityres = calculate(sentence,predict,id2word,id2tag,entityres)entityall = calculate(sentence,tags,id2word,id2tag,entityall)jiaoji = [i for i in entityres if i in entityall]if len(jiaoji)!=0:zhun = float(len(jiaoji))/len(entityres)zhao = float(len(jiaoji))/len(entityall)print("test:")print("zhun:", zhun)print("zhao:", zhao)print("f:", (2 * zhun * zhao) / (zhun + zhao))else:print("zhun:",0)

保存模型

 path_name = "./model"+str(epoch)+".pkl"print(path_name)torch.save(model, path_name)print("model has been saved")

模型能力

epoch=1
train len: 1216
test len: 380

epoch=1
train len: 1600
test len: 500

迁移MSRA数据集

数据处理

  • 分割数据集中的data和lable

    • 按行将单词提取到列表中

      • 按照bme格式,给单字打label
  • 按逻辑(’[,。!?、‘’“”()]/[O]’)分行
  • 自定义tag2id&&id2tag
  • 制作数据集(分单词,分单字,数据拉成一维)
  • 通过pd.Series()给word打id
  • 将word转成id,tag转成id,并进行数据规范(通过填充或删减将其长度固定)
  • 划分训练集,测试集,验证集

注意:生成 tag2id 时,应该将空设置成 id = 0,否则在进行padding时用 0填充会打上其他标签!!!!!影响整个模型的训练
数据集一定要仔细仔细再仔细!!!否则可能有test数据集无法验证,训练出的模型根本没有识别能力等等等问题!!!!,tag如果不多建议自定义,在msra数据集中,自动生成tag2id和id2tag存在bug

BILSTM-CRF&&resuleCal

直接用现成的

训练

  1. 定model,loss,optimizer

  2. START_TAG
    STOP_TAG
    EMBEDDING_DIM
    HIDDEN_DIM
    EPOCHS
  3. 通过训练集进行训练
  4. 通过测试集验证准确率
  5. 保存模型

模型能力

train len: 1440
test len: 200
valid len 360
epoch = 1

train len: 1440
test len: 200
valid len 360
epoch = 1

处理brat标注后的数据

天池瑞金医院MMC人工智能辅助构建知识图谱大赛
处理思路:

  1. 将ann文件内容存到csv中
  2. 按照起始位置和终止位置打标签(BME)
  3. 制作tag2id,id2tag,word2id,id2word数据集
  4. 制作数据集
  5. 存数据到pkl中

ann数据处理

将ann数据中的起始位置,对应列表,实体 (无用,可省去)存储到
csv中

def clean_ann():entity_list = []label_list = []start_list = []end_list = []for line in codecs.open('tea.ann', 'r', 'utf-8'):tab_split = line.strip().split('\t')space_split = tab_split[1].split()entity = tab_split[2].replace('',' ')label = space_split[0]start = space_split[1]end = space_split[-1]entity_list.append(entity)label_list.append(label)start_list.append(int(start))end_list.append(int(end))# print(entity_list)df = pd.DataFrame({'entity':entity_list,'label':label_list,'start':start_list,'end':end_list})df.to_csv('tea.csv')

读csv文件

def word_level_tag2(filename):# 将所有的字和标签存储成对应的listwords=[]labels = []f = codecs.open(filename,'r','utf-8')f = f.read()f = list(f)df = pd.read_csv('tea.csv')#word_point是当前的文本指针word_point = 0# j用来表示csv中的行数j=0

遍历打标签

    while word_point < len(f) and j < df.shape[0]:if word_point < df.iloc[j]['start'] :words.append(f[word_point])labels.append('o')word_point += 1elif word_point == df.iloc[j]['start'] and df.iloc[j]['start'] != df.iloc[j]['end']-1:words.append(f[word_point])labels.append('B'+'-'+df.iloc[j]['label'])word_point += 1elif word_point > df.iloc[j]['start'] and word_point < df.iloc[j]['end']-1:words.append(f[word_point])labels.append('M'+'-'+df.iloc[j]['label'])word_point += 1elif word_point==df.iloc[j]['end']-1 and df.iloc[j]['start']!=df.iloc[j]['end']-1:words.append(f[word_point])labels.append('E' + '-' + df.iloc[j]['label'])word_point += 1j+=1elif df.iloc[j]['start']==df.iloc[j]['end']-1:words.append(f[word_point])labels.append('B' + '-' + df.iloc[j]['label'])word_point += 1j += 1

制做tag2id,id2tag,word2id,id2word

  #获取tag2id,id2tag,word2id,id2word:tags_all = list(set(labels))tags_all.insert(0,'')words_all = list(set(words))tags_ids = list(range(1, len(tags_all) + 1))words_ids = list(range(1,len(words_all) + 1))word2id = pd.Series(words_ids,index=words_all)id2word = pd.Series(words_all,index=words_ids)tag2id = pd.Series(tags_ids,index=tags_all)id2tag = pd.Series(tags_all,index=tags_ids)

数据集准备

    # 按照标签符号分割句子sentences = []for i in range(len(words)):sentence = words[i]+'/'+labels[i]sentences.append(sentence)sentences = ' '.join(sentences)sentences = re.split('[,。;!:?、‘’“”]/[o]',sentences)data_tags = []for i in range(len(sentences)):line = sentences[i].strip().split(' ')data_tags.append(line)# print(data_tags)data = []labels = []for line in data_tags:line_word = []line_label = []for word in line:word = word.split('/')line_word.append(word[0])line_label.append(word[1])# print(line_word)# print(line_label)data.append(line_word)labels.append(line_label)

数据规范

max_len = 50def X_padding(words):"""把 words 转为 id 形式,并自动补全位 max_len 长度。"""# print(type(word2id))ids = list(word2id[word] for word in words)if len(ids) >= max_len:  # 长则弃掉return ids[:max_len]ids.extend([0]*(max_len-len(ids))) # 短则补全return idsdef y_padding(tags):"""把 tags 转为 id 形式, 并自动补全位 max_len 长度。"""# print(type(tag2id))# tag2id是list类型,是unhash的,所以要采用循环方式ids = list(tag2id[tag] for tag in tags)if len(ids) >= max_len:  # 长则弃掉return ids[:max_len]ids.extend([0]*(max_len-len(ids))) # 短则补全return ids

制作待训练数据集,这里可添加训练集测试集的划分

 df_data = pd.DataFrame({'words': data, 'tags': labels}, index=range(len(data)))df_data['x'] = df_data['words'].apply(X_padding)df_data['y'] = df_data['tags'].apply(y_padding)x = np.asarray(list(df_data['x'].values))

存为pkl文件

    with open('data.pkl', 'wb') as outp:pickle.dump(word2id, outp)pickle.dump(id2word, outp)pickle.dump(tag2id, outp)pickle.dump(id2tag, outp)pickle.dump(x, outp)pickle.dump(y, outp)print('** Finished saving the data.')

BISTML-CRF项目源码相关推荐

  1. Spring mvc Data Redis—Pub/Sub(附Web项目源码)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  2. Atitit. 查找linux 项目源码位置

    Atitit. 查找linux 项目源码位置 1. netstat   -anp |grep 801 1.1. 1.3 启动关闭nginx3 1.2. 找到nginx配置文件4 1.3. ./etc/ ...

  3. rust墙壁升级点什么_分享:如何在阅读Rust项目源码中学习

    今天做了一个Substrate相关的小分享,公开出来. 因为我平时也比较忙,昨天才选定了本次分享的主题,准备比较仓促,细节可能不是很充足,但分享的目的也是给大家提供一个学习的思路,更多的细节大家可以在 ...

  4. java进销存系统静态页_java 库存 进销存 商户 多用户管理系统 SSM springmvc 项目源码...

    系统介绍: 1.系统采用主流的 SSM 框架 jsp JSTL bootstrap html5 (PC浏览器使用) 2.springmvc +spring4.3.7+ mybaits3.3  SSM ...

  5. java 库存 进销存 商户 多用户管理系统 SSM springmvc 项目源码

    统介绍: 1.系统采用主流的 SSM 框架 jsp JSTL bootstrap html5 (PC浏览器使用) 2.springmvc +spring4.3.7+ mybaits3.3 SSM 普通 ...

  6. 又搜集一批项目源码,同样改改就能用

    UE4项目源码:家具沙发 http://www.52vr.com/thread-31750-1-1.html UE4项目源码:DynamicClocks 动态时钟 http://www.52vr.co ...

  7. 搜集的一些项目源码,改改就能用

    UE4项目源码:房地产样板间4 http://www.52vr.com/thread-31714-1-1.html UE4项目源码:VR样板间案例,包括布料木料玻璃等 http://www.52vr. ...

  8. ASP.NET 3.5 新特性开发向导实践(附项目源码下载)

    ASP.NET 3.5 新特性开发向导实践(附项目源码下载) 本篇文章将演示ASP.NET 3.5 部分新功能.新特性,包括LINQ.ListView控件.LinqDataSource.DataPag ...

  9. Java智慧社区商业级别项目源码,拿来学习真不错

    介绍 HC小区物业管理系统是由java110团队于2017年4月份发起的前后端分离.分布式架构开源项目,目前我们的代码a开源在github 和gitee上, 开源项目由HC小区管理系统后端,HC小区管 ...

最新文章

  1. 联想 k2450 温度、耗电试验
  2. visual studio 2017 添加自定义代码片段 .snippet文件
  3. webpack为什么加载不了css?
  4. sql server 2000 删除重复数据
  5. C#_MVC_ajax for form
  6. prompt 你到底行不行?
  7. 华为发布国行版P40系列,售价4188元起;大疆回应“至少50%的裁员清扫计划”;Firefox 75发布 | 极客头条...
  8. android 输入支付密码错误,Android 支付宝支付密码输入界面
  9. 选择所在城市html按字母,移动端根据字母定位到指定的城市【原创】
  10. 数学建模练习-----基于无线通信基站的室内定位问题
  11. 计算机基础达 打字训练视频,「跟着八戒学电脑」快速打字必须掌握的基本功:指法练习...
  12. 50.网络安全渗透测试—[穷举篇13]—[wfuzz多线程百万密码测试指定后台破解]
  13. windows无法连接到某个wifi_Windows7无法连接到网络几招解决无线网络办法
  14. 诺基亚Lumia920竞争力分析软件篇—三星ATIV S、GALAXY S3、HTC One X、iPhone 5对比
  15. 使用CSS写正方体,结合JS实现3D轮播图
  16. 一对同居男女同一天的日记对比
  17. 【翻译】智能制造中EDA 应用及益处系列之四:精密故障检测与分类(FDC)
  18. AminoCapital:大数据+机械学习引领今年硅谷趋势
  19. 【JavaScript】MDN 阅读笔记
  20. java怎么设置cookie?java设置cookie教程

热门文章

  1. 玉米社:竞价推广创意如何优化,几个创意撰写技巧分享给你!
  2. matlab画图五角星标记,Matlab---画图线型、符号及颜色
  3. 备受全球瞩目的「USDT集体索赔案」来龙去脉|全文译本
  4. 基于RFID技术下的化工厂定位系统,包含化工厂人员定位解决方案-新导智能
  5. 学游戏原画都需要掌握哪些软件
  6. html 圆圈透明 其他不透明,Javascript HTML5 Canvas绘制透明圆圈
  7. varnish php,php实现监控varnish缓存服务器的状态_PHP
  8. 2023年品牌营销趋势是什么?如何提升品牌知名度
  9. 优秀课程案例:使用Scratch图形化编程工具做一个见缝插针游戏!
  10. 基于LD3320的51智能遥控语音小车