1. 程式人生 > >從CRF測試結果中提取出連續的標註行

從CRF測試結果中提取出連續的標註行

現在在處理一批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)