继上文阅读了论文Neural Relation Extraction with Selective Attention over Instances后,就找源码来修修改改以完成关系抽取的任务。
论文源码是C++实现,在其github上面找到另一个整合了几篇论文更好的框架OpenNER
这不是少包,这是包在目录下没找到,只需要在import framework的地方修改为from . import framework即可
readme提供的数据链接下载下来后还要运行它提供的py文件才可以。而Py文件注意是python2.x的版本(强行转3有点坑)。
json需要用代码生成,如果直接手写内容的,会报编码错误
如果训练文件发生修改,则需要把process_data下的文件删除干净,否则默认读取上一次预处理好的文件
由于里面提供的是英文格式,关系抽取需要做中文的,所以这里记录一下中文的格式。词向量现在是随机,到时候肯定要用预模型。
import thulac
import numpy as np
import json
# 生成词向量
thu1 = thulac.thulac(seg_only=True) #默认模式
text = thu1.cut("工商注册地、税务征管关系及统计关系在广州市南沙区范围内", text=True) #进行一句话分词
print(text)
text1 = thu1.cut("工商注册地、税务征管关系及统计关系在广州市南沙区范围内", text=True) #进行一句话分词
print(text1)
text2 = thu1.cut("企业具有独立法人资格", text=True) #进行一句话分词
print(text2)
words=text.split(" ")
word_list=[]
for w in words:
word_vec={}
w2v=np.random.rand(1,300)
word_vec['word']=w
word_vec['vec']=list(w2v[0])
word_list.append(word_vec)
words=text1.split(" ")
for w in words:
word_vec={}
w2v=np.random.rand(1,300)
word_vec['word']=w
word_vec['vec']=list(w2v[0])
word_list.append(word_vec)
words=text2.split(" ")
for w in words:
word_vec={}
w2v=np.random.rand(1,300)
word_vec['word']=w
word_vec['vec']=list(w2v[0])
word_list.append(word_vec)
jsonArr = json.dumps(word_list, ensure_ascii=False)
with open('word_vec.json','w')as f:
f.write(jsonArr)
### 生成训练集
import json
thu1 = thulac.thulac(seg_only=True) #默认模式
text = thu1.cut("工商注册地、税务征管关系及统计关系在广州市南沙区范围内", text=True) #进行一句话分词
print(text)
text1 = thu1.cut("工商注册地、税务征管关系及统计关系在广州市南沙区范围内", text=True) #进行一句话分词
print(text1)
text2 = thu1.cut("企业具有独立法人资格", text=True) #进行一句话分词
print(text2)
word_list=[
{
"sentence": text,
"head": {"word": "工商注册地","id":"1"},
"tail": {"word": "广州市南沙区","id":"2"},
"relation": "范围内"
},
{
"sentence": text1,
"head": {"word": "税务征管关系","id":"3"},
"tail": {"word": "广州市南沙区","id":"2"},
"relation": "范围内"
},
{
"sentence": text2,
"head": {"word": "企业","id":"4"},
"tail": {"word": "独立法人资格","id":"5"},
"relation": "具有"
}
]
jsonArr = json.dumps(word_list, ensure_ascii=False)
with open('train.json','w')as f:
f.write(jsonArr)
with open('test.json','w')as f:
f.write(jsonArr)
word_list={"NA": 0, "范围内": 1,"具有":2}
jsonArr = json.dumps(word_list, ensure_ascii=False)
with open('rel2id.json','w')as f:
f.write(jsonArr)
计算AUC
flag表示0/1正负
但是没看懂的是为什么prec和recall的底数。然后auc的是根据阈值计算面积的,这里为什么直接就计算auc了。
for i, item in enumerate(sorted_test_result[::-1]):
# 我觉得这个指标有问题
correct += item['flag']
prec.append(float(correct) / (i + 1))
recall.append(float(correct) / self.test_data_loader.relfact_tot)
auc = sklearn.metrics.auc(x=recall, y=prec)
所以AUC一般都是偏低的,哪怕准确率比较高的情况下