自动完形填空系统构建
自動完形填空系統構建要求
問題描述
在語義連貫的句子中去掉一個詞語,形成空格,要求在給出的對應備選答案中,系統自動選出一個最佳的答案,使語句恢復完整。
相關語料
1、 Training data:未標注訓練語料,供同學選擇使用。同學也可根據需要自行選擇其他語料,但需要在在實驗報告中注明所使用訓練語料的規模、來源及性質。
2、 Development set:
提供一份含有 240 句話的語料及答案,供同學自行測試結果,根據結果調整優化自己的算法。
3、 Test set:
提供一份含有 800 句話的測試語料,每句話有一個空格和 5 個備選答案。該語料不提供答案,同學提交測試結果,由助教統一評測。
評測方法
準確率=正確填空句子的個數/全部句子的個數
題目要求
要求同學根據自己設計訓練得到的系統,對測試語料進行預測,對每句話提供一個系統認為正確的選項。
本作業無統一標準方法,同學可自行設計模型,鼓勵同學積極創新。
提示:模型的構建可以簡單也可以復雜。例如,可以基于 n 元模型建立一個樸素的系統;也可以引入詞性、句法樹等;也可以使用神經網絡等其他方法;可以使用自行搜集到的詞典或者規則作為輔助。當然不限于這些方法,鼓勵創新。
作業要求
1、可分組進行,但每個小組的規模不能超過 2 人(即≤ 2)
2、實現相關程序,可用 c/c++、Python 以及 java 語言完成??蓞⒖季W上源代碼,但必須重新實現,要求程序代碼完整,有必要的說明文檔和 Makefile 等文件;
3、提供測試語料的預測結果,輸出文件以“題目號+選項+英文單詞”形式輸出,中間用空格或制表符間隔,每個答案占一行。例如:
1 choice1 answer1
...... ......
...... ......
800 choice 800 answer800
4、撰寫實驗報告以及 PPT。實驗報告以小論文的形式,要有必要的參考文獻等信息,將使用的方法講解清楚;PPT 用于在課堂上報告實驗成果;
5、將預測答案、實驗報告、PPT 及源程序提交到助教用以評分。
自動完形填空系統構建實驗報告
第一章? 基于n元模型構建的樸素系統
1.1?????????問題描述
在語義連貫的句子中去掉一個詞語,形成空格,每個空格有5個備選答案,要求在給出的對應備選答案中,系統自動選出一個最佳的答案,使語句恢復完整。
1.2?????????系統分析
n元模型中,一個詞的出現只與它的前n-1個詞有關。填空題的句子只有一個空格,設空格在句子中的位置為i,則i-2,i-1,i+1位置上的三個詞對于空格處應填詞語十分重要。因此,本系統采用2元模型與3元模型相結合的辦法。
1.3?????????系統設計與實現
系統可分為訓練數據、保存訓練數據、選擇答案、保存結果等部分。其大致流程如圖1.1所示。
圖1.1 系統流程圖
1.3.1讀取數據集
將詞頻、二元模型、三元模型的統計結果存儲到字典當中,字典的key代表詞和詞組,字典的value代表在語料中出現的次數,將字典分別寫入三個文件當中。統計結果如圖1.2所示。
圖1.2? 統計結果
1.3.2? 讀取數據集
在訓練好數據集之后,將上一步寫好的文件讀出來,存到字典當中,字典的key代表詞和詞組,字典的value代表在語料中出現的次數。
1.3.3? 選擇答案
每一道題分成題目和選項兩部分,針對每個選項計算四個參數,計算過程如圖1.3所示。根據四個概率相關的參數,選擇最佳答案。選擇過程如圖1.4所示。
圖1.3? 計算過程
圖1.4? 參數選擇過程
1.4?????????實驗過程與結果
1.4.1? 實驗過程
首先配置python2.7,安裝pip,按照官網提示安裝nltk,在pycharm中創建工程,并將數據集和測試集放在工程的目錄下,創建mynlp.py文件開始編碼,結果如圖1.5所示
圖1.5? 編碼結果
1.4.2? 實驗結果
運行mynlp.py文件,分別得到相關的文件結果。創建test.py,將計算結果與正確答案進行比較。比較結果如圖1.6所示,正確率可達到30%。
圖1.6? 測試結果
?
源碼
# encoding=utf-8 from nltk.util import ngrams from nltk import word_tokenize from nltk import sent_tokenize import osclass mynlp:training_data_path = 'Training_Data' # 該文件夾下存儲著所有的訓練數據test_data_path = 'Test_Data/development_set.txt' # 該文件存儲著用于開發的測試文檔result_file_path = 'result.txt' # 發送給助教的結果#test_data_path = 'Test_Data/test_set.txt'training_gram1_res = {} # 存儲一元模型的結果(詞頻)training_gram2_res = {} # 存儲二元模型的結果training_gram3_res = {} # 存儲三元模型的結果result_list = [] # 存儲計算結果def __init__(self):self.start()def start(self):# 第一步,讀取數據集,將詞頻、二元模型、三元模型存儲到字典當中,將元組寫入一個文件當中,訓練一次后可注釋掉# self.train_data()# 第二步,將寫好的文件讀出來,存到字典當中,(an,apple) : 2self.read_from_training()# 第三步,針對每一道題,將每個答案放到句子中,計算這個詞和前一個詞與后一個詞分別的2元模型,選取概率最大的那個self.select_result()# 第四步,將結果寫入文件,發給助教self.write_result()def train_data(self):datafiles = os.listdir(self.training_data_path)for i in datafiles:filename = self.training_data_path+'/'+if = open(filename)data = self.clear_string(str(f.readlines()))data_sent = sent_tokenize(data)for j in data_sent:data_words = word_tokenize(j)# 訓練一元組,求頻率for t in data_words:# t = self.clear_string(t)if t in self.training_gram1_res:self.training_gram1_res[t] += 1else:self.training_gram1_res[t] = 1# 訓練二元組training_gen = ngrams(data_words, 2)for k in training_gen:# k = self.clear_string(k)if k in self.training_gram2_res:self.training_gram2_res[k] += 1else:self.training_gram2_res[k] = 1# 訓練三元組training_gen = ngrams(data_words, 3)for b in training_gen:# b = self.clear_string(b)if b in self.training_gram3_res:self.training_gram3_res[b] += 1else:self.training_gram3_res[b] = 1f.close()result_file1 = open('result_1.txt', 'w')for i in self.training_gram1_res:result_file1.writelines(str(i)+' '+str(self.training_gram1_res[i])+'\n')result_file1.close()result_file2 = open('result_2.txt', 'w')for i in self.training_gram2_res:result_file2.writelines(str(i)+' '+str(self.training_gram2_res[i])+'\n')result_file2.close()result_file3 = open('result_3.txt', 'w')for i in self.training_gram3_res:result_file3.writelines(str(i)+' '+str(self.training_gram3_res[i])+'\n')result_file3.close()def clear_string(self, s):if len(s) > 1:return s.replace('\\r', '').replace('\\n', '').replace('\\', '').replace("'", "").replace("`", "")else:return sdef read_from_training(self):read_file1 = open('result_1.txt', 'r')for i in read_file1:read_gram_key = i.split(" ")[0]read_gram_num = int(i.split(" ")[1].replace('\n', ''))self.training_gram1_res[read_gram_key] = read_gram_numread_file1.close()read_file2 = open('result_2.txt', 'r')for i in read_file2:read_gram_key = i.split(" ")[0]read_gram_num = int(i.split(" ")[1].replace('\n', ''))self.training_gram2_res[read_gram_key] = read_gram_numread_file2.close()read_file3 = open('result_3.txt', 'r')for i in read_file3:read_gram_key = i.split(" ")[0]read_gram_num = int(i.split(" ")[1].replace('\n', ''))self.training_gram3_res[read_gram_key] = read_gram_numread_file3.close()def select_result(self):test_file = open(self.test_data_path, 'r').readlines()index = 0while index < len(test_file):question = test_file[index]choices = {}for l in range(5):k = test_file[index+l+1].split()[0]v = test_file[index+l+1].split()[1]choices[k] = vresult = self.get_best_choice(question, choices)# print resultself.result_list.append(result)index += 8def get_best_choice(self,question,choices):result = []q = question.split()question_num = q[0]space = q.index('_____')pre_pre = q[space-2]pre = q[space-1]nex = q[space+1]for c in choices:p31 = self.get_p3(pre_pre,pre,choices[c])p32 = self.get_p3(pre,choices[c],nex)p21 = self.get_p2(pre,choices[c])p22 = self.get_p2(choices[c],nex)l = [c,p31,p32,p21,p22]result.append(l)find = False# print question_nummax_choice = ''#第一步,選出p32*p31最大的max_p32_mul_p31 = float(0)for i in range(5):if result[i][1] * result[i][2] > max_p32_mul_p31:max_p32_mul_p31 = result[i][1] * result[i][2]max_choice = result[i][0]find = True# print 'p32*p31'# 第二步,如果第一步沒選出來,選出p32最大的max_p32 = float(0)if not find:for i in range(5):if result[i][2] > max_p32:max_p32 = result[i][2]max_choice = result[i][0]find = True# print 'p32'if max_p32 < 0.0005:find = False# 第三步,如果第一、二步沒選出來,選出p31最大的max_p31 = float(0)if not find:for i in range(5):if result[i][1] > max_p31:max_p31 = result[i][1]max_choice = result[i][0]find = True# print 'p31'if max_p31 < 0.0005:find = False# 第四步,如果第一、二、三步沒選出來,選出p21*p12最大的max_p21_mul_p12 = float(0)if not find:for i in range(5):if result[i][3]*result[i][4] > max_p21_mul_p12:max_p21_mul_p12 = result[i][3]*result[i][4]max_choice = result[i][0]find = True# print 'p2*p1'# 第五步,如果第一、二、三、四步沒選出來,選出p21最大的max_p21 = float(0)if not find:for i in range(5):if result[i][3] > max_p21:max_p21 = result[i][3]max_choice = result[i][0]find = True# print 'p21'# 第六步,如果第一、二、三、四、五步沒選出來,選出p22最大的max_p22 = float(0)if not find:for i in range(5):if result[i][4] > max_p22:max_p22 = result[i][4]max_choice = result[i][0]find = True# print 'p22'# 第七步,如果第一、二、三、四、五、六步沒選出來,選eif not find:max_choice = 'e)'# print 'e'return question_num+' ['+max_choice.replace(')','')+'] '+str(choices[max_choice])def get_p3(self, pre, mid, nex):c = float(0)k3 = "('"+pre+"', '"+mid+"', '"+nex+"')"k2 = "('"+pre+"', '"+mid+"')"if k3 in self.training_gram3_res:c = float(self.training_gram3_res[k3])/float(self.training_gram2_res[k2])return cdef get_p2(self, v1, v2):c = float(0)k = "('"+v1+"', '"+v2+"')"if k in self.training_gram2_res:c = float(self.training_gram2_res[k])/float(self.training_gram1_res[v1])else:if v1 in self.training_gram1_res:c = float(0.5)/float(self.training_gram1_res[v1])else:passreturn cdef write_result(self):result_file = open(self.result_file_path, 'w')for i in self.result_list:result_file.writelines(i+'\n')result_file.close()if __name__ == '__main__':mynlp()測試正確率源代碼
# encoding=utf-8 l1=[] l2=[]file = open('result.txt') for i in file:l1.append(i) file.close()file1 = open('Test_Data/development_set_answers.txt') for i in file1:l2.append(i) file1.close() c = 0 for i in range(len(l1)):if l1[i] == l2[i]:c += 1 # c 代表正確的數目print '結果:正確數目:'+str(c)+' 總共題目:'+str(len(l1))+' 正確率:'+str(float(c)/float(len(l1)))完整項目
https://download.csdn.net/download/kangyucheng/10504044
總結
以上是生活随笔為你收集整理的自动完形填空系统构建的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在“3_人民日报语料”中统计“日语借词”
- 下一篇: SQL语句求解同一人物不同日期,某一属性