自然語言及語音處理項目式教程 實訓指導 實訓6 中文命名實體識別_第1頁
自然語言及語音處理項目式教程 實訓指導 實訓6 中文命名實體識別_第2頁
自然語言及語音處理項目式教程 實訓指導 實訓6 中文命名實體識別_第3頁
自然語言及語音處理項目式教程 實訓指導 實訓6 中文命名實體識別_第4頁
自然語言及語音處理項目式教程 實訓指導 實訓6 中文命名實體識別_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

《自然語言處理技術》表21所示。表STYLEREF1\s2SEQ表\*ARABIC\s11segment_by_window函數的常用參數說明參數名稱參數說明words_list接收numpy數組,表示需要進行滑動窗口分割的詞語列表。無默認值window接收int,表示滑動窗口的大小,即每個窗口包含的元素數量。默認為3運行窗口切分代碼,得到切分后的窗口列表如下。切分后的窗口列表:[['我','愛','自然'],['愛','自然','語言'],['自然','語言','處理']]從切分結果可以看出,表示原詞序列被切分成了3個大小為3的窗口。特征提取特征提取如REF_Ref131952966\h代碼27所示。首先,generator函數將字序列按照指定窗口大小切分成n元序列(word_grams),然后調用extract_feature函數來提取每個n元序列的特征(extract_feature函數將在本任務的第⑧小節(jié)中進行介紹)。最后,generator函數返回提取到的特征和對應的標簽序列。通過這個過程,可以將原始的字序列轉換為適用于訓練CRF模型的特征和標簽序列。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s17特征提取#特征提取defextract_feature(self,word_grams):passdefgenerator(self):#將字序列切分成n元序列word_grams=[self.segment_by_window(word_list)forword_listinself.word_seq]#提取n元序列的特征features=self.extract_feature(word_grams)#返回特征和標簽序列returnfeatures,self.tag_seq#設置詞序列corpus_process.word_seq=[['我','愛','自然','語言','處理']]#調用generator函數features=corpus_process.generator()#輸出結果print("特征序列:\n",features)運行特征提取代碼,針對文本進行特征提取的過程如下。原始文本:[[['我','愛','自然'],['愛','自然','語言'],['自然','語言','處理']]]文本特征:[[{'w-1':'我','w':'愛','w+1':'自然','w-1:w':'我愛','w:w+1':'愛自然','bias':1.0},{'w-1':'愛','w':'自然','w+1':'語言','w-1:w':'愛自然','w:w+1':'自然語言','bias':1.0},{'w-1':'自然','w':'語言','w+1':'處理','w-1:w':'自然語言','w:w+1':'語言處理','bias':1.0}]]特征序列:[[{'w-1':'我','w':'愛','w+1':'自然','w-1:w':'我愛','w:w+1':'愛自然','bias':1.0},{'w-1':'愛','w':'自然','w+1':'語言','w-1:w':'愛自然','w:w+1':'自然語言','bias':1.0},{'w-1':'自然','w':'語言','w+1':'處理','w-1:w':'自然語言','w:w+1':'語言處理','bias':1.0}]]從特征提取結果可以看出,原始文本是一個三維列表,每個子列表表示一句話,其中每個元素是一個單詞。文本特征是一個三維列表,每個子列表表示一句話,其中每個元素是一個字典,表示該單詞的特征,包括前一個單詞、當前單詞、后一個單詞、當前單詞與前一個單詞的組合、當前單詞與后一個單詞的組合以及偏置項。特征序列是一個二維列表,其中每個子列表表示一句話,其中每個元素是一個字典,表示該單詞的特征。為此,文本特征和特征序列的內容是一致的。CorpusProcess類重要函數說明為了更好的理解CorpusProcess類的框架運行過程,針對重要函數,如q_to_b函數、process_t函數、process_nr函數、process_k函數、extract_feature函數進行說明。q_to_b函數q_to_b函數將輸入字符串中的全角字符轉換為半角字符。全角字符是指在顯示時占據兩個半角字符寬度的字符,如全角英文字母、全角數字和全角標點符號。半角字符則僅占用一個標準字符寬度。在處理文本數據時,統(tǒng)一字符格式可以簡化后續(xù)的文本處理和分析任務。具體來說,q_to_b函數接受一個包含全角字符的字符串q_str作為輸入參數,然后遍歷q_str中的每個字符。如果字符是全角空格(內碼為12288),那么將其轉換為半角空格(內碼為32);如果字符是其他全角字符(內碼在65281~65374之間),那么將其內碼減去65248以得到相應的半角字符。最后,將轉換后的半角字符拼接到新字符串b_str中,并返回b_str。通過q_to_b函數將全角符號轉換為半角符號,如REF_Ref131699062\h代碼28所示。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s18q_to_b函數#全角轉半角defq_to_b(self,q_str):#初始化空字符串b_strb_str=""#遍歷字符串中每個字符forucharinq_str:#獲得字符的內碼inside_code=ord(uchar)#如果字符是全角空格,那么直接轉換為半角空格ifinside_code==12288:inside_code=32#如果字符是全角字符(除空格),那么根據關系轉換為半角字符elif65374>=inside_code>=65281:inside_code-=65248#將轉換后的字符拼接到b_str中b_str+=chr(inside_code)returnb_strq_str=',/w'#使用類的實例調用q_to_b函數print('未進行全角轉半角:\n',q_str)b_str=corpus_process.q_to_b(q_str)print('全角轉半角:\n',b_str)運行q_to_b函數代碼,未進行全角轉半角數據和全角轉半角數據如下。未進行全角轉半角:,/w全角轉半角:,/w從全角轉半角數據可以看出,全角逗號(',')被轉換為半角逗號(','),全角空格('')被轉換為半角空格('')。通過轉換全角字符為半角字符,可以使文本更加統(tǒng)一,并減少在后續(xù)文本處理和分析過程中可能出現(xiàn)的錯誤。process_t函數process_t函數合并語料庫中被分開標注的時間詞,將分散的時間詞合并成一個完整的時間表示,有助于簡化后續(xù)任務。process_t函數通過遍歷輸入的單詞列表,并檢查每個單詞是否包含時間標記。如果當前單詞是時間標記,那么函數會將其添加到一個臨時變量temp中,并移除標記。當遇到非時間標記的單詞時,函數會將臨時變量中累積的時間詞添加到處理后的單詞列表pro_words中,并將當前單詞也添加到該列表。最后,函數返回處理后的單詞列表。通過process_t函數將分散時間詞進行合并,如REF_Ref131699082\h代碼29所示。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s19process_t函數defprocess_t(self,words):"""處理時間,合并語料庫分開標注的時間詞,類似:(/w一九九七年/t十二月/t三十一日/t)/w"""pro_words=[]#初始化處理后的單詞列表index=0#初始化單詞位置temp=u''#初始化臨時變量whileTrue:word=words[index]ifindex<len(words)elseu''#獲取當前單詞,如果已經遍歷完了,那么設置為空字符串ifu'/t'inword:#判斷當前單詞是時間標記temp=temp.replace(u'/t',u'')+word#將當前單詞中的標記替換成空字符串,然后添加到臨時變量中eliftemp:#判斷臨時變量不為空pro_words.append(temp)#將臨時變量中的時間標記添加到處理后的單詞列表中pro_words.append(word)#將當前單詞添加到處理后的單詞列表中temp=u''#將臨時變量清空elifword:#判斷當前單詞不為空pro_words.append(word)#直接將當前單詞添加到處理后的單詞列表中else:#break#跳出循環(huán)index+=1#更新單詞位置returnpro_words#返回處理后的單詞列表words=['(/w','一九九七年/t','十二月/t','三十一日/t',')/w']pro_words=corpus_cess_t(words)print('未處理時間數據:\n',words[:])print('處理時間后的數據:\n',pro_words[:])運行process_t函數代碼,輸出未處理時間數據和處理時間后的數據如下。未處理時間數據:['(/w','一九九七年/t','十二月/t','三十一日/t',')/w']處理時間后的數據:['(/w','一九九七年十二月三十一日/t',')/w']從處理前后的時間數據中可以看出,處理時間數據后的列表顯示了將分開的時間詞語合并成一個完整時間,即'一九九七年/t'、'十二月/t'和'三十一日/t'被合并成了'一九九七年十二月三十一日/t'。這個處理過程有助于更準確地識別和表示文本中的時間信息,從而在進行時間實體識別、事件抽取或其他與時間相關的任務時,提高模型的準確性和效果。process_nr函數process_nr函數合并語料庫中分開標注的姓和名。在進行文本處理和分析時,將姓和名合并成一個完整的姓名,有助于簡化后續(xù)任務。process_nr函數通過遍歷輸入的單詞列表,并檢查每個單詞是否包含姓名標記。如果當前單詞是姓名標記,那么函數會檢查下一個單詞是否也是姓名標記。如果下一個單詞也是姓名標記,那么函數會將兩個姓名標記合并成一個完整的姓名。否則,函數會保留當前的姓名標記。最后,函數返回處理后的單詞列表。通過process_nr函數將分開的姓與名進行合并,如REF_Ref131953107\h代碼210所示。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s110process_nr函數defprocess_nr(self,words):"""處理姓名,合并語料庫分開標注的姓和名"""pro_words=[]#用于存儲處理后的詞語列表index=0#當前正在處理的詞語在列表中的索引whileTrue:#獲取當前詞語(如果有)或空字符串word=words[index]ifindex<len(words)elseu''ifu'/nr'inword:#如果當前詞語標注為“人名”(nr)next_index=index+1ifnext_index<len(words)andu'/nr'inwords[next_index]:#如果下一個詞語也是人名,那么將兩個詞語合并成一個pro_words.append(word.replace(u'/nr',u'')+words[next_index])index=next_index#將索引設置為下一個詞語的位置else:#如果下一個詞語不是人名,那么只保留當前詞語,去掉標注pro_words.append(word.replace(u'/nr',u''))elifword:#如果當前詞語不是人名且不為空,那么直接添加到處理后的列表中pro_words.append(word)else:#如果當前詞語為空字符串,那么說明已經處理完了所有詞語,退出循環(huán)breakindex+=1#處理下一個詞語returnpro_wordswords=['張/nr','三/nr','在/p','公司/n','工作/v']pro_words=corpus_cess_nr(words)print('未處理姓名數據:\n',words[:])print('處理姓名后的數據:\n',pro_words[:])運行process_nr函數代碼,輸出未處理姓名數據和處理姓名后的數據如下。未處理姓名數據:['張/nr','三/nr','在/p','公司/n','工作/v']處理姓名后的數據:['張三/nr','在/p','公司/n','工作/v']從輸出結果中可以看出,處理姓名數據后的列表顯示了將分開的姓名詞語合并成一個完整姓名,即'張/nr'和'三/nr'被合并成'張三/nr'。這個處理過程有助于更準確地識別和表示文本中的姓名,從而在進行命名實體識別、關系抽取或其他與人名相關的任務時,提高模型的準確性和效果。process_k函數process_k函數處理大粒度分詞,合并語料庫中括號的大粒度分詞。在分詞任務中,有時會遇到需要將多個連續(xù)的分詞合并為一個實體的情況。process_k函數用于處理這類情況,將括號內的詞組合并成一個整體。process_k函數通過遍歷輸入的單詞列表,并檢查每個單詞是否包含左括號“[”或右括號“]”。如果遇到左括號,那么函數將開始合并括號內的詞語,去除詞性標注,并將它們添加到一個臨時變量temp中。當遇到右括號時,函數會將括號內的詞語和右括號后面的詞性標注合并成一個新詞語,并添加到處理后的單詞列表pro_words中。如果遇到的單詞不屬于大粒度分詞,那么直接添加到處理后的單詞列表中。通過process_k函數處理大粒度分詞,如REF_Ref131699138\h代碼211所示。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s111process_k函數defprocess_k(self,words):"""處理大粒度分詞,合并語料庫中括號的大粒度分詞,類似:[國家/n環(huán)保局/n]nt"""pro_words=[]#用于存儲處理后的詞語列表index=0#當前正在處理的詞語在列表中的索引temp=u''#用于暫時存儲括號中的大粒度分詞whileTrue:#獲取當前詞語(如果有)或空字符串word=words[index]ifindex<len(words)elseu''ifu'['inword:#如果當前詞語包含左括號,那么說明遇到了一個大粒度分詞#去掉左括號和詞性標注,并添加到暫存字符串中temp+=re.sub(pattern=u'/[a-zA-Z]*',repl=u'',string=word.replace(u'[',u''))elifu']'inword:#如果當前詞語包含右括號,那么說明大粒度分詞已經結束#將當前詞語分成兩部分,去掉右括號后面的詞性標注w=word.split(u']')#去掉左括號和詞性標注,并添加到暫存字符串中temp+=re.sub(pattern=u'/[a-zA-Z]*',repl=u'',string=w[0])#將括號中的大粒度分詞和右括號后面的詞性標注合并成一個新詞語,并添加到處理后的列表中pro_words.append(temp+u'/'+w[1])#清空暫存字符串temp=u''eliftemp:#若暫存字符串中有內容,則說明當前詞語屬于大粒度分詞中的一個子詞語#去掉詞性標注,并添加到暫存字符串中temp+=re.sub(pattern=u'/[a-zA-Z]*',repl=u'',string=word)elifword:#若當前詞語不屬于大粒度分詞,也不是空字符串,則直接添加到處理后的列表中pro_words.append(word)else:#若當前詞語是空字符串,則說明已經處理完了所有詞語,退出循環(huán)breakindex+=1#處理下一個詞語returnpro_wordswords=['[上海/ns','浦東/ns]ns','是/v','中國/ns','最大/a','的/u','城市/n','之一/r',',/w','[中國/ns','環(huán)境/n','監(jiān)測/vn','總站/n]nt','位于/v','這里/r','。/w']pro_words=corpus_cess_k(words)print('未處理大粒度分詞的列表:\n',words[:])print('處理大粒度分詞后的列表:\n',pro_words[:])運行process_k函數代碼,未處理大粒度分詞的列表和處理大粒度分詞后的列表如下。未處理大粒度分詞的列表:['[上海/ns','浦東/ns]ns','是/v','中國/ns','最大/a','的/u','城市/n','之一/r',',/w','[中國/ns','環(huán)境/n','監(jiān)測/vn','總站/n]nt','位于/v','這里/r','。/w']處理大粒度分詞后的列表:['上海浦東/ns','是/v','中國/ns','最大/a','的/u','城市/n','之一/r',',/w','中國環(huán)境監(jiān)測總站/nt','位于/v','這里/r','。/w']從輸出結果可以看出,處理大粒度分詞后的列表顯示了將帶有括號的詞合并為一個更大的詞語,即'[上海/ns'和'浦東/ns]ns'被合并成'上海浦東/ns','[中國/ns','環(huán)境/n','監(jiān)測/vn','總站/n]nt'被合并成'中國環(huán)境監(jiān)測總站/nt'。這個處理過程有助于更好地理解和表示文本中的詞語結構和上下文關系。extract_feature函數extract_feature函數從文本中提取特征,將一個句子列表作為輸入,每個句子由多個單詞列表組成。該函數使用一個字窗口特征,它會遍歷每個句子中的每個單詞,并提取該單詞周圍的兩個單詞以及前一個單詞與當前單詞的組合和當前單詞與后一個單詞的組合。使用一個字窗口特征從句子中提取出來的特征構成了一個特征集合,它們被加入到整個句子的特征集合中,并且將特征集合清空。最后,extract_feature函數返回一個特征集合的列表,其中每個句子對應一個特征集合。通過extract_feature函數提取文本特征,如REF_Ref131953260\h代碼212所示。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s112extract_feature函數defextract_feature(self,word_grams):#初始化特征集和單個特征print('原始文本:\n',word_grams)features,feature_list=[],[]#對于每個句子,遍歷其所有的字窗口forindexinrange(len(word_grams)):foriinrange(len(word_grams[index])):#獲取當前窗口的所有單詞word_gram=word_grams[index][i]#提取特征,這里使用了字窗口特征feature={'w-1':word_gram[0],'w':word_gram[1],'w+1':word_gram[2],'w-1:w':word_gram[0]+word_gram[1],'w:w+1':word_gram[1]+word_gram[2],'bias':1.0}#將單個特征加入當前窗口的特征集feature_list.append(feature)#將當前窗口的特征集加入到整個句子的特征集中,并將特征集清空features.append(feature_list)feature_list=[]print('文本特征:\n',features)returnfeatures#訓練數據corpus=[[['我','愛','自然'],['愛','自然','語言'],['自然','語言','處理']],[['自然','語言','處理'],['是','人工','智能','的','核心']]]print('原始文本:\n',corpus)#對語料庫進行特征提取features=corpus_process.extract_feature(corpus)#輸出特征print(features)在REF_Ref131953260\h代碼212中,extract_feature函數的常用參數說明如REF_Ref131953229\h表22所示。表STYLEREF1\s2SEQ表\*ARABIC\s12extract_feature函數的常用參數說明參數名稱參數說明word_grams接收numpy數組,表示一個句子中的若干個字窗口,每個字窗口包含三個單詞。無默認值運行extract_feature函數后,得到原始文本及提取的文本特征如下。原始文本:[[['我','愛','自然'],['愛','自然','語言'],['自然','語言','處理']],[['自然','語言','處理'],['是','人工','智能','的','核心']]]文本特征:[[{'w-1':'我','w':'愛','w+1':'自然','w-1:w':'我愛','w:w+1':'愛自然','bias':1.0},{'w-1':'愛','w':'自然','w+1':'語言','w-1:w':'愛自然','w:w+1':'自然語言','bias':1.0},{'w-1':'自然','w':'語言','w+1':'處理','w-1:w':'自然語言','w:w+1':'語言處理','bias':1.0}],[{'w-1':'自然','w':'語言','w+1':'處理','w-1:w':'自然語言','w:w+1':'語言處理','bias':1.0},{'w-1':'是','w':'人工','w+1':'智能','w-1:w':'是人工','w:w+1':'人工智能','bias':1.0}]][[{'w-1':'我','w':'愛','w+1':'自然','w-1:w':'我愛','w:w+1':'愛自然','bias':1.0},{'w-1':'愛','w':'自然','w+1':'語言','w-1:w':'愛自然','w:w+1':'自然語言','bias':1.0},{'w-1':'自然','w':'語言','w+1':'處理','w-1:w':'自然語言','w:w+1':'語言處理','bias':1.0}],[{'w-1':'自然','w':'語言','w+1':'處理','w-1:w':'自然語言','w:w+1':'語言處理','bias':1.0},{'w-1':'是','w':'人工','w+1':'智能','w-1:w':'是人工','w:w+1':'人工智能','bias':1.0}]]從提取的文本特征可以看出,extract_feature函數對每個句子中的每個三元組進行特征提取。每個三元組生成一個特征集合,其中包含左鄰字、當前字、右鄰字、左鄰字和當前字的組合、當前字和右鄰字的組合以及一個偏置項。每個句子生成一個特征序列,其中包含其所有三元組的特征集合。CRF_NER類實現(xiàn)模型訓練與模型預測CRF_NER類主要實現(xiàn)的內容包括初始化CRF模型參數、定義模型、模型訓練、加載模型,如REF_Ref131699173\h代碼213所示。代碼STYLEREF1\s2SEQ代碼\*ARABIC\s113CRF_NER類的框架classCRF_NER(object):#初始化CRF模型參數def__init__(self):self.algorithm='lbfgs'self.c1='0.1'self.c2='0.1'self.max_iterations=100#迭代次數self.model_path='model.pkl'self.corpus=CorpusProcess()#Corpus實例self.corpus.pre_process()#語料預處理self.corpus.initialize()#初始化語料self.model=None#定義模型definitialize_model(self):algorithm=self.algorithmc1=float(self.c1)c2=float(self.c2)max_iterations=int(self.max_iterations)self.model=sklearn_crfsuite.CRF(algorithm=algorithm,c1=c1,c2=c2,max_iterations=max_iterations,all_possible_transitions=True)#模型訓練deftrain(self):#初始化模型print('訓練模型')self.initialize_model()#生成訓練集和測試集x,y=self.corpus.generator()x_train,y_train=x[100:],y[100:]x_test,y_test=x[:10],y[:10]#擬合模型self.model.fit(x_train,y_train)#計算模型性能并輸出labels=list(self.model.classes_)labels.remove('O')print('訓練結束')y_predict=self.model.predict(x_test)metrics.flat_f1_score(y_test,y_predict,average='weighted',labels=labels)sorted_labels=sorted(labels,key=lambdaname:(name[1:],name[0]))#print(metrics.flat_classification_report(y_test,y_predict,labels=sorted_labels,digits=3))#保存模型print('保存模型')self.save_model()defpredi

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論