구조화되지 않은 텍스트에서 구조화된 정보와 데이터를 추출하는 시스템을 구축하는 방법은 무엇입니까? 이러한 유형의 동작을 사용하는 방법은 무엇입니까? 이 작업에 적합한 말뭉치는 무엇입니까? 모델을 훈련하고 평가하는 것이 가능합니까?
정보 추출, 특히 구조화된 정보 추출은 데이터베이스 기록과 비교할 수 있습니다. 해당 관계는 해당 데이터 정보를 바인딩합니다. 자연어와 같은 비정형 데이터의 경우 해당 관계를 얻기 위해서는 문자열, 요소 등의 일부 데이터 구조를 이용하여 해당 엔터티에 해당하는 특별한 관계를 검색하고 기록해야 합니다.
예: We saw the yellow dog 차단이라는 개념에 따라 마지막 세 단어는 NP로 나뉘고 그 안에 있는 세 단어는 DT/JJ/NN에 해당합니다. ; 각각 VBD에 할당됩니다. 마지막 세 단어의 경우 NP는 청크(더 큰 집합)입니다. 이를 달성하기 위해 정규 표현식과 유사한 NLTK 고유의 청킹 구문을 사용하여 문장 청킹을 구현할 수 있습니다.
청킹 구문 구성다음 세 가지 사항에 주의하세요. 청크: {청크 아래 하위 청크}
(유사: "NP: { 3c7d5858e48edc7bb17af0ecefbb969f?6cfae209252e1b07fe4ad75a2fa1207e*5fc4495b6ab379cc2effe1ed9ae99dc1}"
이와 같은 문자열). 그리고 ?*+는 정규식의 의미를 저장합니다.
组块 :{组块下的子组块}
(类似于:"NP: {3c7d5858e48edc7bb17af0ecefbb969f?6cfae209252e1b07fe4ad75a2fa1207e*5fc4495b6ab379cc2effe1ed9ae99dc1}"
这样的字符串)。而?*+保存了正则表达式的意义。import nltk sentence = [('the','DT'),('little','JJ'),('yellow','JJ'),('dog','NN'),('brak','VBD')] grammer = "NP: {<DT>?<JJ>*<NN>}"cp = nltk.RegexpParser(grammer) #生成规则result = cp.parse(sentence) #进行分块print(result) result.draw() #调用matplotlib库画出来
可以为不包括再大块中的标识符序列定义一个缝隙:}de249b3114fb1469cc68e2fe29baa3f0+{
import nltk sentence = [('the','DT'),('little','JJ'),('yellow','JJ'),('dog','NN'),('bark','VBD'),('at','IN'),('the','DT'),('cat','NN')] grammer = """NP: {<DT>?<JJ>*<NN>} }<VBD|NN>+{ """ #加缝隙,必须保存换行符cp = nltk.RegexpParser(grammer) #生成规则result = cp.parse(sentence) #进行分块print(result)
可以递归式的调用,这符合语言结构中的递归嵌套。例如:VP: {f33e0e9799d61cc5dd2a85bb2d5920ae*} PP:{5fc4495b6ab379cc2effe1ed9ae99dc1c068b0175345b8eb93ba13c561f8b4a4}
。此时,RegexpParser
函数的参数loop
即可以设置为2,多次循环,来防止遗漏。
如果调用print(type(result))
查看类型就会发现,是 nltk.tree.Tree
。从名字看出来这是一种树状结构。nltk.Tree
可以实现树状结构,并且支持拼接技术,提供结点的查询和树的绘制。
tree1 = nltk.Tree('NP',['Alick'])print(tree1) tree2 = nltk.Tree('N',['Alick','Rabbit'])print(tree2) tree3 = nltk.Tree('S',[tree1,tree2])print(tree3.label()) #查看树的结点tree3.draw()
分别代表内部,外部,开始(就是英语单词的首字母)。对于上面讲的 NP,NN这样的分类,只需要在前面加上 I-/B-/O-即可。这样就能使规则外的集合被显式出来,类似上面的加缝隙。
NLTK已经为我们提供了分块器,减少了手动构建规则。同时,也提供了已经分块好的内容,供我们自己构建规则时候进行参考。
#这段代码在python2下运行from nltk.corpus import conll2000print conll2000.chunked_sents('train.txt')[99] #查看已经分块的一个句子text = """ he /PRP/ B-NP accepted /VBD/ B-VP the DT B-NP position NN I-NP of IN B-PP vice NN B-NP chairman NN I-NP of IN B-PP Carlyle NNP B-NP Group NNP I-NP , , O a DT B-NP merchant NN I-NP banking NN I-NP concern NN I-NP . . O"""result = nltk.chunk.conllstr2tree(text,chunk_types=['NP'])
对于之前自己定义的规则cp
,可以使用cp.evaluate(conll2000.chunked_sents('train.txt')[99])
来测试正确率。利用之前学过的Unigram标注器,可以进行名词短语分块,并且测试准确度
class UnigramChunker(nltk.ChunkParserI):""" 一元分块器, 该分块器可以从训练句子集中找出每个词性标注最有可能的分块标记, 然后使用这些信息进行分块 """def __init__(self, train_sents):""" 构造函数 :param train_sents: Tree对象列表 """train_data = []for sent in train_sents:# 将Tree对象转换为IOB标记列表[(word, tag, IOB-tag), ...]conlltags = nltk.chunk.tree2conlltags(sent)# 找出每个词性标注对应的IOB标记ti_list = [(t, i) for w, t, i in conlltags] train_data.append(ti_list)# 使用一元标注器进行训练self.__tagger = nltk.UnigramTagger(train_data)def parse(self, tokens):""" 对句子进行分块 :param tokens: 标注词性的单词列表 :return: Tree对象 """# 取出词性标注tags = [tag for (word, tag) in tokens]# 对词性标注进行分块标记ti_list = self.__tagger.tag(tags)# 取出IOB标记iob_tags = [iob_tag for (tag, iob_tag) in ti_list]# 组合成conll标记conlltags = [(word, pos, iob_tag) for ((word, pos), iob_tag) in zip(tokens, iob_tags)]return nltk.chunk.conlltags2tree(conlltags) test_sents = conll2000.chunked_sents("test.txt", chunk_types=["NP"]) train_sents = conll2000.chunked_sents("train.txt", chunk_types=["NP"]) unigram_chunker = UnigramChunker(train_sents)print(unigram_chunker.evaluate(test_sents))
命名实体:确切的名词短语,指特定类型的个体,如日期、人、组织等 。如果自己去许梿分类器肯定头大(ˉ▽ ̄~)~~。NLTK提供了一个训练好的分类器--nltk.ne_chunk(tagged_sent[,binary=False])
sent = nltk.corpus.treebank.tagged_sents()[22]print(nltk.ne_chunk(sent,binary=True))
더 큰 청크에 포함되지 않은 식별자 시퀀스에 대해 gap을 정의할 수 있습니다: }de249b3114fb1469cc68e2fe29baa3f0+ { code>
#请在Python2下运行import re IN = re.compile(r'.*\bin\b(?!\b.+ing)')for doc in nltk.corpus.ieer.parsed_docs('NYT_19980315'):for rel in nltk.sem.extract_rels('ORG','LOC',doc,corpus='ieer',pattern = IN):print nltk.sem.show_raw_rtuple(rel)
VP: {<np pp:> . 이때, <code>RegexpParser
함수의 loop
매개변수를 2로 설정하여 여러번 반복하여 누락을 방지할 수 있습니다. 🎜🎜트리 다이어그램🎜🎜print(type(result))
를 호출하여 유형을 보면 nltk.tree.Tree라는 것을 알 수 있습니다.
. 이름에서 알 수 있듯이 나무 모양의 구조입니다. nltk.Tree
는 트리 구조를 구현하고 스플라이싱 기술을 지원하며 노드 쿼리 및 트리 그리기를 제공합니다. 🎜🎜rrreee🎜🎜🎜🎜🎜IOB 마크🎜🎜는 각각 내부, 외부, 시작(영문 단어의 첫 글자)을 의미합니다. 위에서 언급한 NP, NN과 같은 분류의 경우 앞에 I-/B-/O-만 추가하면 됩니다. 이를 통해 위의 간격을 추가하는 것과 유사하게 규칙 외부의 컬렉션이 노출될 수 있습니다. 🎜cp
의 경우 cp.evaluate(conll2000.chunked_sents('train.txt')[99])
를 사용할 수 있습니다. 정확성을 테스트하기 위해. 이전에 배운 Unigram 태거를 사용하여 명사구를 덩어리로 분할하고 정확성을 테스트할 수 있습니다🎜🎜rrreee🎜🎜🎜🎜🎜명명된 엔터티 인식 및 정보 추출🎜🎜🎜명명된 엔터티: 특정 유형을 참조하는 정확한 명사구 날짜, 사람, 조직 등 개인 🎜. 서옌분류사 혼자 가보시면 머리 엄청 크실거에요(ˉ▽ ̄~)~~. NLTK는 훈련된 분류기인 nltk.ne_chunk(tagged_sent[,binary=False])
를 제공합니다. 바이너리가 True로 설정되면 명명된 엔터티는 NE로만 태그가 지정됩니다. 그렇지 않으면 태그가 좀 더 복잡해집니다. 🎜🎜rrreee🎜🎜🎜🎜🎜이름이 지정된 개체가 결정되면 🎜관계 추출🎜을 구현하여 정보를 추출할 수 있습니다. 한 가지 방법은 모든 트리플(X,a,Y)을 찾는 것입니다. 여기서 X와 Y는 명명된 엔터티이고 a는 둘 사이의 관계를 나타내는 문자열입니다. 예는 다음과 같습니다. 🎜🎜rrreee🎜🎜🎜위 내용은 시스템을 구축하는 방법?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!