從CRF測試結果中提取出連續的標註行
阿新 • • 發佈:2018-11-10
現在在處理一批CRF標註的語料,需要將測試結果中標為B、I的行提取出來,對於連續的B、I標註行,要在一起抽出。如有以下測試語料標註結果(片斷):
a a1 a2 O
b b1 b2 B
c c1 c2 I
d d1 d2 I
e e1 e2 O
f f1 f2 B
從中將b、c兩行合在一起抽出,f行要單獨抽取,目標結果格式如下:
[[[b,b1,b2,B],[c,c1,c2,I]],[f,f1,f2,B]]
解決思路:
1、利用根據字元切割的方法,將原始標註結果轉為列表型資料。
2、設定前後兩個遊標,遍歷列表中的每一句(標註結果中的空行表示句子結果),當發現有BI標註行時,將其抽取出來。
程式碼如下:
# -*- coding: utf8 -*-
'''
Created on 2015-7-15
@author: admin
'''
sents=[] #用於儲存結果的列表
tempLine=[] #用於儲存當前句的臨時列表
for eachLine in open('corpus/0701/testResult.txt','r',encoding='utf8'): #逐行讀取標結果檔案
if(eachLine!='\n'): #如果當前行不為空
colList=eachLine[0:-1].split('\t'); #根據製表符進行分隔,得到當前行的各列資料
tempLine.append(colList); # 將其追加到臨時列表中
else: #如果當前為空行
sents.append(tempLine); #說明一句讀完了,則新增到結果列表中
tempLine=[]; #清空臨時列表,等待下一句
# print(sents);
dict=[]; #用於儲存最終結果的列表
for sentId in range(len(sents)): #遍歷上述程式碼片斷的結果中的句子
tempDict=[]; #用於儲存當前捕捉到的結果的臨時列表
firstWordId=0; #第一個遍歷當前句子的遊標
while(firstWordId<len(sents[sentId])-1): # 開始迴圈
if(sents[sentId][firstWordId][-1]!='O' ): #如果發現有非O行
secondWordId=firstWordId+1; #設定第二個遍歷當前句子的遊標,從第一個遊標的下一元素開始
tempDict.append(sents[sentId][firstWordId]); #將當前行新增到臨時表中
while(secondWordId<len(sents[sentId])): #開始第二個遊標的迴圈
if(sents[sentId][secondWordId][-1]!='O'): #如果發現非O行
tempDict.append(sents[sentId][secondWordId]); #將當前行新增到臨時表中
else: #如果當前行的標註結果是O,說明前面發現的標結果已經捕捉完畢,
break; #中斷第二個遊標的迴圈
secondWordId+=1; #改變內層迴圈變數
dict.append(tempDict);#當內層迴圈結束時,說明已經發現了一組標註結果了,將他們整體新增到最終結果列表中
tempDict=[]; #清空臨時列表
firstWordId+=1; #改變外層迴圈變數
print(dict)