├── LICENSE ├── code ├── .ipynb_checkpoints │ └── online-checkpoint.py ├── __pycache__ │ ├── baiduSpider.cpython-36.pyc │ ├── featQA.cpython-36.pyc │ ├── loader.cpython-36.pyc │ ├── lossQA.cpython-36.pyc │ ├── online_util.cpython-36.pyc │ ├── preQA.cpython-36.pyc │ ├── simQA.cpython-36.pyc │ ├── test.cpython-36.pyc │ ├── test2.cpython-36.pyc │ ├── train.cpython-36.pyc │ ├── train_loss.cpython-36.pyc │ └── util.cpython-36.pyc ├── baiduSpider.py ├── baselineQA.py ├── crf.py ├── loader.py ├── main.py ├── online_util.py ├── test.py ├── train.py ├── train_crf.py └── util.py ├── data ├── readme.txt ├── validation.ann.h5 └── vocabulary.txt ├── demo展示.mp4 ├── evaluation ├── datapoint.py ├── evaluate-tagging-result.py ├── evaluate-voting-result.py ├── evaluation_stats_util.py ├── example │ ├── raw_prediction_example.txt │ ├── refs │ │ ├── fuzzy-matching.ref │ │ ├── strict-matching.ref │ │ ├── vote-fuzzy-matching.ref │ │ └── vote-strict-matching.ref │ ├── run-example.sh │ └── test_file_example.json.gz ├── fuzzy_matching.py ├── ioutil.py ├── names.py ├── raw_result_parser.py ├── re_util.py ├── state_matcher.py ├── state_names.py ├── synsets.py ├── tagging_evaluation_util.py ├── tagging_util.py └── voter.py ├── model ├── charQA_2017-08-14 │ └── f1-0.5593_0.36519_2 └── test.crfsuite ├── online ├── Lawclf.py ├── __pycache__ │ ├── Lawclf.cpython-34.pyc │ ├── Lawclf.cpython-35.pyc │ ├── model_util.cpython-36.pyc │ ├── models.cpython-34.pyc │ ├── models.cpython-35.pyc │ ├── models.cpython-36.pyc │ ├── start_server_stable.cpython-34.pyc │ ├── util.cpython-34.pyc │ └── util.cpython-35.pyc ├── model_util.py ├── start_server_stable.py ├── static │ ├── css │ │ └── sticky-footer.css │ └── ipin-logo-gray-bg.png └── templates │ ├── base.html │ ├── foot.html │ ├── index.html │ └── main.html ├── readme.txt ├── webQA_data ├── readme.txt ├── validation.ann.json └── 数据集说明.md └── 基于阅读理解的QA综述.pdf /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Shuting Su 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /code/.ipynb_checkpoints/online-checkpoint.py: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /code/__pycache__/baiduSpider.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/baiduSpider.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/featQA.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/featQA.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/loader.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/loader.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/lossQA.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/lossQA.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/online_util.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/online_util.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/preQA.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/preQA.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/simQA.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/simQA.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/test.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/test.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/test2.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/test2.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/train.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/train.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/train_loss.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/train_loss.cpython-36.pyc -------------------------------------------------------------------------------- /code/__pycache__/util.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/code/__pycache__/util.cpython-36.pyc -------------------------------------------------------------------------------- /code/baiduSpider.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | import time 4 | import jieba 5 | import urllib 6 | from tqdm import * 7 | import time, threading 8 | from time import ctime 9 | from sklearn.feature_extraction.text import CountVectorizer 10 | from sklearn.feature_extraction.text import TfidfTransformer 11 | 12 | stopwords = ['是', '的', '谁', '什么', '和', '了', '我', '你', '知道', '哪', '?', '?', ',', ',', '.', '。', ':', ':'] 13 | 14 | def clean_question(question): 15 | ques = list(jieba.cut(question)) 16 | for w in stopwords: 17 | if w in ques: ques.remove(w) 18 | return ques 19 | 20 | def match_key_words(main_ques, other): 21 | #if len(other) < 8: 22 | # return True 23 | for word in main_ques: 24 | if word in other: 25 | return True 26 | return False 27 | 28 | 29 | def get_page(ques, one, url): 30 | evidences = [] 31 | 32 | page_question_No = 1 + one 33 | wb_data = requests.get(url) 34 | wb_data.encoding = ('gbk') 35 | soup = BeautifulSoup(wb_data.text, 'lxml') 36 | webdata = soup.select('a.ti') 37 | 38 | for title,url in zip(webdata, webdata): 39 | #data = [title.get('title'), url.get('href')] 40 | #print(page_question_No, ' ------------------------------------ \n') 41 | #print ('Question: ', title.get_text(), '\n') 42 | 43 | url_sub = url.get('href') 44 | wb_data_sub = requests.get(url_sub) 45 | wb_data_sub.encoding = ('gbk') 46 | soup_sub = BeautifulSoup(wb_data_sub.text, 'lxml') 47 | best_answer = soup_sub.find('pre', class_ = "best-text mb-10") 48 | 49 | if best_answer != None: 50 | best = best_answer.get_text(strip = True) 51 | if match_key_words(ques, best): 52 | evidences.append(best) 53 | 54 | else: 55 | better_answer = soup_sub.find_all('div', class_ = "answer-text line") 56 | 57 | if better_answer != None: 58 | for i_better, better_answer_sub in enumerate(better_answer): 59 | better = better_answer_sub.get_text(strip = True) 60 | if match_key_words(ques, better): 61 | evidences.append(better) 62 | 63 | page_question_No += 1 64 | 65 | return evidences 66 | 67 | evidencess = [] 68 | def get_evidences(question, pages = 20): 69 | print('Getting eivdences from baiduzhidao....') 70 | url = "https://zhidao.baidu.com/search?word=" + urllib.parse.quote(question) + "&pn=" 71 | 72 | ques = clean_question(question) 73 | evidences_list = [] 74 | for one in tqdm(range(0, pages, 10)): 75 | evidencess = [] 76 | #evidences = get_multi_thread_page(ques, one, url + str(one)) 77 | evidences = get_page(ques, one, url + str(one)) 78 | if evidences != []: 79 | evidences_list.extend(evidences) 80 | time.sleep(2) 81 | 82 | print('evidences: ', len(evidences_list)) 83 | #evidences_list = rank(evidneces_list) 84 | return evidences_list 85 | 86 | # --------------------------------- 87 | 88 | 89 | #evidencess = [] 90 | lock = threading.Lock() 91 | def get_href(ques, title, url): 92 | url_sub = url.get('href') 93 | wb_data_sub = requests.get(url_sub) 94 | wb_data_sub.encoding = ('gbk') 95 | soup_sub = BeautifulSoup(wb_data_sub.text, 'lxml') 96 | best_answer = soup_sub.find('pre', class_ = "best-text mb-10") 97 | 98 | evidences = ['no_answer'] 99 | if best_answer != None: 100 | best = best_answer.get_text(strip = True) 101 | if match_key_words(ques, best): 102 | if lock.acquire(): 103 | evidencess.append(best) 104 | lock.release() 105 | #print(evidencess) 106 | else: 107 | better_answer = soup_sub.find_all('div', class_ = "answer-text line") 108 | 109 | if better_answer != None: 110 | for i_better, better_answer_sub in enumerate(better_answer): 111 | better = better_answer_sub.get_text(strip = True) 112 | if match_key_words(ques, better): 113 | if lock.acquire(): 114 | evidencess.append(better) 115 | lock.release() 116 | #print(evidencess) 117 | #return 1 #evidences 118 | 119 | def get_multi_thread_page(ques, one, url): 120 | threads = [] 121 | #evidences = [] 122 | 123 | page_question_No = 1 + one 124 | wb_data = requests.get(url) 125 | wb_data.encoding = ('gbk') 126 | soup = BeautifulSoup(wb_data.text, 'lxml') 127 | webdata = soup.select('a.ti') 128 | nb_thread = len(webdata) 129 | 130 | for i in range(nb_thread): 131 | t = threading.Thread(target=get_href(ques, webdata[i], webdata[i]), name='LoopThread') 132 | threads.append(t) 133 | t.start() 134 | 135 | for t in threads: 136 | t.join() 137 | #href_evidences = t.get_result() 138 | #evidneces.extend(href_evidences) 139 | 140 | return evidencess 141 | 142 | if __name__ == '__main__': 143 | question = '三生三世十里桃花女主角是谁?' 144 | evidences = get_evidences(question) 145 | #print(evidences) 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /code/baselineQA.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.autograd as autograd 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from torch.autograd import Variable 6 | import numpy as np 7 | 8 | class baselineQA(nn.Module): 9 | 10 | def __init__(self, vocab_size, param, embeds): 11 | super(baselineQA, self).__init__() 12 | self.vocab_size = vocab_size 13 | self.embedding_size = param.embedding_size 14 | self.qe_embedding_size = param.qe_embedding_size 15 | 16 | self.tagset_size = param.tagset_size 17 | self.evidence_size = param.evidence_size 18 | self.q_hidden_size = 48 #param.q_hidden_size 19 | self.e_hidden_size = 96 #param.e_hidden_size 20 | self.t_hidden_size = param.t_hidden_size 21 | self.num_layers = 1 22 | 23 | self.lookup = nn.Embedding(self.vocab_size, self.embedding_size) 24 | self.q_lookup = nn.Embedding(2, self.qe_embedding_size) 25 | self.e_lookup = nn.Embedding(2, self.qe_embedding_size) 26 | 27 | if param.pre_embeds == True : 28 | self.lookup.weight.data.copy_(torch.from_numpy(embeds)) 29 | for param in self.lookup.parameters(): 30 | param.requires_grad = False 31 | 32 | self.q_size = self.embedding_size + self.q_hidden_size + self.qe_embedding_size * 2 33 | self.q_lstm = nn.LSTM(self.embedding_size, self.q_hidden_size, self.num_layers, dropout = 0.1) 34 | self.e_lstm = nn.LSTM(self.q_size, self.e_hidden_size // 2, self.num_layers, dropout = 0.2, bidirectional = True) 35 | self.t_lstm = nn.LSTM(self.e_hidden_size, self.t_hidden_size, self.num_layers) 36 | 37 | self.att_linear = nn.Linear(self.q_hidden_size, 1) 38 | self.hidden2tag_linear = nn.Linear(self.e_hidden_size, self.tagset_size + 1) 39 | self.norm = nn.BatchNorm1d(self.evidence_size, self.e_hidden_size) 40 | 41 | #self.weight = torch.FloatTensor([2.0, 2.0, 0.6, 0.6, 0]).cuda() # char 08-12 / 13 42 | #self.weight = torch.FloatTensor([2.2, 2.0, 0.5, 0.5, 0]).cuda() #char 08-11 43 | #self.weight = torch.FloatTensor([2.0, 2.0, 0.8, 0.8, 0]).cuda() #score 08-12 44 | self.weight = torch.FloatTensor([2.0, 2.0, 0.2, 0.2, 0]).cuda() # char 14 45 | self.loss_func = nn.NLLLoss(weight = self.weight) 46 | 47 | #self.loss_func = nn.NLLLoss() 48 | 49 | 50 | def init_hidden(self, num_layers, batch_size, hidden_size): 51 | h0 = Variable(torch.zeros(num_layers, batch_size, hidden_size)).cuda() 52 | c0 = Variable(torch.zeros(num_layers, batch_size, hidden_size)).cuda() 53 | return (h0, c0) 54 | 55 | 56 | # x = (batch, seq_len, hsize) 57 | # return (batch, hidden_size) 58 | def attention(self, x, x_mask): 59 | x_flat = x.view(-1, x.size(-1)) 60 | scores = self.att_linear(x_flat).view(x.size(0), x.size(1)) 61 | scores.data.masked_fill_(x_mask.data, -float('inf')) 62 | weights = F.softmax(scores) 63 | out = weights.unsqueeze(1).bmm(x).squeeze(1) 64 | return out 65 | 66 | 67 | # return pack rnn inputs 68 | def get_pack_rnn_inputs(self, x, x_mask): 69 | lengths = x_mask.data.eq(0).long().sum(1).squeeze() 70 | _, idx_sort = torch.sort(lengths, dim = 0, descending = True) 71 | _, idx_unsort = torch.sort(idx_sort, dim = 0) 72 | 73 | lengths = list(lengths[idx_sort]) 74 | 75 | # sort x 76 | x = x.index_select(0, Variable(idx_sort)) 77 | x = x.transpose(0, 1).contiguous() 78 | rnn_input = nn.utils.rnn.pack_padded_sequence(x, lengths) 79 | 80 | return rnn_input, Variable(idx_unsort) 81 | 82 | 83 | def get_pad_rnn_outputs(self, output, x_mask, idx_unsort): 84 | output = nn.utils.rnn.pad_packed_sequence(output)[0] 85 | 86 | # transpose and unsort 87 | output = output.transpose(0, 1).contiguous() 88 | output = output.index_select(0, idx_unsort) 89 | 90 | # pad up to original batch sequence length 91 | if output.size(1) != x_mask.size(1): 92 | padding = torch.zeros(output.size(0), 93 | x_mask.size(1) - output.size(1), 94 | output.size(2)).type(output.data.type()) 95 | output = torch.cat([output, Variable(padding)], 1) 96 | 97 | return output 98 | 99 | 100 | # embeds = (batch, seq_len, embedding_size) 101 | # return (batch, q_size) 102 | def question_lstm(self, question, q_mask): 103 | batch_size = question.size()[0] 104 | embeds = self.lookup(question) 105 | inputs, idx_unsort = self.get_pack_rnn_inputs(embeds, q_mask) 106 | 107 | init_hidden = self.init_hidden(self.num_layers, batch_size, self.q_hidden_size) 108 | lstm_out, _ = self.q_lstm(inputs, init_hidden) 109 | lstm_out = self.get_pad_rnn_outputs(lstm_out, q_mask, idx_unsort) 110 | 111 | lstm_vector = self.attention(lstm_out, q_mask) 112 | return lstm_vector 113 | 114 | 115 | # return (batch, seq_len, e_size) 116 | def evidence_lstm(self, evidence, q_vector, q_tag, e_tag, e_mask): 117 | batch_size = evidence.size()[0] 118 | embeds = self.lookup(evidence) 119 | q_feat, e_feat = self.q_lookup(q_tag), self.e_lookup(e_tag) 120 | 121 | q_vector = q_vector.expand(self.evidence_size, *q_vector.size()) 122 | q_vector = q_vector.transpose(0,1).contiguous() 123 | 124 | inputs = torch.cat([embeds, q_vector, q_feat, e_feat], -1) 125 | inputs, idx_unsort = self.get_pack_rnn_inputs(inputs, e_mask) 126 | 127 | init_hidden = self.init_hidden(self.num_layers * 2, batch_size, self.e_hidden_size // 2) 128 | lstm_out, _ = self.e_lstm(inputs, init_hidden) 129 | 130 | lstm_out = self.get_pad_rnn_outputs(lstm_out, e_mask, idx_unsort) 131 | return lstm_out 132 | 133 | 134 | # return (batch, seq_len, t_size) 135 | def tagger_lstm(self, inputs, e_mask, batch_size, idx_unsort): 136 | init_hidden = self.init_hidden(self.num_layers, batch_size, self.t_hidden_size) 137 | lstm_out, _ = self.t_lstm(inputs, init_hidden) 138 | lstm_out = self.get_pad_rnn_outputs(lstm_out, e_mask, idx_unsort) 139 | return lstm_out 140 | 141 | 142 | # return (batch, seq_len, tsize) 143 | def get_lstm(self, question, evidence, q_mask, e_mask, q_feat, e_feat): 144 | q_lstm = self.question_lstm(question, q_mask) 145 | e_lstm = self.evidence_lstm(evidence, q_lstm, q_feat, e_feat, e_mask) 146 | #t_lstm = self.tagger_lstm(e_lstm, e_mask, batch_size, idx_unsort) 147 | lstm = self.norm(e_lstm) 148 | return e_lstm 149 | 150 | 151 | # return (batch, seq_len, tag_size) 152 | def forward(self, question, evidence, q_mask, e_mask, q_feat, e_feat): 153 | lstm = self.get_lstm(question, evidence, q_mask, e_mask, q_feat, e_feat) 154 | score_list = [] 155 | for t in lstm: 156 | tag_space = self.hidden2tag_linear(t) 157 | tag_scores = F.log_softmax(tag_space) 158 | score_list.append(tag_scores) 159 | scores = torch.cat(score_list, 0).view(len(score_list), *score_list[0].size()) 160 | return scores 161 | 162 | 163 | # return (batch, seq_len) 164 | def get_tags(self, question, evidence, q_mask, e_mask, q_feat, e_feat): 165 | scores = self.forward(question, evidence, q_mask, e_mask, q_feat, e_feat) 166 | score, tags = torch.max(scores, dim = -1) 167 | return score.data.cpu().tolist(), tags.data.cpu().tolist() 168 | 169 | ''' 170 | # return (batch, seq_len) 171 | def get_tags(self, question, evidence, q_mask, e_mask, q_feat, e_feat): 172 | scores = self.forward(question, evidence, q_mask, e_mask, q_feat, e_feat) 173 | score, tags = torch.max(scores, dim = -1) 174 | return tags.data.cpu().tolist() 175 | ''' 176 | 177 | # return one value 178 | def get_loss(self, question, evidence, q_mask, e_mask, q_feat, e_feat, labels): 179 | scores = self.forward(question, evidence, q_mask, e_mask, q_feat, e_feat) 180 | loss_list = [] 181 | for tag_scores, tag in zip(scores, labels): 182 | loss = self.loss_func(tag_scores, tag) 183 | loss_list.append(loss) 184 | batch_loss = torch.mean(torch.cat(loss_list, -1)) 185 | return batch_loss 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /code/crf.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import pycrfsuite 3 | import h5py 4 | import numpy as np 5 | from tqdm import * 6 | from torch.autograd import Variable 7 | from loader import loadTrainDataset, loadTestDataset 8 | from util import load_vocab 9 | 10 | STOP_TAG = "#OOV#" 11 | 12 | class Hyperparameters: 13 | batch_size = 128 14 | e_hidden_size = 128 15 | evidence_size = 512 16 | 17 | train_path = '../char_data/training.h5' 18 | test_ann_path = '../char_data/test.ann.h5' 19 | test_ir_path = '../char_data/test.ir.h5' 20 | new_test_ir_path = '../char_data/new_test.ir.h5' 21 | val_ann_path = '../char_data/validation.ann.h5' 22 | val_ir_path = '../char_data/validation.ir.h5' 23 | vocab_path = '../char_data/vocabulary.txt' 24 | 25 | crf_path = '../model/test.crfsuite' 26 | crf_train_path = '../char_data/crf_training.h5' 27 | charQA_path = '../model/charQA_2017-08-11/f1-0.5583_0.34799_2' 28 | 29 | param = Hyperparameters() 30 | 31 | 32 | def get_inputs(model, loader, idx2word): 33 | print('Getting inputs...') 34 | x_train = [] 35 | y_train = [] 36 | count = 0 37 | tag2idx = { "b": 0, "i": 1, "o1": 2, "o2":3, STOP_TAG: 4} 38 | idx2tag = dict(zip(tag2idx.values(), tag2idx.keys())) 39 | feats = [ str(i) for i in range(param.e_hidden_size)] 40 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, labels, answer) in tqdm(enumerate(loader)): 41 | 42 | #count += 1 43 | #if count == 2: 44 | # break 45 | 46 | question = Variable(question.long()).cuda() 47 | evidence = Variable(evidence.long()).cuda() 48 | q_feat = Variable(q_feat.long()).cuda() 49 | e_feat = Variable(e_feat.long()).cuda() 50 | q_mask = Variable(q_mask.byte()).cuda() 51 | e_mask = Variable(e_mask.byte()).cuda() 52 | labels = Variable(labels.long(), requires_grad = False).cuda() 53 | 54 | batch_lstm = model.get_lstm(question, evidence, q_mask, e_mask, q_feat, e_feat) 55 | batch_lstm = batch_lstm.data.cpu().tolist() 56 | labels = labels.data.cpu().tolist() 57 | 58 | for ans, label, lstm in zip(answer, labels, batch_lstm): 59 | ans = [ idx2word[a] for a in ans if a != 0 ] 60 | if (''.join(ans) == 'no_answer'): continue 61 | 62 | y_train.append([idx2tag[l] for l in label]) 63 | 64 | seq = [] 65 | for vec in lstm: 66 | seq.append(dict(zip(feats, vec))) 67 | x_train.append(seq) 68 | 69 | 70 | print('y train: (', len(y_train),' , ', len(y_train[0]), ')') 71 | print('x train: (', len(x_train),' , ', len(x_train[0]), ' , ', len(x_train[0][0]),')') 72 | 73 | return x_train, y_train 74 | 75 | 76 | def save_inputs(model, loader, dataset_size, idx2word): 77 | print('Saving inputs...') 78 | file = h5py.File(param.crf_train_path,'w') 79 | tag2idx = { "b": 0, "i": 1, "o1": 2, "o2":3, STOP_TAG: 4} 80 | idx2tag = dict(zip(tag2idx.values(), tag2idx.keys())) 81 | feats = [ str(i) for i in range(param.e_hidden_size)] 82 | 83 | file.create_dataset('y', (dataset_size, param.evidence_size), 'i') 84 | file.create_dataset('x', (dataset_size, param.evidence_size, param.e_hidden_size), 'i') 85 | start = 0 86 | idx = 0 87 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, labels, answer) in tqdm(enumerate(loader)): 88 | 89 | #count += 1 90 | #if count == 2: 91 | # break 92 | 93 | batch_size = len(question) 94 | question = Variable(question.long()).cuda() 95 | evidence = Variable(evidence.long()).cuda() 96 | q_feat = Variable(q_feat.long()).cuda() 97 | e_feat = Variable(e_feat.long()).cuda() 98 | q_mask = Variable(q_mask.byte()).cuda() 99 | e_mask = Variable(e_mask.byte()).cuda() 100 | labels = Variable(labels.long(), requires_grad = False).cuda() 101 | 102 | batch_lstm = model.get_lstm(question, evidence, q_mask, e_mask, q_feat, e_feat) 103 | batch_lstm = batch_lstm.data.cpu().tolist() 104 | labels = labels.data.cpu().tolist() 105 | 106 | i = 0 107 | for ans, label, lstm in zip(answer, labels, batch_lstm): 108 | ans = [ idx2word[a] for a in ans if a != 0 ] 109 | if (''.join(ans) == 'no_answer'): 110 | if i == 10: continue 111 | else: i += 1 112 | 113 | file['y'][idx] = label 114 | file['x'][idx] = lstm 115 | idx += 1 116 | 117 | print(idx) 118 | ''' 119 | end = (batch_idx+1)*batch_size 120 | print('(', start, ',', end, ')') 121 | file['x'][start: end] = batch_lstm 122 | file['y'][start: end] = labels 123 | start = end 124 | ''' 125 | 126 | file.close() 127 | return idx 128 | 129 | 130 | def load_inputs(idx): 131 | print('Loading inputs...') 132 | file = h5py.File(param.crf_train_path) 133 | x = file['x'][:idx] 134 | y = file['y'][:idx] 135 | file.close() 136 | 137 | x_train = [] 138 | y_train = [] 139 | tag2idx = { "b": 0, "i": 1, "o1": 2, "o2":3, STOP_TAG: 4} 140 | idx2tag = dict(zip(tag2idx.values(), tag2idx.keys())) 141 | feats = [ str(i) for i in range(param.e_hidden_size)] 142 | 143 | for label, lstm in tqdm(zip(y, x)): 144 | y_train.append([idx2tag[l] for l in label]) 145 | 146 | seq = [] 147 | for vec in lstm: 148 | seq.append(dict(zip(feats, vec))) 149 | x_train.append(seq) 150 | 151 | print(' y train: (', len(y_train),',', len(y_train[0]), ')') 152 | 153 | return x_train, y_train 154 | 155 | 156 | def train_crf(x_train, y_train): 157 | print('Training...') 158 | trainer = pycrfsuite.Trainer(verbose=False) 159 | for xseq, yseq in zip(x_train, y_train): 160 | trainer.append(xseq, yseq) 161 | 162 | trainer.set_params({ 163 | 'c1': 1.0, # coefficient for L1 penalty 164 | 'c2': 1e-3, # coefficient for L2 penalty 165 | 'max_iterations': 500, # stop earlier 166 | 167 | # include transitions that are possible, but not observed 168 | 'feature.possible_transitions': True 169 | }) 170 | 171 | trainer.train(param.crf_path) 172 | 173 | 174 | 175 | def get_tags(xs, ys): 176 | print('Testing...') 177 | tagger = pycrfsuite.Tagger() 178 | tagger.open(param.crf_path) 179 | 180 | for x , y in zip(xs, ys): 181 | pred_tag = tagger.tag(x) 182 | pred_tag = [ t for t in pred_tag if t != STOP_TAG] 183 | y = [ t for t in y if t != STOP_TAG] 184 | print("Predicted:", ' '.join(pred_tag)) 185 | print("Correct: ", ' '.join(y), '\n') 186 | 187 | #return pred_tag 188 | 189 | 190 | def test(): 191 | X_train = [[{'foo': 1, 'bar': 0, 's':0, 'p': 4, 'd':True, 'a':0.7, 'b': 0.5, 'c': 9}, 192 | {'foo': 0, 'baz': 1, 's':0, 'p': 0, 'd': False, 'a':8.7, 'b': 7.5, 'c': 1}]] 193 | X_train = [[['foo=1', 'bar=0', 'c=9', 's=0', 'sd=12', 'cd=2', 'ca=3', 'd=True', 'cc=89'], 194 | ['foo=4', 'bar=7', 'c=3', 's=1', 'sd=8', 'cd=9', 'ca=1','d=False', 'cc=18']]] 195 | y_train = [['0', '1']] 196 | #print('x train: ', y_train[0]) 197 | 198 | 199 | trainer = pycrfsuite.Trainer(verbose=False) 200 | 201 | for xseq, yseq in zip(X_train, y_train): 202 | print('x: ', xseq) 203 | print('y: ', yseq) 204 | trainer.append(xseq, yseq) 205 | 206 | trainer.set_params({ 207 | 'c1': 1.0, # coefficient for L1 penalty 208 | 'c2': 1e-3, # coefficient for L2 penalty 209 | 'max_iterations': 500, # stop earlier 210 | 211 | # include transitions that are possible, but not observed 212 | 'feature.possible_transitions': True 213 | }) 214 | 215 | 216 | 217 | trainer.train('conll2002-esp.crfsuite') 218 | #print (len(trainer.logparser.iterations), trainer.logparser.iterations[-1]) 219 | 220 | 221 | tagger = pycrfsuite.Tagger() 222 | tagger.open('conll2002-esp.crfsuite') 223 | 224 | print("Predicted:", ' '.join(tagger.tag(X_train[0]))) 225 | print("Correct: ", ' '.join(y_train[0])) 226 | 227 | 228 | if __name__ == '__main__': 229 | #test() 230 | 231 | train_dataset = loadTrainDataset(param.train_path) 232 | val_dataset = loadTestDataset(param.val_ann_path) 233 | test_dataset = loadTestDataset(param.new_test_ir_path) 234 | 235 | train_loader = torch.utils.data.DataLoader(train_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = False) 236 | val_loader = torch.utils.data.DataLoader(val_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = False) 237 | test_loader = torch.utils.data.DataLoader(test_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = False) 238 | 239 | model = torch.load(param.charQA_path) 240 | 241 | 242 | train_dataset_size = train_dataset.__len__() 243 | word_set, word2idx, vocab_size = load_vocab(param.vocab_path) 244 | idx2word = dict(zip(word2idx.values(), word2idx.keys())) 245 | 246 | #idx = save_inputs(model, train_loader, train_dataset_size, idx2word) 247 | #print('idx: ', idx) 248 | 249 | idx = 159753 250 | 251 | x_train, y_train = load_inputs(idx) 252 | 253 | #x_train, y_train = get_inputs(model, train_loader, idx2word) 254 | 255 | train_crf(x_train, y_train) 256 | 257 | get_tags(x_train[0:20], y_train[0:20]) 258 | 259 | 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /code/loader.py: -------------------------------------------------------------------------------- 1 | import h5py 2 | import math 3 | import torch 4 | import torch.utils.data as data 5 | 6 | class loadTrainDataset(data.Dataset): 7 | def __init__(self, path): 8 | self.file = h5py.File(path) 9 | self.nb_samples = len(self.file['question'][:]) 10 | 11 | def __getitem__(self, index): 12 | question = self.file['question'][index] 13 | evidence = self.file['evidence'][index] 14 | q_mask = self.file['q_mask'][index] 15 | e_mask = self.file['e_mask'][index] 16 | q_feat = self.file['q_feat'][index] 17 | e_feat = self.file['e_feat'][index] 18 | tags = self.file['labels'][index] 19 | answer = self.file['answer'][index] 20 | #return question, evidence, q_mask, e_mask, q_feat, e_feat, tags 21 | return question, evidence, q_mask, e_mask, q_feat, e_feat, tags, answer 22 | 23 | def __len__(self): 24 | return self.nb_samples 25 | 26 | 27 | 28 | class loadTestDataset(data.Dataset): 29 | def __init__(self, path): 30 | self.file = h5py.File(path) 31 | self.nb_samples = len(self.file['question'][:]) 32 | 33 | def __getitem__(self, index): 34 | question = self.file['question'][index] 35 | evidence = self.file['evidence'][index] 36 | q_mask = self.file['q_mask'][index] 37 | e_mask = self.file['e_mask'][index] 38 | q_feat = self.file['q_feat'][index] 39 | e_feat = self.file['e_feat'][index] 40 | answer = self.file['answer'][index] 41 | return question, evidence, q_mask, e_mask, q_feat, e_feat, answer 42 | 43 | def __len__(self): 44 | return self.nb_samples 45 | -------------------------------------------------------------------------------- /code/main.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import os 3 | import time 4 | from datetime import datetime 5 | from baselineQA import baselineQA 6 | from loader import loadTrainDataset, loadTestDataset 7 | from util import load_vocab, load_webQA_vocab, load_webQA_embedding 8 | from train_loss import train 9 | from test import test_by_evidences, test_by_questions 10 | 11 | 12 | class Hyperparameters: 13 | nb_epoch = 1000 14 | batch_size = 128 15 | tagset_size = 4 16 | question_size = 64 17 | evidence_size = 512 18 | 19 | qe_embedding_size = 2 20 | embedding_size = 64 21 | 22 | q_hidden_size = 64 23 | e_hidden_size = 128 24 | t_hidden_size = 64 25 | num_layers = 1 26 | 27 | pre_embeds = False 28 | pre_lstm = False 29 | clip = 5.0 30 | learning_rate = 0.001 31 | model_dir = '' 32 | 33 | 34 | class Paths: 35 | train_path = '../data/training.h5' 36 | test_ann_path = '../data/test.ann.h5' 37 | test_ir_path = '../data/test.ir.h5' 38 | new_test_ir_path = '../data/new_test.ir.h5' 39 | val_ann_path = '../data/validation.ann.h5' 40 | val_ir_path = '../data/validation.ir.h5' 41 | vocab_path = '../data/vocabulary.txt' 42 | 43 | attQA_path = '../model/lstm_2017-07-26/weights.0-0.1475' 44 | maskQA_path = '../model/weightQA_2017-08-04/f1-0.4113_0.00173_59' 45 | #featQA_path = '../model/feat2QA_2017-08-08/f1-0.5119_0.04968_5' 46 | featQA_path = '../model/featQA_2017-08-09/f1-0.5132_0.16255_2' 47 | charQA_path = '../model/charQA_2017-08-11/f1-0.5583_0.34799_2' 48 | 49 | path = Paths() 50 | 51 | 52 | def train_featQA(train_loader, val_loader, param): # 2 is not weight 53 | param.model_dir = '../model/baselineQA_' + str(datetime.now()).split('.')[0].split()[0] + '/' 54 | if os.path.exists(param.model_dir) == False: 55 | os.mkdir(param.model_dir) 56 | 57 | word_set, word2idx, vocab_size = load_vocab(path.vocab_path) 58 | idx2word = dict(zip(word2idx.values(), word2idx.keys())) 59 | 60 | model = baselineQA(vocab_size, param, 0).cuda() 61 | train(model, train_loader, val_loader, param, idx2word) 62 | 63 | 64 | def test_model(loader, model_path): 65 | word_set, word2idx, vocab_size = load_vocab(path.vocab_path) 66 | idx2word = dict(zip(word2idx.values(), word2idx.keys())) 67 | 68 | model = torch.load(model_path) 69 | #test_by_evidences(model, loader, idx2word) # 0.58 0.62 70 | test_by_questions(model, loader, idx2word) # 0.61 0.66 71 | 72 | 73 | 74 | if __name__ == '__main__': 75 | param = Hyperparameters() 76 | 77 | train_dataset = loadTrainDataset(path.train_path) 78 | val_dataset = loadTestDataset(path.val_ann_path) 79 | test_dataset = loadTestDataset(path.val_ann_path) 80 | 81 | train_loader = torch.utils.data.DataLoader(train_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = True) 82 | val_loader = torch.utils.data.DataLoader(val_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = True) 83 | test_loader = torch.utils.data.DataLoader(test_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = True) 84 | 85 | print('Biu ~ ~ ~ ~ ~ Give you buffs ~ \n') 86 | 87 | 88 | #train_maskQA(train_loader, val_loader, param) 89 | #train_attQA(train_loader, val_loader, param) 90 | #train_featQA(train_loader, val_loader, param) 91 | 92 | test_model(test_loader, path.charQA_path) 93 | print('test dataset: ', test_dataset.__len__()) 94 | 95 | #print(test_dataset.nb_samples) 96 | 97 | #-------------------- record -------------------------- 98 | 99 | # '../model/feat2QA_2017-08-08/f1-0.5119_0.04968_5' 100 | # test_ann: Pre: 0.46563813811991994 Rec: 0.5778645833333333 F1: 0.5154754567060206 101 | # test_ir: Pre: 0.3044053618532579 Rec: 0.35484035326086955 F1: 0.3275912294056864 102 | 103 | # model/featQA_2017-08-09/f1-0.5132_0.16255_2 104 | # test_ann: Pre: 0.45854179487277863 Rec: 0.5921223958333334 F1: 0.5165802991715742 105 | # test_ir: Pre: 0.3061375799953651 Rec: 0.3651154891304348 F1: 0.3328905391650594 106 | # new_test_ir: Pre: 0.47119347316799043 Rec: 0.59765625 F1: 0.5266610723362033 107 | # ann_can_pred: Pre: 0.6123457108622822 Rec: 0.8700601263366222 F1: 0.7181746023030019 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /code/online_util.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import Tensor 3 | from torch.autograd import Variable 4 | import random 5 | import numpy as np 6 | from test import get_batch_scores, clean_answer, get_corrected_results,get_tagging_results, get_batch_ques2ans, fuzzy_match 7 | from util import load_vocab, pad_sequence 8 | from collections import Counter 9 | from baiduSpider import get_evidences 10 | from loader import loadTrainDataset, loadTestDataset 11 | 12 | 13 | STOP_TAG = "#OOV#" 14 | 15 | class Hyperparameters: 16 | tagset_size = 4 17 | answer_size = 16 18 | question_size = 64 19 | evidence_size = 512 20 | batch_size = 128 21 | 22 | train_path = '../char_data/training.h5' 23 | test_ann_path = '../char_data/test.ann.h5' 24 | test_ir_path = '../char_data/test.ir.h5' 25 | val_ann_path = '../char_data/validation.ann.h5' 26 | val_ir_path = '../char_data/validation.ir.h5' 27 | vocab_path = '../char_data/vocabulary.txt' 28 | 29 | featQA_path = '../model/featQA_2017-08-09/f1-0.5132_0.16255_2' 30 | #charQA_path = '../model/charQA_2017-08-11/f1-0.5583_0.34799_2' 31 | charQA_path = '../model/lossQA_2017-08-14/f1-0.5698_0.26918_5' 32 | 33 | param = Hyperparameters() 34 | 35 | def get_chars(seq, input2idx): 36 | vector = [ input2idx[s] for s in seq if s in input2idx] 37 | return vector, len(vector) 38 | 39 | def get_feats(question, evidence): 40 | q_vector = [] 41 | for e in evidence: 42 | if e in question: 43 | q_vector.append(1) 44 | else: 45 | q_vector.append(0) 46 | return q_vector 47 | 48 | def get_question(): 49 | question = '谁与苗侨伟、黄日华、汤镇业、刘德华并称为"香港无线五虎将"?' 50 | question = '三生三世十里桃花女主角是谁' 51 | question = '我的前半生中,靳东演的是谁' 52 | question = '被英国媒体称为"东方之星"的中国斯诺克选手是谁?' 53 | return question 54 | 55 | def get_inputs(question, evidences, word2idx): 56 | question_list = [] 57 | evidence_list = [] 58 | q_list = [] 59 | e_list = [] 60 | q_mask_list = [] 61 | e_mask_list = [] 62 | 63 | ques, q_len = get_chars(question, word2idx) 64 | question, q_mask = pad_sequence(ques, param.question_size, word2idx) 65 | 66 | nb_evid = len(evidences) 67 | for i, e in enumerate(evidences): 68 | e, e_len = get_chars(e, word2idx) 69 | if e_len == 0: continue 70 | 71 | other_id = random.randint(0, nb_evid-1) 72 | if nb_evid != 1: 73 | while other_id == i: 74 | other_id = random.randint(0, nb_evid-1) 75 | other_evidence = evidences[other_id] 76 | other_evidence, _ = get_chars(other_evidence , word2idx) 77 | 78 | q_feat = get_feats(ques, e) 79 | e_feat = get_feats(other_evidence, e) 80 | 81 | evidence, e_mask = pad_sequence(e, param.evidence_size, word2idx) 82 | q_tags, _ = pad_sequence(q_feat, param.evidence_size, word2idx) 83 | e_tags, _ = pad_sequence(e_feat, param.evidence_size, word2idx) 84 | 85 | question_list.append(question) 86 | evidence_list.append(evidence) 87 | q_list.append(q_tags) 88 | e_list.append(e_tags) 89 | q_mask_list.append(q_mask) 90 | e_mask_list.append(e_mask) 91 | 92 | question = Variable(torch.LongTensor(question_list)).cuda() 93 | evidence = Variable(torch.LongTensor(evidence_list)).cuda() 94 | e_feat = Variable(torch.LongTensor(e_list)).cuda() 95 | q_feat = Variable(torch.LongTensor(q_list)).cuda() 96 | q_mask = Variable(torch.ByteTensor(q_mask_list)).cuda() 97 | e_mask = Variable(torch.ByteTensor(e_mask_list)).cuda() 98 | 99 | return question, evidence, q_mask, e_mask, q_feat, e_feat 100 | 101 | 102 | def get_answers(model, question, evidence, q_mask, e_mask, q_feat, e_feat, idx2word): 103 | pred_scores, pred_tags = model.get_tags(question, evidence, q_mask, e_mask, q_feat, e_feat) 104 | 105 | ques = question.data.cpu().tolist() 106 | ques = ''.join([ idx2word[q] for q in ques[0] if q != 0 ]) 107 | print('Question: ', ques, '\n') 108 | 109 | answers = [] 110 | evidence = evidence.data.cpu().numpy() 111 | for score, pred, evid in zip(pred_scores, pred_tags, evidence): 112 | evid = [ idx2word[e] for e in evid if e != 0 ] 113 | print('Evidence: ', ''.join(evid), '\n') 114 | 115 | #pred_ans = get_tagging_results(evid, pred) 116 | answer, max_answer = get_corrected_results(evid, pred, score) 117 | if max_answer != ['no_answer']: 118 | answers.extend(max_answer) 119 | 120 | print('Predict Answers: ', max_answer, '\n') 121 | print('---------------\n') 122 | 123 | if answers == []: 124 | vote_answer = 'no_answer' 125 | else: 126 | (vote_answer, _) = Counter(answers).most_common(1)[0] 127 | #print('\nFinal Answer: ', vote_answer) 128 | return vote_answer 129 | 130 | def get_tuple_answers(model, question, evidence, q_mask, e_mask, q_feat, e_feat, idx2word): 131 | pred_scores, pred_tags = model.get_tags(question, evidence, q_mask, e_mask, q_feat, e_feat) 132 | 133 | ques = question.data.cpu().tolist() 134 | ques = ''.join([ idx2word[q] for q in ques[0] if q != 0 ]) 135 | print('Question: ', ques, '\n') 136 | 137 | ans2evid = {} 138 | answers = [] 139 | evidence = evidence.data.cpu().numpy() 140 | for score, pred, evid in zip(pred_scores, pred_tags, evidence): 141 | evid = [ idx2word[e] for e in evid if e != 0 ] 142 | print('Evidence: ', ''.join(evid), '\n') 143 | 144 | #pred_ans = get_tagging_results(evid, pred) 145 | answer, max_answer = get_corrected_results(evid, pred, score) 146 | if max_answer != ['no_answer']: 147 | answers.extend(max_answer) 148 | 149 | if max_answer[0] not in ans2evid: 150 | ans2evid[max_answer[0]] = [] 151 | ans2evid[max_answer[0]].append(''.join(evid)) 152 | 153 | print('Predict Answers: ', max_answer, '\n') 154 | print('---------------\n') 155 | 156 | if answers == []: 157 | votes = [('no_answer', 0)] 158 | else: 159 | votes = Counter(answers).most_common(2) 160 | 161 | #print('\nFinal Answer: ', vote_answer) 162 | return votes, ans2evid 163 | 164 | def get_batch_scores(C, A, Q): 165 | if ( A == 0): 166 | pre = 0 167 | else: 168 | pre = C / A 169 | 170 | if ( Q == 0): 171 | rec = 0 172 | else: 173 | rec = C / Q 174 | 175 | if (pre + rec == 0): 176 | f1 = 0 177 | else: 178 | f1 = (2 * pre * rec) / (pre + rec) 179 | return pre, rec, f1 180 | 181 | #Nb_batch: 24 Pre: 0.5909090909090909 Rec: 0.5869565217391305 F1: 0.5889261744966443 182 | def test_online(model, loader, idx2word, word2idx): 183 | print('Testing online ...') 184 | ques2ans = dict() 185 | A, C, Q = 0, 0, 0 186 | nb_batch, nb_epoch = 0, 0 187 | pre_epoch, rec_epoch, f1_epoch = 0, 0, 0 188 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, answer) in enumerate(loader): 189 | nb_batch += 1 190 | #answer = answer.cpu().tolist() 191 | for ques, ans in zip(question, answer): 192 | nb_epoch += 1 193 | ans = ''.join([ idx2word[a] for a in ans if a != 0]) 194 | ques = ''.join([ idx2word[q] for q in ques if q != 0]) 195 | print(nb_epoch, '.Question: ', ques) 196 | 197 | evidences = get_evidences(ques, 20) 198 | if evidences == []: 199 | print('No Evidence\n') 200 | continue 201 | 202 | question, evidence, q_mask, e_mask, q_feat, e_feat = get_inputs(ques, evidences, word2idx) 203 | pred_ans = get_answers(model, question, evidence, q_mask, e_mask, q_feat, e_feat, idx2word) 204 | 205 | print('\n ##################### \n') 206 | print(nb_epoch, '.Question: ', ques) 207 | print('Seclecd Answer: ', pred_ans) 208 | print('Golden Answer: ', ans) 209 | print('\n ##################### \n') 210 | 211 | C += fuzzy_match(pred_ans, ans) 212 | if pred_ans != 'no_answer': A += 1 213 | Q += 1 214 | 215 | pre, rec, f1 = get_batch_scores(C, A, Q) 216 | pre_epoch += pre 217 | rec_epoch += rec 218 | f1_epoch += f1 219 | print('Nb_batch: ', nb_batch ,'Pre:', pre, ' Rec:', rec,' F1:', f1, '\n') 220 | 221 | pre_epoch = pre_epoch / nb_batch 222 | rec_epoch = rec_epoch / nb_batch 223 | f1_epoch = f1_epoch / nb_batch 224 | 225 | print('Pre:', pre_epoch, ' Rec:', rec_epoch, ' F1:', f1_epoch, '\n') 226 | return pre_epoch, rec_epoch, f1_epoch 227 | 228 | 229 | if __name__ == '__main__': 230 | word_set, word2idx, word_set_size = load_vocab(param.vocab_path) 231 | idx2word = dict(zip(word2idx.values(), word2idx.keys())) 232 | model = torch.load(param.charQA_path) 233 | model.eval() 234 | 235 | test_dataset = loadTestDataset(param.test_ann_path) 236 | test_loader = torch.utils.data.DataLoader(test_dataset, batch_size = param.batch_size, num_workers = 1, shuffle = True) 237 | #test_online(model, test_loader, idx2word, word2idx) 238 | 239 | 240 | question = get_question() 241 | #evidences = get_evidences() 242 | evidences = get_evidences(question) 243 | 244 | question, evidence, q_mask, e_mask, q_feat, e_feat = get_inputs(question, evidences, word2idx) 245 | #answers = get_answers(model, question, evidence, q_mask, e_mask, q_feat, e_feat, idx2word) 246 | answers = get_tuple_answers(model, question, evidence, q_mask, e_mask, q_feat, e_feat, idx2word) 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /code/test.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.autograd import Variable 4 | import os 5 | import jieba 6 | import time 7 | from datetime import datetime 8 | from collections import Counter 9 | 10 | STOP_TAG = '#OOV#' 11 | 12 | def fuzzy_match(preds, ans): 13 | if preds == 'no_answer': 14 | return 0 15 | if preds in ans or ans in preds: 16 | return 1 17 | return 0 18 | 19 | def fuzzy_match_list(preds, ans): 20 | for p in preds: 21 | if p in ans or ans in p: 22 | return 1 23 | return 0 24 | 25 | def exact_match(preds, ans): 26 | if preds == 'no_answer': 27 | return 0 28 | if preds == ans: 29 | return 1 30 | return 0 31 | 32 | def clean_answer(text): 33 | std_text = text.replace(' ', '') 34 | std_text = std_text.lstrip(u'"').lstrip(u'“').lstrip(u"'")\ 35 | .lstrip(u"‘").lstrip(u'<').lstrip(u'《')\ 36 | .lstrip(u'【') 37 | std_text = std_text.rstrip(u'"').rstrip(u'”').rstrip(u"'")\ 38 | .rstrip(u"’").rstrip(u'>').rstrip(u'》')\ 39 | .rstrip(u"】") 40 | return std_text 41 | 42 | def get_corrected_results(tokens, tags): 43 | char2word = dict() 44 | words = list(jieba.cut(''.join(tokens))) 45 | c = 0 46 | for i, w in enumerate(words): 47 | for ww in w: 48 | char2word[c] = i 49 | c += 1 50 | 51 | chunks = [] 52 | start = -1 53 | 54 | for i, tok in enumerate(tokens): 55 | tag = tags[i] 56 | if tag == 0: # B 57 | if start >= 0: chunks.append([start, i]) 58 | start = i 59 | elif tag == 1: # I 60 | if start < 0: start = i 61 | else: 62 | if start < 0: continue 63 | chunks.append([start, i]) 64 | start = -1 65 | if start >= 0: 66 | chunks.append([start, len(tokens)-1]) 67 | 68 | answers = set() 69 | for c in chunks: 70 | ans = [] 71 | for i in range(c[0], c[-1]): 72 | w = words[char2word[i]] 73 | if w not in ans: ans.append(w) 74 | ans = clean_answer(''.join(ans)) 75 | if ans != '': answers.add(ans) 76 | 77 | if len(answers) == 0: 78 | answers.add('no_answer') 79 | return list(answers) 80 | 81 | 82 | def get_tagging_results(tokens, tags): 83 | chunks = set() 84 | start = -1 85 | for i, tok in enumerate(tokens): 86 | tag = tags[i] 87 | if tag == 0: # B 88 | if start >= 0: chunks.add(''.join(tokens[start:i])) 89 | start = i 90 | elif tag == 1: # I 91 | if start < 0: start = i 92 | else: 93 | if start < 0: continue 94 | chunks.add(''.join(tokens[start:i])) 95 | start = -1 96 | if start >= 0: 97 | chunks.add(''.join(tokens[start:])) 98 | 99 | if len(chunks) == 0: 100 | chunks.add('no_answer') 101 | return list(chunks) 102 | 103 | 104 | def get_batch_scores(pred_scores, pred_tags, answer, question, evidence, idx2word): 105 | nb_pred = 0 106 | A, C, Q = 0, 0, 0 107 | question = question.data.cpu().numpy() 108 | evidence = evidence.data.cpu().numpy() 109 | for score, pred, ans , ques, evid in zip(pred_scores, pred_tags, answer, question, evidence): 110 | ques = [ idx2word[q] for q in ques if q != 0 ] 111 | evid = [ idx2word[e] for e in evid if e != 0 ] 112 | ans = clean_answer(''.join( [ idx2word[a] for a in ans if a != 0 ] )) 113 | 114 | if ans == '': 115 | ans = 'no_answer' 116 | continue 117 | 118 | #pred_ans = get_tagging_results(evid, pred) 119 | answers, max_answer = get_corrected_results(evid, pred, score) 120 | 121 | 122 | print('Question: ', ''.join(ques), '\n') 123 | print('Evidence: ', ''.join(evid), '\n') 124 | #print('Tags: ', pred, '\n') 125 | print('Predict Answers: ', answers) 126 | if len(answers) > 1 : 127 | print('Select Answer: ', max_answer) 128 | print('Golden Answers: ', ans) 129 | print('\n ---------------------------- \n') 130 | 131 | 132 | if max_answer != ['no_answer']: 133 | nb_pred += 1 134 | 135 | max_answer = answers 136 | 137 | C += fuzzy_match_list(max_answer, ans) 138 | #if max_answer != ['no_answer']: 139 | A += len(max_answer) 140 | #if ans != 'no_answer': Q += 1 141 | Q += 1 142 | 143 | if ( A == 0): 144 | pre = 0 145 | else: 146 | pre = C / A 147 | 148 | if ( Q == 0): 149 | rec = 0 150 | else: 151 | rec = C / Q 152 | 153 | if (pre + rec == 0): 154 | f1 = 0 155 | else: 156 | f1 = (2 * pre * rec) / (pre + rec) 157 | 158 | return pre, rec, f1, C 159 | 160 | # Pre: 0.6158569522114896 Rec: 0.6158569522114896 F1: 0.6158569522114896 161 | # Pre: 0.5424550693527175 Rec: 0.7234684799186578 F1: 0.619153368856323 162 | # select: Pre: 0.7644436058119162 Rec: 0.6160325050838841 F1: 0.6819662141911356 163 | def test_by_evidences(model, loader, idx2word): 164 | print('Testing model...') 165 | nb_batch = 0 166 | epoch_pre, epoch_rec, epoch_f1, epoch_pred = 0, 0, 0, 0 167 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, answer) in enumerate(loader): 168 | nb_batch += 1 169 | 170 | question = Variable(question.long()).cuda() 171 | evidence = Variable(evidence.long()).cuda() 172 | q_feat = Variable(q_feat.long()).cuda() 173 | e_feat = Variable(e_feat.long()).cuda() 174 | q_mask = Variable(q_mask.byte()).cuda() 175 | e_mask = Variable(e_mask.byte()).cuda() 176 | 177 | pred_scores, pred_tags = model.get_tags(question, evidence, q_mask, e_mask, q_feat, e_feat) 178 | pre, rec, f1 , nb_pred = get_batch_scores(pred_scores, pred_tags, answer, question, evidence, idx2word) 179 | print('batch:',batch_idx,' nb_pred:', nb_pred, ' || pre: ', pre, ' rec: ', rec, ' f1 :', f1) 180 | 181 | epoch_pre += pre 182 | epoch_rec += rec 183 | epoch_f1 += f1 184 | epoch_pred += nb_pred 185 | 186 | epoch_pre = epoch_pre / nb_batch 187 | epoch_rec = epoch_rec / nb_batch 188 | epoch_f1 = epoch_f1 / nb_batch 189 | print('Pre:', epoch_pre, ' Rec:', epoch_rec,' F1:', epoch_f1, '\n') 190 | return epoch_pre, epoch_rec, epoch_f1, epoch_pred 191 | 192 | 193 | # --------------------------------------------------- 194 | def get_corrected_results(tokens, tags, scores): 195 | char2word = dict() 196 | words = list(jieba.cut(''.join(tokens))) 197 | c = 0 198 | for i, w in enumerate(words): 199 | for ww in w: 200 | char2word[c] = i 201 | c += 1 202 | 203 | chunks = [] 204 | start = -1 205 | score = 0 206 | for i, tok in enumerate(tokens): 207 | if tags[i] == 0: # B 208 | score += scores[i] 209 | if start >= 0: 210 | chunks.append([start, i, score]) 211 | score = 0 212 | start = i 213 | elif tags[i] == 1: # I 214 | score += scores[i] 215 | if start < 0: start = i 216 | else: 217 | if start < 0: continue 218 | chunks.append([start, i, score]) 219 | start = -1 220 | score = 0 221 | if start >= 0: 222 | chunks.append([start, len(tokens)-1, score]) 223 | 224 | answers = set() 225 | max_score = -1000 226 | max_answer = 'no_answer' 227 | for c in chunks: 228 | ans = [] 229 | for i in range(c[0], c[1]): 230 | w = words[char2word[i]] 231 | if w not in ans: ans.append(w) 232 | ans = clean_answer(''.join(ans)) 233 | if ans != '': answers.add(ans) 234 | 235 | if (c[-1] > max_score and ans != ''): 236 | max_score = c[-1] 237 | max_answer = ans 238 | 239 | if len(answers) == 0: 240 | answers.add('no_answer') 241 | return list(answers), [max_answer] 242 | 243 | 244 | def get_batch_ques2ans(pred_scores, pred_tags, answer, question, evidence, idx2word, ques2ans): 245 | question = question.data.cpu().numpy() 246 | evidence = evidence.data.cpu().numpy() 247 | for score, pred, ans , ques, evid in zip(pred_scores, pred_tags, answer, question, evidence): 248 | ques = ''.join( [idx2word[q] for q in ques if q != 0] ) 249 | evid = [ idx2word[e] for e in evid if e != 0 ] 250 | ans = clean_answer(''.join( [ idx2word[a] for a in ans if a != 0 ] )) 251 | if ans == '': ans = 'no_answer' 252 | 253 | #pred_ans = get_tagging_results(evid, pred) 254 | answers, max_answer = get_corrected_results(evid, pred, score) 255 | 256 | #max_answer = answers 257 | 258 | ques2ans[ques] = (set([]), []) 259 | ques2ans[ques][0].add(ans) 260 | ques2ans[ques][1].extend(max_answer) 261 | 262 | print('Question: ', ''.join(ques), '\n') 263 | print('Evidence: ', ''.join(evid), '\n') 264 | #print('Tags: ', pred, '\n') 265 | print('Predict Answers: ', answers) 266 | if len(answers) > 1 : 267 | print('Select Answer: ', max_answer) 268 | print('Golden Answers: ', ans) 269 | print('\n ---------------------------- \n') 270 | 271 | return ques2ans 272 | 273 | 274 | def get_epoch_scores(ques2ans): 275 | A, C, Q = 0, 0, 0 276 | for (question, answers) in ques2ans.items(): 277 | ans = ''.join(list(answers[0])) 278 | pred = answers[1] 279 | pred = [ a for a in pred if a != 'no_answer' ] 280 | if pred == []: 281 | pred_ans = 'no_answer' 282 | else: 283 | (pred_ans, _) = Counter(pred).most_common(1)[0] 284 | 285 | print('Question: ', question) 286 | print('Predict Answers: ', pred_ans) 287 | print('Golden Answers: ', ans) 288 | print('\n ---------------------------- \n') 289 | 290 | C += fuzzy_match(pred_ans, ans) 291 | if pred_ans != 'no_answer': A += 1 292 | Q += 1 293 | 294 | if ( A == 0): 295 | pre = 0 296 | else: 297 | pre = C / A 298 | 299 | if ( Q == 0): 300 | rec = 0 301 | else: 302 | rec = C / Q 303 | 304 | if (pre + rec == 0): 305 | f1 = 0 306 | else: 307 | f1 = (2 * pre * rec) / (pre + rec) 308 | 309 | return pre, rec, f1 310 | 311 | # new_ir 312 | # all: Pre: 0.7 Rec: 0.5422701246210846 F1: 0.6111216549629911 313 | # score: Pre: 0.7524924143909839 Rec: 0.5847086561131695 F1: 0.6580742987111448 314 | 315 | # ir 316 | # max score: Pre: 0.6128342245989304 Rec: 0.37896825396825395 F1: 0.46832856559051 317 | # all: Pre: 0.5743207245604688 Rec: 0.35648148148148145 F1: 0.43991022240359107 318 | def test_by_questions(model, loader, idx2word): 319 | print('Testing model...') 320 | nb_batch = 0 321 | ques2ans = dict() 322 | epoch_pre, epoch_rec, epoch_f1, epoch_pred = 0, 0, 0, 0 323 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, answer) in enumerate(loader): 324 | nb_batch += 1 325 | question = Variable(question.long()).cuda() 326 | evidence = Variable(evidence.long()).cuda() 327 | q_feat = Variable(q_feat.long()).cuda() 328 | e_feat = Variable(e_feat.long()).cuda() 329 | q_mask = Variable(q_mask.byte()).cuda() 330 | e_mask = Variable(e_mask.byte()).cuda() 331 | 332 | pred_scores, pred_tags = model.get_tags(question, evidence, q_mask, e_mask, q_feat, e_feat) 333 | ques2ans = get_batch_ques2ans(pred_scores, pred_tags, answer, question, evidence, idx2word, ques2ans) 334 | #print('batch:',batch_idx,' nb_pred:', nb_pred, ' || pre: ', pre, ' rec: ', rec, ' f1 :', f1) 335 | 336 | pre, rec, f1 = get_epoch_scores(ques2ans) 337 | print('Question: ', len(ques2ans)) 338 | print('Pre:', pre, ' Rec:', rec,' F1:', f1, '\n') 339 | return pre, rec, f1 340 | 341 | 342 | 343 | if __name__ == '__main__': 344 | 345 | print('Hey') 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | -------------------------------------------------------------------------------- /code/train.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Variable 3 | from sklearn.metrics import accuracy_score, roc_auc_score 4 | import numpy as np 5 | import csv 6 | 7 | def save_model(model, epoch, loss, acc, model_dir): 8 | model_path = model_dir + 'loss' + str(round(loss, 4)) + '_acc' + str(round(acc, 4)) + '_' + str(epoch) 9 | with open(model_path, 'wb') as f: 10 | torch.save(model, f) 11 | 12 | def train(model, train_loader, param): 13 | print('Training model...') 14 | parameters = filter(lambda p: p.requires_grad, model.parameters()) 15 | optimizer = torch.optim.Adam(parameters, lr = param.learning_rate) 16 | 17 | vaild_loss = 0 18 | best_acc = 0 19 | for epoch in range(param.nb_epoch): 20 | train_loss, acc = train_epoch(model, epoch, train_loader, optimizer) 21 | 22 | if(acc >= best_acc): 23 | best_acc = acc 24 | save_model(model, epoch, train_loss, acc, param.model_dir) 25 | 26 | print('Train End.\n') 27 | 28 | 29 | def train_epoch(model, epoch, loader, optimizer): 30 | print('Train epoch :', epoch) 31 | model.train() 32 | 33 | label_list = [] 34 | pred_list = [] 35 | prob_list = [] 36 | 37 | epoch_loss = 0.0 38 | nb_batch = 0 39 | for batch_idx, (attribute, label) in enumerate(loader): 40 | nb_batch += 1 41 | 42 | attribute = Variable(attribute.float())#.cuda() 43 | label = Variable(label.long(), requires_grad = False) 44 | 45 | if torch.cuda.is_available(): 46 | attribute = attribute.cuda() 47 | label = label.cuda() 48 | 49 | batch_loss = model.get_loss(attribute, label) 50 | pred = model.get_tags(attribute) 51 | 52 | 53 | optimizer.zero_grad() 54 | batch_loss.backward() 55 | optimizer.step() 56 | 57 | epoch_loss += sum(batch_loss.data.cpu().numpy()) 58 | print('-----epoch:', epoch, ' batch:',batch_idx,' train_loss:', batch_loss.data[0]) 59 | 60 | label_list.extend(label.data.cpu().tolist()) 61 | pred_list.extend(pred) 62 | 63 | 64 | epoch_loss = epoch_loss / nb_batch 65 | 66 | acc = accuracy_score(np.asarray(label_list), np.asarray(pred_list)) 67 | 68 | print('\nEpoch: ', epoch, ', Train Loss: ', epoch_loss, '\n', 'Accuracy: ', acc) 69 | 70 | return epoch_loss, acc 71 | 72 | def test(model, loader, param): 73 | print('Getting test csv file ....') 74 | pred_list = [] 75 | headers = ['ImageId','Label'] 76 | f = open(param.res_path, 'w') 77 | f_csv = csv.writer(f) 78 | f_csv.writerow(headers) 79 | 80 | i = 1 81 | for batch_idx, (attribute) in enumerate(loader): 82 | attribute = Variable(attribute.float())#.cuda() 83 | if torch.cuda.is_available(): 84 | attribute = attribute.cuda() 85 | 86 | pred = model.get_tags(attribute) 87 | for p in pred: 88 | f_csv.writerow([i, p]) 89 | i = i+1 90 | 91 | f.close() 92 | print('Test over') 93 | 94 | 95 | if __name__ == '__main__': 96 | print('Hey') -------------------------------------------------------------------------------- /code/train_crf.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.autograd import Variable 4 | import os 5 | import time 6 | from datetime import datetime 7 | from test import get_batch_scores 8 | 9 | def save_train_model(model, epoch, f1, loss, model_dir): 10 | model_path = model_dir + 'loss-' + str(round(loss, 6)) + '_' + str(round(f1, 3)) + '_' + str(epoch) 11 | with open(model_path, 'wb') as f: 12 | torch.save(model, f) 13 | 14 | def save_vaild_model(model, epoch, f1, loss, model_dir): 15 | model_path = model_dir + 'f1-' + str(round(f1, 4)) + '_' + str(round(loss, 5)) + '_' + str(epoch) 16 | with open(model_path, 'wb') as f: 17 | torch.save(model, f) 18 | 19 | def train(model, train_loader, valid_loader, param, idx2word): 20 | print('Training model...') 21 | parameters = filter(lambda p: p.requires_grad, model.parameters()) 22 | optimizer = torch.optim.Adam(parameters, lr = param.learning_rate) 23 | 24 | vaild_loss = 0 25 | best_loss = 1000 26 | best_f1 = 0 27 | for epoch in range(param.nb_epoch): 28 | epoch = epoch 29 | train_loss = train_epoch(model, epoch, train_loader, optimizer) 30 | pre, rec, f1 = eval_epoch(model, epoch, valid_loader, idx2word) 31 | 32 | if(f1 > best_f1): 33 | best_f1 = f1 34 | save_vaild_model(model, epoch, f1, train_loss, param.model_dir) 35 | 36 | elif(train_loss < best_loss): 37 | best_loss = train_loss 38 | save_train_model(model, epoch, f1, train_loss, param.model_dir) 39 | 40 | print('Train End.\n') 41 | 42 | 43 | def train_epoch(model, epoch, loader, optimizer): 44 | print('Train epoch :', epoch) 45 | model.train() 46 | 47 | epoch_loss = 0.0 48 | nb_batch = 0 49 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, labels) in enumerate(loader): 50 | nb_batch += 1 51 | 52 | question = Variable(question.long()).cuda() 53 | evidence = Variable(evidence.long()).cuda() 54 | q_feat = Variable(q_feat.long()).cuda() 55 | e_feat = Variable(e_feat.long()).cuda() 56 | q_mask = Variable(q_mask.byte()).cuda() 57 | e_mask = Variable(e_mask.byte()).cuda() 58 | labels = Variable(labels.long(), requires_grad = False).cuda() 59 | 60 | lstm = get_lstm(self, question, evidence, q_mask, e_mask, q_feat, e_feat) 61 | batch_loss = model.get_lstm(question, evidence, q_mask, e_mask, q_feat, e_feat, labels) 62 | 63 | optimizer.zero_grad() 64 | batch_loss.backward() 65 | #nn.utils.clip_grad_norm(model.parameters(), max_norm = 5.0) 66 | optimizer.step() 67 | 68 | epoch_loss += sum(batch_loss.data.cpu().numpy()) 69 | print('-----epoch:', epoch, ' batch:',batch_idx,' train_loss:', batch_loss.data[0]) 70 | 71 | epoch_loss = epoch_loss / nb_batch 72 | print('\nEpoch: ', epoch, ', Train Loss: ', epoch_loss, '\n') 73 | return epoch_loss 74 | 75 | 76 | def eval_epoch(model, epoch, loader, idx2word): 77 | print('Eval epoch :', epoch) 78 | model.eval() 79 | 80 | nb_batch = 0 81 | epoch_pre, epoch_rec, epoch_f1, epoch_pred = 0, 0, 0, 0 82 | for batch_idx, (question, evidence, q_mask, e_mask, q_feat, e_feat, answer) in enumerate(loader): 83 | nb_batch += 1 84 | question = Variable(question.long()).cuda() 85 | evidence = Variable(evidence.long()).cuda() 86 | e_feat = Variable(e_feat.long()).cuda() 87 | q_feat = Variable(q_feat.long()).cuda() 88 | q_mask = Variable(q_mask.byte()).cuda() 89 | e_mask = Variable(e_mask.byte()).cuda() 90 | 91 | pred_scores, pred_tags = model.get_tags(question, evidence, q_mask, e_mask, q_feat, e_feat) 92 | 93 | question = question.data.cpu().numpy() 94 | evidence = evidence.data.cpu().numpy() 95 | pre, rec, f1 , nb_pred = get_batch_scores(pred_tags, answer, question, evidence, idx2word) 96 | print('-----epoch:', epoch, ' batch:',batch_idx,' can_pred:', nb_pred, ' || pre: ', pre, ' rec: ', rec, ' f1 :', f1) 97 | 98 | epoch_pre += pre 99 | epoch_rec += rec 100 | epoch_f1 += f1 101 | epoch_pred += nb_pred 102 | 103 | epoch_pre = epoch_pre / nb_batch 104 | epoch_rec = epoch_rec / nb_batch 105 | epoch_f1 = epoch_f1 / nb_batch 106 | print('\nEpoch: ', epoch, ' Pred: ', epoch_pred, ' || Pre:', epoch_pre, ' Rec:', epoch_rec,' F1:', epoch_f1, '\n') 107 | return epoch_pre, epoch_rec, epoch_f1 108 | 109 | 110 | 111 | 112 | if __name__ == '__main__': 113 | 114 | print('Hey') 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /code/util.py: -------------------------------------------------------------------------------- 1 | import json 2 | import jieba 3 | import pickle 4 | import csv, h5py 5 | import pandas as pd 6 | import numpy as np 7 | from tqdm import * 8 | import torch 9 | from torch import Tensor 10 | from torch.autograd import Variable 11 | import torch.utils.data as data 12 | 13 | STOP_TAG = "#OOV#" 14 | 15 | class Hyperparameters: 16 | tagset_size = 4 17 | answer_size = 16 18 | question_size = 64 19 | evidence_size = 512 20 | 21 | webQA_train_path = '../data/training.json' 22 | webQA_test_ann_path = '../data/test.ann.json' 23 | webQA_test_ir_path = '../data/test.ir.json' 24 | webQA_val_ann_path = '../data/validation.ann.json' 25 | webQA_val_ir_path = '../data/validation.ir.json' 26 | 27 | train_path = '../data/training.h5' 28 | test_ann_path = '../data/test.ann.h5' 29 | test_ir_path = '../data/test.ir.h5' 30 | val_ann_path = '../data/validation.ann.h5' 31 | val_ir_path = '../data/validation.ir.h5' 32 | vocab_path = '../data/vocabulary.txt' 33 | 34 | 35 | param = Hyperparameters() 36 | 37 | 38 | def load_words(path, ret): 39 | with open(path) as f: 40 | for line in tqdm(f): 41 | txt = json.loads(line) 42 | question_tokens = ''.join(txt['question_tokens']) 43 | evidences = txt['evidences'] 44 | for e in evidences: 45 | evidence_tokens = ''.join(e['evidence_tokens']) 46 | for i in evidence_tokens: 47 | ret.add(i) 48 | golden_answers = ''.join(e['golden_answers'][0]) 49 | if golden_answers == 'no_answer': 50 | ret.add(golden_answers) 51 | else: 52 | for a in golden_answers: 53 | ret.add(a) 54 | for q in question_tokens: 55 | ret.add(q) 56 | return ret 57 | 58 | 59 | def get_vocab(paths): 60 | print('Getting vacabulary...') 61 | ret = set() 62 | for p in paths: 63 | ret = load_words(p, ret) 64 | 65 | ret = sorted(list(ret)) 66 | input_set = [STOP_TAG] 67 | input_set.extend(list(ret)) 68 | input_set_size = len(input_set) 69 | input2idx = dict(zip(input_set, range(input_set_size))) 70 | print('Vacabulary size:', input_set_size, '\n') 71 | return input_set, input2idx, input_set_size 72 | 73 | 74 | def save_vocab(path, input2idx): 75 | print('Saving bocabulary...') 76 | f = open(path,'wb') 77 | pickle.dump(input2idx, f) 78 | f.close() 79 | 80 | 81 | def load_vocab(path): 82 | print('Loading vocabulary...') 83 | f = open(path, 'rb') 84 | input2idx = pickle.load(f) 85 | input_set = list(input2idx.keys()) 86 | input_set_size = len(input_set) 87 | f.close() 88 | print('Vacabulary size:', input_set_size, '\n') 89 | return input_set, input2idx, input_set_size 90 | 91 | 92 | def load_webQA_vocab(): 93 | print('Loading webQA vacabulary...') 94 | input_set = [] 95 | with open(param.pre_vocab_path) as f: 96 | for word in tqdm(f): 97 | word = word.strip('\n') 98 | input_set.append(word) 99 | input_set_size = len(input_set) 100 | input2idx = dict(zip(input_set, range(input_set_size))) 101 | print('Vacabulary size:', input_set_size, '\n') 102 | return input_set, input2idx, input_set_size 103 | 104 | 105 | def load_webQA_embedding(): 106 | print('Loading webQA word embedding...') 107 | matrix = [] 108 | i = 0 109 | with open(param.pre_embedding_path) as f: 110 | for embed in tqdm(f): 111 | embed = embed.strip('\n').split(',') 112 | embed = [ float(e) for e in embed ] 113 | embed = np.array(embed) 114 | matrix.append(embed) 115 | 116 | matrix = np.array(matrix) 117 | print('embedding size: ', matrix.shape) 118 | return matrix 119 | 120 | 121 | # ------------------ save the file --------------------------- # 122 | 123 | def load_chars(seq, input2idx): 124 | seq = ''.join(seq) 125 | vector = [ input2idx[s] for s in seq if s in input2idx] 126 | return vector, len(vector) 127 | 128 | 129 | def load_evidence_and_feats(evidence, q_feats, e_feats, input2idx): 130 | evidence_vector = [] 131 | q_vector = [] 132 | e_vector = [] 133 | for evid, qf, ef in zip(evidence, q_feats, e_feats): 134 | for e in evid: 135 | if e in input2idx: 136 | evidence_vector.append(input2idx[e]) 137 | q_vector.append(qf) 138 | e_vector.append(ef) 139 | return evidence_vector, q_vector, e_vector 140 | 141 | 142 | def load_tags(evidence, tags, word2idx, tag2idx): 143 | tags_vector = [] 144 | for evid, t in zip(evidence, tags): 145 | first = True 146 | for e in evid: 147 | if e not in word2idx: 148 | continue 149 | 150 | if t == 'b' : 151 | if first == True: 152 | first = False 153 | tags_vector.append(tag2idx['b']) 154 | else: 155 | tags_vector.append(tag2idx['i']) 156 | else: 157 | tags_vector.append(tag2idx[t]) 158 | 159 | return tags_vector 160 | 161 | 162 | def pad_sequence(seq, seq_size, input2idx): 163 | vector = [] 164 | for i in range(seq_size): 165 | if i >= len(seq): 166 | vector.append(input2idx[STOP_TAG]) 167 | else: 168 | vector.append(seq[i]) 169 | mask = Tensor(vector).le(0).tolist() 170 | return vector, mask 171 | 172 | 173 | def compare(labels, golden_labels): 174 | for l, g in zip(labels, golden_labels): 175 | if l != g: 176 | return False 177 | return True 178 | 179 | def save_h5py_file(old_path, new_path, word2idx, idx2word, tag2idx): 180 | print('Saving (', new_path, ')...') 181 | file = h5py.File(new_path,'w') 182 | question_list = [] 183 | evidence_list = [] 184 | labels_list = [] 185 | q_list = [] 186 | e_list = [] 187 | pos_list = [] 188 | ner_list = [] 189 | q_mask_list = [] 190 | e_mask_list = [] 191 | answer_list = [] 192 | 193 | questions_size = 0 194 | evidences_size = 0 195 | active_evidences_size = 0 196 | negetive_evidences_size = 0 197 | has_labels = True 198 | with open(old_path) as f: 199 | for line in tqdm(f): 200 | txt = json.loads(line) 201 | question_tokens = txt['question_tokens'] 202 | question, q_length = load_chars(question_tokens, word2idx) 203 | question, q_mask = pad_sequence(question, param.question_size, word2idx) 204 | 205 | no_ans = 0 206 | evidences = txt['evidences'] 207 | for e in evidences: 208 | golden_answers = e['golden_answers'][0] 209 | evidence_tokens = e['evidence_tokens'] 210 | q_feats = e['q-e.comm_features'] 211 | e_feats = e['eecom_features_list'][0]['e-e.comm_features'] 212 | 213 | # new ir 214 | ans_str = ''.join(golden_answers) 215 | evid_str = ''.join(evidence_tokens) 216 | if question_tokens != 'no_answer' and ans_str not in evid_str: 217 | continue 218 | 219 | 220 | if len(evidence_tokens) > param.evidence_size: 221 | continue 222 | 223 | if ''.join(golden_answers) == 'no_answer': 224 | no_ans += 1 225 | negetive_evidences_size += 1 226 | else : 227 | active_evidences_size += 1 228 | 229 | if no_ans > 8: 230 | continue 231 | 232 | 233 | evidence, q_feats , e_feats = load_evidence_and_feats(evidence_tokens, q_feats, e_feats, word2idx) 234 | evidence, e_mask = pad_sequence(evidence, param.evidence_size, word2idx) 235 | q_tags, _ = pad_sequence(q_feats, param.evidence_size, word2idx) 236 | e_tags, _ = pad_sequence(e_feats, param.evidence_size, word2idx) 237 | 238 | golden_answers, _ = load_chars(golden_answers, word2idx) 239 | answer, _ = pad_sequence(golden_answers, param.answer_size, word2idx) 240 | 241 | if 'golden_labels' in e: 242 | golden_labels = e['golden_labels'] 243 | labels = load_tags(evidence_tokens, golden_labels, word2idx, tag2idx) 244 | labels, _ = pad_sequence(labels, param.evidence_size, tag2idx) 245 | labels_list.append(labels) 246 | else: 247 | has_labels = False 248 | 249 | 250 | question_list.append(question) 251 | evidence_list.append(evidence) 252 | q_list.append(q_tags) 253 | e_list.append(e_tags) 254 | q_mask_list.append(q_mask) 255 | e_mask_list.append(e_mask) 256 | answer_list.append(answer) 257 | 258 | evidences_size += 1 259 | questions_size += 1 260 | 261 | file.create_dataset('question', data = np.asarray(question_list)) 262 | file.create_dataset('evidence', data = np.asarray(evidence_list)) 263 | file.create_dataset('answer', data = np.asarray(answer_list)) 264 | file.create_dataset('q_mask', data = np.asarray(q_mask_list)) 265 | file.create_dataset('e_mask', data = np.asarray(e_mask_list)) 266 | file.create_dataset('q_feat', data = np.asarray(q_list)) 267 | file.create_dataset('e_feat', data = np.asarray(e_list)) 268 | 269 | if has_labels == True: 270 | file.create_dataset('labels', data = np.asarray(labels_list)) 271 | 272 | file.close() 273 | print('questions size: ', questions_size) 274 | print('evidences size: ', evidences_size, '\n') 275 | 276 | 277 | def save_files(old_paths, new_paths, word2idx, idx2word, tag2idx): 278 | print('Saving h5py files...') 279 | for i in range(len(old_paths)): 280 | save_h5py_file(old_paths[i], new_paths[i], word2idx, idx2word, tag2idx) 281 | print('Files Saved') 282 | 283 | 284 | 285 | if __name__ == '__main__': 286 | 287 | webQA_paths = [param.webQA_train_path, param.webQA_test_ann_path, 288 | param.webQA_test_ir_path, param.webQA_val_ann_path, param.webQA_val_ir_path] 289 | 290 | h5py_paths = [param.train_path, param.test_ann_path, param.test_ir_path, param.val_ann_path, param.val_ir_path] 291 | 292 | #h5py_paths = [param.pre_train_path, param.pre_test_ann_path, param.pre_test_ir_path, param.pre_val_ann_path, param.pre_val_ir_path] 293 | 294 | #word_set, word2idx, word_set_size = get_vocab(webQA_paths) 295 | #save_vocab(param.vocab_path, word2idx) 296 | 297 | word_set, word2idx, word_set_size = load_vocab(param.vocab_path) 298 | #word_set, word2idx, word_set_size = load_webQA_vocab() 299 | 300 | idx2word = dict(zip(word2idx.values(), word2idx.keys())) 301 | tag2idx = { "b": 0, "i": 1, "o1": 2, "o2":3, STOP_TAG: 4} 302 | 303 | save_files(webQA_paths, h5py_paths, word2idx, idx2word, tag2idx) 304 | 305 | 306 | #new_test_ir_path = '../char_data/new_test.ir.h5' 307 | #save_h5py_file(param.webQA_test_ir_path, new_test_ir_path, word2idx, idx2word, tag2idx) 308 | 309 | #save_test_file(param.webQA_val_ir_path, param.lonely_test_ann_path, word2idx, idx2word, tag2idx) 310 | 311 | 312 | 313 | 314 | 315 | -------------------------------------------------------------------------------- /data/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/data/readme.txt -------------------------------------------------------------------------------- /data/validation.ann.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/data/validation.ann.h5 -------------------------------------------------------------------------------- /data/vocabulary.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/data/vocabulary.txt -------------------------------------------------------------------------------- /demo展示.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/demo展示.mp4 -------------------------------------------------------------------------------- /evaluation/datapoint.py: -------------------------------------------------------------------------------- 1 | __all__ = ['EecommFeatures', 'Evidence', 'DataPoint'] 2 | 3 | class EecommFeatures(object): 4 | # field keys 5 | EECOMM_FEATURES = 'e-e.comm_features' 6 | OTHER_E_TYPE = 'other_evi_type' 7 | OTHER_E_KEY = 'other_evi_key' 8 | # optional 9 | OTHER_EVIDENCE_TOKENS = 'other_evi_tokens' 10 | 11 | @staticmethod 12 | def create(eecom_features, other_e_type, other_e_key, 13 | other_evi_tokens=None): 14 | ''' 15 | @param eecom_features: a list of 0-1 labels 16 | @param other_e_type: the type of the other evidence used for computing 17 | the feature values, one of Evidence.POSITIVE, 18 | Evidence.HIT_ANS_NEGATIVE and Evidence.OTHER_NEGATIVE 19 | @param other_e_key: the key of the other evidence used for computing 20 | the feature values 21 | @param other_evi_tokens: optional, the tokens of the other evidence used 22 | for computing the feature values 23 | ''' 24 | ret = {EecommFeatures.EECOMM_FEATURES:eecom_features, 25 | EecommFeatures.OTHER_E_TYPE:other_e_type, 26 | EecommFeatures.OTHER_E_KEY:other_e_key,} 27 | if other_evi_tokens is not None: 28 | ret[EecommFeatures.OTHER_EVIDENCE_TOKENS] = other_evi_tokens 29 | return ret 30 | 31 | 32 | class Evidence(object): 33 | # field keys 34 | E_KEY = 'e_key' 35 | E_TOKENS = 'evidence_tokens' 36 | GOLDEN_LABELS = 'golden_labels' 37 | QECOMM_FEATURES = 'q-e.comm_features' 38 | GOLDEN_ANSWERS = 'golden_answers' 39 | TYPE = 'type' # seed 40 | SRC = 'source' # ANN - annotated, IR - retrieved 41 | EECOMM_FEATURES_LIST = 'eecom_features_list' 42 | 43 | # evidence types 44 | # the evidence is positive 45 | POSITIVE = 'positive' 46 | # the evidence is negative and contains the golden answer 47 | HIT_ANS_NEGATIVE = 'hit_answer_negative' 48 | # the evidence is negative and does not contain the golden answer 49 | OTHER_NEGATIVE = 'other_negative' 50 | 51 | # src 52 | ANNOTATED = 'ANN' # the evidence is annotated 53 | IR = 'IR' # the evidence is retrieved 54 | 55 | @staticmethod 56 | def create(e_key, e_tokens, golden_labels, qecomm_features, golden_answers, 57 | type_, src, eecomm_features_list=lambda: []): 58 | ''' 59 | @param e_key: the key of this evidence 60 | @param e_tokens: evidence tokens, a list of strings 61 | @param golden_labels: BIO/BIO2 labels for each token of the evidence, 62 | a list of string 63 | @param qecomm_features: q-e.comm feature, a list of 0-1 values 64 | @param golden_answers: golden answers, a list of answers, each answer 65 | is a list of tokens 66 | @param type_: evidnece type, one of Evidence.POSITIVE, 67 | Evidence.HIT_ANS_NEGATIVE and Evidence.OTHER_NEGATIVE 68 | @param src: source of this evidence, one of Evidence.ANNOTATED or 69 | Evidence.IR 70 | @param eecomm_features_list: a list of EecommFeatures 71 | ''' 72 | ret = {Evidence.E_KEY:e_key, 73 | Evidence.E_TOKENS:e_tokens, 74 | Evidence.QECOMM_FEATURES:qecomm_features, 75 | Evidence.GOLDEN_ANSWERS:golden_answers, 76 | Evidence.TYPE:type_, 77 | Evidence.SRC:src, 78 | Evidence.EECOMM_FEATURES_LIST:eecomm_features_list,} 79 | if golden_labels is not None: 80 | ret[Evidence.GOLDEN_LABELS] = golden_labels 81 | return ret 82 | 83 | 84 | class DataPoint(object): 85 | # field keys 86 | Q_KEY = 'q_key' 87 | Q_TOKENS = 'question_tokens' 88 | EVIDENCES = 'evidences' 89 | 90 | @staticmethod 91 | def create(q_key, q_tokens, evidences): 92 | ''' 93 | @param q_key: the key of the question 94 | @param q_tokens: question tokens, a list of strings 95 | @param evidences: a list of Evidence 96 | ''' 97 | ret = {DataPoint.Q_KEY:q_key, 98 | DataPoint.Q_TOKENS:q_tokens, 99 | DataPoint.EVIDENCES:evidences,} 100 | return ret 101 | -------------------------------------------------------------------------------- /evaluation/evaluate-tagging-result.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | curdir = os.path.dirname(os.path.abspath(__file__)) 4 | sys.path += [curdir] 5 | import argparse 6 | from tagging_evaluation_util import get_tagging_results 7 | from evaluation_stats_util import F1Stats 8 | from raw_result_parser import iter_results 9 | from ioutil import open_file 10 | 11 | def main(): 12 | parser = argparse.ArgumentParser() 13 | parser.add_argument('raw_prediction') 14 | parser.add_argument('test_file') 15 | parser.add_argument('-s', '--schema', default='BIO2', 16 | choices=['BO', 'BO2', 'BIO', 'BIO2', 'BIO3']) 17 | parser.add_argument('-o', '--output', default='-') 18 | parser.add_argument('-f', '--fuzzy', action='store_true', 19 | help='fuzzy evaluation') 20 | options = parser.parse_args() 21 | 22 | stats = F1Stats(options.fuzzy) 23 | for q_tokens, e_tokens, tags, golden_answers in \ 24 | iter_results(options.raw_prediction, options.test_file, 25 | options.schema): 26 | if q_tokens is None: continue # one question has been processed 27 | pred_answers = get_tagging_results(e_tokens, tags) 28 | stats.update(golden_answers, pred_answers) 29 | 30 | output = sys.stdout if options.output == '-' else open_file(options.output, 'w') 31 | print >> output, stats.get_metrics_str() 32 | output.close() 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /evaluation/evaluate-voting-result.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | curdir = os.path.dirname(os.path.abspath(__file__)) 4 | sys.path += [curdir] 5 | import argparse 6 | from evaluation_stats_util import F1Stats 7 | from voter import iter_voting_results 8 | from ioutil import open_file 9 | 10 | def main(): 11 | parser = argparse.ArgumentParser() 12 | parser.add_argument('raw_prediction') 13 | parser.add_argument('test_file') 14 | parser.add_argument('-s', '--schema', default='BIO2', 15 | choices=['BO', 'BO2', 'BIO', 'BIO2', 'BIO3']) 16 | parser.add_argument('-o', '--output', default='-') 17 | parser.add_argument('-f', '--fuzzy', action='store_true', 18 | help='fuzzy evaluation') 19 | options = parser.parse_args() 20 | 21 | stats = F1Stats(options.fuzzy) 22 | for q_tokens, golden_answers, pred_answers, freqs in \ 23 | iter_voting_results(options.raw_prediction, options.test_file, 24 | options.schema): 25 | stats.update(golden_answers, pred_answers) 26 | 27 | output = sys.stdout if options.output == '-' else open_file(options.output, 'w') 28 | print >> output, stats.get_metrics_str() 29 | output.close() 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /evaluation/evaluation_stats_util.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | import tagging_evaluation_util 4 | 5 | def f1_metrics(total, total_gen, right): 6 | precision = right/float(total_gen) if total_gen != 0 else 0 7 | recall = right/float(total) if total != 0 else 0 8 | try: 9 | f1 = 2*recall*precision/(recall+precision) 10 | except ZeroDivisionError: 11 | f1 = 0 12 | 13 | return precision, recall, f1 14 | 15 | 16 | class F1Stats(object): 17 | _PATTHERN_SPACE = re.compile(r'\s+', re.UNICODE) 18 | def __init__(self, is_fuzzy): 19 | self.is_fuzzy = is_fuzzy 20 | self.total = 0 21 | self.total_gen = 0 22 | self.right = 0 23 | 24 | def norm(self, text): 25 | if not isinstance(text, unicode): text = text.decode('utf-8') 26 | text = self._PATTHERN_SPACE.sub('', text) 27 | return text.lower() 28 | 29 | def is_correct(self, pred_ans, golden_answers): 30 | for golden_answer in golden_answers: 31 | if tagging_evaluation_util.is_right(pred_ans, golden_answer, 32 | self.is_fuzzy): 33 | return True 34 | return False 35 | 36 | def update(self, golden_answers, pred_answers): 37 | # NOTE: self.norm() will remove space 38 | golden_answers = [self.norm(golden_answer) for golden_answer \ 39 | in golden_answers] 40 | golden_answers = filter(None, golden_answers) 41 | 42 | self.total += 1 43 | self.total_gen += len(pred_answers) 44 | 45 | is_right = 0 46 | for pred_ans in pred_answers: 47 | pred_ans = self.norm(pred_ans) 48 | if self.is_correct(pred_ans, golden_answers): 49 | is_right = True 50 | break 51 | 52 | if is_right: 53 | self.right += 1 54 | 55 | def get_metrics_str(self): 56 | precision, recall, f1 = f1_metrics(self.total, self.total_gen, self.right) 57 | return ("chunk_f1=%8.6f chunk_precision=%8.6f " 58 | "chunk_recall=%8.6f true_chunks=%d result_chunks=%d" 59 | " correct_chunks=%d") % \ 60 | (f1, precision, recall, self.total, 61 | self.total_gen, self.right) 62 | -------------------------------------------------------------------------------- /evaluation/example/refs/fuzzy-matching.ref: -------------------------------------------------------------------------------- 1 | chunk_f1=0.460345 chunk_precision=0.485706 chunk_recall=0.437500 true_chunks=4000 result_chunks=3603 correct_chunks=1750 2 | -------------------------------------------------------------------------------- /evaluation/example/refs/strict-matching.ref: -------------------------------------------------------------------------------- 1 | chunk_f1=0.413521 chunk_precision=0.436303 chunk_recall=0.393000 true_chunks=4000 result_chunks=3603 correct_chunks=1572 2 | -------------------------------------------------------------------------------- /evaluation/example/refs/vote-fuzzy-matching.ref: -------------------------------------------------------------------------------- 1 | chunk_f1=0.680952 chunk_precision=0.650000 chunk_recall=0.715000 true_chunks=200 result_chunks=220 correct_chunks=143 2 | -------------------------------------------------------------------------------- /evaluation/example/refs/vote-strict-matching.ref: -------------------------------------------------------------------------------- 1 | chunk_f1=0.614286 chunk_precision=0.586364 chunk_recall=0.645000 true_chunks=200 result_chunks=220 correct_chunks=129 2 | -------------------------------------------------------------------------------- /evaluation/example/run-example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | # strict matching evaluation 4 | python ../evaluate-tagging-result.py \ 5 | ./raw_prediction_example.txt \ 6 | ./test_file_example.json.gz \ 7 | -o strict-matching.ref 8 | 9 | # fuzzy matching evaluation 10 | python ../evaluate-tagging-result.py -f \ 11 | ./raw_prediction_example.txt \ 12 | ./test_file_example.json.gz \ 13 | -o fuzzy-matching.ref 14 | 15 | # strict matching evaluation 16 | python ../evaluate-voting-result.py \ 17 | ./raw_prediction_example.txt \ 18 | ./test_file_example.json.gz \ 19 | -o vote-strict-matching.ref 20 | 21 | # fuzzy matching evaluation 22 | python ../evaluate-voting-result.py -f \ 23 | ./raw_prediction_example.txt \ 24 | ./test_file_example.json.gz \ 25 | -o vote-fuzzy-matching.ref 26 | -------------------------------------------------------------------------------- /evaluation/example/test_file_example.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/evaluation/example/test_file_example.json.gz -------------------------------------------------------------------------------- /evaluation/fuzzy_matching.py: -------------------------------------------------------------------------------- 1 | #--*-- encoding:utf-8 --*-- 2 | import sys 3 | import re 4 | import codecs 5 | from collections import defaultdict 6 | from state_matcher import StateMatcher 7 | from names import country_and_region_names as crnames 8 | from names import chemical_element_names as cenames 9 | from names import measure_names 10 | from re_util import build_greedy_regex_str 11 | 12 | __all__ = ['FuzzyMatcher'] 13 | 14 | DEBUG=False 15 | 16 | class FuzzyMatcher(object): 17 | def __init__(self): 18 | self.__PATTERN_SPACE = re.compile(r'\s+', re.UNICODE) 19 | self.synsets = defaultdict(lambda: set()) 20 | self.reverse_synsets = defaultdict(lambda: []) 21 | 22 | from synsets import synsets as synsets_ 23 | for i, synset in enumerate(synsets_): 24 | for word in synset: 25 | synset = self.__key(word) 26 | self.synsets[word].add(i) 27 | self.reverse_synsets[i] = synset 28 | del synsets_ 29 | 30 | self.__build_patterns() 31 | self.state_matcher = StateMatcher() 32 | 33 | def __key(self, text): 34 | if not isinstance(text, unicode): 35 | text = text.decode('utf-8') 36 | return self.__PATTERN_SPACE.sub('', text).lower() 37 | 38 | def is_synonym(self, std_text, other_text): 39 | std_text_ori, other_text_ori = std_text, other_text 40 | std_text, other_text = self.__key(std_text), self.__key(other_text) 41 | 42 | if DEBUG: print >> sys.stderr, std_text.encode('utf-8'), ' ||| ', 43 | if DEBUG: print >> sys.stderr, other_text.encode('utf-8') 44 | 45 | # equal 46 | if std_text == other_text: return True 47 | if DEBUG: print >> sys.stderr, '\tnot equal' 48 | 49 | # in synonym list 50 | synset1 = self.synsets[std_text] 51 | synset2 = self.synsets[other_text] 52 | if len(synset1 & synset2) != 0: 53 | return True 54 | if DEBUG: print >> sys.stderr, '\tnot synset' 55 | 56 | # other rules 57 | if self.check_prefix_and_suffix(std_text, other_text): 58 | return True 59 | if DEBUG: print >> sys.stderr, '\tnot other rules' 60 | 61 | # state names 62 | if self.check_state_names(std_text_ori, other_text_ori): 63 | return True 64 | if DEBUG: print >> sys.stderr, '\tnot state names' 65 | 66 | if DEBUG: print >> sys.stderr, '\tOK, not synonym ' 67 | return False 68 | 69 | __PATTERN_STATE_NAME = re.compile(u'^(.+)((自治)?(市|县|旗|区|盟|州)|特别行政区)$') 70 | def generate_candidate_synonym(self, std_text): 71 | if not isinstance(std_text, unicode): 72 | std_text = std_text.decode('utf-8') 73 | 74 | candidates = set() 75 | candidates.add(std_text) 76 | 77 | # clean up 78 | std_text = std_text.replace(' ', '').lower() 79 | std_text = std_text.lstrip(u'"').lstrip(u'“').lstrip(u"'")\ 80 | .lstrip(u"‘").lstrip(u'<').lstrip(u'《')\ 81 | .lstrip(u'【') 82 | std_text = std_text.rstrip(u'"').rstrip(u'”').rstrip(u"'")\ 83 | .rstrip(u"’").rstrip(u'>').rstrip(u'》')\ 84 | .rstrip(u"】") 85 | candidates.add(std_text) 86 | 87 | # synonyms 88 | candidates.update(self.reverse_synsets[std_text]) 89 | 90 | # dynasty 91 | if std_text.endswith(u'朝') and self.is_synonym(std_text, std_text[0:-1]): 92 | candidates.add(std_text[0:-1]) 93 | 94 | # state names 95 | m = self.__PATTERN_STATE_NAME.match(std_text) 96 | if m and self.is_synonym(std_text, m.group(1)): 97 | candidates.add(m.group(1)) 98 | 99 | return candidates 100 | 101 | def check_state_names(self, std_text, other_text): 102 | return self.state_matcher.is_same_complex_state(std_text, other_text) 103 | 104 | def __build_patterns(self): 105 | measures = u'|'.join(measure_names) 106 | digits = ur'〇一二三四五六七八九十百千万亿兆\d' 107 | country_and_region_names = build_greedy_regex_str(crnames) 108 | chemical_element_names = build_greedy_regex_str(cenames) 109 | pattern_pairs1 = [ # short, long 110 | (ur'^([{digits}]+)#第?\1({measures})$'.format(digits=digits, measures=measures)), 111 | (ur'^([{digits}]+({measures}))#第\1$'.format(digits=digits, measures=measures)), 112 | (ur'^([{digits}]+)#\1[岁]$'.format(digits=digits)), 113 | (ur'^([{digits}]+个)#\1[人月]$'.format(digits=digits)), 114 | (ur'^(十一|十二|[〇一二三四五六七八九十]|\d+)月?#\1月份$'), 115 | (ur'^([{digits}]+)年?#公元前?\1年?$'.format(digits=digits)), 116 | (ur'^([{digits}]+(分|秒))#\1钟$'.format(digits=digits)), 117 | (ur'^[《<]?(.+)>?[>》]#[《<]\1>?[>》]$'), 118 | (ur'^[《<]?(.+)>?[>》]?#[《<]?\1>?[>》]$'), 119 | (ur'^[《<]?(.+)>?[>》]?#[《<]\1>?[>》]?$'), 120 | (ur'^(..)#\1座$'), # constellation 121 | (ur'^(.+国)#\1人$'), 122 | (ur'^({names})#\1人$'.format(names=country_and_region_names)), 123 | (ur'^([男女])#\1性$'), 124 | (ur'^(.+)#\1地区$'), 125 | (ur'^(.+)#\1(族|民族)$'), 126 | (ur'^(.+)#\1色$'), 127 | (ur'^(夏|商|周|秦|汉|晋|南北|南|北|隋|唐|宋|金|元|明|清)#\1朝$'), 128 | (ur'^(正比|反比)#成\1$'), 129 | (ur'^(正比|反比)#\1例$'), 130 | (ur'^({names})#\1元素$'.format(names=chemical_element_names)), 131 | ] 132 | 133 | pattern_pairs2 = [ # std, other 134 | (ur'^(.+)的#\1$'), 135 | (ur'^([鼠|牛|虎|兔|龙|蛇|马|羊|猴|鸡|狗|猪])年#\1$'), 136 | (ur'^(.+)#\1(公司|大学|罪)$'), 137 | (ur'^[“‘\'"](.+)[”’\'"]#\1$'), 138 | (ur'^(.+)#\1国$'), 139 | ] 140 | 141 | for i in range(len(pattern_pairs1)): 142 | pattern_pairs1[i] = re.compile(pattern_pairs1[i], re.UNICODE) 143 | 144 | for i in range(len(pattern_pairs2)): 145 | pattern_pairs2[i] = re.compile(pattern_pairs2[i], re.UNICODE) 146 | 147 | self.pattern_pairs1 = pattern_pairs1 148 | self.pattern_pairs2 = pattern_pairs2 149 | 150 | def check_prefix_and_suffix(self, std_text, other_text): 151 | if len(std_text) < len(other_text): 152 | sstr, lstr = std_text, other_text 153 | else: 154 | sstr, lstr = other_text, std_text 155 | 156 | pos = lstr.find(sstr) 157 | if pos < 0: return False 158 | 159 | for i, p in enumerate(self.pattern_pairs1): 160 | if p.match(sstr+'#'+lstr): 161 | if DEBUG: print >> sys.stderr, '\trule set 1 #%d matched' % i 162 | return True 163 | 164 | for i, p in enumerate(self.pattern_pairs2): 165 | if p.match(std_text+'#'+other_text): 166 | if DEBUG: print >> sys.stderr, '\trule set 2 #%d matched' % i 167 | return True 168 | 169 | return False 170 | -------------------------------------------------------------------------------- /evaluation/ioutil.py: -------------------------------------------------------------------------------- 1 | from gzip import GzipFile 2 | import os 3 | 4 | # for python 2.6 5 | class GzipFileHack(GzipFile): 6 | def __enter__(self): 7 | return self 8 | def __exit__(self, type, value, tb): 9 | self.close() 10 | 11 | def open_file(filename, *args1, **args2): 12 | if filename.endswith('.gz'): 13 | return GzipFileHack(filename, *args1, **args2) 14 | else: 15 | return open(filename, *args1, **args2) 16 | 17 | def mkdirs(dirname, mode=0755): 18 | if os.path.exists(dirname): return 19 | os.makedirs(dirname, mode) 20 | 21 | def is_not_empty(filename): 22 | if not os.path.exists(filename): return False 23 | return os.path.getsize(filename) != 0 24 | -------------------------------------------------------------------------------- /evaluation/names.py: -------------------------------------------------------------------------------- 1 | #--*-- encoding:utf-8 --*-- 2 | country_and_region_names = ( 3 | ur'不丹', ur'东帝汶', ur'中国', ur'中非', ur'中非共和国', 4 | ur'丹麦', ur'乌克兰', ur'乌兹别克斯坦', ur'乌干达', ur'乌拉圭', 5 | ur'乍得', ur'乔丹', ur'也门', ur'亚洲国家列表', ur'亚美尼亚', 6 | ur'亚美尼亚共和国', ur'以色列', ur'伊拉克', ur'伊朗', ur'伯利兹', 7 | ur'佛得角', ur'俄罗斯', ur'俄罗斯联邦', ur'保加利亚', ur'克罗地亚', 8 | ur'关岛', ur'冈比亚', ur'冰岛', ur'几内亚', ur'几内亚比绍', 9 | ur'列支敦士登', ur'刚果', ur'刚果(布)', ur'刚果(金)', ur'利比亚', 10 | ur'利比里亚', ur'加拿大', ur'加纳', ur'加蓬', ur'匈牙利', 11 | ur'北马里亚纳群岛', ur'南斯拉夫', ur'南非', ur'博茨瓦纳', ur'卡塔尔', 12 | ur'卢旺达', ur'卢森堡', ur'印尼', ur'印度', ur'印度尼西亚', 13 | ur'危地马拉', ur'厄瓜多尔', ur'厄立特里亚', ur'叙利亚', ur'古巴共和国', 14 | ur'台湾', ur'吉尔吉斯共和国', ur'吉尔吉斯斯坦', ur'吉布提', ur'哈萨克斯坦', 15 | ur'哥伦比亚', ur'哥斯达黎加', ur'喀麦隆', ur'图瓦卢', ur'土库曼斯坦', 16 | ur'土耳其', ur'圣卢西亚', ur'圣基茨和尼维斯', ur'圣多美和普林西比', ur'圣文森特和格林纳丁斯', 17 | ur'圣赫勒拿', ur'圣露西亚', ur'圣马力诺', ur'圭亚那', ur'坦桑尼亚', 18 | ur'埃及', ur'埃塞俄比亚', ur'基里巴斯', ur'塔吉克斯坦', ur'塞内加尔', 19 | ur'塞尔维亚和黑山共和国', ur'塞拉利昂', ur'塞浦路斯', ur'塞舌尔', ur'墨西哥', 20 | ur'多哥', ur'多米尼克', ur'多米尼加', ur'大洋洲国家列表', ur'奥地利', 21 | ur'委内瑞拉', ur'孟加拉', ur'孟加拉国', ur'安哥拉', ur'安圭拉', 22 | ur'安提瓜和巴布达', ur'安道尔', ur'密克罗尼西亚联邦', ur'尼加拉瓜', ur'尼日利亚', 23 | ur'尼日尔', ur'尼泊尔', ur'巴勒斯坦', ur'巴哈马', ur'巴基斯坦', 24 | ur'巴巴多斯', ur'巴布亚新几内亚', ur'巴拉圭', ur'巴拿马', ur'巴林', 25 | ur'巴西', ur'布基纳法索', ur'布维岛', ur'布隆迪', ur'希腊', 26 | ur'库克群岛', ur'开曼群岛', ur'德国', ur'意大利', ur'所罗门群岛', 27 | ur'扎伊尔', ur'拉脱维亚', ur'挪威', ur'捷克', ur'摩尔多瓦', 28 | ur'摩洛哥', ur'摩纳哥', ur'文莱', ur'斐济', ur'斯威士兰', 29 | ur'斯洛伐克', ur'斯洛文尼亚', ur'斯瓦尔巴和扬马延岛', ur'斯里兰卡', ur'新加坡', 30 | ur'新喀里多', ur'新西兰', ur'日本', ur'智利', ur'朝鲜', 31 | ur'柬埔寨', ur'格林纳达', ur'格陵兰', ur'格鲁吉亚', ur'梵蒂冈', 32 | ur'比利时', ur'毛里塔尼亚', ur'毛里求斯', ur'汤加', ur'沙特阿拉伯', 33 | ur'法国', ur'法属圭亚那', ur'法属波利尼西亚', ur'法属美特罗波利坦', ur'法罗群岛', 34 | ur'波兰', ur'波多黎各', ur'波斯尼亚和黑塞哥维那', ur'泰国', ur'津巴布韦', 35 | ur'洪都拉斯', ur'海地', ur'澳大利亚', ur'澳门', ur'爱尔兰', 36 | ur'爱沙尼亚', ur'牙买加', ur'特克斯和凯科斯群岛', ur'特立尼达和多巴哥', ur'玻利维亚', 37 | ur'瑙鲁', ur'瑞典', ur'瑞士', ur'瓜德罗普岛', ur'瓦努阿图', 38 | ur'留尼旺', ur'白俄罗斯', ur'百慕大', ur'皮特凯恩群岛', ur'直布罗陀', 39 | ur'福克兰群岛', ur'科威特', ur'科摩罗', ur'科特迪瓦', ur'科特迪瓦哈加格', 40 | ur'秘鲁', ur'突尼斯', ur'立陶宛', ur'索马里', ur'约旦', 41 | ur'纳米比亚', ur'缅甸', ur'罗马尼亚', ur'美国', ur'美属萨摩亚', 42 | ur'美洲国家列表', ur'老挝', ur'肯尼亚', ur'芬兰', ur'苏丹', 43 | ur'苏里南', ur'英国', ur'英属印度洋领地', ur'英属维尔京群岛', ur'荷兰', 44 | ur'荷属安地列斯群岛', ur'莫桑比克', ur'莱索托', ur'菲律宾', ur'萨尔瓦多', 45 | ur'葡萄牙', ur'蒙古', ur'西撒哈拉', ur'西班牙', ur'贝劳', 46 | ur'贝宁', ur'赞比亚', ur'赤道几内亚', ur'越南', ur'阿塞拜疆', 47 | ur'阿塞拜疆共和国', ur'阿富汗', ur'阿尔及利亚', ur'阿尔巴尼亚', ur'阿拉伯联合酋长国', 48 | ur'阿曼', ur'阿根廷', ur'阿鲁巴', ur'非洲国家列表', ur'韩国', 49 | ur'香港', ur'马其顿', ur'马尔代夫', ur'马拉维', ur'马提尼克岛', 50 | ur'马来西亚', ur'马约', ur'马绍尔群岛', ur'马耳他', ur'马达加斯加', 51 | ur'马里', ur'黎巴嫩', 52 | ) 53 | 54 | chemical_element_names = ( 55 | ur'氦', ur'硼', ur'碳', ur'氧', ur'氟', ur'氢', ur'锂', ur'氖', ur'氮', ur'铍', 56 | ur'镁', ur'钾', ur'硫', ur'钙', ur'硅', ur'氩', ur'铝', ur'钠', ur'氯', ur'磷', 57 | ur'钛', ur'锌', ur'铁', ur'铜', ur'钴', ur'钪', ur'镍', ur'锰', ur'钒', ur'铬', 58 | ur'锆', ur'氪', ur'硒', ur'镓', ur'铷', ur'锗', ur'锶', ur'钇', ur'砷', ur'溴', 59 | ur'锡', ur'钌', ur'铌', ur'银', ur'锝', ur'钼', ur'镉', ur'铑', ur'钯', ur'铟', 60 | ur'铯', ur'镨', ur'镧', ur'钕', ur'钡', ur'铈', ur'锑', ur'碘', ur'氙', ur'碲', 61 | ur'钐', ur'钷', ur'镝', ur'铕', ur'铥', ur'铽', ur'镱', ur'钆', ur'铒', ur'钬', 62 | ur'汞', ur'铼', ur'镥', ur'铂', ur'金', ur'钽', ur'铪', ur'钨', ur'铱', ur'锇', 63 | ur'钫', ur'钍', ur'锕', ur'钋', ur'砹', ur'氡', ur'铊', ur'铅', ur'铋', ur'镭', 64 | ur'钚', ur'铀', ur'锎', ur'镤', ur'锔', ur'镎', ur'镅', ur'锫', ur'锿', ur'镄', 65 | ) 66 | 67 | measure_names = ( 68 | ur'ml', ur'k', ur'下', ur'kb', ur'mile', ur'miles', ur'cm', ur'mb', ur'kg', ur'丝', 69 | ur'亩', ur'个', ur'些', ur'个月', ur'两', ur'串', ur'个人', ur'人', ur'人次', ur'人民币', 70 | ur'倍', ur'份', ur'伏特', ur'元', ur'代', ur'例', ur'件', ur'位', ur'伙', ur'兆瓦', 71 | ur'公克', ur'公亩', ur'公斤', ur'先令', ur'兆赫', ur'公分', ur'公吨', ur'克朗', ur'公升', ur'克', 72 | ur'分米', ur'公顷', ur'册', ur'出', ur'公里', ur'公尺', ur'分钟', ur'分', ur'具', ur'刀', 73 | ur'则', ur'列', ur'刻钟', ur'刻', ur'剂', ur'加元', ur'划', ur'副', ur'包', ur'加仑', 74 | ur'千克', ur'千伏', ur'厘', ur'匹', ur'卢比', ur'升', ur'卷', ur'千瓦', ur'华里', ur'千瓦时', 75 | ur'叠', ur'名', ur'双', ur'台套', ur'口', ur'句', ur'台', ur'台币', ur'厘米', ur'只', 76 | ur'回', ur'员', ur'场', ur'周岁', ur'圈', ur'周', ur'团', ur'味', ur'吨级', ur'吨', 77 | ur'堆', ur'块', ur'堵', ur'夥', ur'堂', ur'处', ur'坪', ur'壶', ur'块儿', ur'声', 78 | ur'寸', ur'对', ur'季', ur'家', ur'字', ur'室', ur'天', ur'套', ur'宗', ur'头', 79 | ur'岁', ur'小时', ur'尊', ur'层', ur'尾', ur'局', ur'届', ur'屡', ur'封', ur'尺', 80 | ur'幢', ur'幕', ur'平公里', ur'平方公里', ur'平米', ur'平方英尺', ur'幅', ur'席', ur'帖', ur'平方米', 81 | ur'年', ur'张', ur'座', ur'截', ur'度', ur'年度', ur'年岁', ur'张儿', ur'成', ur'微米', 82 | ur'扇', ur'批次', ur'把', ur'打', ur'担', ur'户', ur'手', ur'所', ur'批', ur'扎', 83 | ur'拳', ur'拨', ur'摄氏度', ur'新元', ur'招', ur'斗', ur'排', ur'支', ur'摊', ur'斤', 84 | ur'方', ur'月', ur'期', ur'新币', ur'日元', ur'本', ur'曲', ur'朵', ur'日', ur'星期', 85 | ur'杆', ur'条', ur'架', ur'杯', ur'枪', ur'枝', ur'架次', ur'束', ur'栋', ur'枚', 86 | ur'欧元', ur'桶', ur'档', ur'根', ur'桩', ur'次', ur'棵', ur'株', ur'欧分', ur'桌', 87 | ur'段', ur'毛', ur'比索', ur'步', ur'毫米', ur'款', ur'毫', ur'法郎', ur'沓', ur'毫升', 88 | ur'港币', ur'波', ur'派', ur'澳币', ur'澳元', ur'溜', ur'滴', ur'港元', ur'滩', ur'海里', 89 | ur'瑞尔', ur'炮', ur'点儿', ur'球', ur'班', ur'点', ur'片', ur'版', ur'环', ur'瓦', 90 | ur'盎司', ur'盆', ur'碗', ur'盒', ur'瓶', ur'盏', ur'眼', ur'盘', ur'瓦特', ur'磅', 91 | ur'立方米', ur'第纳尔', ur'站', ur'秒', ur'章', ur'种', ur'科', ur'立方毫米', ur'笔', ur'秒钟', 92 | ur'箱', ur'篇儿', ur'笼', ur'粒', ur'篓', ur'级段', ur'篇', ur'米', ur'级', ur'类', 93 | ur'缸', ur'组', ur'美', ur'纳米', ur'美分', ur'美元', ur'美金', ur'罐', ur'群', ur'缕', 94 | ur'英尺', ur'艘', ur'英哩', ur'英亩', ur'英里', ur'艘次', ur'英镑', ur'航次', ur'节', ur'英寸', 95 | ur'通', ur'轮', ur'身', ur'角', ur'袋', ur'起', ur'课', ur'跳', ur'辆', ur'趟', 96 | ur'部', ur'锭', ur'酒杯', ur'里', ur'遭', ur'道', ur'部分', ur'遍', ur'锅', ur'针', 97 | ur'面', ur'队', ur'门', ur'顶', ur'间', ur'页', ur'集', ur'阵', ur'韩元', ur'阶', 98 | ur'首', ur'驾次', ur'项', ur'餐', ur'顷', ur'顿', ur'颗', ur'毫安', ur'马克', ur'任', 99 | ur'拍', ur'伏', ur'画', 100 | ) 101 | 102 | ethnic_group_names = ( 103 | ur'汉族', ur'苗族', ur'维吾尔族', ur'藏族', ur'蒙古族', ur'回族', 104 | ur'布依族', ur'满族', ur'侗族', ur'彝族', ur'朝鲜族', ur'壮族', 105 | ur'瑶族', ur'白族', ur'傣族', ur'哈萨克族', ur'土家族', ur'哈尼族', 106 | ur'畲族', ur'拉祜族', ur'黎族', ur'佤族', ur'水族', ur'傈僳族', 107 | ur'纳西族', ur'景颇族', ur'土族', ur'达斡尔族', ur'柯尔克孜族', ur'东乡族', 108 | ur'撒拉族', ur'毛南族', ur'仫佬族', ur'仡佬族', ur'羌族', ur'布朗族', 109 | ur'锡伯族', ur'塔吉克族', ur'乌兹别克族', ur'怒族', ur'普米族', ur'阿昌族', 110 | ur'鄂温克族', ur'俄罗斯族', ur'裕固族', ur'京族', ur'保安族', ur'德昂族', 111 | ur'鄂伦春族', ur'门巴族', ur'赫哲族', ur'独龙族', ur'塔塔尔族', ur'珞巴族', 112 | ) 113 | -------------------------------------------------------------------------------- /evaluation/raw_result_parser.py: -------------------------------------------------------------------------------- 1 | import json 2 | from tagging_util import get_label 3 | from ioutil import open_file 4 | from datapoint import DataPoint, Evidence 5 | 6 | __all__ = ['iter_results'] 7 | 8 | def parse_line(line): 9 | def concat_answers(answers): 10 | return [u' '.join(answer) for answer in answers] 11 | 12 | data = json.loads(line) 13 | q_tokens = data[DataPoint.Q_TOKENS] 14 | evis = data[DataPoint.EVIDENCES] 15 | evi_tokens_list = [evi[Evidence.E_TOKENS] for evi in evis] 16 | golden_answers_list = [concat_answers(evi[Evidence.GOLDEN_ANSWERS]) \ 17 | for evi in evis] 18 | return q_tokens, evi_tokens_list, golden_answers_list 19 | 20 | def iter_results(raw_prediction_file, test_file, schema): 21 | predictions = [] 22 | with open_file(raw_prediction_file) as predict: 23 | for line in predict: 24 | label = get_label(int(line.split(';')[0]), schema) 25 | predictions.append(label) 26 | 27 | idx = 0 28 | with open_file(test_file) as test_file: 29 | for line in test_file: 30 | q_tokens, evi_tokens_list, golden_answers_list = parse_line(line) 31 | for e_tokens, golden_answers in \ 32 | zip(evi_tokens_list, golden_answers_list): 33 | tags = predictions[idx:idx+len(e_tokens)] 34 | yield q_tokens, e_tokens, tags, golden_answers 35 | idx += len(e_tokens) 36 | # one question has been parsed, needed by voters 37 | yield None, None, None, None 38 | 39 | assert idx == len(predictions) 40 | -------------------------------------------------------------------------------- /evaluation/re_util.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def build_greedy_regex_str(words): 4 | words = sorted(words, key=lambda w: len(w), reverse=True) 5 | return '|'.join(words) 6 | -------------------------------------------------------------------------------- /evaluation/state_matcher.py: -------------------------------------------------------------------------------- 1 | #--*-- encoding:utf-8 --*-- 2 | import re 3 | import sys 4 | from state_names import state_names 5 | from names import ethnic_group_names 6 | from re_util import build_greedy_regex_str 7 | from collections import defaultdict 8 | 9 | __all__ = ['StateMatcher'] 10 | 11 | # TODO: smaller state, city etc. names 12 | # TODO: foreign state and city names 13 | # TODO: names such as 新疆维吾尔自治区 14 | # TODO: cases such as "云南 云南" 15 | 16 | DEBUG = False 17 | 18 | class StateMatcher(object): 19 | 20 | STATE_SUFFIXES = (u'省', u'市', u'县', u'旗', u'区', u'盟', u'州', 21 | u'自治省', u'自治市', u'自治县', u'自治旗', u'自治区', 22 | u'自治盟', u'自治州', u'特别行政区') 23 | PATTERN_SPACE = re.compile(r'\s+', re.UNICODE) 24 | 25 | def __init__(self): 26 | regex = build_greedy_regex_str(ethnic_group_names) 27 | self.PATTERN_ETHNIC_GROUPS = re.compile(u'^(.+)(%s)$' % regex) 28 | 29 | self.state_ids = defaultdict(lambda: set()) 30 | self.full_name_ids = {} 31 | for id_, name in state_names: 32 | full_name = name 33 | name = self.get_simple_state_name(name) 34 | if len(name) == 0: continue 35 | self.state_ids[name].add(id_) 36 | self.full_name_ids[full_name] = id_ 37 | self.state_ids.default_factory = None 38 | 39 | # match all simple state names 40 | regex = build_greedy_regex_str(self.state_ids.keys()) 41 | self.PATTERN_STATE = re.compile(regex) 42 | 43 | names = self.state_ids.keys() + self.full_name_ids.keys() 44 | regex = build_greedy_regex_str(names) 45 | self.PATTERN_COMPLEX_STATE = re.compile(u'^(%s)+$' % regex) 46 | 47 | def get_simple_state_name(self, name): 48 | '''name: a single state name''' 49 | suffix = name[-1].strip() 50 | if suffix in u'省市县旗区盟州': 51 | name = name[0:-1].strip() 52 | if name.endswith(u'自治'): 53 | name = name[0:-2].strip() 54 | if name.endswith(u'特别行政'): 55 | name = name[0:-4].strip() 56 | m = self.PATTERN_ETHNIC_GROUPS.match(name) 57 | if m: name = m.group(1) 58 | suffixes = [u'维吾尔', u'哈萨克', u'蒙古', u'柯尔克孜', 59 | u'塔吉克', u'锡伯',] 60 | for suffix in suffixes: 61 | if name.endswith(suffix): 62 | name = name[0:-len(suffix)] 63 | return name 64 | 65 | def get_all_state_names(self, text): 66 | return self.PATTERN_STATE.findall(self.__norm(text)) 67 | 68 | def __key(self, name): 69 | name = self.__norm(name) 70 | if name in self.state_ids: 71 | return name 72 | return self.get_simple_state_name(name) 73 | 74 | def __norm(self, text): 75 | if not isinstance(text, unicode): text = text.decode('utf-8') 76 | return self.PATTERN_SPACE.sub('', text) 77 | 78 | def is_in(self, small_state, big_state): 79 | ids1 = self.state_ids.get(self.__key(small_state)) 80 | ids2 = self.state_ids.get(self.__key(big_state)) 81 | 82 | if not ids1 or not ids2: 83 | return False 84 | ids1 = [id_.rstrip('0') for id_ in ids1] 85 | ids2 = [id_.rstrip('0') for id_ in ids2] 86 | for id1 in ids1: 87 | for id2 in ids2: 88 | if id1 == id2: continue 89 | if id1.startswith(id2): 90 | return True 91 | return False 92 | 93 | def is_same_state(self, state1, state2): 94 | state1, state2 = self.__norm(state1), self.__norm(state2) 95 | if len(state1) < len(state2): 96 | sstate, lstate = state1, state2 97 | else: 98 | sstate, lstate = state2, state1 99 | if not lstate.startswith(sstate): 100 | return False 101 | if sstate not in self.state_ids: 102 | return False 103 | if lstate not in self.full_name_ids: 104 | return False 105 | if self.__key(lstate) not in self.state_ids: 106 | return False 107 | return True 108 | 109 | def is_same_complex_state(self, std_text, other_text): 110 | if not self.maybe_complex_state_name(std_text): return False 111 | if not self.maybe_complex_state_name(other_text): return False 112 | 113 | std_text, other_text = self.__norm(std_text), self.__norm(other_text) 114 | # break into state names 115 | std_sub_names = self.get_all_state_names(std_text) 116 | std_text = ''.join(std_sub_names) 117 | 118 | other_sub_names = self.get_all_state_names(other_text) 119 | other_text = ''.join(other_sub_names) 120 | 121 | if DEBUG: print >> sys.stderr, 'std_text:', std_text.encode('utf-8') 122 | if DEBUG: print >> sys.stderr, 'other_text:', other_text.encode('utf-8') 123 | 124 | if not other_text.endswith(std_text) and \ 125 | not std_text.endswith(other_text): 126 | return False 127 | 128 | # verify every part is a state name 129 | for sub_names in [std_sub_names, other_sub_names]: 130 | if DEBUG: print >> sys.stderr, 'check is state name: ', 131 | if DEBUG: print >> sys.stderr, ' '.join(sub_names).encode('utf-8') 132 | for sub_name in sub_names: 133 | if not self.is_state_name(sub_name): 134 | return False 135 | if DEBUG: print >> sys.stderr, '\t', sub_name, '\tpass' 136 | if DEBUG: print >> sys.stderr, '\tevery part is a state name' 137 | 138 | if len(std_sub_names) < len(other_sub_names): 139 | sub_names = other_sub_names 140 | else: 141 | sub_names = std_sub_names 142 | 143 | # verify order 144 | if DEBUG: print >> sys.stderr, 'verify order:' 145 | if DEBUG: print >> sys.stderr, ' '.join(sub_names).encode('utf-8') 146 | for i in range(1, len(sub_names)): 147 | if not self.is_in(sub_names[i], sub_names[0]): 148 | return False 149 | if DEBUG: print >> sys.stderr, '\t', sub_names[i], '|', sub_names[0], '\tpass' 150 | if DEBUG: print >> sys.stderr, '\torder ok' 151 | 152 | return True 153 | 154 | def is_state_name(self, name): 155 | return self.__key(name) in self.state_ids 156 | 157 | def maybe_complex_state_name(self, name): 158 | return bool(self.PATTERN_COMPLEX_STATE.match(self.__norm(name))) 159 | -------------------------------------------------------------------------------- /evaluation/state_names.py: -------------------------------------------------------------------------------- 1 | #--*-- encoding:utf-8 --*-- 2 | #names from http://www.gov.cn/test/2009-03/30/content_1272354.htm 3 | import re 4 | __state_name_strs = u''' 5 | 110000 北京市 6 | 110100 市辖区 7 | 110101 东城区 8 | 110102 西城区 9 | 110103 崇文区 10 | 110104 宣武区 11 | 110105 朝阳区 12 | 110106 丰台区 13 | 110107 石景山区 14 | 110108 海淀区 15 | 110109 门头沟区 16 | 110111 房山区 17 | 110112 通州区 18 | 110113 顺义区 19 | 110114 昌平区 20 | 110115 大兴区 21 | 110116 怀柔区 22 | 110117 平谷区 23 | 110200 县 24 | 110228 密云县 25 | 110229 延庆县 26 | 27 | 120000 天津市 28 | 120100 市辖区 29 | 120101 和平区 30 | 120102 河东区 31 | 120103 河西区 32 | 120104 南开区 33 | 120105 河北区 34 | 120106 红桥区 35 | 120107 塘沽区 36 | 120108 汉沽区 37 | 120109 大港区 38 | 120110 东丽区 39 | 120111 西青区 40 | 120112 津南区 41 | 120113 北辰区 42 | 120114 武清区 43 | 120115 宝坻区 44 | 120200 县 45 | 120221 宁河县 46 | 120223 静海县 47 | 120225 蓟 县 48 | 49 | 130000 河北省 50 | 130100 石家庄市 51 | 130101 市辖区 52 | 130102 长安区 53 | 130103 桥东区 54 | 130104 桥西区 55 | 130105 新华区 56 | 130107 井陉矿区 57 | 130108 裕华区 58 | 130121 井陉县 59 | 130123 正定县 60 | 130124 栾城县 61 | 130125 行唐县 62 | 130126 灵寿县 63 | 130127 高邑县 64 | 130128 深泽县 65 | 130129 赞皇县 66 | 130130 无极县 67 | 130131 平山县 68 | 130132 元氏县 69 | 130133 赵 县 70 | 130181 辛集市 71 | 130182 藁城市 72 | 130183 晋州市 73 | 130184 新乐市 74 | 130185 鹿泉市 75 | 130200 唐山市 76 | 130201 市辖区 77 | 130202 路南区 78 | 130203 路北区 79 | 130204 古冶区 80 | 130205 开平区 81 | 130207 丰南区 82 | 130208 丰润区 83 | 130223 滦 县 84 | 130224 滦南县 85 | 130225 乐亭县 86 | 130227 迁西县 87 | 130229 玉田县 88 | 130230 唐海县 89 | 130281 遵化市 90 | 130283 迁安市 91 | 130300 秦皇岛市 92 | 130301 市辖区 93 | 130302 海港区 94 | 130303 山海关区 95 | 130304 北戴河区 96 | 130321 青龙满族自治县 97 | 130322 昌黎县 98 | 130323 抚宁县 99 | 130324 卢龙县 100 | 130400 邯郸市 101 | 130401 市辖区 102 | 130402 邯山区 103 | 130403 丛台区 104 | 130404 复兴区 105 | 130406 峰峰矿区 106 | 130421 邯郸县 107 | 130423 临漳县 108 | 130424 成安县 109 | 130425 大名县 110 | 130426 涉 县 111 | 130427 磁 县 112 | 130428 肥乡县 113 | 130429 永年县 114 | 130430 邱 县 115 | 130431 鸡泽县 116 | 130432 广平县 117 | 130433 馆陶县 118 | 130434 魏 县 119 | 130435 曲周县 120 | 130481 武安市 121 | 130500 邢台市 122 | 130501 市辖区 123 | 130502 桥东区 124 | 130503 桥西区 125 | 130521 邢台县 126 | 130522 临城县 127 | 130523 内丘县 128 | 130524 柏乡县 129 | 130525 隆尧县 130 | 130526 任 县 131 | 130527 南和县 132 | 130528 宁晋县 133 | 130529 巨鹿县 134 | 130530 新河县 135 | 130531 广宗县 136 | 130532 平乡县 137 | 130533 威 县 138 | 130534 清河县 139 | 130535 临西县 140 | 130581 南宫市 141 | 130582 沙河市 142 | 130600 保定市 143 | 130601 市辖区 144 | 130602 新市区 145 | 130603 北市区 146 | 130604 南市区 147 | 130621 满城县 148 | 130622 清苑县 149 | 130623 涞水县 150 | 130624 阜平县 151 | 130625 徐水县 152 | 130626 定兴县 153 | 130627 唐 县 154 | 130628 高阳县 155 | 130629 容城县 156 | 130630 涞源县 157 | 130631 望都县 158 | 130632 安新县 159 | 130633 易 县 160 | 130634 曲阳县 161 | 130635 蠡 县 162 | 130636 顺平县 163 | 130637 博野县 164 | 130638 雄 县 165 | 130681 涿州市 166 | 130682 定州市 167 | 130683 安国市 168 | 130684 高碑店市 169 | 130700 张家口市 170 | 130701 市辖区 171 | 130702 桥东区 172 | 130703 桥西区 173 | 130705 宣化区 174 | 130706 下花园区 175 | 130721 宣化县 176 | 130722 张北县 177 | 130723 康保县 178 | 130724 沽源县 179 | 130725 尚义县 180 | 130726 蔚 县 181 | 130727 阳原县 182 | 130728 怀安县 183 | 130729 万全县 184 | 130730 怀来县 185 | 130731 涿鹿县 186 | 130732 赤城县 187 | 130733 崇礼县 188 | 130800 承德市 189 | 130801 市辖区 190 | 130802 双桥区 191 | 130803 双滦区 192 | 130804 鹰手营子矿区 193 | 130821 承德县 194 | 130822 兴隆县 195 | 130823 平泉县 196 | 130824 滦平县 197 | 130825 隆化县 198 | 130826 丰宁满族自治县 199 | 130827 宽城满族自治县 200 | 130828 围场满族蒙古族自治县 201 | 130900 沧州市 202 | 130901 市辖区 203 | 130902 新华区 204 | 130903 运河区 205 | 130921 沧 县 206 | 130922 青 县 207 | 130923 东光县 208 | 130924 海兴县 209 | 130925 盐山县 210 | 130926 肃宁县 211 | 130927 南皮县 212 | 130928 吴桥县 213 | 130929 献 县 214 | 130930 孟村回族自治县 215 | 130981 泊头市 216 | 130982 任丘市 217 | 130983 黄骅市 218 | 130984 河间市 219 | 131000 廊坊市 220 | 131001 市辖区 221 | 131002 安次区 222 | 131003 广阳区 223 | 131022 固安县 224 | 131023 永清县 225 | 131024 香河县 226 | 131025 大城县 227 | 131026 文安县 228 | 131028 大厂回族自治县 229 | 131081 霸州市 230 | 131082 三河市 231 | 131100 衡水市 232 | 131101 市辖区 233 | 131102 桃城区 234 | 131121 枣强县 235 | 131122 武邑县 236 | 131123 武强县 237 | 131124 饶阳县 238 | 131125 安平县 239 | 131126 故城县 240 | 131127 景 县 241 | 131128 阜城县 242 | 131181 冀州市 243 | 131182 深州市 244 | 245 | 140000 山西省 246 | 140100 太原市 247 | 140101 市辖区 248 | 140105 小店区 249 | 140106 迎泽区 250 | 140107 杏花岭区 251 | 140108 尖草坪区 252 | 140109 万柏林区 253 | 140110 晋源区 254 | 140121 清徐县 255 | 140122 阳曲县 256 | 140123 娄烦县 257 | 140181 古交市 258 | 140200 大同市 259 | 140201 市辖区 260 | 140202 城 区 261 | 140203 矿 区 262 | 140211 南郊区 263 | 140212 新荣区 264 | 140221 阳高县 265 | 140222 天镇县 266 | 140223 广灵县 267 | 140224 灵丘县 268 | 140225 浑源县 269 | 140226 左云县 270 | 140227 大同县 271 | 140300 阳泉市 272 | 140301 市辖区 273 | 140302 城 区 274 | 140303 矿 区 275 | 140311 郊 区 276 | 140321 平定县 277 | 140322 盂 县 278 | 140400 长治市 279 | 140401 市辖区 280 | 140402 城 区 281 | 140411 郊 区 282 | 140421 长治县 283 | 140423 襄垣县 284 | 140424 屯留县 285 | 140425 平顺县 286 | 140426 黎城县 287 | 140427 壶关县 288 | 140428 长子县 289 | 140429 武乡县 290 | 140430 沁 县 291 | 140431 沁源县 292 | 140481 潞城市 293 | 140500 晋城市 294 | 140501 市辖区 295 | 140502 城 区 296 | 140521 沁水县 297 | 140522 阳城县 298 | 140524 陵川县 299 | 140525 泽州县 300 | 140581 高平市 301 | 140600 朔州市 302 | 140601 市辖区 303 | 140602 朔城区 304 | 140603 平鲁区 305 | 140621 山阴县 306 | 140622 应 县 307 | 140623 右玉县 308 | 140624 怀仁县 309 | 140700 晋中市 310 | 140701 市辖区 311 | 140702 榆次区 312 | 140721 榆社县 313 | 140722 左权县 314 | 140723 和顺县 315 | 140724 昔阳县 316 | 140725 寿阳县 317 | 140726 太谷县 318 | 140727 祁 县 319 | 140728 平遥县 320 | 140729 灵石县 321 | 140781 介休市 322 | 140800 运城市 323 | 140801 市辖区 324 | 140802 盐湖区 325 | 140821 临猗县 326 | 140822 万荣县 327 | 140823 闻喜县 328 | 140824 稷山县 329 | 140825 新绛县 330 | 140826 绛 县 331 | 140827 垣曲县 332 | 140828 夏 县 333 | 140829 平陆县 334 | 140830 芮城县 335 | 140881 永济市 336 | 140882 河津市 337 | 140900 忻州市 338 | 140901 市辖区 339 | 140902 忻府区 340 | 140921 定襄县 341 | 140922 五台县 342 | 140923 代 县 343 | 140924 繁峙县 344 | 140925 宁武县 345 | 140926 静乐县 346 | 140927 神池县 347 | 140928 五寨县 348 | 140929 岢岚县 349 | 140930 河曲县 350 | 140931 保德县 351 | 140932 偏关县 352 | 140981 原平市 353 | 141000 临汾市 354 | 141001 市辖区 355 | 141002 尧都区 356 | 141021 曲沃县 357 | 141022 翼城县 358 | 141023 襄汾县 359 | 141024 洪洞县 360 | 141025 古 县 361 | 141026 安泽县 362 | 141027 浮山县 363 | 141028 吉 县 364 | 141029 乡宁县 365 | 141030 大宁县 366 | 141031 隰 县 367 | 141032 永和县 368 | 141033 蒲 县 369 | 141034 汾西县 370 | 141081 侯马市 371 | 141082 霍州市 372 | 141100 吕梁市 373 | 141101 市辖区 374 | 141102 离石区 375 | 141121 文水县 376 | 141122 交城县 377 | 141123 兴 县 378 | 141124 临 县 379 | 141125 柳林县 380 | 141126 石楼县 381 | 141127 岚 县 382 | 141128 方山县 383 | 141129 中阳县 384 | 141130 交口县 385 | 141181 孝义市 386 | 141182 汾阳市 387 | 388 | 150000 内蒙古自治区 389 | 150100 呼和浩特市 390 | 150101 市辖区 391 | 150102 新城区 392 | 150103 回民区 393 | 150104 玉泉区 394 | 150105 赛罕区 395 | 150121 土默特左旗 396 | 150122 托克托县 397 | 150123 和林格尔县 398 | 150124 清水河县 399 | 150125 武川县 400 | 150200 包头市 401 | 150201 市辖区 402 | 150202 东河区 403 | 150203 昆都仑区 404 | 150204 青山区 405 | 150205 石拐区 406 | 150206 白云矿区 407 | 150207 九原区 408 | 150221 土默特右旗 409 | 150222 固阳县 410 | 150223 达尔罕茂明安联合旗 411 | 150300 乌海市 412 | 150301 市辖区 413 | 150302 海勃湾区 414 | 150303 海南区 415 | 150304 乌达区 416 | 150400 赤峰市 417 | 150401 市辖区 418 | 150402 红山区 419 | 150403 元宝山区 420 | 150404 松山区 421 | 150421 阿鲁科尔沁旗 422 | 150422 巴林左旗 423 | 150423 巴林右旗 424 | 150424 林西县 425 | 150425 克什克腾旗 426 | 150426 翁牛特旗 427 | 150428 喀喇沁旗 428 | 150429 宁城县 429 | 150430 敖汉旗 430 | 150500 通辽市 431 | 150501 市辖区 432 | 150502 科尔沁区 433 | 150521 科尔沁左翼中旗 434 | 150522 科尔沁左翼后旗 435 | 150523 开鲁县 436 | 150524 库伦旗 437 | 150525 奈曼旗 438 | 150526 扎鲁特旗 439 | 150581 霍林郭勒市 440 | 150600 鄂尔多斯市 441 | 150602 东胜区 442 | 150621 达拉特旗 443 | 150622 准格尔旗 444 | 150623 鄂托克前旗 445 | 150624 鄂托克旗 446 | 150625 杭锦旗 447 | 150626 乌审旗 448 | 150627 伊金霍洛旗 449 | 150700 呼伦贝尔市 450 | 150701 市辖区 451 | 150702 海拉尔区 452 | 150721 阿荣旗 453 | 150722 莫力达瓦达斡尔族自治旗 454 | 150723 鄂伦春自治旗 455 | 150724 鄂温克族自治旗 456 | 150725 陈巴尔虎旗 457 | 150726 新巴尔虎左旗 458 | 150727 新巴尔虎右旗 459 | 150781 满洲里市 460 | 150782 牙克石市 461 | 150783 扎兰屯市 462 | 150784 额尔古纳市 463 | 150785 根河市 464 | 150800 巴彦淖尔市 465 | 150801 市辖区 466 | 150802 临河区 467 | 150821 五原县 468 | 150822 磴口县 469 | 150823 乌拉特前旗 470 | 150824 乌拉特中旗 471 | 150825 乌拉特后旗 472 | 150826 杭锦后旗 473 | 150900 乌兰察布市 474 | 150901 市辖区 475 | 150902 集宁区 476 | 150921 卓资县 477 | 150922 化德县 478 | 150923 商都县 479 | 150924 兴和县 480 | 150925 凉城县 481 | 150926 察哈尔右翼前旗 482 | 150927 察哈尔右翼中旗 483 | 150928 察哈尔右翼后旗 484 | 150929 四子王旗 485 | 150981 丰镇市 486 | 152200 兴安盟 487 | 152201 乌兰浩特市 488 | 152202 阿尔山市 489 | 152221 科尔沁右翼前旗 490 | 152222 科尔沁右翼中旗 491 | 152223 扎赉特旗 492 | 152224 突泉县 493 | 152500 锡林郭勒盟 494 | 152501 二连浩特市 495 | 152502 锡林浩特市 496 | 152522 阿巴嘎旗 497 | 152523 苏尼特左旗 498 | 152524 苏尼特右旗 499 | 152525 东乌珠穆沁旗 500 | 152526 西乌珠穆沁旗 501 | 152527 太仆寺旗 502 | 152528 镶黄旗 503 | 152529 正镶白旗 504 | 152530 正蓝旗 505 | 152531 多伦县 506 | 152900 阿拉善盟 507 | 152921 阿拉善左旗 508 | 152922 阿拉善右旗 509 | 152923 额济纳旗 510 | 511 | 210000 辽宁省 512 | 210100 沈阳市 513 | 210101 市辖区 514 | 210102 和平区 515 | 210103 沈河区 516 | 210104 大东区 517 | 210105 皇姑区 518 | 210106 铁西区 519 | 210111 苏家屯区 520 | 210112 东陵区 521 | 210113 新城子区 522 | 210114 于洪区 523 | 210122 辽中县 524 | 210123 康平县 525 | 210124 法库县 526 | 210181 新民市 527 | 210200 大连市 528 | 210201 市辖区 529 | 210202 中山区 530 | 210203 西岗区 531 | 210204 沙河口区 532 | 210211 甘井子区 533 | 210212 旅顺口区 534 | 210213 金州区 535 | 210224 长海县 536 | 210281 瓦房店市 537 | 210282 普兰店市 538 | 210283 庄河市 539 | 210300 鞍山市 540 | 210301 市辖区 541 | 210302 铁东区 542 | 210303 铁西区 543 | 210304 立山区 544 | 210311 千山区 545 | 210321 台安县 546 | 210323 岫岩满族自治县 547 | 210381 海城市 548 | 210400 抚顺市 549 | 210401 市辖区 550 | 210402 新抚区 551 | 210403 东洲区 552 | 210404 望花区 553 | 210411 顺城区 554 | 210421 抚顺县 555 | 210422 新宾满族自治县 556 | 210423 清原满族自治县 557 | 210500 本溪市 558 | 210501 市辖区 559 | 210502 平山区 560 | 210503 溪湖区 561 | 210504 明山区 562 | 210505 南芬区 563 | 210521 本溪满族自治县 564 | 210522 桓仁满族自治县 565 | 210600 丹东市 566 | 210601 市辖区 567 | 210602 元宝区 568 | 210603 振兴区 569 | 210604 振安区 570 | 210624 宽甸满族自治县 571 | 210681 东港市 572 | 210682 凤城市 573 | 210700 锦州市 574 | 210701 市辖区 575 | 210702 古塔区 576 | 210703 凌河区 577 | 210711 太和区 578 | 210726 黑山县 579 | 210727 义 县 580 | 210781 凌海市 581 | 210782 北宁市 582 | 210800 营口市 583 | 210801 市辖区 584 | 210802 站前区 585 | 210803 西市区 586 | 210804 鲅鱼圈区 587 | 210811 老边区 588 | 210881 盖州市 589 | 210882 大石桥市 590 | 210900 阜新市 591 | 210901 市辖区 592 | 210902 海州区 593 | 210903 新邱区 594 | 210904 太平区 595 | 210905 清河门区 596 | 210911 细河区 597 | 210921 阜新蒙古族自治县 598 | 210922 彰武县 599 | 211000 辽阳市 600 | 211001 市辖区 601 | 211002 白塔区 602 | 211003 文圣区 603 | 211004 宏伟区 604 | 211005 弓长岭区 605 | 211011 太子河区 606 | 211021 辽阳县 607 | 211081 灯塔市 608 | 211100 盘锦市 609 | 211101 市辖区 610 | 211102 双台子区 611 | 211103 兴隆台区 612 | 211121 大洼县 613 | 211122 盘山县 614 | 211200 铁岭市 615 | 211201 市辖区 616 | 211202 银州区 617 | 211204 清河区 618 | 211221 铁岭县 619 | 211223 西丰县 620 | 211224 昌图县 621 | 211281 调兵山市 622 | 211282 开原市 623 | 211300 朝阳市 624 | 211301 市辖区 625 | 211302 双塔区 626 | 211303 龙城区 627 | 211321 朝阳县 628 | 211322 建平县 629 | 211324 喀喇沁左翼蒙古族自治县 630 | 211381 北票市 631 | 211382 凌源市 632 | 211400 葫芦岛市 633 | 211401 市辖区 634 | 211402 连山区 635 | 211403 龙港区 636 | 211404 南票区 637 | 211421 绥中县 638 | 211422 建昌县 639 | 211481 兴城市 640 | 641 | 220000 吉林省 642 | 220100 长春市 643 | 220101 市辖区 644 | 220102 南关区 645 | 220103 宽城区 646 | 220104 朝阳区 647 | 220105 二道区 648 | 220106 绿园区 649 | 220112 双阳区 650 | 220122 农安县 651 | 220181 九台市 652 | 220182 榆树市 653 | 220183 德惠市 654 | 220200 吉林市 655 | 220201 市辖区 656 | 220202 昌邑区 657 | 220203 龙潭区 658 | 220204 船营区 659 | 220211 丰满区 660 | 220221 永吉县 661 | 220281 蛟河市 662 | 220282 桦甸市 663 | 220283 舒兰市 664 | 220284 磐石市 665 | 220300 四平市 666 | 220301 市辖区 667 | 220302 铁西区 668 | 220303 铁东区 669 | 220322 梨树县 670 | 220323 伊通满族自治县 671 | 220381 公主岭市 672 | 220382 双辽市 673 | 220400 辽源市 674 | 220401 市辖区 675 | 220402 龙山区 676 | 220403 西安区 677 | 220421 东丰县 678 | 220422 东辽县 679 | 220500 通化市 680 | 220501 市辖区 681 | 220502 东昌区 682 | 220503 二道江区 683 | 220521 通化县 684 | 220523 辉南县 685 | 220524 柳河县 686 | 220581 梅河口市 687 | 220582 集安市 688 | 220600 白山市 689 | 220600 浑江市 690 | 220601 市辖区 691 | 220602 八道江区 692 | 220621 抚松县 693 | 220622 靖宇县 694 | 220623 长白朝鲜族自治县 695 | 220625 江源县 696 | 220681 临江市 697 | 220700 松原市 698 | 220701 市辖区 699 | 220702 宁江区 700 | 220721 前郭尔罗斯蒙古族自治县 701 | 220722 长岭县 702 | 220723 乾安县 703 | 220724 扶余县 704 | 220800 白城市 705 | 220801 市辖区 706 | 220802 洮北区 707 | 220821 镇赉县 708 | 220822 通榆县 709 | 220881 洮南市 710 | 220882 大安市 711 | 222400 延边朝鲜族自治州 712 | 222401 延吉市 713 | 222402 图们市 714 | 222403 敦化市 715 | 222404 珲春市 716 | 222405 龙井市 717 | 222406 和龙市 718 | 222424 汪清县 719 | 222426 安图县 720 | 721 | 230000 黑龙江省 722 | 230100 哈尔滨市 723 | 230101 市辖区 724 | 230102 道里区 725 | 230103 南岗区 726 | 230104 道外区 727 | 230106 香坊区 728 | 230107 动力区 729 | 230108 平房区 730 | 230109 松北区 731 | 230111 呼兰区 732 | 230123 依兰县 733 | 230124 方正县 734 | 230125 宾 县 735 | 230126 巴彦县 736 | 230127 木兰县 737 | 230128 通河县 738 | 230129 延寿县 739 | 230181 阿城市 740 | 230182 双城市 741 | 230183 尚志市 742 | 230184 五常市 743 | 230200 齐齐哈尔市 744 | 230201 市辖区 745 | 230202 龙沙区 746 | 230203 建华区 747 | 230204 铁锋区 748 | 230205 昂昂溪区 749 | 230206 富拉尔基区 750 | 230207 碾子山区 751 | 230208 梅里斯达斡尔族区 752 | 230221 龙江县 753 | 230223 依安县 754 | 230224 泰来县 755 | 230225 甘南县 756 | 230227 富裕县 757 | 230229 克山县 758 | 230230 克东县 759 | 230231 拜泉县 760 | 230281 讷河市 761 | 230300 鸡西市 762 | 230301 市辖区 763 | 230302 鸡冠区 764 | 230303 恒山区 765 | 230304 滴道区 766 | 230305 梨树区 767 | 230306 城子河区 768 | 230307 麻山区 769 | 230321 鸡东县 770 | 230381 虎林市 771 | 230382 密山市 772 | 230400 鹤岗市 773 | 230401 市辖区 774 | 230402 向阳区 775 | 230403 工农区 776 | 230404 南山区 777 | 230405 兴安区 778 | 230406 东山区 779 | 230407 兴山区 780 | 230421 萝北县 781 | 230422 绥滨县 782 | 230500 双鸭山市 783 | 230501 市辖区 784 | 230502 尖山区 785 | 230503 岭东区 786 | 230505 四方台区 787 | 230506 宝山区 788 | 230521 集贤县 789 | 230522 友谊县 790 | 230523 宝清县 791 | 230524 饶河县 792 | 230600 大庆市 793 | 230601 市辖区 794 | 230602 萨尔图区 795 | 230603 龙凤区 796 | 230604 让胡路区 797 | 230605 红岗区 798 | 230606 大同区 799 | 230621 肇州县 800 | 230622 肇源县 801 | 230623 林甸县 802 | 230624 杜尔伯特蒙古族自治县 803 | 230700 伊春市 804 | 230701 市辖区 805 | 230702 伊春区 806 | 230703 南岔区 807 | 230704 友好区 808 | 230705 西林区 809 | 230706 翠峦区 810 | 230707 新青区 811 | 230708 美溪区 812 | 230709 金山屯区 813 | 230710 五营区 814 | 230711 乌马河区 815 | 230712 汤旺河区 816 | 230713 带岭区 817 | 230714 乌伊岭区 818 | 230715 红星区 819 | 230716 上甘岭区 820 | 230722 嘉荫县 821 | 230781 铁力市 822 | 230800 佳木斯市 823 | 230801 市辖区 824 | 230802 永红区 825 | 230803 向阳区 826 | 230804 前进区 827 | 230805 东风区 828 | 230811 郊 区 829 | 230822 桦南县 830 | 230826 桦川县 831 | 230828 汤原县 832 | 230833 抚远县 833 | 230881 同江市 834 | 230882 富锦市 835 | 230900 七台河市 836 | 230901 市辖区 837 | 230902 新兴区 838 | 230903 桃山区 839 | 230904 茄子河区 840 | 230921 勃利县 841 | 231000 牡丹江市 842 | 231001 市辖区 843 | 231002 东安区 844 | 231003 阳明区 845 | 231004 爱民区 846 | 231005 西安区 847 | 231024 东宁县 848 | 231025 林口县 849 | 231081 绥芬河市 850 | 231083 海林市 851 | 231084 宁安市 852 | 231085 穆棱市 853 | 231100 黑河市 854 | 231101 市辖区 855 | 231102 爱辉区 856 | 231121 嫩江县 857 | 231123 逊克县 858 | 231124 孙吴县 859 | 231181 北安市 860 | 231182 五大连池市 861 | 231200 绥化市 862 | 231201 市辖区 863 | 231202 北林区 864 | 231221 望奎县 865 | 231222 兰西县 866 | 231223 青冈县 867 | 231224 庆安县 868 | 231225 明水县 869 | 231226 绥棱县 870 | 231281 安达市 871 | 231282 肇东市 872 | 231283 海伦市 873 | 232700 大兴安岭地区 874 | 232721 呼玛县 875 | 232722 塔河县 876 | 232723 漠河县 877 | 878 | 310000 上海市 879 | 310100 市辖区 880 | 310101 黄浦区 881 | 310103 卢湾区 882 | 310104 徐汇区 883 | 310105 长宁区 884 | 310106 静安区 885 | 310107 普陀区 886 | 310108 闸北区 887 | 310109 虹口区 888 | 310110 杨浦区 889 | 310112 闵行区 890 | 310113 宝山区 891 | 310114 嘉定区 892 | 310115 浦东新区 893 | 310116 金山区 894 | 310117 松江区 895 | 310118 青浦区 896 | 310119 南汇区 897 | 310120 奉贤区 898 | 310200 县 899 | 310230 崇明县 900 | 901 | 320000 江苏省 902 | 320100 南京市 903 | 320101 市辖区 904 | 320102 玄武区 905 | 320103 白下区 906 | 320104 秦淮区 907 | 320105 建邺区 908 | 320106 鼓楼区 909 | 320107 下关区 910 | 320111 浦口区 911 | 320113 栖霞区 912 | 320114 雨花台区 913 | 320115 江宁区 914 | 320116 六合区 915 | 320124 溧水县 916 | 320125 高淳县 917 | 320200 无锡市 918 | 320201 市辖区 919 | 320202 崇安区 920 | 320203 南长区 921 | 320204 北塘区 922 | 320205 锡山区 923 | 320206 惠山区 924 | 320211 滨湖区 925 | 320281 江阴市 926 | 320282 宜兴市 927 | 320300 徐州市 928 | 320301 市辖区 929 | 320302 鼓楼区 930 | 320303 云龙区 931 | 320304 九里区 932 | 320305 贾汪区 933 | 320311 泉山区 934 | 320321 丰 县 935 | 320322 沛 县 936 | 320323 铜山县 937 | 320324 睢宁县 938 | 320381 新沂市 939 | 320382 邳州市 940 | 320400 常州市 941 | 320401 市辖区 942 | 320402 天宁区 943 | 320404 钟楼区 944 | 320405 戚墅堰区 945 | 320411 新北区 946 | 320412 武进区 947 | 320481 溧阳市 948 | 320482 金坛市 949 | 320500 苏州市 950 | 320501 市辖区 951 | 320502 沧浪区 952 | 320503 平江区 953 | 320504 金阊区 954 | 320505 虎丘区 955 | 320506 吴中区 956 | 320507 相城区 957 | 320581 常熟市 958 | 320582 张家港市 959 | 320583 昆山市 960 | 320584 吴江市 961 | 320585 太仓市 962 | 320600 南通市 963 | 320601 市辖区 964 | 320602 崇川区 965 | 320611 港闸区 966 | 320621 海安县 967 | 320623 如东县 968 | 320681 启东市 969 | 320682 如皋市 970 | 320683 通州市 971 | 320684 海门市 972 | 320700 连云港市 973 | 320701 市辖区 974 | 320703 连云区 975 | 320705 新浦区 976 | 320706 海州区 977 | 320721 赣榆县 978 | 320722 东海县 979 | 320723 灌云县 980 | 320724 灌南县 981 | 320800 淮安市 982 | 320801 市辖区 983 | 320802 清河区 984 | 320803 楚州区 985 | 320804 淮阴区 986 | 320811 清浦区 987 | 320826 涟水县 988 | 320829 洪泽县 989 | 320830 盱眙县 990 | 320831 金湖县 991 | 320900 盐城市 992 | 320901 市辖区 993 | 320902 亭湖区 994 | 320903 盐都区 995 | 320921 响水县 996 | 320922 滨海县 997 | 320923 阜宁县 998 | 320924 射阳县 999 | 320925 建湖县 1000 | 320981 东台市 1001 | 320982 大丰市 1002 | 321000 扬州市 1003 | 321001 市辖区 1004 | 321002 广陵区 1005 | 321003 邗江区 1006 | 321011 维扬区 1007 | 321023 宝应县 1008 | 321081 仪征市 1009 | 321084 高邮市 1010 | 321088 江都市 1011 | 321100 镇江市 1012 | 321101 市辖区 1013 | 321102 京口区 1014 | 321111 润州区 1015 | 321112 丹徒区 1016 | 321181 丹阳市 1017 | 321182 扬中市 1018 | 321183 句容市 1019 | 321200 泰州市 1020 | 321201 市辖区 1021 | 321202 海陵区 1022 | 321203 高港区 1023 | 321281 兴化市 1024 | 321282 靖江市 1025 | 321283 泰兴市 1026 | 321284 姜堰市 1027 | 321300 宿迁市 1028 | 321301 市辖区 1029 | 321302 宿城区 1030 | 321311 宿豫区 1031 | 321322 沭阳县 1032 | 321323 泗阳县 1033 | 321324 泗洪县 1034 | 1035 | 330000 浙江省 1036 | 330100 杭州市 1037 | 330101 市辖区 1038 | 330102 上城区 1039 | 330103 下城区 1040 | 330104 江干区 1041 | 330105 拱墅区 1042 | 330106 西湖区 1043 | 330108 滨江区 1044 | 330109 萧山区 1045 | 330110 余杭区 1046 | 330122 桐庐县 1047 | 330127 淳安县 1048 | 330182 建德市 1049 | 330183 富阳市 1050 | 330185 临安市 1051 | 330200 宁波市 1052 | 330201 市辖区 1053 | 330203 海曙区 1054 | 330204 江东区 1055 | 330205 江北区 1056 | 330206 北仑区 1057 | 330211 镇海区 1058 | 330212 鄞州区 1059 | 330225 象山县 1060 | 330226 宁海县 1061 | 330281 余姚市 1062 | 330282 慈溪市 1063 | 330283 奉化市 1064 | 330300 温州市 1065 | 330301 市辖区 1066 | 330302 鹿城区 1067 | 330303 龙湾区 1068 | 330304 瓯海区 1069 | 330322 洞头县 1070 | 330324 永嘉县 1071 | 330326 平阳县 1072 | 330327 苍南县 1073 | 330328 文成县 1074 | 330329 泰顺县 1075 | 330381 瑞安市 1076 | 330382 乐清市 1077 | 330400 嘉兴市 1078 | 330401 市辖区 1079 | 330402 秀城区 1080 | 330411 秀洲区 1081 | 330421 嘉善县 1082 | 330424 海盐县 1083 | 330481 海宁市 1084 | 330482 平湖市 1085 | 330483 桐乡市 1086 | 330500 湖州市 1087 | 330501 市辖区 1088 | 330502 吴兴区 1089 | 330503 南浔区 1090 | 330521 德清县 1091 | 330522 长兴县 1092 | 330523 安吉县 1093 | 330600 绍兴市 1094 | 330601 市辖区 1095 | 330602 越城区 1096 | 330621 绍兴县 1097 | 330624 新昌县 1098 | 330681 诸暨市 1099 | 330682 上虞市 1100 | 330683 嵊州市 1101 | 330700 金华市 1102 | 330701 市辖区 1103 | 330702 婺城区 1104 | 330703 金东区 1105 | 330723 武义县 1106 | 330726 浦江县 1107 | 330727 磐安县 1108 | 330781 兰溪市 1109 | 330782 义乌市 1110 | 330783 东阳市 1111 | 330784 永康市 1112 | 330800 衢州市 1113 | 330801 市辖区 1114 | 330802 柯城区 1115 | 330803 衢江区 1116 | 330822 常山县 1117 | 330824 开化县 1118 | 330825 龙游县 1119 | 330881 江山市 1120 | 330900 舟山市 1121 | 330901 市辖区 1122 | 330902 定海区 1123 | 330903 普陀区 1124 | 330921 岱山县 1125 | 330922 嵊泗县 1126 | 331000 台州市 1127 | 331001 市辖区 1128 | 331002 椒江区 1129 | 331003 黄岩区 1130 | 331004 路桥区 1131 | 331021 玉环县 1132 | 331022 三门县 1133 | 331023 天台县 1134 | 331024 仙居县 1135 | 331081 温岭市 1136 | 331082 临海市 1137 | 331100 丽水市 1138 | 331101 市辖区 1139 | 331102 莲都区 1140 | 331121 青田县 1141 | 331122 缙云县 1142 | 331123 遂昌县 1143 | 331124 松阳县 1144 | 331125 云和县 1145 | 331126 庆元县 1146 | 331127 景宁畲族自治县 1147 | 331181 龙泉市 1148 | 1149 | 340000 安徽省 1150 | 340100 合肥市 1151 | 340101 市辖区 1152 | 340102 瑶海区 1153 | 340103 庐阳区 1154 | 340104 蜀山区 1155 | 340111 包河区 1156 | 340121 长丰县 1157 | 340122 肥东县 1158 | 340123 肥西县 1159 | 340200 芜湖市 1160 | 340201 市辖区 1161 | 340202 镜湖区 1162 | 340203 马塘区 1163 | 340204 新芜区 1164 | 340207 鸠江区 1165 | 340221 芜湖县 1166 | 340222 繁昌县 1167 | 340223 南陵县 1168 | 340300 蚌埠市 1169 | 340301 市辖区 1170 | 340302 龙子湖区 1171 | 340303 蚌山区 1172 | 340304 禹会区 1173 | 340311 淮上区 1174 | 340321 怀远县 1175 | 340322 五河县 1176 | 340323 固镇县 1177 | 340400 淮南市 1178 | 340401 市辖区 1179 | 340402 大通区 1180 | 340403 田家庵区 1181 | 340404 谢家集区 1182 | 340405 八公山区 1183 | 340406 潘集区 1184 | 340421 凤台县 1185 | 340500 马鞍山市 1186 | 340501 市辖区 1187 | 340502 金家庄区 1188 | 340503 花山区 1189 | 340504 雨山区 1190 | 340521 当涂县 1191 | 340600 淮北市 1192 | 340601 市辖区 1193 | 340602 杜集区 1194 | 340603 相山区 1195 | 340604 烈山区 1196 | 340621 濉溪县 1197 | 340700 铜陵市 1198 | 340701 市辖区 1199 | 340702 铜官山区 1200 | 340703 狮子山区 1201 | 340711 郊 区 1202 | 340721 铜陵县 1203 | 340800 安庆市 1204 | 340801 市辖区 1205 | 340802 迎江区 1206 | 340803 大观区 1207 | 340811 宜秀区 1208 | 340822 怀宁县 1209 | 340823 枞阳县 1210 | 340824 潜山县 1211 | 340825 太湖县 1212 | 340826 宿松县 1213 | 340827 望江县 1214 | 340828 岳西县 1215 | 340881 桐城市 1216 | 341000 黄山市 1217 | 341001 市辖区 1218 | 341002 屯溪区 1219 | 341003 黄山区 1220 | 341004 徽州区 1221 | 341021 歙 县 1222 | 341022 休宁县 1223 | 341023 黟 县 1224 | 341024 祁门县 1225 | 341100 滁州市 1226 | 341101 市辖区 1227 | 341102 琅琊区 1228 | 341103 南谯区 1229 | 341122 来安县 1230 | 341124 全椒县 1231 | 341125 定远县 1232 | 341126 凤阳县 1233 | 341181 天长市 1234 | 341182 明光市 1235 | 341200 阜阳市 1236 | 341201 市辖区 1237 | 341202 颍州区 1238 | 341203 颍东区 1239 | 341204 颍泉区 1240 | 341221 临泉县 1241 | 341222 太和县 1242 | 341225 阜南县 1243 | 341226 颍上县 1244 | 341282 界首市 1245 | 341300 宿州市 1246 | 341301 市辖区 1247 | 341302 埇桥区 1248 | 341321 砀山县 1249 | 341322 萧 县 1250 | 341323 灵璧县 1251 | 341324 泗 县 1252 | 341400 巢湖市 1253 | 341401 市辖区 1254 | 341402 居巢区 1255 | 341421 庐江县 1256 | 341422 无为县 1257 | 341423 含山县 1258 | 341424 和 县 1259 | 341500 六安市 1260 | 341501 市辖区 1261 | 341502 金安区 1262 | 341503 裕安区 1263 | 341521 寿 县 1264 | 341522 霍邱县 1265 | 341523 舒城县 1266 | 341524 金寨县 1267 | 341525 霍山县 1268 | 341600 亳州市 1269 | 341601 市辖区 1270 | 341602 谯城区 1271 | 341621 涡阳县 1272 | 341622 蒙城县 1273 | 341623 利辛县 1274 | 341700 池州市 1275 | 341701 市辖区 1276 | 341702 贵池区 1277 | 341721 东至县 1278 | 341722 石台县 1279 | 341723 青阳县 1280 | 341800 宣城市 1281 | 341801 市辖区 1282 | 341802 宣州区 1283 | 341821 郎溪县 1284 | 341822 广德县 1285 | 341823 泾 县 1286 | 341824 绩溪县 1287 | 341825 旌德县 1288 | 341881 宁国市 1289 | 1290 | 350000 福建省 1291 | 350100 福州市 1292 | 350101 市辖区 1293 | 350102 鼓楼区 1294 | 350103 台江区 1295 | 350104 仓山区 1296 | 350105 马尾区 1297 | 350111 晋安区 1298 | 350121 闽侯县 1299 | 350122 连江县 1300 | 350123 罗源县 1301 | 350124 闽清县 1302 | 350125 永泰县 1303 | 350128 平潭县 1304 | 350181 福清市 1305 | 350182 长乐市 1306 | 350200 厦门市 1307 | 350201 市辖区 1308 | 350203 思明区 1309 | 350205 海沧区 1310 | 350206 湖里区 1311 | 350211 集美区 1312 | 350212 同安区 1313 | 350213 翔安区 1314 | 350300 莆田市 1315 | 350301 市辖区 1316 | 350302 城厢区 1317 | 350303 涵江区 1318 | 350304 荔城区 1319 | 350305 秀屿区 1320 | 350322 仙游县 1321 | 350400 三明市 1322 | 350401 市辖区 1323 | 350402 梅列区 1324 | 350403 三元区 1325 | 350421 明溪县 1326 | 350423 清流县 1327 | 350424 宁化县 1328 | 350425 大田县 1329 | 350426 尤溪县 1330 | 350427 沙 县 1331 | 350428 将乐县 1332 | 350429 泰宁县 1333 | 350430 建宁县 1334 | 350481 永安市 1335 | 350500 泉州市 1336 | 350501 市辖区 1337 | 350502 鲤城区 1338 | 350503 丰泽区 1339 | 350504 洛江区 1340 | 350505 泉港区 1341 | 350521 惠安县 1342 | 350524 安溪县 1343 | 350525 永春县 1344 | 350526 德化县 1345 | 350527 金门县 1346 | 350581 石狮市 1347 | 350582 晋江市 1348 | 350583 南安市 1349 | 350600 漳州市 1350 | 350601 市辖区 1351 | 350602 芗城区 1352 | 350603 龙文区 1353 | 350622 云霄县 1354 | 350623 漳浦县 1355 | 350624 诏安县 1356 | 350625 长泰县 1357 | 350626 东山县 1358 | 350627 南靖县 1359 | 350628 平和县 1360 | 350629 华安县 1361 | 350681 龙海市 1362 | 350700 南平市 1363 | 350701 市辖区 1364 | 350702 延平区 1365 | 350721 顺昌县 1366 | 350722 浦城县 1367 | 350723 光泽县 1368 | 350724 松溪县 1369 | 350725 政和县 1370 | 350781 邵武市 1371 | 350782 武夷山市 1372 | 350783 建瓯市 1373 | 350784 建阳市 1374 | 350800 龙岩市 1375 | 350801 市辖区 1376 | 350802 新罗区 1377 | 350821 长汀县 1378 | 350822 永定县 1379 | 350823 上杭县 1380 | 350824 武平县 1381 | 350825 连城县 1382 | 350881 漳平市 1383 | 350900 宁德市 1384 | 350901 市辖区 1385 | 350902 蕉城区 1386 | 350921 霞浦县 1387 | 350922 古田县 1388 | 350923 屏南县 1389 | 350924 寿宁县 1390 | 350925 周宁县 1391 | 350926 柘荣县 1392 | 350981 福安市 1393 | 350982 福鼎市 1394 | 1395 | 360000 江西省 1396 | 360100 南昌市 1397 | 360101 市辖区 1398 | 360102 东湖区 1399 | 360103 西湖区 1400 | 360104 青云谱区 1401 | 360105 湾里区 1402 | 360111 青山湖区 1403 | 360121 南昌县 1404 | 360122 新建县 1405 | 360123 安义县 1406 | 360124 进贤县 1407 | 360200 景德镇市 1408 | 360201 市辖区 1409 | 360202 昌江区 1410 | 360203 珠山区 1411 | 360222 浮梁县 1412 | 360281 乐平市 1413 | 360300 萍乡市 1414 | 360301 市辖区 1415 | 360302 安源区 1416 | 360313 湘东区 1417 | 360321 莲花县 1418 | 360322 上栗县 1419 | 360323 芦溪县 1420 | 360400 九江市 1421 | 360401 市辖区 1422 | 360402 庐山区 1423 | 360403 浔阳区 1424 | 360421 九江县 1425 | 360423 武宁县 1426 | 360424 修水县 1427 | 360425 永修县 1428 | 360426 德安县 1429 | 360427 星子县 1430 | 360428 都昌县 1431 | 360429 湖口县 1432 | 360430 彭泽县 1433 | 360481 瑞昌市 1434 | 360500 新余市 1435 | 360501 市辖区 1436 | 360502 渝水区 1437 | 360521 分宜县 1438 | 360600 鹰潭市 1439 | 360601 市辖区 1440 | 360602 月湖区 1441 | 360622 余江县 1442 | 360681 贵溪市 1443 | 360700 赣州市 1444 | 360701 市辖区 1445 | 360702 章贡区 1446 | 360721 赣 县 1447 | 360722 信丰县 1448 | 360723 大余县 1449 | 360724 上犹县 1450 | 360725 崇义县 1451 | 360726 安远县 1452 | 360727 龙南县 1453 | 360728 定南县 1454 | 360729 全南县 1455 | 360730 宁都县 1456 | 360731 于都县 1457 | 360732 兴国县 1458 | 360733 会昌县 1459 | 360734 寻乌县 1460 | 360735 石城县 1461 | 360781 瑞金市 1462 | 360782 南康市 1463 | 360800 吉安市 1464 | 360801 市辖区 1465 | 360802 吉州区 1466 | 360803 青原区 1467 | 360821 吉安县 1468 | 360822 吉水县 1469 | 360823 峡江县 1470 | 360824 新干县 1471 | 360825 永丰县 1472 | 360826 泰和县 1473 | 360827 遂川县 1474 | 360828 万安县 1475 | 360829 安福县 1476 | 360830 永新县 1477 | 360881 井冈山市 1478 | 360900 宜春市 1479 | 360901 市辖区 1480 | 360902 袁州区 1481 | 360921 奉新县 1482 | 360922 万载县 1483 | 360923 上高县 1484 | 360924 宜丰县 1485 | 360925 靖安县 1486 | 360926 铜鼓县 1487 | 360981 丰城市 1488 | 360982 樟树市 1489 | 360983 高安市 1490 | 361000 抚州市 1491 | 361001 市辖区 1492 | 361002 临川区 1493 | 361021 南城县 1494 | 361022 黎川县 1495 | 361023 南丰县 1496 | 361024 崇仁县 1497 | 361025 乐安县 1498 | 361026 宜黄县 1499 | 361027 金溪县 1500 | 361028 资溪县 1501 | 361029 东乡县 1502 | 361030 广昌县 1503 | 361100 上饶市 1504 | 361101 市辖区 1505 | 361102 信州区 1506 | 361121 上饶县 1507 | 361122 广丰县 1508 | 361123 玉山县 1509 | 361124 铅山县 1510 | 361125 横峰县 1511 | 361126 弋阳县 1512 | 361127 余干县 1513 | 361128 鄱阳县 1514 | 361129 万年县 1515 | 361130 婺源县 1516 | 361181 德兴市 1517 | 1518 | 370000 山东省 1519 | 370100 济南市 1520 | 370101 市辖区 1521 | 370102 历下区 1522 | 370103 市中区 1523 | 370104 槐荫区 1524 | 370105 天桥区 1525 | 370112 历城区 1526 | 370113 长清区 1527 | 370124 平阴县 1528 | 370125 济阳县 1529 | 370126 商河县 1530 | 370181 章丘市 1531 | 370200 青岛市 1532 | 370201 市辖区 1533 | 370202 市南区 1534 | 370203 市北区 1535 | 370205 四方区 1536 | 370211 黄岛区 1537 | 370212 崂山区 1538 | 370213 李沧区 1539 | 370214 城阳区 1540 | 370281 胶州市 1541 | 370282 即墨市 1542 | 370283 平度市 1543 | 370284 胶南市 1544 | 370285 莱西市 1545 | 370300 淄博市 1546 | 370301 市辖区 1547 | 370302 淄川区 1548 | 370303 张店区 1549 | 370304 博山区 1550 | 370305 临淄区 1551 | 370306 周村区 1552 | 370321 桓台县 1553 | 370322 高青县 1554 | 370323 沂源县 1555 | 370400 枣庄市 1556 | 370401 市辖区 1557 | 370402 市中区 1558 | 370403 薛城区 1559 | 370404 峄城区 1560 | 370405 台儿庄区 1561 | 370406 山亭区 1562 | 370481 滕州市 1563 | 370500 东营市 1564 | 370501 市辖区 1565 | 370502 东营区 1566 | 370503 河口区 1567 | 370521 垦利县 1568 | 370522 利津县 1569 | 370523 广饶县 1570 | 370600 烟台市 1571 | 370601 市辖区 1572 | 370602 芝罘区 1573 | 370611 福山区 1574 | 370612 牟平区 1575 | 370613 莱山区 1576 | 370634 长岛县 1577 | 370681 龙口市 1578 | 370682 莱阳市 1579 | 370683 莱州市 1580 | 370684 蓬莱市 1581 | 370685 招远市 1582 | 370686 栖霞市 1583 | 370687 海阳市 1584 | 370700 潍坊市 1585 | 370701 市辖区 1586 | 370702 潍城区 1587 | 370703 寒亭区 1588 | 370704 坊子区 1589 | 370705 奎文区 1590 | 370724 临朐县 1591 | 370725 昌乐县 1592 | 370781 青州市 1593 | 370782 诸城市 1594 | 370783 寿光市 1595 | 370784 安丘市 1596 | 370785 高密市 1597 | 370786 昌邑市 1598 | 370800 济宁市 1599 | 370801 市辖区 1600 | 370802 市中区 1601 | 370811 任城区 1602 | 370826 微山县 1603 | 370827 鱼台县 1604 | 370828 金乡县 1605 | 370829 嘉祥县 1606 | 370830 汶上县 1607 | 370831 泗水县 1608 | 370832 梁山县 1609 | 370881 曲阜市 1610 | 370882 兖州市 1611 | 370883 邹城市 1612 | 370900 泰安市 1613 | 370901 市辖区 1614 | 370902 泰山区 1615 | 370903 岱岳区 1616 | 370921 宁阳县 1617 | 370923 东平县 1618 | 370982 新泰市 1619 | 370983 肥城市 1620 | 371000 威海市 1621 | 371001 市辖区 1622 | 371002 环翠区 1623 | 371081 文登市 1624 | 371082 荣成市 1625 | 371083 乳山市 1626 | 371100 日照市 1627 | 371101 市辖区 1628 | 371102 东港区 1629 | 371103 岚山区 1630 | 371121 五莲县 1631 | 371122 莒 县 1632 | 371200 莱芜市 1633 | 371201 市辖区 1634 | 371202 莱城区 1635 | 371203 钢城区 1636 | 371300 临沂市 1637 | 371301 市辖区 1638 | 371302 兰山区 1639 | 371311 罗庄区 1640 | 371312 河东区 1641 | 371321 沂南县 1642 | 371322 郯城县 1643 | 371323 沂水县 1644 | 371324 苍山县 1645 | 371325 费 县 1646 | 371326 平邑县 1647 | 371327 莒南县 1648 | 371328 蒙阴县 1649 | 371329 临沭县 1650 | 371400 德州市 1651 | 371401 市辖区 1652 | 371402 德城区 1653 | 371421 陵 县 1654 | 371422 宁津县 1655 | 371423 庆云县 1656 | 371424 临邑县 1657 | 371425 齐河县 1658 | 371426 平原县 1659 | 371427 夏津县 1660 | 371428 武城县 1661 | 371481 乐陵市 1662 | 371482 禹城市 1663 | 371500 聊城市 1664 | 371501 市辖区 1665 | 371502 东昌府区 1666 | 371521 阳谷县 1667 | 371522 莘 县 1668 | 371523 茌平县 1669 | 371524 东阿县 1670 | 371525 冠 县 1671 | 371526 高唐县 1672 | 371581 临清市 1673 | 371600 滨州市 1674 | 371601 市辖区 1675 | 371602 滨城区 1676 | 371621 惠民县 1677 | 371622 阳信县 1678 | 371623 无棣县 1679 | 371624 沾化县 1680 | 371625 博兴县 1681 | 371626 邹平县 1682 | 371700 菏泽市 1683 | 371701 市辖区 1684 | 371702 牡丹区 1685 | 371721 曹 县 1686 | 371722 单 县 1687 | 371723 成武县 1688 | 371724 巨野县 1689 | 371725 郓城县 1690 | 371726 鄄城县 1691 | 371727 定陶县 1692 | 371728 东明县 1693 | 1694 | 410000 河南省 1695 | 410100 郑州市 1696 | 410101 市辖区 1697 | 410102 中原区 1698 | 410103 二七区 1699 | 410104 管城回族区 1700 | 410105 金水区 1701 | 410106 上街区 1702 | 410108 惠济区 1703 | 410122 中牟县 1704 | 410181 巩义市 1705 | 410182 荥阳市 1706 | 410183 新密市 1707 | 410184 新郑市 1708 | 410185 登封市 1709 | 410200 开封市 1710 | 410201 市辖区 1711 | 410202 龙亭区 1712 | 410203 顺河回族区 1713 | 410204 鼓楼区 1714 | 410205 禹王台区 1715 | 410211 金明区 1716 | 410221 杞 县 1717 | 410222 通许县 1718 | 410223 尉氏县 1719 | 410224 开封县 1720 | 410225 兰考县 1721 | 410300 洛阳市 1722 | 410301 市辖区 1723 | 410302 老城区 1724 | 410303 西工区 1725 | 410304 廛河回族区 1726 | 410305 涧西区 1727 | 410306 吉利区 1728 | 410307 洛龙区 1729 | 410322 孟津县 1730 | 410323 新安县 1731 | 410324 栾川县 1732 | 410325 嵩 县 1733 | 410326 汝阳县 1734 | 410327 宜阳县 1735 | 410328 洛宁县 1736 | 410329 伊川县 1737 | 410381 偃师市 1738 | 410400 平顶山市 1739 | 410401 市辖区 1740 | 410402 新华区 1741 | 410403 卫东区 1742 | 410404 石龙区 1743 | 410411 湛河区 1744 | 410421 宝丰县 1745 | 410422 叶 县 1746 | 410423 鲁山县 1747 | 410425 郏 县 1748 | 410481 舞钢市 1749 | 410482 汝州市 1750 | 410500 安阳市 1751 | 410501 市辖区 1752 | 410502 文峰区 1753 | 410503 北关区 1754 | 410505 殷都区 1755 | 410506 龙安区 1756 | 410522 安阳县 1757 | 410523 汤阴县 1758 | 410526 滑 县 1759 | 410527 内黄县 1760 | 410581 林州市 1761 | 410600 鹤壁市 1762 | 410601 市辖区 1763 | 410602 鹤山区 1764 | 410603 山城区 1765 | 410611 淇滨区 1766 | 410621 浚 县 1767 | 410622 淇 县 1768 | 410700 新乡市 1769 | 410701 市辖区 1770 | 410702 红旗区 1771 | 410703 卫滨区 1772 | 410704 凤泉区 1773 | 410711 牧野区 1774 | 410721 新乡县 1775 | 410724 获嘉县 1776 | 410725 原阳县 1777 | 410726 延津县 1778 | 410727 封丘县 1779 | 410728 长垣县 1780 | 410781 卫辉市 1781 | 410782 辉县市 1782 | 410800 焦作市 1783 | 410801 市辖区 1784 | 410802 解放区 1785 | 410803 中站区 1786 | 410804 马村区 1787 | 410811 山阳区 1788 | 410821 修武县 1789 | 410822 博爱县 1790 | 410823 武陟县 1791 | 410825 温 县 1792 | 410881 济源市 1793 | 410882 沁阳市 1794 | 410883 孟州市 1795 | 410900 濮阳市 1796 | 410901 市辖区 1797 | 410902 华龙区 1798 | 410922 清丰县 1799 | 410923 南乐县 1800 | 410926 范 县 1801 | 410927 台前县 1802 | 410928 濮阳县 1803 | 411000 许昌市 1804 | 411001 市辖区 1805 | 411002 魏都区 1806 | 411023 许昌县 1807 | 411024 鄢陵县 1808 | 411025 襄城县 1809 | 411081 禹州市 1810 | 411082 长葛市 1811 | 411100 漯河市 1812 | 411101 市辖区 1813 | 411102 源汇区 1814 | 411103 郾城区 1815 | 411104 召陵区 1816 | 411121 舞阳县 1817 | 411122 临颍县 1818 | 411200 三门峡市 1819 | 411201 市辖区 1820 | 411202 湖滨区 1821 | 411221 渑池县 1822 | 411222 陕 县 1823 | 411224 卢氏县 1824 | 411281 义马市 1825 | 411282 灵宝市 1826 | 411300 南阳市 1827 | 411301 市辖区 1828 | 411302 宛城区 1829 | 411303 卧龙区 1830 | 411321 南召县 1831 | 411322 方城县 1832 | 411323 西峡县 1833 | 411324 镇平县 1834 | 411325 内乡县 1835 | 411326 淅川县 1836 | 411327 社旗县 1837 | 411328 唐河县 1838 | 411329 新野县 1839 | 411330 桐柏县 1840 | 411381 邓州市 1841 | 411400 商丘市 1842 | 411401 市辖区 1843 | 411402 梁园区 1844 | 411403 睢阳区 1845 | 411421 民权县 1846 | 411422 睢 县 1847 | 411423 宁陵县 1848 | 411424 柘城县 1849 | 411425 虞城县 1850 | 411426 夏邑县 1851 | 411481 永城市 1852 | 411500 信阳市 1853 | 411501 市辖区 1854 | 411502 浉河区 1855 | 411503 平桥区 1856 | 411521 罗山县 1857 | 411522 光山县 1858 | 411523 新 县 1859 | 411524 商城县 1860 | 411525 固始县 1861 | 411526 潢川县 1862 | 411527 淮滨县 1863 | 411528 息 县 1864 | 411600 周口市 1865 | 411601 市辖区 1866 | 411602 川汇区 1867 | 411621 扶沟县 1868 | 411622 西华县 1869 | 411623 商水县 1870 | 411624 沈丘县 1871 | 411625 郸城县 1872 | 411626 淮阳县 1873 | 411627 太康县 1874 | 411628 鹿邑县 1875 | 411681 项城市 1876 | 411700 驻马店市 1877 | 411701 市辖区 1878 | 411702 驿城区 1879 | 411721 西平县 1880 | 411722 上蔡县 1881 | 411723 平舆县 1882 | 411724 正阳县 1883 | 411725 确山县 1884 | 411726 泌阳县 1885 | 411727 汝南县 1886 | 411728 遂平县 1887 | 411729 新蔡县 1888 | 1889 | 420000 湖北省 1890 | 420100 武汉市 1891 | 420101 市辖区 1892 | 420102 江岸区 1893 | 420103 江汉区 1894 | 420104 硚口区 1895 | 420105 汉阳区 1896 | 420106 武昌区 1897 | 420107 青山区 1898 | 420111 洪山区 1899 | 420112 东西湖区 1900 | 420113 汉南区 1901 | 420114 蔡甸区 1902 | 420115 江夏区 1903 | 420116 黄陂区 1904 | 420117 新洲区 1905 | 420200 黄石市 1906 | 420201 市辖区 1907 | 420202 黄石港区 1908 | 420203 西塞山区 1909 | 420204 下陆区 1910 | 420205 铁山区 1911 | 420222 阳新县 1912 | 420281 大冶市 1913 | 420300 十堰市 1914 | 420301 市辖区 1915 | 420302 茅箭区 1916 | 420303 张湾区 1917 | 420321 郧 县 1918 | 420322 郧西县 1919 | 420323 竹山县 1920 | 420324 竹溪县 1921 | 420325 房 县 1922 | 420381 丹江口市 1923 | 420500 宜昌市 1924 | 420501 市辖区 1925 | 420502 西陵区 1926 | 420503 伍家岗区 1927 | 420504 点军区 1928 | 420505 猇亭区 1929 | 420506 夷陵区 1930 | 420525 远安县 1931 | 420526 兴山县 1932 | 420527 秭归县 1933 | 420528 长阳土家族自治县 1934 | 420529 五峰土家族自治县 1935 | 420581 宜都市 1936 | 420582 当阳市 1937 | 420583 枝江市 1938 | 420600 襄樊市 1939 | 420601 市辖区 1940 | 420602 襄城区 1941 | 420606 樊城区 1942 | 420607 襄阳区 1943 | 420624 南漳县 1944 | 420625 谷城县 1945 | 420626 保康县 1946 | 420682 老河口市 1947 | 420683 枣阳市 1948 | 420684 宜城市 1949 | 420700 鄂州市 1950 | 420701 市辖区 1951 | 420702 梁子湖区 1952 | 420703 华容区 1953 | 420704 鄂城区 1954 | 420800 荆门市 1955 | 420801 市辖区 1956 | 420802 东宝区 1957 | 420804 掇刀区 1958 | 420821 京山县 1959 | 420822 沙洋县 1960 | 420881 钟祥市 1961 | 420900 孝感市 1962 | 420901 市辖区 1963 | 420902 孝南区 1964 | 420921 孝昌县 1965 | 420922 大悟县 1966 | 420923 云梦县 1967 | 420981 应城市 1968 | 420982 安陆市 1969 | 420984 汉川市 1970 | 421000 荆州市 1971 | 421001 市辖区 1972 | 421002 沙市区 1973 | 421003 荆州区 1974 | 421022 公安县 1975 | 421023 监利县 1976 | 421024 江陵县 1977 | 421081 石首市 1978 | 421083 洪湖市 1979 | 421087 松滋市 1980 | 421100 黄冈市 1981 | 421101 市辖区 1982 | 421102 黄州区 1983 | 421121 团风县 1984 | 421122 红安县 1985 | 421123 罗田县 1986 | 421124 英山县 1987 | 421125 浠水县 1988 | 421126 蕲春县 1989 | 421127 黄梅县 1990 | 421181 麻城市 1991 | 421182 武穴市 1992 | 421200 咸宁市 1993 | 421201 市辖区 1994 | 421202 咸安区 1995 | 421221 嘉鱼县 1996 | 421222 通城县 1997 | 421223 崇阳县 1998 | 421224 通山县 1999 | 421281 赤壁市 2000 | 421300 随州市 2001 | 421301 市辖区 2002 | 421302 曾都区 2003 | 421381 广水市 2004 | 422800 恩施土家族苗族自治州 2005 | 422801 恩施市 2006 | 422802 利川市 2007 | 422822 建始县 2008 | 422823 巴东县 2009 | 422825 宣恩县 2010 | 422826 咸丰县 2011 | 422827 来凤县 2012 | 422828 鹤峰县 2013 | 429000 省直辖行政单位 2014 | 429004 仙桃市 2015 | 429005 潜江市 2016 | 429006 天门市 2017 | 429021 神农架林区 2018 | 2019 | 430000 湖南省 2020 | 430100 长沙市 2021 | 430101 市辖区 2022 | 430102 芙蓉区 2023 | 430103 天心区 2024 | 430104 岳麓区 2025 | 430105 开福区 2026 | 430111 雨花区 2027 | 430121 长沙县 2028 | 430122 望城县 2029 | 430124 宁乡县 2030 | 430181 浏阳市 2031 | 430200 株洲市 2032 | 430201 市辖区 2033 | 430202 荷塘区 2034 | 430203 芦淞区 2035 | 430204 石峰区 2036 | 430211 天元区 2037 | 430221 株洲县 2038 | 430223 攸 县 2039 | 430224 茶陵县 2040 | 430225 炎陵县 2041 | 430281 醴陵市 2042 | 430300 湘潭市 2043 | 430301 市辖区 2044 | 430302 雨湖区 2045 | 430304 岳塘区 2046 | 430321 湘潭县 2047 | 430381 湘乡市 2048 | 430382 韶山市 2049 | 430400 衡阳市 2050 | 430401 市辖区 2051 | 430405 珠晖区 2052 | 430406 雁峰区 2053 | 430407 石鼓区 2054 | 430408 蒸湘区 2055 | 430412 南岳区 2056 | 430421 衡阳县 2057 | 430422 衡南县 2058 | 430423 衡山县 2059 | 430424 衡东县 2060 | 430426 祁东县 2061 | 430481 耒阳市 2062 | 430482 常宁市 2063 | 430500 邵阳市 2064 | 430501 市辖区 2065 | 430502 双清区 2066 | 430503 大祥区 2067 | 430511 北塔区 2068 | 430521 邵东县 2069 | 430522 新邵县 2070 | 430523 邵阳县 2071 | 430524 隆回县 2072 | 430525 洞口县 2073 | 430527 绥宁县 2074 | 430528 新宁县 2075 | 430529 城步苗族自治县 2076 | 430581 武冈市 2077 | 430600 岳阳市 2078 | 430601 市辖区 2079 | 430602 岳阳楼区 2080 | 430603 云溪区 2081 | 430611 君山区 2082 | 430621 岳阳县 2083 | 430623 华容县 2084 | 430624 湘阴县 2085 | 430626 平江县 2086 | 430681 汨罗市 2087 | 430682 临湘市 2088 | 430700 常德市 2089 | 430701 市辖区 2090 | 430702 武陵区 2091 | 430703 鼎城区 2092 | 430721 安乡县 2093 | 430722 汉寿县 2094 | 430723 澧 县 2095 | 430724 临澧县 2096 | 430725 桃源县 2097 | 430726 石门县 2098 | 430781 津市市 2099 | 430800 张家界市 2100 | 430801 市辖区 2101 | 430802 永定区 2102 | 430811 武陵源区 2103 | 430821 慈利县 2104 | 430822 桑植县 2105 | 430900 益阳市 2106 | 430901 市辖区 2107 | 430902 资阳区 2108 | 430903 赫山区 2109 | 430921 南 县 2110 | 430922 桃江县 2111 | 430923 安化县 2112 | 430981 沅江市 2113 | 431000 郴州市 2114 | 431001 市辖区 2115 | 431002 北湖区 2116 | 431003 苏仙区 2117 | 431021 桂阳县 2118 | 431022 宜章县 2119 | 431023 永兴县 2120 | 431024 嘉禾县 2121 | 431025 临武县 2122 | 431026 汝城县 2123 | 431027 桂东县 2124 | 431028 安仁县 2125 | 431081 资兴市 2126 | 431100 永州市 2127 | 431101 市辖区 2128 | 431102 芝山区 2129 | 431103 冷水滩区 2130 | 431121 祁阳县 2131 | 431122 东安县 2132 | 431123 双牌县 2133 | 431124 道 县 2134 | 431125 江永县 2135 | 431126 宁远县 2136 | 431127 蓝山县 2137 | 431128 新田县 2138 | 431129 江华瑶族自治县 2139 | 431200 怀化市 2140 | 431201 市辖区 2141 | 431202 鹤城区 2142 | 431221 中方县 2143 | 431222 沅陵县 2144 | 431223 辰溪县 2145 | 431224 溆浦县 2146 | 431225 会同县 2147 | 431226 麻阳苗族自治县 2148 | 431227 新晃侗族自治县 2149 | 431228 芷江侗族自治县 2150 | 431229 靖州苗族侗族自治县 2151 | 431230 通道侗族自治县 2152 | 431281 洪江市 2153 | 431300 娄底市 2154 | 431301 市辖区 2155 | 431302 娄星区 2156 | 431321 双峰县 2157 | 431322 新化县 2158 | 431381 冷水江市 2159 | 431382 涟源市 2160 | 433100 湘西土家族苗族自治州 2161 | 433101 吉首市 2162 | 433122 泸溪县 2163 | 433123 凤凰县 2164 | 433124 花垣县 2165 | 433125 保靖县 2166 | 433126 古丈县 2167 | 433127 永顺县 2168 | 433130 龙山县 2169 | 2170 | 440000 广东省 2171 | 440100 广州市 2172 | 440101 市辖区 2173 | 440103 荔湾区 2174 | 440104 越秀区 2175 | 440105 海珠区 2176 | 440106 天河区 2177 | 440111 白云区 2178 | 440112 黄埔区 2179 | 440113 番禺区 2180 | 440114 花都区 2181 | 440115 南沙区 2182 | 440116 萝岗区 2183 | 440183 增城市 2184 | 440184 从化市 2185 | 440200 韶关市 2186 | 440201 市辖区 2187 | 440203 武江区 2188 | 440204 浈江区 2189 | 440205 曲江区 2190 | 440222 始兴县 2191 | 440224 仁化县 2192 | 440229 翁源县 2193 | 440232 乳源瑶族自治县 2194 | 440233 新丰县 2195 | 440281 乐昌市 2196 | 440282 南雄市 2197 | 440300 深圳市 2198 | 440301 市辖区 2199 | 440303 罗湖区 2200 | 440304 福田区 2201 | 440305 南山区 2202 | 440306 宝安区 2203 | 440307 龙岗区 2204 | 440308 盐田区 2205 | 440400 珠海市 2206 | 440401 市辖区 2207 | 440402 香洲区 2208 | 440403 斗门区 2209 | 440404 金湾区 2210 | 440500 汕头市 2211 | 440501 市辖区 2212 | 440507 龙湖区 2213 | 440511 金平区 2214 | 440512 濠江区 2215 | 440513 潮阳区 2216 | 440514 潮南区 2217 | 440515 澄海区 2218 | 440523 南澳县 2219 | 440600 佛山市 2220 | 440601 市辖区 2221 | 440604 禅城区 2222 | 440605 南海区 2223 | 440606 顺德区 2224 | 440607 三水区 2225 | 440608 高明区 2226 | 440700 江门市 2227 | 440701 市辖区 2228 | 440703 蓬江区 2229 | 440704 江海区 2230 | 440705 新会区 2231 | 440781 台山市 2232 | 440783 开平市 2233 | 440784 鹤山市 2234 | 440785 恩平市 2235 | 440800 湛江市 2236 | 440801 市辖区 2237 | 440802 赤坎区 2238 | 440803 霞山区 2239 | 440804 坡头区 2240 | 440811 麻章区 2241 | 440823 遂溪县 2242 | 440825 徐闻县 2243 | 440881 廉江市 2244 | 440882 雷州市 2245 | 440883 吴川市 2246 | 440900 茂名市 2247 | 440901 市辖区 2248 | 440902 茂南区 2249 | 440903 茂港区 2250 | 440923 电白县 2251 | 440981 高州市 2252 | 440982 化州市 2253 | 440983 信宜市 2254 | 441200 肇庆市 2255 | 441201 市辖区 2256 | 441202 端州区 2257 | 441203 鼎湖区 2258 | 441223 广宁县 2259 | 441224 怀集县 2260 | 441225 封开县 2261 | 441226 德庆县 2262 | 441283 高要市 2263 | 441284 四会市 2264 | 441300 惠州市 2265 | 441301 市辖区 2266 | 441302 惠城区 2267 | 441303 惠阳区 2268 | 441322 博罗县 2269 | 441323 惠东县 2270 | 441324 龙门县 2271 | 441400 梅州市 2272 | 441401 市辖区 2273 | 441402 梅江区 2274 | 441421 梅 县 2275 | 441422 大埔县 2276 | 441423 丰顺县 2277 | 441424 五华县 2278 | 441426 平远县 2279 | 441427 蕉岭县 2280 | 441481 兴宁市 2281 | 441500 汕尾市 2282 | 441501 市辖区 2283 | 441502 城 区 2284 | 441521 海丰县 2285 | 441523 陆河县 2286 | 441581 陆丰市 2287 | 441600 河源市 2288 | 441601 市辖区 2289 | 441602 源城区 2290 | 441621 紫金县 2291 | 441622 龙川县 2292 | 441623 连平县 2293 | 441624 和平县 2294 | 441625 东源县 2295 | 441700 阳江市 2296 | 441701 市辖区 2297 | 441702 江城区 2298 | 441721 阳西县 2299 | 441723 阳东县 2300 | 441781 阳春市 2301 | 441800 清远市 2302 | 441801 市辖区 2303 | 441802 清城区 2304 | 441821 佛冈县 2305 | 441823 阳山县 2306 | 441825 连山壮族瑶族自治县 2307 | 441826 连南瑶族自治县 2308 | 441827 清新县 2309 | 441881 英德市 2310 | 441882 连州市 2311 | 441900 东莞市 2312 | 442000 中山市 2313 | 445100 潮州市 2314 | 445101 市辖区 2315 | 445102 湘桥区 2316 | 445121 潮安县 2317 | 445122 饶平县 2318 | 445200 揭阳市 2319 | 445201 市辖区 2320 | 445202 榕城区 2321 | 445221 揭东县 2322 | 445222 揭西县 2323 | 445224 惠来县 2324 | 445281 普宁市 2325 | 445300 云浮市 2326 | 445301 市辖区 2327 | 445302 云城区 2328 | 445321 新兴县 2329 | 445322 郁南县 2330 | 445323 云安县 2331 | 445381 罗定市 2332 | 2333 | 450000 广西壮族自治区 2334 | 450100 南宁市 2335 | 450101 市辖区 2336 | 450102 兴宁区 2337 | 450103 青秀区 2338 | 450105 江南区 2339 | 450107 西乡塘区 2340 | 450108 良庆区 2341 | 450109 邕宁区 2342 | 450122 武鸣县 2343 | 450123 隆安县 2344 | 450124 马山县 2345 | 450125 上林县 2346 | 450126 宾阳县 2347 | 450127 横 县 2348 | 450200 柳州市 2349 | 450201 市辖区 2350 | 450202 城中区 2351 | 450203 鱼峰区 2352 | 450204 柳南区 2353 | 450205 柳北区 2354 | 450221 柳江县 2355 | 450222 柳城县 2356 | 450223 鹿寨县 2357 | 450224 融安县 2358 | 450225 融水苗族自治县 2359 | 450226 三江侗族自治县 2360 | 450300 桂林市 2361 | 450301 市辖区 2362 | 450302 秀峰区 2363 | 450303 叠彩区 2364 | 450304 象山区 2365 | 450305 七星区 2366 | 450311 雁山区 2367 | 450321 阳朔县 2368 | 450322 临桂县 2369 | 450323 灵川县 2370 | 450324 全州县 2371 | 450325 兴安县 2372 | 450326 永福县 2373 | 450327 灌阳县 2374 | 450328 龙胜各族自治县 2375 | 450329 资源县 2376 | 450330 平乐县 2377 | 450331 荔蒲县 2378 | 450332 恭城瑶族自治县 2379 | 450400 梧州市 2380 | 450401 市辖区 2381 | 450403 万秀区 2382 | 450404 蝶山区 2383 | 450405 长洲区 2384 | 450421 苍梧县 2385 | 450422 藤 县 2386 | 450423 蒙山县 2387 | 450481 岑溪市 2388 | 450500 北海市 2389 | 450501 市辖区 2390 | 450502 海城区 2391 | 450503 银海区 2392 | 450512 铁山港区 2393 | 450521 合浦县 2394 | 450600 防城港市 2395 | 450601 市辖区 2396 | 450602 港口区 2397 | 450603 防城区 2398 | 450621 上思县 2399 | 450681 东兴市 2400 | 450700 钦州市 2401 | 450701 市辖区 2402 | 450702 钦南区 2403 | 450703 钦北区 2404 | 450721 灵山县 2405 | 450722 浦北县 2406 | 450800 贵港市 2407 | 450801 市辖区 2408 | 450802 港北区 2409 | 450803 港南区 2410 | 450804 覃塘区 2411 | 450821 平南县 2412 | 450881 桂平市 2413 | 450900 玉林市 2414 | 450901 市辖区 2415 | 450902 玉州区 2416 | 450921 容 县 2417 | 450922 陆川县 2418 | 450923 博白县 2419 | 450924 兴业县 2420 | 450981 北流市 2421 | 451000 百色市 2422 | 451001 市辖区 2423 | 451002 右江区 2424 | 451021 田阳县 2425 | 451022 田东县 2426 | 451023 平果县 2427 | 451024 德保县 2428 | 451025 靖西县 2429 | 451026 那坡县 2430 | 451027 凌云县 2431 | 451028 乐业县 2432 | 451029 田林县 2433 | 451030 西林县 2434 | 451031 隆林各族自治县 2435 | 451100 贺州市 2436 | 451101 市辖区 2437 | 451102 八步区 2438 | 451121 昭平县 2439 | 451122 钟山县 2440 | 451123 富川瑶族自治县 2441 | 451200 河池市 2442 | 451201 市辖区 2443 | 451202 金城江区 2444 | 451221 南丹县 2445 | 451222 天峨县 2446 | 451223 凤山县 2447 | 451224 东兰县 2448 | 451225 罗城仫佬族自治县 2449 | 451226 环江毛南族自治县 2450 | 451227 巴马瑶族自治县 2451 | 451228 都安瑶族自治县 2452 | 451229 大化瑶族自治县 2453 | 451281 宜州市 2454 | 451300 来宾市 2455 | 451301 市辖区 2456 | 451302 兴宾区 2457 | 451321 忻城县 2458 | 451322 象州县 2459 | 451323 武宣县 2460 | 451324 金秀瑶族自治县 2461 | 451381 合山市 2462 | 451400 崇左市 2463 | 451401 市辖区 2464 | 451402 江洲区 2465 | 451421 扶绥县 2466 | 451422 宁明县 2467 | 451423 龙州县 2468 | 451424 大新县 2469 | 451425 天等县 2470 | 451481 凭祥市 2471 | 2472 | 460000 海南省 2473 | 460100 海口市 2474 | 460101 市辖区 2475 | 460105 秀英区 2476 | 460106 龙华区 2477 | 460107 琼山区 2478 | 460108 美兰区 2479 | 460200 三亚市 2480 | 460201 市辖区 2481 | 469000 省直辖县级行政单位 2482 | 469001 五指山市 2483 | 469002 琼海市 2484 | 469003 儋州市 2485 | 469005 文昌市 2486 | 469006 万宁市 2487 | 469007 东方市 2488 | 469025 定安县 2489 | 469026 屯昌县 2490 | 469027 澄迈县 2491 | 469028 临高县 2492 | 469030 白沙黎族自治县 2493 | 469031 昌江黎族自治县 2494 | 469033 乐东黎族自治县 2495 | 469034 陵水黎族自治县 2496 | 469035 保亭黎族苗族自治县 2497 | 469036 琼中黎族苗族自治县 2498 | 469037 西沙群岛 2499 | 469038 南沙群岛 2500 | 469039 中沙群岛的岛礁及其海域 2501 | 2502 | 500000 重庆市 2503 | 500100 市辖区 2504 | 500101 万州区 2505 | 500102 涪陵区 2506 | 500103 渝中区 2507 | 500104 大渡口区 2508 | 500105 江北区 2509 | 500106 沙坪坝区 2510 | 500107 九龙坡区 2511 | 500108 南岸区 2512 | 500109 北碚区 2513 | 500110 万盛区 2514 | 500111 双桥区 2515 | 500112 渝北区 2516 | 500113 巴南区 2517 | 500114 黔江区 2518 | 500115 长寿区 2519 | 500200 县 2520 | 500222 綦江县 2521 | 500223 潼南县 2522 | 500224 铜梁县 2523 | 500225 大足县 2524 | 500226 荣昌县 2525 | 500227 璧山县 2526 | 500228 梁平县 2527 | 500229 城口县 2528 | 500230 丰都县 2529 | 500231 垫江县 2530 | 500232 武隆县 2531 | 500233 忠 县 2532 | 500234 开 县 2533 | 500235 云阳县 2534 | 500236 奉节县 2535 | 500237 巫山县 2536 | 500238 巫溪县 2537 | 500240 石柱土家族自治县 2538 | 500241 秀山土家族苗族自治县 2539 | 500242 酉阳土家族苗族自治县 2540 | 500243 彭水苗族土家族自治县 2541 | 500300 市 2542 | 500381 江津市 2543 | 500382 合川市 2544 | 500383 永川市 2545 | 500384 南川市 2546 | 2547 | 510000 四川省 2548 | 510100 成都市 2549 | 510101 市辖区 2550 | 510104 锦江区 2551 | 510105 青羊区 2552 | 510106 金牛区 2553 | 510107 武侯区 2554 | 510108 成华区 2555 | 510112 龙泉驿区 2556 | 510113 青白江区 2557 | 510114 新都区 2558 | 510115 温江区 2559 | 510121 金堂县 2560 | 510122 双流县 2561 | 510124 郫 县 2562 | 510129 大邑县 2563 | 510131 蒲江县 2564 | 510132 新津县 2565 | 510181 都江堰市 2566 | 510182 彭州市 2567 | 510183 邛崃市 2568 | 510184 崇州市 2569 | 510300 自贡市 2570 | 510301 市辖区 2571 | 510302 自流井区 2572 | 510303 贡井区 2573 | 510304 大安区 2574 | 510311 沿滩区 2575 | 510321 荣 县 2576 | 510322 富顺县 2577 | 510400 攀枝花市 2578 | 510401 市辖区 2579 | 510402 东 区 2580 | 510403 西 区 2581 | 510411 仁和区 2582 | 510421 米易县 2583 | 510422 盐边县 2584 | 510500 泸州市 2585 | 510501 市辖区 2586 | 510502 江阳区 2587 | 510503 纳溪区 2588 | 510504 龙马潭区 2589 | 510521 泸 县 2590 | 510522 合江县 2591 | 510524 叙永县 2592 | 510525 古蔺县 2593 | 510600 德阳市 2594 | 510601 市辖区 2595 | 510603 旌阳区 2596 | 510623 中江县 2597 | 510626 罗江县 2598 | 510681 广汉市 2599 | 510682 什邡市 2600 | 510683 绵竹市 2601 | 510700 绵阳市 2602 | 510701 市辖区 2603 | 510703 涪城区 2604 | 510704 游仙区 2605 | 510722 三台县 2606 | 510723 盐亭县 2607 | 510724 安 县 2608 | 510725 梓潼县 2609 | 510726 北川羌族自治县 2610 | 510727 平武县 2611 | 510781 江油市 2612 | 510800 广元市 2613 | 510801 市辖区 2614 | 510802 市中区 2615 | 510811 元坝区 2616 | 510812 朝天区 2617 | 510821 旺苍县 2618 | 510822 青川县 2619 | 510823 剑阁县 2620 | 510824 苍溪县 2621 | 510900 遂宁市 2622 | 510901 市辖区 2623 | 510903 船山区 2624 | 510904 安居区 2625 | 510921 蓬溪县 2626 | 510922 射洪县 2627 | 510923 大英县 2628 | 511000 内江市 2629 | 511001 市辖区 2630 | 511002 市中区 2631 | 511011 东兴区 2632 | 511024 威远县 2633 | 511025 资中县 2634 | 511028 隆昌县 2635 | 511100 乐山市 2636 | 511101 市辖区 2637 | 511102 市中区 2638 | 511111 沙湾区 2639 | 511112 五通桥区 2640 | 511113 金口河区 2641 | 511123 犍为县 2642 | 511124 井研县 2643 | 511126 夹江县 2644 | 511129 沐川县 2645 | 511132 峨边彝族自治县 2646 | 511133 马边彝族自治县 2647 | 511181 峨眉山市 2648 | 511300 南充市 2649 | 511301 市辖区 2650 | 511302 顺庆区 2651 | 511303 高坪区 2652 | 511304 嘉陵区 2653 | 511321 南部县 2654 | 511322 营山县 2655 | 511323 蓬安县 2656 | 511324 仪陇县 2657 | 511325 西充县 2658 | 511381 阆中市 2659 | 511400 眉山市 2660 | 511401 市辖区 2661 | 511402 东坡区 2662 | 511421 仁寿县 2663 | 511422 彭山县 2664 | 511423 洪雅县 2665 | 511424 丹棱县 2666 | 511425 青神县 2667 | 511500 宜宾市 2668 | 511501 市辖区 2669 | 511502 翠屏区 2670 | 511521 宜宾县 2671 | 511522 南溪县 2672 | 511523 江安县 2673 | 511524 长宁县 2674 | 511525 高 县 2675 | 511526 珙 县 2676 | 511527 筠连县 2677 | 511528 兴文县 2678 | 511529 屏山县 2679 | 511600 广安市 2680 | 511601 市辖区 2681 | 511602 广安区 2682 | 511621 岳池县 2683 | 511622 武胜县 2684 | 511623 邻水县 2685 | 511681 华蓥市 2686 | 511700 达州市 2687 | 511701 市辖区 2688 | 511702 通川区 2689 | 511721 达 县 2690 | 511722 宣汉县 2691 | 511723 开江县 2692 | 511724 大竹县 2693 | 511725 渠 县 2694 | 511781 万源市 2695 | 511800 雅安市 2696 | 511801 市辖区 2697 | 511802 雨城区 2698 | 511821 名山县 2699 | 511822 荥经县 2700 | 511823 汉源县 2701 | 511824 石棉县 2702 | 511825 天全县 2703 | 511826 芦山县 2704 | 511827 宝兴县 2705 | 511900 巴中市 2706 | 511901 市辖区 2707 | 511902 巴州区 2708 | 511921 通江县 2709 | 511922 南江县 2710 | 511923 平昌县 2711 | 512000 资阳市 2712 | 512001 市辖区 2713 | 512002 雁江区 2714 | 512021 安岳县 2715 | 512022 乐至县 2716 | 512081 简阳市 2717 | 513200 阿坝藏族羌族自治州 2718 | 513221 汶川县 2719 | 513222 理 县 2720 | 513223 茂 县 2721 | 513224 松潘县 2722 | 513225 九寨沟县 2723 | 513226 金川县 2724 | 513227 小金县 2725 | 513228 黑水县 2726 | 513229 马尔康县 2727 | 513230 壤塘县 2728 | 513231 阿坝县 2729 | 513232 若尔盖县 2730 | 513233 红原县 2731 | 513300 甘孜藏族自治州 2732 | 513321 康定县 2733 | 513322 泸定县 2734 | 513323 丹巴县 2735 | 513324 九龙县 2736 | 513325 雅江县 2737 | 513326 道孚县 2738 | 513327 炉霍县 2739 | 513328 甘孜县 2740 | 513329 新龙县 2741 | 513330 德格县 2742 | 513331 白玉县 2743 | 513332 石渠县 2744 | 513333 色达县 2745 | 513334 理塘县 2746 | 513335 巴塘县 2747 | 513336 乡城县 2748 | 513337 稻城县 2749 | 513338 得荣县 2750 | 513400 凉山彝族自治州 2751 | 513401 西昌市 2752 | 513422 木里藏族自治县 2753 | 513423 盐源县 2754 | 513424 德昌县 2755 | 513425 会理县 2756 | 513426 会东县 2757 | 513427 宁南县 2758 | 513428 普格县 2759 | 513429 布拖县 2760 | 513430 金阳县 2761 | 513431 昭觉县 2762 | 513432 喜德县 2763 | 513433 冕宁县 2764 | 513434 越西县 2765 | 513435 甘洛县 2766 | 513436 美姑县 2767 | 513437 雷波县 2768 | 2769 | 520000 贵州省 2770 | 520100 贵阳市 2771 | 520101 市辖区 2772 | 520102 南明区 2773 | 520103 云岩区 2774 | 520111 花溪区 2775 | 520112 乌当区 2776 | 520113 白云区 2777 | 520114 小河区 2778 | 520121 开阳县 2779 | 520122 息烽县 2780 | 520123 修文县 2781 | 520181 清镇市 2782 | 520200 六盘水市 2783 | 520201 钟山区 2784 | 520203 六枝特区 2785 | 520221 水城县 2786 | 520222 盘 县 2787 | 520300 遵义市 2788 | 520301 市辖区 2789 | 520302 红花岗区 2790 | 520303 汇川区 2791 | 520321 遵义县 2792 | 520322 桐梓县 2793 | 520323 绥阳县 2794 | 520324 正安县 2795 | 520325 道真仡佬族苗族自治县 2796 | 520326 务川仡佬族苗族自治县 2797 | 520327 凤冈县 2798 | 520328 湄潭县 2799 | 520329 余庆县 2800 | 520330 习水县 2801 | 520381 赤水市 2802 | 520382 仁怀市 2803 | 520400 安顺市 2804 | 520401 市辖区 2805 | 520402 西秀区 2806 | 520421 平坝县 2807 | 520422 普定县 2808 | 520423 镇宁布依族苗族自治县 2809 | 520424 关岭布依族苗族自治县 2810 | 520425 紫云苗族布依族自治县 2811 | 522200 铜仁地区 2812 | 522201 铜仁市 2813 | 522222 江口县 2814 | 522223 玉屏侗族自治县 2815 | 522224 石阡县 2816 | 522225 思南县 2817 | 522226 印江土家族苗族自治县 2818 | 522227 德江县 2819 | 522228 沿河土家族自治县 2820 | 522229 松桃苗族自治县 2821 | 522230 万山特区 2822 | 522300 黔西南布依族苗族自治州 2823 | 522301 兴义市 2824 | 522322 兴仁县 2825 | 522323 普安县 2826 | 522324 晴隆县 2827 | 522325 贞丰县 2828 | 522326 望谟县 2829 | 522327 册亨县 2830 | 522328 安龙县 2831 | 522400 毕节地区 2832 | 522401 毕节市 2833 | 522422 大方县 2834 | 522423 黔西县 2835 | 522424 金沙县 2836 | 522425 织金县 2837 | 522426 纳雍县 2838 | 522427 威宁彝族回族苗族自治县 2839 | 522428 赫章县 2840 | 522600 黔东南苗族侗族自治州 2841 | 522601 凯里市 2842 | 522622 黄平县 2843 | 522623 施秉县 2844 | 522624 三穗县 2845 | 522625 镇远县 2846 | 522626 岑巩县 2847 | 522627 天柱县 2848 | 522628 锦屏县 2849 | 522629 剑河县 2850 | 522630 台江县 2851 | 522631 黎平县 2852 | 522632 榕江县 2853 | 522633 从江县 2854 | 522634 雷山县 2855 | 522635 麻江县 2856 | 522636 丹寨县 2857 | 522700 黔南布依族苗族自治州 2858 | 522701 都匀市 2859 | 522702 福泉市 2860 | 522722 荔波县 2861 | 522723 贵定县 2862 | 522725 瓮安县 2863 | 522726 独山县 2864 | 522727 平塘县 2865 | 522728 罗甸县 2866 | 522729 长顺县 2867 | 522730 龙里县 2868 | 522731 惠水县 2869 | 522732 三都水族自治县 2870 | 2871 | 530000 云南省 2872 | 530100 昆明市 2873 | 530101 市辖区 2874 | 530102 五华区 2875 | 530103 盘龙区 2876 | 530111 官渡区 2877 | 530112 西山区 2878 | 530113 东川区 2879 | 530121 呈贡县 2880 | 530122 晋宁县 2881 | 530124 富民县 2882 | 530125 宜良县 2883 | 530126 石林彝族自治县 2884 | 530127 嵩明县 2885 | 530128 禄劝彝族苗族自治县 2886 | 530129 寻甸回族彝族自治县 2887 | 530181 安宁市 2888 | 530300 曲靖市 2889 | 530301 市辖区 2890 | 530302 麒麟区 2891 | 530321 马龙县 2892 | 530322 陆良县 2893 | 530323 师宗县 2894 | 530324 罗平县 2895 | 530325 富源县 2896 | 530326 会泽县 2897 | 530328 沾益县 2898 | 530381 宣威市 2899 | 530400 玉溪市 2900 | 530401 市辖区 2901 | 530402 红塔区 2902 | 530421 江川县 2903 | 530422 澄江县 2904 | 530423 通海县 2905 | 530424 华宁县 2906 | 530425 易门县 2907 | 530426 峨山彝族自治县 2908 | 530427 新平彝族傣族自治县 2909 | 530428 元江哈尼族彝族傣族自治县 2910 | 530500 保山市 2911 | 530501 市辖区 2912 | 530502 隆阳区 2913 | 530521 施甸县 2914 | 530522 腾冲县 2915 | 530523 龙陵县 2916 | 530524 昌宁县 2917 | 530600 昭通市 2918 | 530601 市辖区 2919 | 530602 昭阳区 2920 | 530621 鲁甸县 2921 | 530622 巧家县 2922 | 530623 盐津县 2923 | 530624 大关县 2924 | 530625 永善县 2925 | 530626 绥江县 2926 | 530627 镇雄县 2927 | 530628 彝良县 2928 | 530629 威信县 2929 | 530630 水富县 2930 | 530700 丽江市 2931 | 530701 市辖区 2932 | 530702 古城区 2933 | 530721 玉龙纳西族自治县 2934 | 530722 永胜县 2935 | 530723 华坪县 2936 | 530724 宁蒗彝族自治县 2937 | 530800 思茅市 2938 | 530801 市辖区 2939 | 530802 翠云区 2940 | 530821 普洱哈尼族彝族自治县 2941 | 530822 墨江哈尼族自治县 2942 | 530823 景东彝族自治县 2943 | 530824 景谷傣族彝族自治县 2944 | 530825 镇沅彝族哈尼族拉祜族自治县 2945 | 530826 江城哈尼族彝族自治县 2946 | 530827 孟连傣族拉祜族佤族自治县 2947 | 530828 澜沧拉祜族自治县 2948 | 530829 西盟佤族自治县 2949 | 530900 临沧市 2950 | 530901 市辖区 2951 | 530902 临翔区 2952 | 530921 凤庆县 2953 | 530922 云 县 2954 | 530923 永德县 2955 | 530924 镇康县 2956 | 530925 双江拉祜族佤族布朗族傣族自治县 2957 | 530926 耿马傣族佤族自治县 2958 | 530927 沧源佤族自治县 2959 | 532300 楚雄彝族自治州 2960 | 532301 楚雄市 2961 | 532322 双柏县 2962 | 532323 牟定县 2963 | 532324 南华县 2964 | 532325 姚安县 2965 | 532326 大姚县 2966 | 532327 永仁县 2967 | 532328 元谋县 2968 | 532329 武定县 2969 | 532331 禄丰县 2970 | 532500 红河哈尼族彝族自治州 2971 | 532501 个旧市 2972 | 532502 开远市 2973 | 532522 蒙自县 2974 | 532523 屏边苗族自治县 2975 | 532524 建水县 2976 | 532525 石屏县 2977 | 532526 弥勒县 2978 | 532527 泸西县 2979 | 532528 元阳县 2980 | 532529 红河县 2981 | 532530 金平苗族瑶族傣族自治县 2982 | 532531 绿春县 2983 | 532532 河口瑶族自治县 2984 | 532600 文山壮族苗族自治州 2985 | 532621 文山县 2986 | 532622 砚山县 2987 | 532623 西畴县 2988 | 532624 麻栗坡县 2989 | 532625 马关县 2990 | 532626 丘北县 2991 | 532627 广南县 2992 | 532628 富宁县 2993 | 532800 西双版纳傣族自治州 2994 | 532801 景洪市 2995 | 532822 勐海县 2996 | 532823 勐腊县 2997 | 532900 大理白族自治州 2998 | 532901 大理市 2999 | 532922 漾濞彝族自治县 3000 | 532923 祥云县 3001 | 532924 宾川县 3002 | 532925 弥渡县 3003 | 532926 南涧彝族自治县 3004 | 532927 巍山彝族回族自治县 3005 | 532928 永平县 3006 | 532929 云龙县 3007 | 532930 洱源县 3008 | 532931 剑川县 3009 | 532932 鹤庆县 3010 | 533100 德宏傣族景颇族自治州 3011 | 533102 瑞丽市 3012 | 533103 潞西市 3013 | 533122 梁河县 3014 | 533123 盈江县 3015 | 533124 陇川县 3016 | 533300 怒江傈僳族自治州 3017 | 533321 泸水县 3018 | 533323 福贡县 3019 | 533324 贡山独龙族怒族自治县 3020 | 533325 兰坪白族普米族自治县 3021 | 533400 迪庆藏族自治州 3022 | 533421 香格里拉县 3023 | 533422 德钦县 3024 | 533423 维西傈僳族自治县 3025 | 3026 | 540000 西藏自治区 3027 | 540100 拉萨市 3028 | 540101 市辖区 3029 | 540102 城关区 3030 | 540121 林周县 3031 | 540122 当雄县 3032 | 540123 尼木县 3033 | 540124 曲水县 3034 | 540125 堆龙德庆县 3035 | 540126 达孜县 3036 | 540127 墨竹工卡县 3037 | 542100 昌都地区 3038 | 542121 昌都县 3039 | 542122 江达县 3040 | 542123 贡觉县 3041 | 542124 类乌齐县 3042 | 542125 丁青县 3043 | 542126 察雅县 3044 | 542127 八宿县 3045 | 542128 左贡县 3046 | 542129 芒康县 3047 | 542132 洛隆县 3048 | 542133 边坝县 3049 | 542200 山南地区 3050 | 542221 乃东县 3051 | 542222 扎囊县 3052 | 542223 贡嘎县 3053 | 542224 桑日县 3054 | 542225 琼结县 3055 | 542226 曲松县 3056 | 542227 措美县 3057 | 542228 洛扎县 3058 | 542229 加查县 3059 | 542231 隆子县 3060 | 542232 错那县 3061 | 542233 浪卡子县 3062 | 542300 日喀则地区 3063 | 542301 日喀则市 3064 | 542322 南木林县 3065 | 542323 江孜县 3066 | 542324 定日县 3067 | 542325 萨迦县 3068 | 542326 拉孜县 3069 | 542327 昂仁县 3070 | 542328 谢通门县 3071 | 542329 白朗县 3072 | 542330 仁布县 3073 | 542331 康马县 3074 | 542332 定结县 3075 | 542333 仲巴县 3076 | 542334 亚东县 3077 | 542335 吉隆县 3078 | 542336 聂拉木县 3079 | 542337 萨嘎县 3080 | 542338 岗巴县 3081 | 542400 那曲地区 3082 | 542421 那曲县 3083 | 542422 嘉黎县 3084 | 542423 比如县 3085 | 542424 聂荣县 3086 | 542425 安多县 3087 | 542426 申扎县 3088 | 542427 索 县 3089 | 542428 班戈县 3090 | 542429 巴青县 3091 | 542430 尼玛县 3092 | 542500 阿里地区 3093 | 542521 普兰县 3094 | 542522 札达县 3095 | 542523 噶尔县 3096 | 542524 日土县 3097 | 542525 革吉县 3098 | 542526 改则县 3099 | 542527 措勤县 3100 | 542600 林芝地区 3101 | 542621 林芝县 3102 | 542622 工布江达县 3103 | 542623 米林县 3104 | 542624 墨脱县 3105 | 542625 波密县 3106 | 542626 察隅县 3107 | 542627 朗 县 3108 | 3109 | 610000 陕西省 3110 | 610100 西安市 3111 | 610101 市辖区 3112 | 610102 新城区 3113 | 610103 碑林区 3114 | 610104 莲湖区 3115 | 610111 灞桥区 3116 | 610112 未央区 3117 | 610113 雁塔区 3118 | 610114 阎良区 3119 | 610115 临潼区 3120 | 610116 长安区 3121 | 610122 蓝田县 3122 | 610124 周至县 3123 | 610125 户 县 3124 | 610126 高陵县 3125 | 610200 铜川市 3126 | 610201 市辖区 3127 | 610202 王益区 3128 | 610203 印台区 3129 | 610204 耀州区 3130 | 610222 宜君县 3131 | 610300 宝鸡市 3132 | 610301 市辖区 3133 | 610302 渭滨区 3134 | 610303 金台区 3135 | 610304 陈仓区 3136 | 610322 凤翔县 3137 | 610323 岐山县 3138 | 610324 扶风县 3139 | 610326 眉 县 3140 | 610327 陇 县 3141 | 610328 千阳县 3142 | 610329 麟游县 3143 | 610330 凤 县 3144 | 610331 太白县 3145 | 610400 咸阳市 3146 | 610401 市辖区 3147 | 610402 秦都区 3148 | 610403 杨凌区 3149 | 610404 渭城区 3150 | 610422 三原县 3151 | 610423 泾阳县 3152 | 610424 乾 县 3153 | 610425 礼泉县 3154 | 610426 永寿县 3155 | 610427 彬 县 3156 | 610428 长武县 3157 | 610429 旬邑县 3158 | 610430 淳化县 3159 | 610431 武功县 3160 | 610481 兴平市 3161 | 610500 渭南市 3162 | 610501 市辖区 3163 | 610502 临渭区 3164 | 610521 华 县 3165 | 610522 潼关县 3166 | 610523 大荔县 3167 | 610524 合阳县 3168 | 610525 澄城县 3169 | 610526 蒲城县 3170 | 610527 白水县 3171 | 610528 富平县 3172 | 610581 韩城市 3173 | 610582 华阴市 3174 | 610600 延安市 3175 | 610601 市辖区 3176 | 610602 宝塔区 3177 | 610621 延长县 3178 | 610622 延川县 3179 | 610623 子长县 3180 | 610624 安塞县 3181 | 610625 志丹县 3182 | 610626 吴旗县 3183 | 610627 甘泉县 3184 | 610628 富 县 3185 | 610629 洛川县 3186 | 610630 宜川县 3187 | 610631 黄龙县 3188 | 610632 黄陵县 3189 | 610700 汉中市 3190 | 610701 市辖区 3191 | 610702 汉台区 3192 | 610721 南郑县 3193 | 610722 城固县 3194 | 610723 洋 县 3195 | 610724 西乡县 3196 | 610725 勉 县 3197 | 610726 宁强县 3198 | 610727 略阳县 3199 | 610728 镇巴县 3200 | 610729 留坝县 3201 | 610730 佛坪县 3202 | 610800 榆林市 3203 | 610801 市辖区 3204 | 610802 榆阳区 3205 | 610821 神木县 3206 | 610822 府谷县 3207 | 610823 横山县 3208 | 610824 靖边县 3209 | 610825 定边县 3210 | 610826 绥德县 3211 | 610827 米脂县 3212 | 610828 佳 县 3213 | 610829 吴堡县 3214 | 610830 清涧县 3215 | 610831 子洲县 3216 | 610900 安康市 3217 | 610901 市辖区 3218 | 610902 汉滨区 3219 | 610921 汉阴县 3220 | 610922 石泉县 3221 | 610923 宁陕县 3222 | 610924 紫阳县 3223 | 610925 岚皋县 3224 | 610926 平利县 3225 | 610927 镇坪县 3226 | 610928 旬阳县 3227 | 610929 白河县 3228 | 611000 商洛市 3229 | 611001 市辖区 3230 | 611002 商州区 3231 | 611021 洛南县 3232 | 611022 丹凤县 3233 | 611023 商南县 3234 | 611024 山阳县 3235 | 611025 镇安县 3236 | 611026 柞水县 3237 | 3238 | 620000 甘肃省 3239 | 620100 兰州市 3240 | 620101 市辖区 3241 | 620102 城关区 3242 | 620103 七里河区 3243 | 620104 西固区 3244 | 620105 安宁区 3245 | 620111 红古区 3246 | 620121 永登县 3247 | 620122 皋兰县 3248 | 620123 榆中县 3249 | 620200 嘉峪关市 3250 | 620201 市辖区 3251 | 620300 金昌市 3252 | 620301 市辖区 3253 | 620302 金川区 3254 | 620321 永昌县 3255 | 620400 白银市 3256 | 620401 市辖区 3257 | 620402 白银区 3258 | 620403 平川区 3259 | 620421 靖远县 3260 | 620422 会宁县 3261 | 620423 景泰县 3262 | 620500 天水市 3263 | 620501 市辖区 3264 | 620502 秦城区 3265 | 620503 北道区 3266 | 620521 清水县 3267 | 620522 秦安县 3268 | 620523 甘谷县 3269 | 620524 武山县 3270 | 620525 张家川回族自治县 3271 | 620600 武威市 3272 | 620601 市辖区 3273 | 620602 凉州区 3274 | 620621 民勤县 3275 | 620622 古浪县 3276 | 620623 天祝藏族自治县 3277 | 620700 张掖市 3278 | 620701 市辖区 3279 | 620702 甘州区 3280 | 620721 肃南裕固族自治县 3281 | 620722 民乐县 3282 | 620723 临泽县 3283 | 620724 高台县 3284 | 620725 山丹县 3285 | 620800 平凉市 3286 | 620801 市辖区 3287 | 620802 崆峒区 3288 | 620821 泾川县 3289 | 620822 灵台县 3290 | 620823 崇信县 3291 | 620824 华亭县 3292 | 620825 庄浪县 3293 | 620826 静宁县 3294 | 620900 酒泉市 3295 | 620901 市辖区 3296 | 620902 肃州区 3297 | 620921 金塔县 3298 | 620922 安西县 3299 | 620923 肃北蒙古族自治县 3300 | 620924 阿克塞哈萨克族自治县 3301 | 620981 玉门市 3302 | 620982 敦煌市 3303 | 621000 庆阳市 3304 | 621001 市辖区 3305 | 621002 西峰区 3306 | 621021 庆城县 3307 | 621022 环 县 3308 | 621023 华池县 3309 | 621024 合水县 3310 | 621025 正宁县 3311 | 621026 宁 县 3312 | 621027 镇原县 3313 | 621100 定西市 3314 | 621101 市辖区 3315 | 621102 安定区 3316 | 621121 通渭县 3317 | 621122 陇西县 3318 | 621123 渭源县 3319 | 621124 临洮县 3320 | 621125 漳 县 3321 | 621126 岷 县 3322 | 621200 陇南市 3323 | 621201 市辖区 3324 | 621202 武都区 3325 | 621221 成 县 3326 | 621222 文 县 3327 | 621223 宕昌县 3328 | 621224 康 县 3329 | 621225 西和县 3330 | 621226 礼 县 3331 | 621227 徽 县 3332 | 621228 两当县 3333 | 622900 临夏回族自治州 3334 | 622901 临夏市 3335 | 622921 临夏县 3336 | 622922 康乐县 3337 | 622923 永靖县 3338 | 622924 广河县 3339 | 622925 和政县 3340 | 622926 东乡族自治县 3341 | 622927 积石山保安族东乡族撒拉族自治县 3342 | 623000 甘南藏族自治州 3343 | 623001 合作市 3344 | 623021 临潭县 3345 | 623022 卓尼县 3346 | 623023 舟曲县 3347 | 623024 迭部县 3348 | 623025 玛曲县 3349 | 623026 碌曲县 3350 | 623027 夏河县 3351 | 3352 | 630000 青海省 3353 | 630100 西宁市 3354 | 630101 市辖区 3355 | 630102 城东区 3356 | 630103 城中区 3357 | 630104 城西区 3358 | 630105 城北区 3359 | 630121 大通回族土族自治县 3360 | 630122 湟中县 3361 | 630123 湟源县 3362 | 632100 海东地区 3363 | 632121 平安县 3364 | 632122 民和回族土族自治县 3365 | 632123 乐都县 3366 | 632126 互助土族自治县 3367 | 632127 化隆回族自治县 3368 | 632128 循化撒拉族自治县 3369 | 632200 海北藏族自治州 3370 | 632221 门源回族自治县 3371 | 632222 祁连县 3372 | 632223 海晏县 3373 | 632224 刚察县 3374 | 632300 黄南藏族自治州 3375 | 632321 同仁县 3376 | 632322 尖扎县 3377 | 632323 泽库县 3378 | 632324 河南蒙古族自治县 3379 | 632500 海南藏族自治州 3380 | 632521 共和县 3381 | 632522 同德县 3382 | 632523 贵德县 3383 | 632524 兴海县 3384 | 632525 贵南县 3385 | 632600 果洛藏族自治州 3386 | 632621 玛沁县 3387 | 632622 班玛县 3388 | 632623 甘德县 3389 | 632624 达日县 3390 | 632625 久治县 3391 | 632626 玛多县 3392 | 632700 玉树藏族自治州 3393 | 632721 玉树县 3394 | 632722 杂多县 3395 | 632723 称多县 3396 | 632724 治多县 3397 | 632725 囊谦县 3398 | 632726 曲麻莱县 3399 | 632800 海西蒙古族藏族自治州 3400 | 632801 格尔木市 3401 | 632802 德令哈市 3402 | 632821 乌兰县 3403 | 632822 都兰县 3404 | 632823 天峻县 3405 | 3406 | 3407 | 640000 宁夏回族自治区 3408 | 640100 银川市 3409 | 640101 市辖区 3410 | 640104 兴庆区 3411 | 640105 西夏区 3412 | 640106 金凤区 3413 | 640121 永宁县 3414 | 640122 贺兰县 3415 | 640181 灵武市 3416 | 640200 石嘴山市 3417 | 640201 市辖区 3418 | 640202 大武口区 3419 | 640205 惠农区 3420 | 640221 平罗县 3421 | 640300 吴忠市 3422 | 640301 市辖区 3423 | 640302 利通区 3424 | 640323 盐池县 3425 | 640324 同心县 3426 | 640381 青铜峡市 3427 | 640400 固原市 3428 | 640401 市辖区 3429 | 640402 原州区 3430 | 640422 西吉县 3431 | 640423 隆德县 3432 | 640424 泾源县 3433 | 640425 彭阳县 3434 | 640500 中卫市 3435 | 640501 市辖区 3436 | 640502 沙坡头区 3437 | 640521 中宁县 3438 | 640522 海原县 3439 | 3440 | 650000 新疆维吾尔自治区 3441 | 650100 乌鲁木齐市 3442 | 650101 市辖区 3443 | 650102 天山区 3444 | 650103 沙依巴克区 3445 | 650104 新市区 3446 | 650105 水磨沟区 3447 | 650106 头屯河区 3448 | 650107 达坂城区 3449 | 650108 东山区 3450 | 650121 乌鲁木齐县 3451 | 650200 克拉玛依市 3452 | 650201 市辖区 3453 | 650202 独山子区 3454 | 650203 克拉玛依区 3455 | 650204 白碱滩区 3456 | 650205 乌尔禾区 3457 | 652100 吐鲁番地区 3458 | 652101 吐鲁番市 3459 | 652122 鄯善县 3460 | 652123 托克逊县 3461 | 652200 哈密地区 3462 | 652201 哈密市 3463 | 652222 巴里坤哈萨克自治县 3464 | 652223 伊吾县 3465 | 652300 昌吉回族自治州 3466 | 652301 昌吉市 3467 | 652302 阜康市 3468 | 652303 米泉市 3469 | 652323 呼图壁县 3470 | 652324 玛纳斯县 3471 | 652325 奇台县 3472 | 652327 吉木萨尔县 3473 | 652328 木垒哈萨克自治县 3474 | 652700 博尔塔拉蒙古自治州 3475 | 652701 博乐市 3476 | 652722 精河县 3477 | 652723 温泉县 3478 | 652800 巴音郭楞蒙古自治州 3479 | 652801 库尔勒市 3480 | 652822 轮台县 3481 | 652823 尉犁县 3482 | 652824 若羌县 3483 | 652825 且末县 3484 | 652826 焉耆回族自治县 3485 | 652827 和静县 3486 | 652828 和硕县 3487 | 652829 博湖县 3488 | 652900 阿克苏地区 3489 | 652901 阿克苏市 3490 | 652922 温宿县 3491 | 652923 库车县 3492 | 652924 沙雅县 3493 | 652925 新和县 3494 | 652926 拜城县 3495 | 652927 乌什县 3496 | 652928 阿瓦提县 3497 | 652929 柯坪县 3498 | 653000 克孜勒苏柯尔克孜自治州 3499 | 653001 阿图什市 3500 | 653022 阿克陶县 3501 | 653023 阿合奇县 3502 | 653024 乌恰县 3503 | 653100 喀什地区 3504 | 653101 喀什市 3505 | 653121 疏附县 3506 | 653122 疏勒县 3507 | 653123 英吉沙县 3508 | 653124 泽普县 3509 | 653125 莎车县 3510 | 653126 叶城县 3511 | 653127 麦盖提县 3512 | 653128 岳普湖县 3513 | 653129 伽师县 3514 | 653130 巴楚县 3515 | 653131 塔什库尔干塔吉克自治县 3516 | 653200 和田地区 3517 | 653201 和田市 3518 | 653221 和田县 3519 | 653222 墨玉县 3520 | 653223 皮山县 3521 | 653224 洛浦县 3522 | 653225 策勒县 3523 | 653226 于田县 3524 | 653227 民丰县 3525 | 654000 伊犁哈萨克自治州 3526 | 654002 伊宁市 3527 | 654003 奎屯市 3528 | 654021 伊宁县 3529 | 654022 察布查尔锡伯自治县 3530 | 654023 霍城县 3531 | 654024 巩留县 3532 | 654025 新源县 3533 | 654026 昭苏县 3534 | 654027 特克斯县 3535 | 654028 尼勒克县 3536 | 654200 塔城地区 3537 | 654201 塔城市 3538 | 654202 乌苏市 3539 | 654221 额敏县 3540 | 654223 沙湾县 3541 | 654224 托里县 3542 | 654225 裕民县 3543 | 654226 和布克赛尔蒙古自治县 3544 | 654300 阿勒泰地区 3545 | 654301 阿勒泰市 3546 | 654321 布尔津县 3547 | 654322 富蕴县 3548 | 654323 福海县 3549 | 654324 哈巴河县 3550 | 654325 青河县 3551 | 654326 吉木乃县 3552 | 659000 省直辖行政单位 3553 | 659001 石河子市 3554 | 659002 阿拉尔市 3555 | 659003 图木舒克市 3556 | 659004 五家渠市 3557 | 3558 | 710000 台湾省 3559 | 3560 | 810000 香港特别行政区 3561 | 3562 | 820000 澳门特别行政区 3563 | ''' 3564 | state_names = [] 3565 | 3566 | __PATTERN_SPACE = re.compile(r'\s+', re.UNICODE) 3567 | for line in __state_name_strs.split('\n'): 3568 | line = __PATTERN_SPACE.sub(' ', line).strip() 3569 | if line.startswith('#') or len(line) == 0: 3570 | continue 3571 | 3572 | pos = line.find(' ') 3573 | assert(pos > 0) 3574 | id_, name = line[0:pos], line[pos+1:] 3575 | name = __PATTERN_SPACE.sub('', name) 3576 | state_names.append((id_, name)) 3577 | 3578 | if __name__ == '__main__': 3579 | suffix = set() 3580 | for id_, name in state_names: 3581 | suffix.add(name[-1]) 3582 | 3583 | for s in suffix: 3584 | print s.encode('utf-8') 3585 | -------------------------------------------------------------------------------- /evaluation/tagging_evaluation_util.py: -------------------------------------------------------------------------------- 1 | #--*-- encoding:utf-8 --*-- 2 | import sys 3 | from collections import Counter 4 | from fuzzy_matching import FuzzyMatcher 5 | 6 | def get_tagging_results(tokens, tags): 7 | ''' 8 | @param tokens: a list of unicode strings 9 | @param tags: a list of B/I/O1/O2 10 | ''' 11 | chunks = [] 12 | start = -1 13 | for i, tok in enumerate(tokens): 14 | tag = tags[i] 15 | if tag == 'B': 16 | if start >= 0: chunks.append(' '.join(tokens[start:i])) 17 | start = i 18 | elif tag == 'I': 19 | if start < 0: start = i 20 | else: 21 | if start < 0: continue 22 | chunks.append(' '.join(tokens[start:i])) 23 | start = -1 24 | if start >= 0: 25 | chunks.append(' '.join(tokens[start:])) 26 | 27 | return chunks 28 | 29 | __fuzzy_matcher = None 30 | def is_right(upred_ans, ugolden_ans, fuzzy): 31 | ''' 32 | @param upred_ans: predicted answer, unicode 33 | @param ugolden_ans: golden answer, unicode 34 | @param fuzzy: use fuzzy match if True 35 | ''' 36 | global __fuzzy_matcher 37 | if upred_ans.lower() == u'no_result' and ugolden_ans == u'no_answer': 38 | return True 39 | if fuzzy: 40 | if not __fuzzy_matcher: __fuzzy_matcher = FuzzyMatcher() 41 | return __fuzzy_matcher.is_synonym(ugolden_ans, upred_ans) 42 | else: 43 | upred_ans = upred_ans.replace(' ', '').lower() 44 | ugolden_ans = ugolden_ans.replace(' ', '').lower() 45 | return upred_ans == ugolden_ans 46 | -------------------------------------------------------------------------------- /evaluation/tagging_util.py: -------------------------------------------------------------------------------- 1 | __all__ = ['get_label'] 2 | 3 | BO = {0:'B', 1:'O'} 4 | BO2 = {0:'B', 1:'O1', 2:'O2'} 5 | 6 | BIO = {0:'B', 1:'I', 2:'O1'} 7 | BIO2 = {0:'B', 1:'I', 2:'O1', 3:'O2'} 8 | BIO3 = {0:'B', 1:'I', 2:'O1', 3:'O2', 4:'O3'} 9 | 10 | label_maps = {'BO':BO, 'BO2':BO2, 'BIO':BIO, 'BIO2':BIO2, 'BIO3':BIO3} 11 | 12 | def get_label(label_id, schema): 13 | return label_maps[schema][label_id] 14 | 15 | -------------------------------------------------------------------------------- /evaluation/voter.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | import json 4 | from collections import defaultdict 5 | from tagging_evaluation_util import get_tagging_results 6 | from raw_result_parser import iter_results 7 | 8 | __all__ = ['iter_voting_results', 'Voter'] 9 | 10 | class Voter(object): 11 | __PATTERN_SPACE = re.compile(ur'\s+', re.UNICODE) 12 | 13 | def __init__(self, q_tokens, golden_answers): 14 | self.first = None 15 | self.q_tokens = q_tokens 16 | self.results = defaultdict(int) 17 | self.golden_answers = golden_answers 18 | self.update_time = 0 19 | 20 | def norm(self, text): 21 | if not isinstance(text, unicode): text = text.decode('utf-8') 22 | text = self.__PATTERN_SPACE.sub('', text) 23 | return text 24 | 25 | def update(self, pred_answers, golden_answers, *others, **other_maps): 26 | if self.golden_answers is None: 27 | self.golden_answers = golden_answers 28 | elif len(self.golden_answers) == 1 \ 29 | and self.golden_answers[0].lower() == u'no_answer': 30 | self.golden_answers = golden_answers 31 | else: 32 | assert self.golden_answers == golden_answers 33 | 34 | if not self.first: 35 | self.first = defaultdict(int) 36 | for pred in pred_answers: 37 | self.first[self.norm(pred)] += 1 38 | for pred in pred_answers: 39 | pred = self.norm(pred) 40 | self.results[pred] += 1 41 | self.update_time += 1 42 | 43 | def get_update_time(self): 44 | return self.update_time 45 | 46 | def transfer(self, d): 47 | pred_answers, freqs = [], [] 48 | for pred_answer, freq in d.iteritems(): 49 | pred_answers.append(pred_answer) 50 | freqs.append(freq) 51 | return self.q_tokens, self.golden_answers, pred_answers, freqs 52 | 53 | def vote(self): 54 | if len(self.results) == 0: 55 | return self.transfer({}) 56 | 57 | max_freq = max(self.results.values()) 58 | if max_freq == 1: 59 | return self.transfer(self.first) 60 | else: 61 | results = {} 62 | for key, value in self.results.iteritems(): 63 | if value == max_freq: 64 | results[key] = value 65 | return self.transfer(results) 66 | 67 | def iter_voting_results(raw_prediction_file, test_file, schema): 68 | voter = None 69 | for q_tokens, e_tokens, tags, golden_answers in\ 70 | iter_results(raw_prediction_file, test_file, schema): 71 | if not voter: voter = Voter(q_tokens, golden_answers) 72 | if q_tokens is None: 73 | # one question has been processed 74 | yield voter.vote() 75 | voter = None 76 | else: 77 | pred_answers = get_tagging_results(e_tokens, tags) 78 | voter.update(pred_answers, golden_answers) 79 | 80 | if voter and voter.get_update_time(): 81 | yield voter.vote() 82 | -------------------------------------------------------------------------------- /model/charQA_2017-08-14/f1-0.5593_0.36519_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/model/charQA_2017-08-14/f1-0.5593_0.36519_2 -------------------------------------------------------------------------------- /model/test.crfsuite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/model/test.crfsuite -------------------------------------------------------------------------------- /online/Lawclf.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('../main') 3 | import numpy as np 4 | from util import split_law 5 | 6 | def trace(pre, x): 7 | ret = [] 8 | if 'val' in x: 9 | ret.append((pre, x['val'])) 10 | order = [] 11 | for i in x: 12 | if i == 'val': 13 | continue 14 | if 'val' in x[i]: 15 | order.append((x[i]['val'], i)) 16 | else: 17 | order.append((0, i)) 18 | order = sorted(order, reverse=True) 19 | for i in order: 20 | ret.extend(trace(i[1], x[i[1]])) 21 | return ret 22 | 23 | 24 | def reorder(x): 25 | tree = {} 26 | for i in x: 27 | split_res = split_law(str(i[0])) 28 | now = tree 29 | for j in split_res: 30 | if j not in now: 31 | now[j] = {} 32 | now = now[j] 33 | now['val'] = i[1] 34 | ret = trace('', tree) 35 | ret = list(filter(lambda x: len(split_law(str(x[0])))>1, ret)) 36 | return ret 37 | 38 | 39 | def tem_normalise_name(x): 40 | source = set(['《最高人民法院关于办理妨害信用卡管理刑事案件具体应用法律若干问题的解释》', 41 | '《最高人民法院、最高人民检察院﹤关于办理妨害信用卡管理刑事案件具体应用法律若干问题的解释﹥》', 42 | '《最高人民法院最高人民检察院关于办理妨害信用卡管理刑事案件具体应用法律若干问题的解释》']) 43 | tar = '《最高人民法院、最高人民检察院关于办理妨害信用卡管理刑事案件具体应用法律若干问题的解释》' 44 | if x in source: 45 | return tar 46 | return x 47 | 48 | 49 | def tem_remove(x): 50 | return x not in ['《中华人民共和国刑法》第五十二条', '《中华人民共和国刑法》第五十三条'] 51 | 52 | def pri(text): 53 | for i in text: 54 | print(i) 55 | 56 | def pred(clf, x): 57 | #print(x) 58 | inputs = list(filter(lambda x:len(x)>0, x.split('。'))) 59 | if len(inputs)>1: 60 | inputs.extend([x]) 61 | combine_ret = clf.match(inputs) 62 | print("\nmatch res:") 63 | pri(combine_ret) 64 | ret = {} 65 | for idx,res in enumerate(combine_ret): 66 | res = list(filter(lambda x:tem_remove(x[0]), res)) 67 | res = reorder(res) 68 | combine_ret[idx] = (inputs[idx], res) 69 | for i in res: 70 | ret[i[0]] = max(ret.get(i[0], 0), i[1]) 71 | ret = ret.items() 72 | ret = reorder(ret) 73 | combine_ret.append(('', ret)) 74 | ''' 75 | for i in range(len(combine_ret)): 76 | text = combine_ret[i][0] 77 | res = list(map(lambda x:(x[0],str(x[1])), combine_ret[i][1])) 78 | combine_ret[i] = (text, res) 79 | #print("\npred res:") 80 | #pri(combine_ret) 81 | ''' 82 | return combine_ret 83 | 84 | 85 | if __name__ == '__main__': 86 | reorder([('《中华刑法》第三条',123), ('《中华刑法》第二条',226), ('《中华刑法》第三条第四款第五项',226) 87 | ]) 88 | -------------------------------------------------------------------------------- /online/__pycache__/Lawclf.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/Lawclf.cpython-34.pyc -------------------------------------------------------------------------------- /online/__pycache__/Lawclf.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/Lawclf.cpython-35.pyc -------------------------------------------------------------------------------- /online/__pycache__/model_util.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/model_util.cpython-36.pyc -------------------------------------------------------------------------------- /online/__pycache__/models.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/models.cpython-34.pyc -------------------------------------------------------------------------------- /online/__pycache__/models.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/models.cpython-35.pyc -------------------------------------------------------------------------------- /online/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /online/__pycache__/start_server_stable.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/start_server_stable.cpython-34.pyc -------------------------------------------------------------------------------- /online/__pycache__/util.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/util.cpython-34.pyc -------------------------------------------------------------------------------- /online/__pycache__/util.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/__pycache__/util.cpython-35.pyc -------------------------------------------------------------------------------- /online/model_util.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('../code') 3 | 4 | import h5py 5 | import random 6 | import torch 7 | import numpy as np 8 | from util import load_vocab 9 | from online_util import get_inputs, get_answers, get_tuple_answers 10 | from baiduSpider import get_evidences 11 | 12 | STOP_TAG = "#OOV#" 13 | 14 | class Hyperparameters: 15 | vocab_path = '../char_data/vocabulary.txt' 16 | random_path = '../char_data/training.h5' 17 | #charQA_path = '../model/charQA_2017-08-11/f1-0.5583_0.34799_2' 18 | charQA_path = '../model/lossQA_2017-08-14/f1-0.5698_0.26918_5' 19 | 20 | param = Hyperparameters() 21 | word_set, word2idx, word_set_size = load_vocab(param.vocab_path) 22 | idx2word = dict(zip(word2idx.values(), word2idx.keys())) 23 | 24 | 25 | def random_sample(): 26 | file = h5py.File(param.random_path) 27 | nb_samples = len(file['question'][:]) 28 | 29 | index = random.randint(0, nb_samples-1) 30 | question = file['question'][index] 31 | question = ''.join([ idx2word[q] for q in question if q != 0 ]) 32 | return question 33 | 34 | 35 | class baselineQA(object): 36 | def __init__(self): 37 | self.word_set, self.word2idx, self.word_set_size = word_set, word2idx, word_set_size 38 | self.idx2word = idx2word 39 | self.model = torch.load(param.charQA_path) 40 | 41 | def pred(self, question, pages = 20): 42 | evidences = get_evidences(question, pages) 43 | question, evidence, q_mask, e_mask, q_feat, e_feat = get_inputs(question, evidences, self.word2idx) 44 | #answer = get_answers(self.model, question, evidence, q_mask, e_mask, q_feat, e_feat, self.idx2word) 45 | answer, ans2evid = get_tuple_answers(self.model, question, evidence, q_mask, e_mask, q_feat, e_feat, self.idx2word) 46 | return answer, ans2evid 47 | 48 | 49 | if __name__ == '__main__': 50 | question = '我的前半生中,靳东演的是谁' 51 | model = baselineQA() 52 | p = model.pred(question) 53 | 54 | -------------------------------------------------------------------------------- /online/start_server_stable.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | #import sys 3 | import random 4 | #sys.path.append('../') 5 | from flask import Flask, request, render_template, make_response 6 | from flask_bootstrap import Bootstrap 7 | from flask_wtf import FlaskForm 8 | from flask_moment import Moment 9 | from wtforms.validators import Required 10 | from wtforms import SelectField, TextAreaField, SubmitField 11 | from model_util import baselineQA, random_sample 12 | 13 | app = Flask(__name__) 14 | model = baselineQA() 15 | 16 | bootstrap = Bootstrap(app) 17 | moment = Moment(app) 18 | app.config['SECRET_KEY'] = 'hard to guess string' 19 | 20 | class NnSelected(FlaskForm): 21 | input_question = TextAreaField('',validators=[Required()],render_kw={"rows": 2}) 22 | submit = SubmitField('搜索') 23 | 24 | 25 | @app.route('/', methods=['GET', 'POST']) 26 | def index(): 27 | form = NnSelected() 28 | if form.validate_on_submit(): 29 | print('look') 30 | input_question = form.input_question.data 31 | answers, ans2evid = model.pred(input_question) 32 | 33 | res = [] 34 | for (ans, _) in answers: 35 | for i, e in enumerate(ans2evid[ans]): 36 | ans2evid[ans][i] = str(i+1) + '. ' + e 37 | 38 | evid = '\n\n'.join(ans2evid[ans]) 39 | ans = ans + ' (' + str(_) + ')' 40 | 41 | res.append((ans, evid)) 42 | return render_template('index.html', form = form, res = res ) 43 | else: 44 | print('??') 45 | form.input_question.data = random_sample() 46 | return render_template('index.html', form = form) 47 | 48 | @app.route('/random') 49 | def random_text(): 50 | return random_sample() 51 | 52 | 53 | from werkzeug.contrib.fixers import ProxyFix 54 | app.wsgi_app = ProxyFix(app.wsgi_app) 55 | if __name__ == '__main__': 56 | app.run(debug=0, host='0.0.0.0', port=10001) 57 | 58 | -------------------------------------------------------------------------------- /online/static/css/sticky-footer.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer styles 2 | -------------------------------------------------- */ 3 | html { 4 | position: relative; 5 | min-height: 100%; 6 | } 7 | body { 8 | /* Margin bottom by footer height */ 9 | margin-bottom: 213px; 10 | } 11 | .footer { 12 | position: absolute; 13 | bottom: 0; 14 | /* Set the fixed height of the footer here */ 15 | height: 213px; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /online/static/ipin-logo-gray-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/susht3/webQA_sequence_labelling_pytorch/7a53322b0da1f99dbc90125501daebb866741559/online/static/ipin-logo-gray-bg.png -------------------------------------------------------------------------------- /online/templates/base.html: -------------------------------------------------------------------------------- 1 | {% extends "bootstrap/base.html" %} 2 | 3 | {% block title %}webQA{% endblock %} 4 | 5 | {% block head %} 6 | {{ super() }} 7 | 8 | 9 | 10 | {% endblock %} 11 | 12 | {% block navbar %} 13 |
31 | {% endblock %} 32 | 33 | {% block content %} 34 |