├── LICENSE ├── Models ├── CRF.py ├── ERNIE.py ├── __pycache__ │ ├── CRF.cpython-37.pyc │ └── bert.cpython-37.pyc └── bert.py ├── README.md ├── __init__.py ├── __pycache__ ├── train_eval.cpython-37.pyc └── utils.cpython-37.pyc ├── datas ├── dev │ ├── source.txt │ └── target.txt ├── train │ ├── source.txt │ └── target.txt └── vocab_tag │ ├── tag.txt │ └── vocab.txt ├── pytorch_pretrained ├── __init__.py ├── __main__.py ├── __pycache__ │ ├── __init__.cpython-37.pyc │ ├── file_utils.cpython-37.pyc │ ├── modeling.cpython-37.pyc │ ├── modeling_gpt2.cpython-37.pyc │ ├── modeling_openai.cpython-37.pyc │ ├── modeling_transfo_xl.cpython-37.pyc │ ├── modeling_transfo_xl_utilities.cpython-37.pyc │ ├── optimization.cpython-37.pyc │ ├── optimization_openai.cpython-37.pyc │ ├── tokenization.cpython-37.pyc │ ├── tokenization_gpt2.cpython-37.pyc │ ├── tokenization_openai.cpython-37.pyc │ └── tokenization_transfo_xl.cpython-37.pyc ├── convert_gpt2_checkpoint_to_pytorch.py ├── convert_openai_checkpoint_to_pytorch.py ├── convert_tf_checkpoint_to_pytorch.py ├── convert_transfo_xl_checkpoint_to_pytorch.py ├── file_utils.py ├── modeling.py ├── modeling_gpt2.py ├── modeling_openai.py ├── modeling_transfo_xl.py ├── modeling_transfo_xl_utilities.py ├── optimization.py ├── optimization_openai.py ├── tokenization.py ├── tokenization_gpt2.py ├── tokenization_openai.py └── tokenization_transfo_xl.py ├── run.py ├── train_eval.py └── utils.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 cjhayes16 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 | -------------------------------------------------------------------------------- /Models/CRF.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 5 | 6 | 7 | class CRF(nn.Module): 8 | """线性条件随机场""" 9 | def __init__(self, num_tag): 10 | if num_tag <= 0: 11 | raise ValueError("Invalid value of num_tag: %d" % num_tag) 12 | super(CRF, self).__init__() 13 | self.num_tag = num_tag 14 | self.start_tag = num_tag 15 | self.end_tag = num_tag + 1 16 | # 转移矩阵transitions:P_jk 表示从tag_j到tag_k的概率 17 | # P_j* 表示所有从tag_j出发的边 18 | # P_*k 表示所有到tag_k的边 19 | self.transitions = nn.Parameter(torch.Tensor(num_tag + 2, num_tag + 2)) 20 | nn.init.uniform_(self.transitions, -0.1, 0.1) 21 | self.transitions.data[self.end_tag, :] = -10000 # 表示从EOS->其他标签为不可能事件, 如果发生,则产生一个极大的损失 22 | self.transitions.data[:, self.start_tag] = -10000 # 表示从其他标签->SOS为不可能事件, 同上 23 | 24 | def real_path_score(self, features, tags): 25 | """ 26 | features: (seq_len, num_tag) 27 | tags:real tags 28 | real_path_score表示真实路径分数 29 | 它由Emission score和Transition score两部分相加组成 30 | Emission score由LSTM输出结合真实的tag决定,表示我们希望由输出得到真实的标签 31 | Transition score则是crf层需要进行训练的参数,它是随机初始化的,表示标签序列前后间的约束关系(转移概率) 32 | Transition矩阵存储的是标签序列相互间的约束关系 33 | 在训练的过程中,希望real_path_score最高,因为这是所有路径中最可能的路径 34 | """ 35 | r = torch.LongTensor(range(features.size(0))) 36 | r = r.to(DEVICE) 37 | pad_start_tags = torch.cat([torch.LongTensor([self.start_tag]).to(DEVICE), tags]) 38 | pad_stop_tags = torch.cat([tags, torch.LongTensor([self.end_tag]).to(DEVICE)]) 39 | # Transition score + Emission score 40 | score = torch.sum(self.transitions[pad_start_tags, pad_stop_tags]) + torch.sum(features[r, tags]) 41 | return score 42 | 43 | def all_possible_path_score(self, features): 44 | """ 45 | features (seq_len, num_tag) 46 | 计算所有可能的路径分数的log和:前向算法 47 | step1: 将forward列expand成3*3 48 | step2: 将下个单词的emission行expand成3*3 49 | step3: 将1和2和对应位置的转移矩阵相加 50 | step4: 更新forward,合并行 51 | step5: 取forward指数的对数计算total 52 | """ 53 | time_steps = features.size(0) 54 | # 初始化 55 | forward = torch.zeros(self.num_tag) # 初始化START_TAG的发射分数为0 56 | forward = forward.to(DEVICE) 57 | 58 | for i in range(0, time_steps): # START_TAG -> 1st word -> 2nd word ->...->END_TAG 59 | emission_start = forward.expand(self.num_tag, self.num_tag).t() 60 | emission_end = features[i,:].expand(self.num_tag, self.num_tag) 61 | if i == 0: 62 | trans_score = self.transitions[self.start_tag, :self.start_tag] 63 | else: 64 | trans_score = self.transitions[:self.start_tag, :self.start_tag] 65 | sum = emission_start + emission_end + trans_score 66 | forward = log_sum(sum, dim=0) 67 | forward = forward + self.transitions[:self.start_tag, self.end_tag] # END_TAG 68 | total_score = log_sum(forward, dim=0) 69 | return total_score 70 | 71 | def negative_log_loss(self, inputs, output_mask, tags): 72 | """ 73 | inputs:(batch_size, seq_len, num_tag) 74 | output_mask:(batch_size, seq_len) 75 | tags:(batch_size, seq_len) # tags中不包括[CLS]和[SEP] 76 | target_function = P_real_path_score/P_all_possible_path_score 77 | = exp(S_real_path_score)/ sum(exp(certain_path_score)) 78 | 我们希望P_real_path_score的概率越高越好,即target_function的值越大越好 79 | 因此,loss_function取其相反数,越小越好,其实是负对数似然 80 | loss_function = -log(target_function) 81 | = -S_real_path_score + log(exp(S_1 + exp(S_2) + exp(S_3) + ...)) 82 | = -S_real_path_score + log(all_possible_path_score) 83 | """ 84 | loss = torch.tensor(0.,requires_grad=True).to(DEVICE) 85 | num_tag = inputs.size(2)#序列length 86 | num_chars = torch.sum(output_mask.detach()).float() #tag的token的个数 87 | for ix, (features, tag) in enumerate(zip(inputs, tags)): 88 | # 过滤[CLS] [SEP] 89 | # features (seq_len, num_tag) 90 | # output_mask (batch_size, seq_len) 91 | # tag: seq_len 92 | num_valid = torch.sum(output_mask[ix].detach()) 93 | features = features[output_mask[ix]==1] 94 | tag = tag[:num_valid] 95 | real_score = self.real_path_score(features, tag) 96 | total_score = self.all_possible_path_score(features) 97 | cost = total_score - real_score 98 | loss = loss + cost 99 | return loss/num_chars 100 | 101 | def viterbi(self, features): 102 | time_steps = features.size(0) 103 | forward = torch.zeros(self.num_tag) # START_TAG 104 | forward = forward.to(DEVICE) 105 | # back_points 到该点的最大分数 last_points 前一个点的索引 106 | back_points, index_points = [self.transitions[self.start_tag, :self.start_tag].to(DEVICE)], [torch.LongTensor([-1]).expand_as(forward).to(DEVICE)] 107 | for i in range(1, time_steps): # START_TAG -> 1st word -> 2nd word ->...->END_TAG 108 | emission_start = forward.expand(self.num_tag, self.num_tag).t() 109 | emission_end = features[i,:].expand(self.num_tag, self.num_tag) 110 | trans_score = self.transitions[:self.start_tag, :self.start_tag] 111 | sum = emission_start + emission_end + trans_score 112 | forward, index = torch.max(sum.detach(), dim=0) 113 | back_points.append(forward) 114 | index_points.append(index) 115 | back_points.append(forward + self.transitions[:self.start_tag, self.end_tag].to(DEVICE)) # END_TAG 116 | return back_points, index_points 117 | 118 | def get_best_path(self, features): 119 | back_points, index_points = self.viterbi(features) 120 | # 找到线头 121 | best_last_point = argmax(back_points[-1]) 122 | index_points = torch.stack(index_points) # 堆成矩阵 123 | m = index_points.size(0) 124 | # 初始化矩阵 125 | best_path = [best_last_point] 126 | # 循着线头找到其对应的最佳路径 127 | for i in range(m-1, 0, -1): 128 | best_index_point = index_points[i][best_last_point] 129 | best_path.append(best_index_point) 130 | best_last_point = best_index_point 131 | best_path.reverse() 132 | return best_path 133 | 134 | def get_batch_best_path(self, inputs, output_mask): 135 | 136 | batch_best_path = [] 137 | max_len = inputs.size(1) 138 | num_tag = inputs.size(2) 139 | for ix, features in enumerate(inputs): 140 | features = features[output_mask[ix]==1] 141 | best_path = self.get_best_path(features) 142 | best_path = torch.Tensor(best_path).long() 143 | best_path = padding(best_path, max_len) 144 | batch_best_path.append(best_path) 145 | batch_best_path = torch.stack(batch_best_path, dim=0) 146 | return batch_best_path 147 | 148 | def log_sum(matrix, dim): 149 | """ 150 | 前向算法是不断累积之前的结果,这样就会有个缺点 151 | 指数和累积到一定程度后,会超过计算机浮点值的最大值,变成inf,这样取log后也是inf 152 | 为了避免这种情况,我们做了改动: 153 | 1. 用一个合适的值clip去提指数和的公因子,这样就不会使某项变得过大而无法计算 154 | SUM = log(exp(s1)+exp(s2)+...+exp(s100)) 155 | = log{exp(clip)*[exp(s1-clip)+exp(s2-clip)+...+exp(s100-clip)]} 156 | = clip + log[exp(s1-clip)+exp(s2-clip)+...+exp(s100-clip)] 157 | where clip=max 158 | """ 159 | clip_value = torch.max(matrix) # 极大值 160 | clip_value = int(clip_value.data.tolist()) 161 | log_sum_value = clip_value + torch.log(torch.sum(torch.exp(matrix-clip_value), dim=dim)) 162 | return log_sum_value 163 | 164 | def argmax(matrix, dim=0): 165 | """(0.5, 0.4, 0.3)""" 166 | _, index = torch.max(matrix, dim=dim) 167 | return index 168 | 169 | def padding(vec, max_len, pad_token=-1): 170 | new_vec = torch.zeros(max_len).long() 171 | new_vec[:vec.size(0)] = vec 172 | new_vec[vec.size(0):] = pad_token 173 | return new_vec 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /Models/ERNIE.py: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | import torch 3 | import torch.nn as nn 4 | from sklearn.metrics import f1_score, classification_report 5 | import numpy as np 6 | from pytorch_pretrained import BertModel, BertTokenizer 7 | from torch.autograd import Variable 8 | from .CRF import * 9 | 10 | 11 | class Config(object): 12 | """配置参数""" 13 | 14 | def __init__(self): 15 | self.model_name = 'Bert_Bilstm_crf' 16 | 17 | self.train_data_path = './datas/train/source.txt' # 文本训练集 18 | self.train_label_path = './datas/train/target.txt' # 标签训练集 19 | self.dev_data_path = './datas/dev/source.txt' # 文本验证集 20 | self.dev_label_path = './datas/dev/target.txt' # 标签验证集 21 | self.save_path = './Result/Save_path/' + self.model_name + '.ckpt' # 模型训练结果 22 | self.bert_path = './bert_pretrain' 23 | 24 | self.tokenizer = BertTokenizer.from_pretrained('./bert_pretrain') 25 | self.tokenizer = BertTokenizer.from_pretrained(self.bert_path) 26 | 27 | self.vocab_class = {'B_T': 0, 'I_T': 1, 'B_LOC': 2, 'I_LOC': 3, 'B_ORG': 4, 28 | 'I_ORG': 5, 'B_PER': 6, 'I_PER': 7, 'O': 8} # 词性类别名单 29 | self.tagset_size = len(self.vocab_class) 30 | self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设备 31 | 32 | self.num_epochs = 6 # epoch数 33 | self.batch_size = 20 34 | self.pad_size = 100 # 每句话处理成的长度(短填长切) 35 | self.learning_rate = 5e-5 # 学习率 36 | self.learning_rate_decay = 5e-6 # 学习率衰减 37 | self.hidden_size = 128 38 | self.embedding_dim = 768 39 | self.num_layers = 1 40 | self.dropout = 0.5 41 | 42 | 43 | class Model(nn.Module): 44 | 45 | def __init__(self, config): 46 | super(Model, self).__init__() 47 | self.embedding_dim = config.embedding_dim 48 | self.num_layers = config.num_layers 49 | self.hidden_size = config.hidden_size 50 | self.device=config.device 51 | 52 | self.bert = BertModel.from_pretrained(config.bert_path) 53 | self.lstm = nn.LSTM(config.embedding_dim, config.hidden_size, num_layers=config.num_layers, 54 | bidirectional=True, dropout=config.dropout,batch_first=True) 55 | self.dropout = nn.Dropout(config.dropout) 56 | self.crf = CRF(config.tagset_size) 57 | self.fc = nn.Linear(config.hidden_size * 2, config.tagset_size) 58 | 59 | def init_hidden(self, batch_size): 60 | return torch.randn(2 * self.num_layers, batch_size, self.hidden_size).to(self.device),torch.randn(2 * self.num_layers, batch_size, self.hidden_size).to(self.device) 61 | 62 | def forward(self, input): 63 | context = input[0] # 输入的句子 64 | mask = input[1] 65 | batch_size = context.size(0) 66 | seq_len = context.size(1) 67 | with torch.no_grad(): 68 | embeds, _ = self.bert(context, attention_mask=mask, output_all_encoded_layers=False) 69 | hidden = self.init_hidden(batch_size=batch_size) 70 | out, hidden = self.lstm(embeds, hidden) 71 | out = out.contiguous().view(-1, self.hidden_size * 2) 72 | out = self.dropout(out) 73 | out = self.fc(out) 74 | out = out.contiguous().view(batch_size, seq_len, -1) 75 | return out 76 | 77 | def loss(self, features, mask, label): 78 | loss_value = self.crf.negative_log_loss(features, mask, label) 79 | batch_size = features.size(0) 80 | loss_value /= float(batch_size) 81 | return loss_value 82 | 83 | def predict(self, bert_encode, output_mask): 84 | predicts = self.crf.get_batch_best_path(bert_encode, output_mask) 85 | return predicts 86 | 87 | def acc_f1(self, y_pred, y_true): 88 | y_pred = y_pred.cpu().numpy() 89 | y_true = y_true.cpu().numpy() 90 | f1 = f1_score(y_true, y_pred, average="macro") 91 | correct = np.sum((y_true == y_pred).astype(int)) 92 | acc = correct / y_pred.shape[0] 93 | print('acc: {}'.format(acc)) 94 | print('f1: {}'.format(f1)) 95 | return acc, f1 96 | 97 | def class_report(self, y_pred, y_true): 98 | y_true = y_true.cpu().numpy() 99 | y_pred = y_pred.cpu().numpy() 100 | classify_report = classification_report(y_true, y_pred) 101 | print('\n\nclassify_report:\n', classify_report) 102 | -------------------------------------------------------------------------------- /Models/__pycache__/CRF.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/Models/__pycache__/CRF.cpython-37.pyc -------------------------------------------------------------------------------- /Models/__pycache__/bert.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/Models/__pycache__/bert.cpython-37.pyc -------------------------------------------------------------------------------- /Models/bert.py: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | import torch 3 | import torch.nn as nn 4 | from sklearn.metrics import f1_score, classification_report 5 | import numpy as np 6 | from pytorch_pretrained import BertModel, BertTokenizer 7 | from torch.autograd import Variable 8 | from .CRF import * 9 | 10 | 11 | class Config(object): 12 | """配置参数""" 13 | 14 | def __init__(self): 15 | self.model_name = 'Bert_Bilstm_crf' 16 | 17 | self.train_data_path = './datas/train/source.txt' # 文本训练集 18 | self.train_label_path = './datas/train/target.txt' # 标签训练集 19 | self.dev_data_path = './datas/dev/source.txt' # 文本验证集 20 | self.dev_label_path = './datas/dev/target.txt' # 标签验证集 21 | self.save_path = './Result/Save_path/' + self.model_name + '.ckpt' # 模型训练结果 22 | self.bert_path = './bert_pretrain' 23 | 24 | self.tokenizer = BertTokenizer.from_pretrained('./bert_pretrain') 25 | self.tokenizer = BertTokenizer.from_pretrained(self.bert_path) 26 | 27 | self.vocab_class = {'B_T': 0, 'I_T': 1, 'B_LOC': 2, 'I_LOC': 3, 'B_ORG': 4, 28 | 'I_ORG': 5, 'B_PER': 6, 'I_PER': 7, 'O': 8} # 词性类别名单 29 | self.tagset_size = len(self.vocab_class) 30 | self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设备 31 | 32 | self.num_epochs = 6 # epoch数 33 | self.batch_size = 20 34 | self.pad_size = 100 # 每句话处理成的长度(短填长切) 35 | self.learning_rate = 5e-5 # 学习率 36 | self.learning_rate_decay = 5e-6 # 学习率衰减 37 | self.hidden_size = 128 38 | self.embedding_dim = 768 39 | self.num_layers = 1 40 | self.dropout = 0.5 41 | 42 | 43 | class Model(nn.Module): 44 | 45 | def __init__(self, config): 46 | super(Model, self).__init__() 47 | self.embedding_dim = config.embedding_dim 48 | self.num_layers = config.num_layers 49 | self.hidden_size = config.hidden_size 50 | self.device=config.device 51 | 52 | self.bert = BertModel.from_pretrained(config.bert_path) 53 | self.lstm = nn.LSTM(config.embedding_dim, config.hidden_size, num_layers=config.num_layers, 54 | bidirectional=True, dropout=config.dropout,batch_first=True) 55 | self.dropout = nn.Dropout(config.dropout) 56 | self.crf = CRF(config.tagset_size) 57 | self.fc = nn.Linear(config.hidden_size * 2, config.tagset_size) 58 | 59 | def init_hidden(self, batch_size): 60 | return torch.randn(2 * self.num_layers, batch_size, self.hidden_size).to(self.device),torch.randn(2 * self.num_layers, batch_size, self.hidden_size).to(self.device) 61 | 62 | def forward(self, input): 63 | context = input[0] # 输入的句子 64 | mask = input[1] 65 | batch_size = context.size(0) 66 | seq_len = context.size(1) 67 | with torch.no_grad(): 68 | embeds, _ = self.bert(context, attention_mask=mask, output_all_encoded_layers=False) 69 | hidden = self.init_hidden(batch_size=batch_size) 70 | out, hidden = self.lstm(embeds, hidden) 71 | out = out.contiguous().view(-1, self.hidden_size * 2) 72 | out = self.dropout(out) 73 | out = self.fc(out) 74 | out = out.contiguous().view(batch_size, seq_len, -1) 75 | return out 76 | 77 | def loss(self, features, mask, label): 78 | loss_value = self.crf.negative_log_loss(features, mask, label) 79 | batch_size = features.size(0) 80 | loss_value /= float(batch_size) 81 | return loss_value 82 | 83 | def predict(self, bert_encode, output_mask): 84 | predicts = self.crf.get_batch_best_path(bert_encode, output_mask) 85 | return predicts 86 | 87 | def acc_f1(self, y_pred, y_true): 88 | y_pred = y_pred.cpu().numpy() 89 | y_true = y_true.cpu().numpy() 90 | f1 = f1_score(y_true, y_pred, average="macro") 91 | correct = np.sum((y_true == y_pred).astype(int)) 92 | acc = correct / y_pred.shape[0] 93 | print('acc: {}'.format(acc)) 94 | print('f1: {}'.format(f1)) 95 | return acc, f1 96 | 97 | def class_report(self, y_pred, y_true): 98 | y_true = y_true.cpu().numpy() 99 | y_pred = y_pred.cpu().numpy() 100 | classify_report = classification_report(y_true, y_pred) 101 | print('\n\nclassify_report:\n', classify_report) 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chinese-Ner-pytorch 2 | 中文实体识别 bert/xlnet/albert ...预训练模型 +bilstm+crf / +crf 3 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/__init__.py -------------------------------------------------------------------------------- /__pycache__/train_eval.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/__pycache__/train_eval.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/utils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/__pycache__/utils.cpython-37.pyc -------------------------------------------------------------------------------- /datas/dev/source.txt: -------------------------------------------------------------------------------- 1 | 比 赛 中 李 娜 开 局 略 显 慢 热 , 首 盘 比 赛 双 方 展 开 苦 战 , 李 娜 直 到 第 1 2 局 才 完 成 关 键 破 发 以 7 : 5 先 胜 一 盘 , 第 二 盘 李 娜 逐 渐 控 制 了 局 面 , 最 终 以 6 : 3 锁 定 胜 局 。 凭 借 这 场 胜 利 , 李 娜 将 与 兹 沃 娜 列 娃 的 交 锋 纪 录 改 写 为 4 胜 4 负 , 成 功 迈 出 了 卫 冕 的 第 一 步 。 2 | “ 第 一 场 比 赛 都 是 比 较 艰 难 的 , 说 老 实 话 , 不 知 道 自 己 在 场 上 发 生 什 么 状 况 , 因 为 已 经 有 快 2 个 月 没 有 正 式 比 赛 。 今 天 自 己 表 现 得 还 不 错 , 来 这 边 的 时 候 一 直 找 不 到 感 觉 , 因 为 在 北 京 冬 训 时 一 直 是 室 内 练 习 , 总 体 来 说 很 满 意 。 ” 对 于 新 赛 季 首 秀 , 李 娜 这 样 评 价 。 3 | 据 李 娜 介 绍 , 新 赛 季 自 己 的 选 赛 和 去 年 一 样 , 计 划 参 加 1 5 站 比 赛 。 4 | 私 人 订 制 卫 冕 遇 “ 头 彩 ” 5 | 作 为 深 圳 公 开 赛 的 卫 冕 冠 军 , 李 娜 在 深 圳 的 生 活 非 常 愉 快 。 2 0 1 3 年 1 2 月 2 6 日 上 午 , 刚 刚 抵 达 深 圳 的 李 娜 就 收 获 了 一 份 大 礼 — — 一 套 “ 私 人 订 制 ” 的 彩 票 。 6 | 此 次 深 圳 公 开 赛 的 官 方 赞 助 商 之 一 , 5 0 0 彩 票 网 董 事 长 兼 C E O 罗 昭 行 送 给 了 李 娜 一 套 私 人 订 制 的 彩 票 , 据 赛 事 方 介 绍 , 李 娜 获 赠 的 彩 票 彩 种 是 体 育 彩 票 “ 大 乐 透 ” , 号 码 是 “ 0 6 、 1 7 、 2 4 、 2 9 、 3 1 丨 0 1 、 0 3 ” , 每 一 个 数 字 对 李 娜 来 讲 , 都 有 特 殊 含 义 : “ 6 ” 岁 的 李 娜 初 次 接 触 网 球 ; “ 1 7 ” 岁 便 成 为 职 业 选 手 ; “ 2 4 ” 岁 结 婚 ; “ 2 9 ” 岁 成 为 第 一 位 获 得 大 满 贯 赛 事 冠 军 的 亚 洲 人 ; 如 今 世 界 排 名 第 “ 3 ” 的 李 娜 , 要 在 自 己 “ 3 1 ” 岁 的 时 候 全 力 卫 冕 深 网 公 开 赛 第 “ 1 ” 并 争 取 年 终 世 界 排 名 第 “ 1 ” 。 7 | 用 彩 票 的 语 言 , 来 浓 缩 李 娜 的 部 分 职 业 生 涯 并 和 配 上 美 好 的 祝 福 , 独 具 匠 心 的 设 计 , 让 李 娜 颇 感 惊 奇 , 接 连 询 问 何 时 开 奖 、 最 高 奖 金 是 多 少 … … 在 得 知 彩 票 最 高 可 以 中 得 1 5 0 0 万 之 后 , 李 娜 开 玩 笑 道 : “ 那 太 好 了 , 中 了 我 就 不 打 球 了 。 ” 8 | N B A 常 规 赛 继 续 进 行 , 火 箭 主 场 迎 战 国 王 。 本 场 比 赛 , 哈 登 交 出 3 8 分 1 0 篮 板 2 抢 断 的 华 丽 数 据 , 但 却 在 关 键 时 刻 连 续 出 现 两 次 失 误 。 最 终 , 火 箭 以 1 0 6 - 1 1 0 惜 败 对 手 。 四 节 具 体 比 分 为 : 2 9 - 2 4 、 2 9 - 2 8 、 2 2 - 3 4 、 3 0 - 2 0 ( 国 王 在 前 ) 。 9 | 数 据 方 面 , 火 箭 队 林 书 豪 得 到 1 4 分 6 助 攻 2 抢 断 , 霍 华 德 1 5 分 8 篮 板 2 助 攻 , 其 中 第 二 节 独 得 1 3 分 ; 帕 森 斯 1 3 分 5 篮 板 , 琼 斯 1 2 分 1 1 篮 板 2 抢 断 4 盖 帽 。 10 | 国 王 全 队 6 人 得 分 上 双 , 考 辛 斯 全 场 贡 献 1 7 分 1 6 篮 板 4 抢 断 , 关 键 时 刻 连 续 两 个 进 球 外 加 助 攻 队 友 得 分 帮 助 球 队 在 最 后 时 刻 实 现 反 超 。 盖 伊 2 5 分 6 篮 板 , 小 托 马 斯 1 7 分 1 0 助 攻 , 索 顿 1 5 分 , 新 秀 麦 克 勒 摩 1 3 分 4 篮 板 3 助 攻 。 11 | 双 方 首 发 阵 容 : 12 | 国 王 : 汤 普 森 、 盖 伊 、 考 辛 斯 、 托 马 斯 、 麦 克 勒 摩 13 | 火 箭 : 霍 华 德 、 琼 斯 、 帕 森 斯 、 林 书 豪 、 哈 登 14 | 原 标 题 : 专 家 回 应 被 窝 里 玩 手 机 致 盲 : 无 依 据 全 是 废 话 15 | 如 今 越 来 越 多 的 人 在 生 活 中 “ 机 不 离 手 ” , 甚 至 熄 灯 临 睡 前 还 要 摸 黑 儿 玩 手 机 。 然 而 近 日 有 网 友 发 微 博 称 , 由 于 长 期 睡 前 关 灯 看 手 机 , 竟 遭 遇 短 暂 “ 失 明 ” 。 对 此 , 眼 科 专 家 表 示 , 黑 暗 中 玩 手 机 致 盲 一 说 言 过 其 实 , 但 这 的 确 是 不 健 康 的 生 活 习 惯 , 易 导 致 视 疲 劳 , 提 醒 大 家 夜 间 使 用 手 机 可 在 床 边 开 盏 灯 , 并 适 当 调 低 手 机 屏 幕 亮 度 。 16 | 网 友 吐 槽 17 | 睡 前 玩 手 机 眼 睛 险 失 明 18 | 近 日 , “ 黑 暗 中 玩 手 机 易 失 明 ” 的 消 息 在 网 上 以 及 微 信 朋 友 圈 上 一 出 , 引 发 广 泛 关 注 , 很 多 “ 手 机 党 ” 、 “ 微 博 控 ” 不 禁 为 视 力 担 忧 , 临 睡 前 躺 在 被 窝 里 刷 微 博 、 玩 游 戏 、 看 电 影 已 经 成 了 他 们 的 日 常 习 惯 之 一 。 19 | “ 游 戏 迷 ” 鲍 女 士 就 曾 因 为 常 常 半 夜 关 灯 打 游 戏 , 导 致 视 力 出 现 问 题 。 她 告 诉 北 京 晨 报 记 者 , “ 那 晚 我 像 往 常 一 样 黑 着 灯 、 躺 床 上 玩 游 戏 , 那 是 一 款 考 察 眼 力 的 智 力 游 戏 , 需 要 特 别 仔 细 盯 着 屏 幕 才 能 打 通 关 。 可 玩 着 玩 着 , 我 突 然 感 觉 右 眼 看 东 西 模 糊 起 来 。 当 时 还 以 为 是 自 己 忘 了 摘 隐 形 , 可 后 来 发 现 已 经 摘 了 , 我 这 才 意 识 到 右 眼 是 ‘ 看 不 见 ’ 了 。 可 把 我 吓 坏 了 , 赶 紧 关 机 睡 觉 。 第 二 天 一 觉 醒 来 , 视 力 就 恢 复 正 常 了 。 ” 经 历 过 这 次 教 训 后 , 鲍 女 士 再 不 敢 在 晚 上 长 时 间 玩 手 机 了 。 20 | 大 部 分 网 友 在 采 访 中 表 示 , 晚 上 在 黑 暗 中 玩 手 机 时 间 一 久 , 常 感 到 眼 睛 发 酸 发 胀 , 个 别 网 友 的 视 力 还 急 剧 下 降 、 近 视 加 深 。 “ 手 机 屏 幕 相 对 较 小 、 注 意 力 又 要 长 时 间 高 度 集 中 在 一 个 发 光 屏 上 , 眼 睛 肯 定 会 不 舒 服 。 ” 网 友 范 先 生 告 诉 记 者 , “ 我 和 身 边 朋 友 都 有 过 玩 手 机 时 间 稍 长 眼 睛 就 会 出 现 重 影 的 情 况 , 要 过 很 久 才 能 恢 复 。 ” 21 | 专 家 说 法 22 | 致 盲 无 依 据 用 眼 需 适 度 23 | 关 灯 后 在 黑 暗 中 玩 手 机 , 真 的 会 产 生 这 么 大 的 危 害 吗 ? 记 者 就 此 咨 询 了 中 国 中 医 科 学 院 眼 科 医 院 视 网 膜 科 巢 国 俊 主 任 , 他 表 示 “ 黑 暗 中 玩 手 机 致 盲 ” 这 种 说 法 目 前 缺 乏 相 关 科 学 依 据 , “ 眼 睛 突 然 看 不 见 了 , 多 半 是 视 网 膜 动 脉 痉 挛 发 生 供 血 不 足 所 造 成 。 不 过 暂 时 性 ‘ 失 明 ’ 的 情 况 在 爱 玩 手 机 的 人 中 还 是 比 较 普 遍 的 , 只 要 日 后 加 强 注 意 , 不 要 过 度 用 眼 , 应 该 就 不 会 再 出 现 了 。 ” 巢 主 任 表 示 , 长 期 入 睡 前 关 灯 玩 手 机 是 一 种 不 良 习 惯 , 对 视 力 会 有 一 定 影 响 , 眼 睛 容 易 干 涩 酸 胀 , 易 引 起 眼 部 的 疲 劳 。 24 | [ 北 京 德 胜 门 中 医 院 眼 科 专 家 提 醒 广 大 网 友 , 平 时 尽 量 不 要 过 度 使 用 电 子 设 备 , 使 用 半 小 时 需 要 休 息 一 下 。 “ 若 要 在 夜 间 使 用 手 机 , 可 以 选 择 在 旁 边 开 盏 低 亮 度 的 背 景 灯 , 以 减 少 亮 光 对 眼 睛 的 刺 激 。 或 者 调 整 手 机 屏 幕 的 对 比 度 , 使 亮 度 和 色 泽 尽 量 柔 和 些 , 这 样 可 以 适 当 降 低 眼 睛 的 负 荷 。 ” 25 | 记 者 樊 一 婧 26 | 线 索 : 辰 先 生 27 | 饮 食 注 重 营 养 搭 配 本 是 健 康 生 活 的 好 习 惯 , 可 近 来 网 上 流 传 的 一 些 所 谓 “ 食 物 搭 配 禁 忌 ” 却 搞 得 人 一 头 雾 水 , 比 如 “ 菠 菜 与 豆 腐 不 能 同 吃 ” 、 “ 牛 奶 不 能 和 鸡 蛋 一 起 煮 ” 、 “ 螃 蟹 和 柿 子 一 起 吃 会 中 毒 腹 泻 ” 等 , 恍 惚 间 人 们 都 不 敢 吃 了 。 记 者 近 日 在 丰 台 洋 桥 采 访 市 民 丁 女 士 , 她 说 家 里 厨 房 墙 壁 上 贴 着 一 张 “ 食 用 相 克 ” 表 , 时 刻 提 醒 自 己 不 要 “ 放 错 菜 ” 。 28 | 记 者 根 据 市 民 流 传 的 版 本 , 整 理 出 一 份 “ 食 物 相 克 ” 表 , 请 教 食 品 营 养 学 界 的 专 家 , 发 现 不 少 “ 常 识 ” 都 是 谬 误 。 29 | 误 解 1 菠 菜 豆 腐 忌 同 食 30 | 有 人 认 为 , 菠 菜 中 含 有 草 酸 , 它 和 钙 结 合 形 成 沉 淀 , 会 引 起 肾 结 石 。 因 此 菠 菜 不 能 和 豆 腐 同 吃 。 同 理 , 小 葱 也 不 能 拌 豆 腐 。 31 | [ 中 国 农 业 大 学 食 品 学 院 副 教 授 范 志 红 否 定 了 这 种 说 法 。 她 介 绍 , 草 酸 是 一 种 植 物 当 中 广 泛 存 在 的 物 质 , 苋 菜 、 菠 菜 等 叶 菜 的 草 酸 含 量 较 高 , 而 瓜 类 蔬 菜 的 草 酸 含 量 相 当 低 。 范 志 红 表 示 , 食 物 中 的 草 酸 被 吸 收 后 , 确 实 会 增 加 肾 结 石 的 危 险 。 但 现 代 膳 食 中 , 人 们 的 蔬 菜 摄 入 量 在 减 少 , 一 般 数 量 的 草 酸 摄 入 不 至 于 引 起 结 石 问 题 。 更 重 要 的 是 , 调 查 发 现 钙 摄 入 量 与 肾 结 石 的 发 生 率 呈 现 负 相 关 , 即 钙 摄 入 量 越 高 , 结 石 发 生 率 越 低 。 因 此 市 民 应 当 在 吃 蔬 菜 时 多 吃 豆 制 品 、 奶 类 等 富 含 钙 的 食 物 , 让 草 酸 和 钙 结 合 沉 淀 , 以 减 少 草 酸 的 吸 收 , 降 低 结 石 发 生 的 概 率 。 32 | 误 解 2 牛 奶 鸡 蛋 不 同 煮 33 | 许 多 人 认 为 : 牛 奶 中 含 有 碳 酸 盐 , 鸡 蛋 黄 中 含 有 铁 , 这 两 种 物 质 结 合 在 一 起 可 生 成 不 易 吸 收 的 磷 酸 铁 。 时 间 一 长 , 会 出 现 缺 铁 性 贫 血 , 临 床 上 称 作 “ 牛 奶 鸡 蛋 贫 血 症 ” 。 34 | 范 志 红 表 示 , “ 碳 酸 盐 和 铁 结 合 成 为 不 容 易 吸 收 的 磷 酸 铁 ” 显 然 不 科 学 。 牛 奶 中 富 含 的 是 钙 、 磷 、 钾 元 素 , 而 并 没 有 什 么 “ 碳 酸 盐 ” 。 鸡 蛋 黄 中 富 含 铁 , 但 是 蛋 黄 中 的 高 磷 蛋 白 就 会 与 铁 结 合 , 妨 碍 它 的 吸 收 , 因 此 鸡 蛋 本 身 并 不 是 一 种 提 供 铁 的 好 食 品 。 无 论 是 否 遇 到 牛 奶 , 用 鸡 蛋 来 补 铁 都 不 理 想 。 如 果 真 想 补 铁 , 大 可 不 必 和 牛 奶 、 鸡 蛋 过 意 不 去 。 牛 奶 是 典 型 的 贫 铁 食 品 , 而 鸡 蛋 是 典 型 的 低 铁 吸 收 率 食 品 。 只 要 吃 些 富 含 血 红 素 铁 的 红 肉 和 内 脏 类 以 及 富 含 维 生 素 C 帮 助 铁 吸 收 的 蔬 菜 水 果 类 , 就 能 解 决 补 铁 问 题 。 只 要 膳 食 中 有 足 够 的 富 铁 食 品 , 即 便 每 天 吃 牛 奶 煮 鸡 蛋 , 也 不 会 患 上 “ 牛 奶 鸡 蛋 贫 血 症 ” 。 35 | 饮 食 注 重 营 养 搭 配 本 是 健 康 生 活 的 好 习 惯 , 可 近 来 网 上 流 传 的 一 些 所 谓 “ 食 物 搭 配 禁 忌 ” 却 搞 得 人 一 头 雾 水 , 比 如 “ 菠 菜 与 豆 腐 不 能 同 吃 ” 、 “ 牛 奶 不 能 和 鸡 蛋 一 起 煮 ” 、 “ 螃 蟹 和 柿 子 一 起 吃 会 中 毒 腹 泻 ” 等 , 恍 惚 间 人 们 都 不 敢 吃 了 。 记 者 近 日 在 丰 台 洋 桥 采 访 市 民 丁 女 士 , 她 说 家 里 厨 房 墙 壁 上 贴 着 一 张 “ 食 用 相 克 ” 表 , 时 刻 提 醒 自 己 不 要 “ 放 错 菜 ” 。 36 | 记 者 根 据 市 民 流 传 的 版 本 , 整 理 出 一 份 “ 食 物 相 克 ” 表 , 请 教 食 品 营 养 学 界 的 专 家 , 发 现 不 少 “ 常 识 ” 都 是 谬 误 。 37 | 误 解 1 菠 菜 豆 腐 忌 同 食 38 | 有 人 认 为 , 菠 菜 中 含 有 草 酸 , 它 和 钙 结 合 形 成 沉 淀 , 会 引 起 肾 结 石 。 因 此 菠 菜 不 能 和 豆 腐 同 吃 。 同 理 , 小 葱 也 不 能 拌 豆 腐 。 39 | [ 中 国 农 业 大 学 食 品 学 院 副 教 授 范 志 红 否 定 了 这 种 说 法 。 她 介 绍 , 草 酸 是 一 种 植 物 当 中 广 泛 存 在 的 物 质 , 苋 菜 、 菠 菜 等 叶 菜 的 草 酸 含 量 较 高 , 而 瓜 类 蔬 菜 的 草 酸 含 量 相 当 低 。 范 志 红 表 示 , 食 物 中 的 草 酸 被 吸 收 后 , 确 实 会 增 加 肾 结 石 的 危 险 。 但 现 代 膳 食 中 , 人 们 的 蔬 菜 摄 入 量 在 减 少 , 一 般 数 量 的 草 酸 摄 入 不 至 于 引 起 结 石 问 题 。 更 重 要 的 是 , 调 查 发 现 钙 摄 入 量 与 肾 结 石 的 发 生 率 呈 现 负 相 关 , 即 钙 摄 入 量 越 高 , 结 石 发 生 率 越 低 。 因 此 市 民 应 当 在 吃 蔬 菜 时 多 吃 豆 制 品 、 奶 类 等 富 含 钙 的 食 物 , 让 草 酸 和 钙 结 合 沉 淀 , 以 减 少 草 酸 的 吸 收 , 降 低 结 石 发 生 的 概 率 。 40 | 误 解 2 牛 奶 鸡 蛋 不 同 煮 41 | 许 多 人 认 为 : 牛 奶 中 含 有 碳 酸 盐 , 鸡 蛋 黄 中 含 有 铁 , 这 两 种 物 质 结 合 在 一 起 可 生 成 不 易 吸 收 的 磷 酸 铁 。 时 间 一 长 , 会 出 现 缺 铁 性 贫 血 , 临 床 上 称 作 “ 牛 奶 鸡 蛋 贫 血 症 ” 。 42 | 范 志 红 表 示 , “ 碳 酸 盐 和 铁 结 合 成 为 不 容 易 吸 收 的 磷 酸 铁 ” 显 然 不 科 学 。 牛 奶 中 富 含 的 是 钙 、 磷 、 钾 元 素 , 而 并 没 有 什 么 “ 碳 酸 盐 ” 。 鸡 蛋 黄 中 富 含 铁 , 但 是 蛋 黄 中 的 高 磷 蛋 白 就 会 与 铁 结 合 , 妨 碍 它 的 吸 收 , 因 此 鸡 蛋 本 身 并 不 是 一 种 提 供 铁 的 好 食 品 。 无 论 是 否 遇 到 牛 奶 , 用 鸡 蛋 来 补 铁 都 不 理 想 。 如 果 真 想 补 铁 , 大 可 不 必 和 牛 奶 、 鸡 蛋 过 意 不 去 。 牛 奶 是 典 型 的 贫 铁 食 品 , 而 鸡 蛋 是 典 型 的 低 铁 吸 收 率 食 品 。 只 要 吃 些 富 含 血 红 素 铁 的 红 肉 和 内 脏 类 以 及 富 含 维 生 素 C 帮 助 铁 吸 收 的 蔬 菜 水 果 类 , 就 能 解 决 补 铁 问 题 。 只 要 膳 食 中 有 足 够 的 富 铁 食 品 , 即 便 每 天 吃 牛 奶 煮 鸡 蛋 , 也 不 会 患 上 “ 牛 奶 鸡 蛋 贫 血 症 ” 。 43 | 由 杨 幂 和 冯 绍 峰 主 演 的 古 装 爱 情 片 《 大 寒 桃 花 开 》 将 于 1 月 1 7 日 全 国 公 映 , 虽 然 号 称 是 两 人 继 《 画 皮 2 》 后 的 首 次 银 幕 重 逢 , 但 其 实 影 片 拍 摄 于 1 0 年 前 的 2 0 0 4 年 , 那 时 杨 幂 才 高 中 毕 业 ! 压 舱 这 么 久 才 上 映 , 显 然 是 时 移 势 易 , 两 位 曾 经 名 不 见 经 传 的 主 演 现 在 已 经 是 当 红 一 方 了 。 44 | 新 年 前 夕 , 国 家 主 席 习 近 平 通 过 中 国 国 际 广 播 电 台 、 中 央 人 民 广 播 电 台 、 中 央 电 视 台 发 表 二 〇 一 四 年 新 年 贺 词 。 新 华 社 记 者 兰 红 光 摄 45 | 习 近 平 主 席 发 表 2 0 1 4 年 新 年 贺 词 46 | 据 新 华 社 电 新 年 前 夕 , 国 家 主 席 习 近 平 通 过 中 国 国 际 广 播 电 台 、 中 央 人 民 广 播 电 台 、 中 央 电 视 台 , 发 表 了 二 〇 一 四 年 新 年 贺 词 。 全 文 如 下 : 47 | 从 短 片 可 见 , 习 近 平 的 办 公 室 采 用 深 色 的 实 木 家 俬 、 杏 色 地 毯 , 显 得 平 实 、 素 雅 。 习 近 平 的 办 公 桌 十 分 大 , 目 测 至 少 有 2 米 长 。 办 公 桌 后 面 , 竖 立 着 一 面 中 国 国 旗 , 墙 上 挂 着 一 幅 万 里 长 城 的 图 画 , 两 边 的 书 柜 井 井 有 条 地 摆 放 着 书 籍 。 48 | 书 柜 内 的 相 架 放 了 至 少 6 张 家 庭 照 , 其 中 右 边 的 一 张 , 是 曾 经 见 报 的 , 早 年 习 近 平 在 福 建 骑 单 车 载 爱 女 习 明 泽 的 照 片 , 还 有 妻 子 彭 丽 媛 的 照 片 , 另 外 一 张 依 稀 可 见 到 是 习 与 彭 的 夫 妻 合 照 。 49 | 领 导 人 的 办 公 桌 除 了 够 大 , 放 了 笔 筒 、 文 具 外 , 习 的 右 边 手 还 有 两 红 一 白 2 部 电 话 。 50 | [ 热 点 新 闻 : 51 | 女 星 有 意 无 意 秀 胸 贴 龚 玥 菲 近 全 裸 吓 傻 网 友 ( 图 ) 52 | 那 些 被 成 龙 父 子 潜 规 则 过 的 十 大 性 感 女 星 ( 组 图 ) 53 | 老 情 人 死 对 头 恶 情 敌 明 星 “ 冤 家 ” 尴 尬 合 影 瞬 间 54 | 探 秘 朝 鲜 5 大 国 宝 级 美 女 海 量 美 照 曝 光 ( 图 ) 55 | 两 未 成 年 女 孩 遭 爷 爷 猥 亵 盘 点 爷 爷 级 那 些 龌 龊 事 ( 图 ) 56 | 全 球 十 大 令 人 叹 为 观 止 的 旅 游 胜 地 57 | 3 0 个 性 爱 挑 逗 绝 招 变 身 性 感 坏 女 孩 58 | 两 性 养 生 : 安 全 套 你 真 的 知 道 怎 么 戴 吗 ? ( 组 图 ) 59 | 晚 餐 吃 姜 等 于 吃 砒 霜 健 康 晚 餐 3 原 则 60 | 枸 杞 子 滋 阴 明 目 泡 水 喝 有 4 大 养 生 功 效 61 | 两 性 养 生 : 揭 秘 男 女 间 情 感 的 二 十 个 秘 密 【 组 图 】 62 | 北 京 小 客 车 超 两 年 摇 号 不 中 者 中 签 率 将 上 升 63 | 从 今 天 起 , 小 客 车 摇 号 将 执 行 修 改 后 的 新 政 策 , 也 就 是 阶 梯 中 签 规 则 , 以 及 增 加 了 纯 电 动 车 指 标 等 。 昨 天 , 北 京 晨 报 记 者 从 市 交 通 委 获 悉 , 新 版 小 客 车 指 标 调 控 管 理 信 息 系 统 已 进 行 了 升 级 改 造 , 于 今 天 零 时 上 线 , 系 统 增 加 了 4 个 功 能 。 由 于 今 年 摇 号 设 置 了 阶 梯 中 签 规 则 , 新 版 网 站 上 , 摇 号 者 可 查 看 自 己 的 累 计 摇 号 次 数 、 历 次 摇 号 情 况 和 下 一 期 阶 梯 。 64 | 题 : 开 启 全 面 深 化 改 革 元 年 中 国 2 0 1 4 年 大 事 前 瞻 65 | 2 0 1 4 年 , 从 今 日 开 启 。 这 一 年 , 是 中 国 新 一 届 领 导 层 履 职 次 年 , 也 被 视 为 全 面 深 化 改 革 元 年 。 当 下 , 改 革 已 成 中 国 各 界 共 识 。 在 新 的 一 年 里 , 诸 如 收 入 分 配 改 革 细 则 等 多 项 关 乎 国 计 民 生 的 重 大 改 革 方 案 将 面 世 , 养 老 金 并 轨 等 “ 硬 骨 头 ” 有 望 获 得 积 极 进 展 。 改 革 为 年 满 6 5 岁 的 中 国 注 入 动 力 的 同 时 , 将 为 世 界 带 来 什 么 , 各 界 期 待 。 66 | 1 、 建 国 6 5 周 年 : 中 国 迎 全 面 深 化 改 革 元 年 67 | 今 年 , 中 国 将 迎 来 建 国 6 5 周 年 。 在 既 得 利 益 群 体 已 然 存 在 、 利 益 藩 篱 日 趋 固 化 的 当 下 , 改 革 , 再 成 各 界 共 识 。 68 | 刚 刚 过 去 的 一 年 , 被 视 为 中 国 改 革 的 新 起 点 。 这 一 年 里 , 执 政 的 中 国 共 产 党 迎 来 十 八 届 三 中 全 会 , 沿 着 3 5 年 前 改 革 开 放 启 程 的 足 迹 , 这 次 “ 关 键 性 会 议 ” 突 破 性 地 为 中 国 改 革 “ 升 级 ” , 提 出 “ 全 面 深 化 改 革 ” 的 全 新 主 张 。 不 日 后 , 全 会 审 议 通 过 的 《 中 共 中 央 关 于 全 面 深 化 改 革 若 干 重 大 问 题 的 决 定 》 得 以 公 布 。 这 份 2 万 余 字 的 纲 领 性 文 件 , 共 计 1 3 7 次 提 到 “ 改 革 ” 一 词 。 69 | 中 共 改 革 的 决 心 , 还 体 现 在 专 设 机 构 方 面 。 十 八 届 三 中 全 会 首 次 提 出 成 立 中 央 全 面 深 化 改 革 领 导 小 组 。 2 0 1 3 年 岁 末 , 中 共 中 央 政 治 局 召 开 会 议 , 即 决 定 成 立 上 述 机 构 , 由 习 近 平 任 组 长 。 这 被 解 读 为 “ 有 利 于 突 破 利 益 固 化 对 深 化 改 革 的 障 碍 ” 。 70 | 蓝 图 绘 就 , 中 国 改 革 大 幕 旋 即 掀 开 。 分 析 称 , 在 全 会 决 定 涉 及 的 1 5 个 领 域 6 0 项 任 务 中 , 目 前 已 经 有 至 少 2 3 项 陆 续 出 台 了 相 关 措 施 或 已 着 手 细 化 改 革 内 容 。 71 | 2 0 1 4 年 , 被 视 为 中 国 全 面 深 化 改 革 元 年 , 也 被 视 作 上 述 改 革 举 措 能 否 切 实 落 实 的 “ 验 证 年 ” 。 这 一 年 里 , “ 单 独 二 孩 ” 新 政 将 全 面 启 动 , 收 入 分 配 改 革 细 则 、 新 型 城 镇 化 规 划 、 不 动 产 统 一 登 记 制 度 、 招 考 改 革 总 体 方 案 将 面 世 , 国 企 改 革 总 体 方 案 真 容 有 望 揭 开 , 养 老 金 并 轨 有 望 破 题 , 此 外 , 国 防 和 军 队 等 领 域 改 革 也 或 有 新 进 展 , 各 界 期 待 。 72 | 动 车 上 吸 烟 最 高 罚 2 0 0 0 元 、 无 许 可 证 排 污 水 最 高 可 罚 5 0 万 、 法 院 裁 判 文 书 全 面 上 网 接 受 公 众 监 督 、 个 人 海 外 资 产 需 申 报 … … 进 入 2 0 1 4 年 1 月 , 《 城 镇 排 水 与 污 水 处 理 条 例 》 、 《 铁 路 安 全 管 理 条 例 》 、 《 最 高 人 民 法 院 关 于 人 民 法 院 在 互 联 网 公 布 裁 判 文 书 的 规 定 》 、 新 修 订 的 《 国 际 收 支 统 计 申 报 办 法 》 等 一 批 法 律 法 规 正 式 实 施 。 73 | 动 车 上 严 禁 吸 烟 违 者 最 高 罚 2 0 0 0 元 74 | 由 国 务 院 制 定 的 《 铁 路 安 全 管 理 条 例 》 将 自 今 日 起 施 行 , 《 条 例 》 明 确 , 在 动 车 组 列 车 上 吸 烟 或 者 在 其 他 列 车 的 禁 烟 区 域 吸 烟 , 对 个 人 处 5 0 0 元 以 上 2 0 0 0 元 以 下 的 罚 款 。 75 | 《 条 例 》 规 定 , 禁 止 在 铁 路 线 路 安 全 保 护 区 内 烧 荒 、 放 养 牲 畜 、 种 植 影 响 铁 路 线 路 安 全 和 行 车 瞭 望 的 树 木 等 植 物 。 在 铁 路 线 路 两 侧 建 造 、 设 立 生 产 、 加 工 、 储 存 或 者 销 售 易 燃 、 易 爆 或 者 放 射 性 物 品 等 危 险 物 品 的 场 所 、 仓 库 , 应 当 符 合 国 家 标 准 、 行 业 标 准 规 定 的 安 全 防 护 距 离 。 76 | 《 条 例 》 指 出 , 铁 路 运 输 企 业 应 当 按 照 国 务 院 铁 路 行 业 监 督 管 理 部 门 的 规 定 实 施 火 车 票 实 名 购 买 、 查 验 制 度 。 实 施 火 车 票 实 名 购 买 、 查 验 制 度 的 , 旅 客 应 当 凭 有 效 身 份 证 件 购 票 乘 车 ; 对 车 票 所 记 载 身 份 信 息 与 所 持 身 份 证 件 或 者 真 实 身 份 不 符 的 持 票 人 , 铁 路 运 输 企 业 有 权 拒 绝 其 进 站 乘 车 。 77 | 《 条 例 》 强 调 禁 止 实 施 下 列 危 害 铁 路 安 全 的 行 为 : 从 列 车 上 抛 扔 杂 物 ; 在 动 车 组 列 车 上 吸 烟 或 者 在 其 他 列 车 的 禁 烟 区 域 吸 烟 ; 冲 击 、 堵 塞 、 占 用 进 出 站 通 道 或 者 候 车 区 、 站 台 。 违 反 规 定 的 , 对 单 位 处 1 万 元 以 上 5 万 元 以 下 的 罚 款 , 对 个 人 处 5 0 0 元 以 上 2 0 0 0 元 以 下 的 罚 款 。 78 | 另 外 , 《 铁 路 机 车 车 辆 设 计 制 造 维 修 进 口 许 可 办 法 》 、 《 铁 路 运 输 基 础 设 备 生 产 企 业 审 批 办 法 》 、 《 铁 路 机 车 车 辆 驾 驶 人 员 资 格 许 可 办 法 》 和 《 违 反 〈 铁 路 安 全 管 理 条 例 〉 行 政 处 罚 实 施 办 法 》 四 件 配 套 规 章 , 将 于 今 日 起 与 《 铁 路 安 全 管 理 条 例 》 同 步 施 行 , 铁 路 行 政 许 可 和 行 政 处 罚 工 作 将 更 加 规 范 化 、 法 制 化 。 79 | 禁 烟 令 : 中 央 要 求 领 导 干 部 带 头 禁 烟 80 | 中 办 、 国 办 日 前 印 发 《 关 于 领 导 干 部 带 头 在 公 共 场 所 禁 烟 有 关 事 项 的 通 知 》 , 提 出 各 级 领 导 干 部 不 得 在 禁 止 吸 烟 的 公 共 场 所 吸 烟 、 各 级 党 政 机 关 公 务 活 动 中 严 禁 吸 烟 、 要 把 各 级 党 政 机 关 建 成 无 烟 机 关 等 五 项 要 求 。 记 者 日 前 在 湖 南 、 河 南 、 浙 江 等 地 走 访 发 现 , 在 吸 烟 成 为 一 种 “ 普 遍 礼 仪 ” 的 当 下 , 政 府 机 关 禁 烟 实 效 仍 有 待 观 察 。 81 | [ 郑 州 市 委 书 记 吴 天 君 在 自 助 售 卖 机 前 买 票 。 82 | 吴 天 君 搭 乘 地 铁 接 受 采 访 。 83 | 实 拍 记 者 采 访 偶 遇 书 记 乘 地 铁 好 巧 啊 ! 84 | 女 儿 看 到 “ 圣 诞 老 人 ” 。 85 | 女 儿 忍 不 住 哭 了 。 86 | 女 儿 蹲 在 地 上 哭 , 不 能 自 已 。 87 | 杜 慧 颖 和 圣 诞 老 爸 合 影 。 88 | 杜 慧 颖 和 老 爸 。 图 片 由 本 人 提 供 89 | 当 你 走 出 教 室 , 突 然 看 到 一 个 神 奇 的 圣 诞 老 人 站 在 你 面 前 , 走 过 去 , 发 现 , 原 来 竟 是 久 未 相 见 的 爸 爸 ! 原 来 是 爸 爸 装 扮 成 圣 诞 老 人 来 看 望 你 了 ! 那 会 是 怎 样 的 惊 喜 ! 刚 刚 过 去 的 圣 诞 节 , 南 京 工 业 大 学 的 大 一 女 生 杜 慧 颖 就 经 历 了 这 样 的 感 动 , 见 到 “ 圣 诞 老 爸 ” 的 时 候 , 瞬 间 泪 奔 , 周 围 的 人 也 被 这 种 浓 浓 的 父 爱 感 动 。 网 友 将 照 片 发 上 微 博 , 不 少 人 被 感 动 , 并 称 这 是 “ 中 国 好 爸 爸 ” 。 90 | 舒 马 赫 滑 雪 出 事 地 点 91 | 专 家 医 疗 小 组 在 格 勒 诺 布 尔 大 学 医 疗 中 心 介 绍 舒 马 赫 病 情 新 华 社 发 92 | [ 北 京 时 间 2 0 1 3 年 1 2 月 3 1 日 消 息 , 舒 马 赫 滑 雪 发 生 意 外 事 故 , 头 部 受 到 重 伤 , 根 据 德 国 、 法 国 等 多 家 国 外 媒 体 的 报 道 , 院 方 表 示 舒 马 赫 已 接 受 二 次 手 术 , 情 况 略 有 好 转 , 但 尚 未 脱 离 危 险 , 目 前 不 会 对 车 王 的 病 情 做 出 任 何 判 断 , 但 可 以 肯 定 的 是 , 未 来 4 8 小 时 决 定 舒 马 赫 的 命 运 。 93 | [ 解 放 日 报 报 业 大 厦 大 堂 《 解 放 日 报 》 旗 下 的 报 纸 品 牌 雕 塑 。 本 报 记 者 高 四 维 摄 94 | 在 上 海 报 业 集 团 成 立 以 后 , 《 新 闻 晚 报 》 成 为 旗 下 第 一 张 休 刊 的 报 纸 , 与 此 同 时 , 《 东 方 早 报 》 展 开 上 海 报 业 有 史 以 来 最 大 的 互 联 网 招 募 行 动 。 一 时 间 , 上 海 报 业 瞬 息 万 变 。 95 | 1 月 1 日 , 《 新 闻 晚 报 》 正 式 休 刊 , 它 的 生 命 在 1 5 周 岁 这 一 天 戛 然 而 止 。 96 | 《 新 闻 晚 报 》 的 办 公 室 在 上 海 莘 庄 都 市 路 解 放 日 报 大 厦 的 第 9 、 1 0 两 层 , 宣 布 休 刊 后 的 几 天 , 办 公 室 里 没 有 太 大 的 变 化 , 依 然 人 来 人 往 , 公 告 栏 上 贴 着 2 0 1 3 年 上 海 新 闻 采 编 人 员 岗 位 培 训 的 通 知 , 工 作 台 上 的 一 排 排 绿 色 植 物 同 以 往 一 样 , 长 得 茂 盛 。 97 | 针 对 高 校 引 进 人 才 时 片 面 追 求 数 量 、 审 核 把 关 不 严 , 少 数 高 层 次 人 才 流 动 频 繁 、 到 岗 不 足 、 兼 职 过 多 的 问 题 , 教 育 部 昨 天 发 布 《 关 于 进 一 步 加 强 和 规 范 高 校 人 才 引 进 工 作 的 若 干 意 见 》 , 明 确 表 示 支 持 高 层 次 人 才 向 中 西 部 高 校 流 动 , 东 部 高 校 不 得 到 中 西 部 高 校 招 聘 长 江 学 者 , 禁 止 采 取 “ 不 要 人 事 档 案 、 不 要 户 口 、 不 要 流 动 手 续 ” 或 另 建 人 事 档 案 的 违 规 做 法 招 揽 和 引 进 全 职 人 才 。 98 | 教 育 部 要 求 , 全 面 实 行 公 开 招 聘 制 度 , 坚 持 “ 双 方 自 愿 、 平 等 协 商 、 程 序 规 范 、 手 续 完 备 ” 的 原 则 , 促 进 人 才 合 理 流 动 和 有 效 配 置 , 支 持 高 层 次 人 才 向 中 西 部 高 校 流 动 , 东 部 高 校 不 得 到 中 西 部 高 校 招 聘 长 江 学 者 , 禁 止 采 取 “ 不 要 人 事 档 案 、 不 要 户 口 、 不 要 流 动 手 续 ” 或 另 建 人 事 档 案 的 违 规 做 法 招 揽 和 引 进 全 职 人 才 。 因 学 校 责 任 导 致 合 同 终 止 的 , 不 得 以 扣 压 档 案 等 形 式 阻 止 人 才 流 动 。 99 | “ 千 人 计 划 ” 国 家 特 聘 专 家 、 长 江 学 者 特 聘 教 授 等 在 同 一 时 间 内 应 只 有 一 个 全 职 工 作 岗 位 , 不 得 兼 职 ; 长 江 学 者 特 聘 教 授 在 聘 期 内 不 得 担 任 学 校 领 导 职 务 或 调 离 受 聘 岗 位 。 ( 记 者 郭 莹 ) 100 | 2 0 1 4 年 1 月 1 日 , 澳 大 利 亚 悉 尼 , 海 港 大 桥 和 歌 剧 院 上 方 烟 花 盛 放 , 庆 祝 新 年 到 来 。 101 | -------------------------------------------------------------------------------- /datas/dev/target.txt: -------------------------------------------------------------------------------- 1 | O O O B_PER I_PER O O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O B_PER I_PER I_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O 2 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O 3 | O B_PER I_PER O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O 4 | O O O O O O O O O O O 5 | O O B_LOC I_LOC O O O O O O O O O B_PER I_PER O B_LOC I_LOC O O O O O O O O B_T I_T I_T I_T I_T I_T I_T I_T I_T I_T I_T I_T I_T O O O O O B_LOC I_LOC O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O 6 | O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER I_PER O O O B_PER I_PER O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O 7 | O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O 8 | O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O O B_T I_T I_T I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 9 | O O O O O O O O B_PER I_PER I_PER O O B_T I_T I_T I_T O O O O O O B_PER I_PER I_PER I_T I_T I_T I_T O O O O O O O O O O O O O B_T I_T I_T O B_PER I_PER I_PER I_T I_T I_T I_T O O O B_PER I_PER I_T I_T I_T I_T I_T O O O O O O O O O 10 | O O O O O O O O O O O B_PER I_PER I_PER O O O O B_T I_T I_T I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER I_T I_T I_T I_T O O O B_PER I_PER I_PER I_PER I_T I_T I_T I_T I_T O O O B_PER I_PER I_T I_T I_T O O O B_PER I_PER I_PER I_PER I_T I_T I_T I_T O O O O O O 11 | O O O O O O O 12 | O O O B_PER I_PER I_PER O B_PER I_PER O B_PER I_PER I_PER O B_PER I_PER I_PER O B_PER I_PER I_PER I_PER 13 | O O O B_PER I_PER I_PER O B_PER I_PER O B_PER I_PER I_PER O B_PER I_PER I_PER O B_PER I_PER 14 | O O O O O O O O O O O O O O O O O O O O O O O O 15 | B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 16 | O O O O 17 | O O O O O O O O O O 18 | B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 19 | O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O 20 | O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 21 | O O O O 22 | O O O O O O O O O O 23 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 24 | B_LOC I_LOC I_LOC O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 25 | O O B_PER I_PER I_PER 26 | O O O O O O 27 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 28 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 29 | O O O O O O O O O O 30 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 31 | B_LOC I_LOC I_LOC O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O B_ORG I_ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 32 | O O O O O O O O O O 33 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 34 | B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 35 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 36 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 37 | O O O O O O O O O O 38 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 39 | B_LOC I_LOC I_LOC O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O B_ORG I_ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 40 | O O O O O O O O O O 41 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 42 | B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 43 | O B_PER I_PER O B_PER I_PER I_PER O O O O O O O O O B_T I_T O O O O O O B_T I_T I_T I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T I_T O B_T I_T I_T I_T I_T O O O B_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O 44 | B_T I_T O O O O O O O B_PER I_PER I_PER O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O B_ORG I_ORG I_ORG O O B_PER I_PER I_PER O 45 | B_PER I_PER I_PER O O O O B_T I_T I_T I_T I_T I_T I_T O O 46 | O B_ORG I_ORG I_ORG O B_T I_T O O O O O O O B_PER I_PER I_PER O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O 47 | O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 48 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_PER I_PER I_PER O B_LOC I_LOC O O O O O O B_PER I_PER I_PER O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O 49 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 50 | O O O O O O 51 | O O O O O O O O O B_PER I_PER O O O O O O O O O O O 52 | O O O B_PER I_PER O O O O O O O O O O O O O O O O O 53 | O O O O O O O O O O O O O O O O O O O O O 54 | O O B_LOC I_LOC O O O O O O O O O O O O O O O O 55 | O O O O O O O O O O O O O O O O O O O O O O O O 56 | O O O O O O O O O O O O O O O 57 | O O O O O O O O O O O O O O O O 58 | O O O O O O O O O O O O O O O O O O O O O O 59 | O O O O O O O O O O O O O O O O 60 | O O O O O O O O O O O O O O O O O 61 | O O O O O O O O O O O O O O O O O O O O O O 62 | B_LOC I_LOC O O O O O O O O O O O O O O O O O 63 | O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T I_T O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 64 | O O O O O O O O O O B_T I_T I_LOC I_LOC I_T I_T I_T I_T I_T O O O O 65 | B_T I_T I_T I_T I_T O O B_T I_T O O O O O O O O B_LOC I_LOC O O O O O O O O B_T I_T O O O O O O O O O O O B_T I_T O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O 66 | O O O O O O O O O B_LOC I_LOC O O O O O O O B_T I_T 67 | B_T I_T O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 68 | O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O B_ORG I_ORG I_ORG I_ORG I_ORG O O O O O O O O O O O O B_T I_T I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_ORG I_ORG I_ORG I_ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 69 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T I_T I_T I_T I_T O B_ORG I_ORG I_ORG I_ORG O O O O O O O O O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 70 | O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O 71 | B_T I_T I_T I_T I_T O O O O B_LOC I_LOC O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 72 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T I_T I_T I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O B_ORG I_ORG I_ORG I_ORG I_ORG I_ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 73 | O O O O O O O O O O O O O O O O O 74 | O B_ORG I_ORG I_ORG O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 75 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 76 | O O O O O O O O O O O O O O O O O B_ORG I_ORG I_ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 77 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 78 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 79 | O O O O O O O O O O O O O O O O 80 | O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O B_LOC I_LOC O B_LOC I_LOC O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 81 | B_LOC I_LOC I_LOC O O O O B_PER I_PER I_PER O O O O O O O O O O 82 | B_PER I_PER I_PER O O O O O O O O O 83 | O O O O O O O O O O O O O O O O O 84 | O O O O O O O O O O O 85 | O O O O O O O O 86 | O O O O O O O O O O O O O 87 | B_PER I_PER I_PER O B_T I_T O O O O O 88 | B_PER I_PER I_PER O O O O O O O O O O O 89 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T O B_LOC I_LOC O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O B_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O 90 | B_PER I_PER I_PER O O O O O O 91 | O O O O O O O B_PER I_PER I_PER I_PER O O O O O O O O O B_PER I_PER I_PER O O B_ORG I_ORG I_ORG O 92 | B_LOC I_LOC I_LOC O O B_T I_T I_T I_T I_T I_T I_T I_T I_T I_T I_T O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O B_LOC I_LOC O B_LOC I_LOC O O O O O O O O O O O O O O O B_PER I_PER I_PER O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O B_PER I_PER O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O B_PER I_PER I_PER O O O O 93 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 94 | O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O 95 | B_T I_T I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 96 | O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T I_T I_T I_T I_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O B_T I_T O O O O O O O O 97 | O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_ORG I_ORG I_ORG I_T I_T O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 98 | B_ORG I_ORG I_ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 99 | O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_LOC I_LOC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B_PER I_PER O 100 | B_T I_T I_T I_T I_T I_T I_T I_T I_T O B_LOC I_LOC I_LOC I_LOC I_LOC I_LOC O O O O O O O O O O O O O O O O O O B_T I_T O O O 101 | -------------------------------------------------------------------------------- /datas/vocab_tag/tag.txt: -------------------------------------------------------------------------------- 1 | [PAD] 2 | O 3 | B_T 4 | I_T 5 | B_LOC 6 | I_LOC 7 | B_ORG 8 | I_ORG 9 | B_PER 10 | I_PER 11 | [CLS] 12 | [SEP] -------------------------------------------------------------------------------- /pytorch_pretrained/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.6.2" 2 | from .tokenization import BertTokenizer, BasicTokenizer, WordpieceTokenizer 3 | from .tokenization_openai import OpenAIGPTTokenizer 4 | from .tokenization_transfo_xl import (TransfoXLTokenizer, TransfoXLCorpus) 5 | from .tokenization_gpt2 import GPT2Tokenizer 6 | 7 | from .modeling import (BertConfig, BertModel, BertForPreTraining, 8 | BertForMaskedLM, BertForNextSentencePrediction, 9 | BertForSequenceClassification, BertForMultipleChoice, 10 | BertForTokenClassification, BertForQuestionAnswering, 11 | load_tf_weights_in_bert) 12 | from .modeling_openai import (OpenAIGPTConfig, OpenAIGPTModel, 13 | OpenAIGPTLMHeadModel, OpenAIGPTDoubleHeadsModel, 14 | load_tf_weights_in_openai_gpt) 15 | from .modeling_transfo_xl import (TransfoXLConfig, TransfoXLModel, TransfoXLLMHeadModel, 16 | load_tf_weights_in_transfo_xl) 17 | from .modeling_gpt2 import (GPT2Config, GPT2Model, 18 | GPT2LMHeadModel, GPT2DoubleHeadsModel, 19 | load_tf_weights_in_gpt2) 20 | 21 | from .optimization import BertAdam 22 | from .optimization_openai import OpenAIAdam 23 | 24 | from .file_utils import PYTORCH_PRETRAINED_BERT_CACHE, cached_path, WEIGHTS_NAME, CONFIG_NAME 25 | -------------------------------------------------------------------------------- /pytorch_pretrained/__main__.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | def main(): 3 | import sys 4 | if (len(sys.argv) != 4 and len(sys.argv) != 5) or sys.argv[1] not in [ 5 | "convert_tf_checkpoint_to_pytorch", 6 | "convert_openai_checkpoint", 7 | "convert_transfo_xl_checkpoint", 8 | "convert_gpt2_checkpoint", 9 | ]: 10 | print( 11 | "Should be used as one of: \n" 12 | ">> `pytorch_pretrained_bert convert_tf_checkpoint_to_pytorch TF_CHECKPOINT TF_CONFIG PYTORCH_DUMP_OUTPUT`, \n" 13 | ">> `pytorch_pretrained_bert convert_openai_checkpoint OPENAI_GPT_CHECKPOINT_FOLDER_PATH PYTORCH_DUMP_OUTPUT [OPENAI_GPT_CONFIG]`, \n" 14 | ">> `pytorch_pretrained_bert convert_transfo_xl_checkpoint TF_CHECKPOINT_OR_DATASET PYTORCH_DUMP_OUTPUT [TF_CONFIG]` or \n" 15 | ">> `pytorch_pretrained_bert convert_gpt2_checkpoint TF_CHECKPOINT PYTORCH_DUMP_OUTPUT [GPT2_CONFIG]`") 16 | else: 17 | if sys.argv[1] == "convert_tf_checkpoint_to_pytorch": 18 | try: 19 | from .convert_tf_checkpoint_to_pytorch import convert_tf_checkpoint_to_pytorch 20 | except ImportError: 21 | print("pytorch_pretrained_bert can only be used from the commandline to convert TensorFlow Models in PyTorch, " 22 | "In that case, it requires TensorFlow to be installed. Please see " 23 | "https://www.tensorflow.org/install/ for installation instructions.") 24 | raise 25 | 26 | if len(sys.argv) != 5: 27 | # pylint: disable=line-too-long 28 | print("Should be used as `pytorch_pretrained_bert convert_tf_checkpoint_to_pytorch TF_CHECKPOINT TF_CONFIG PYTORCH_DUMP_OUTPUT`") 29 | else: 30 | PYTORCH_DUMP_OUTPUT = sys.argv.pop() 31 | TF_CONFIG = sys.argv.pop() 32 | TF_CHECKPOINT = sys.argv.pop() 33 | convert_tf_checkpoint_to_pytorch(TF_CHECKPOINT, TF_CONFIG, PYTORCH_DUMP_OUTPUT) 34 | elif sys.argv[1] == "convert_openai_checkpoint": 35 | from .convert_openai_checkpoint_to_pytorch import convert_openai_checkpoint_to_pytorch 36 | OPENAI_GPT_CHECKPOINT_FOLDER_PATH = sys.argv[2] 37 | PYTORCH_DUMP_OUTPUT = sys.argv[3] 38 | if len(sys.argv) == 5: 39 | OPENAI_GPT_CONFIG = sys.argv[4] 40 | else: 41 | OPENAI_GPT_CONFIG = "" 42 | convert_openai_checkpoint_to_pytorch(OPENAI_GPT_CHECKPOINT_FOLDER_PATH, 43 | OPENAI_GPT_CONFIG, 44 | PYTORCH_DUMP_OUTPUT) 45 | elif sys.argv[1] == "convert_transfo_xl_checkpoint": 46 | try: 47 | from .convert_transfo_xl_checkpoint_to_pytorch import convert_transfo_xl_checkpoint_to_pytorch 48 | except ImportError: 49 | print("pytorch_pretrained_bert can only be used from the commandline to convert TensorFlow Models in PyTorch, " 50 | "In that case, it requires TensorFlow to be installed. Please see " 51 | "https://www.tensorflow.org/install/ for installation instructions.") 52 | raise 53 | 54 | if 'ckpt' in sys.argv[2].lower(): 55 | TF_CHECKPOINT = sys.argv[2] 56 | TF_DATASET_FILE = "" 57 | else: 58 | TF_DATASET_FILE = sys.argv[2] 59 | TF_CHECKPOINT = "" 60 | PYTORCH_DUMP_OUTPUT = sys.argv[3] 61 | if len(sys.argv) == 5: 62 | TF_CONFIG = sys.argv[4] 63 | else: 64 | TF_CONFIG = "" 65 | convert_transfo_xl_checkpoint_to_pytorch(TF_CHECKPOINT, TF_CONFIG, PYTORCH_DUMP_OUTPUT, TF_DATASET_FILE) 66 | else: 67 | try: 68 | from .convert_gpt2_checkpoint_to_pytorch import convert_gpt2_checkpoint_to_pytorch 69 | except ImportError: 70 | print("pytorch_pretrained_bert can only be used from the commandline to convert TensorFlow Models in PyTorch, " 71 | "In that case, it requires TensorFlow to be installed. Please see " 72 | "https://www.tensorflow.org/install/ for installation instructions.") 73 | raise 74 | 75 | TF_CHECKPOINT = sys.argv[2] 76 | PYTORCH_DUMP_OUTPUT = sys.argv[3] 77 | if len(sys.argv) == 5: 78 | TF_CONFIG = sys.argv[4] 79 | else: 80 | TF_CONFIG = "" 81 | convert_gpt2_checkpoint_to_pytorch(TF_CHECKPOINT, TF_CONFIG, PYTORCH_DUMP_OUTPUT) 82 | if __name__ == '__main__': 83 | main() 84 | -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/file_utils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/file_utils.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/modeling.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/modeling.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/modeling_gpt2.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/modeling_gpt2.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/modeling_openai.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/modeling_openai.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/modeling_transfo_xl.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/modeling_transfo_xl.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/modeling_transfo_xl_utilities.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/modeling_transfo_xl_utilities.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/optimization.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/optimization.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/optimization_openai.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/optimization_openai.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/tokenization.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/tokenization.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/tokenization_gpt2.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/tokenization_gpt2.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/tokenization_openai.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/tokenization_openai.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/__pycache__/tokenization_transfo_xl.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjhayes16/Chinese-Ner-pytorch/b300ffe50443416e5119f4a671d070baa52422de/pytorch_pretrained/__pycache__/tokenization_transfo_xl.cpython-37.pyc -------------------------------------------------------------------------------- /pytorch_pretrained/convert_gpt2_checkpoint_to_pytorch.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Convert OpenAI GPT checkpoint.""" 16 | 17 | from __future__ import absolute_import, division, print_function 18 | 19 | import argparse 20 | from io import open 21 | 22 | import torch 23 | 24 | from pytorch_pretrained_bert.modeling_gpt2 import (CONFIG_NAME, WEIGHTS_NAME, 25 | GPT2Config, 26 | GPT2Model, 27 | load_tf_weights_in_gpt2) 28 | 29 | 30 | def convert_gpt2_checkpoint_to_pytorch(gpt2_checkpoint_path, gpt2_config_file, pytorch_dump_folder_path): 31 | # Construct model 32 | if gpt2_config_file == "": 33 | config = GPT2Config() 34 | else: 35 | config = GPT2Config(gpt2_config_file) 36 | model = GPT2Model(config) 37 | 38 | # Load weights from numpy 39 | load_tf_weights_in_gpt2(model, gpt2_checkpoint_path) 40 | 41 | # Save pytorch-model 42 | pytorch_weights_dump_path = pytorch_dump_folder_path + '/' + WEIGHTS_NAME 43 | pytorch_config_dump_path = pytorch_dump_folder_path + '/' + CONFIG_NAME 44 | print("Save PyTorch model to {}".format(pytorch_weights_dump_path)) 45 | torch.save(model.state_dict(), pytorch_weights_dump_path) 46 | print("Save configuration file to {}".format(pytorch_config_dump_path)) 47 | with open(pytorch_config_dump_path, "w", encoding="utf-8") as f: 48 | f.write(config.to_json_string()) 49 | 50 | 51 | if __name__ == "__main__": 52 | parser = argparse.ArgumentParser() 53 | ## Required parameters 54 | parser.add_argument("--gpt2_checkpoint_path", 55 | default = None, 56 | type = str, 57 | required = True, 58 | help = "Path the TensorFlow checkpoint path.") 59 | parser.add_argument("--pytorch_dump_folder_path", 60 | default = None, 61 | type = str, 62 | required = True, 63 | help = "Path to the output PyTorch model.") 64 | parser.add_argument("--gpt2_config_file", 65 | default = "", 66 | type = str, 67 | help = "An optional Config json file corresponding to the pre-trained OpenAI model. \n" 68 | "This specifies the model architecture.") 69 | args = parser.parse_args() 70 | convert_gpt2_checkpoint_to_pytorch(args.gpt2_checkpoint_path, 71 | args.gpt2_config_file, 72 | args.pytorch_dump_folder_path) 73 | -------------------------------------------------------------------------------- /pytorch_pretrained/convert_openai_checkpoint_to_pytorch.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Convert OpenAI GPT checkpoint.""" 16 | 17 | from __future__ import absolute_import, division, print_function 18 | 19 | import argparse 20 | from io import open 21 | 22 | import torch 23 | 24 | from pytorch_pretrained_bert.modeling_openai import (CONFIG_NAME, WEIGHTS_NAME, 25 | OpenAIGPTConfig, 26 | OpenAIGPTModel, 27 | load_tf_weights_in_openai_gpt) 28 | 29 | 30 | def convert_openai_checkpoint_to_pytorch(openai_checkpoint_folder_path, openai_config_file, pytorch_dump_folder_path): 31 | # Construct model 32 | if openai_config_file == "": 33 | config = OpenAIGPTConfig() 34 | else: 35 | config = OpenAIGPTConfig(openai_config_file) 36 | model = OpenAIGPTModel(config) 37 | 38 | # Load weights from numpy 39 | load_tf_weights_in_openai_gpt(model, openai_checkpoint_folder_path) 40 | 41 | # Save pytorch-model 42 | pytorch_weights_dump_path = pytorch_dump_folder_path + '/' + WEIGHTS_NAME 43 | pytorch_config_dump_path = pytorch_dump_folder_path + '/' + CONFIG_NAME 44 | print("Save PyTorch model to {}".format(pytorch_weights_dump_path)) 45 | torch.save(model.state_dict(), pytorch_weights_dump_path) 46 | print("Save configuration file to {}".format(pytorch_config_dump_path)) 47 | with open(pytorch_config_dump_path, "w", encoding="utf-8") as f: 48 | f.write(config.to_json_string()) 49 | 50 | 51 | if __name__ == "__main__": 52 | parser = argparse.ArgumentParser() 53 | ## Required parameters 54 | parser.add_argument("--openai_checkpoint_folder_path", 55 | default = None, 56 | type = str, 57 | required = True, 58 | help = "Path the TensorFlow checkpoint path.") 59 | parser.add_argument("--pytorch_dump_folder_path", 60 | default = None, 61 | type = str, 62 | required = True, 63 | help = "Path to the output PyTorch model.") 64 | parser.add_argument("--openai_config_file", 65 | default = "", 66 | type = str, 67 | help = "An optional Config json file corresponding to the pre-trained OpenAI model. \n" 68 | "This specifies the model architecture.") 69 | args = parser.parse_args() 70 | convert_openai_checkpoint_to_pytorch(args.openai_checkpoint_folder_path, 71 | args.openai_config_file, 72 | args.pytorch_dump_folder_path) 73 | -------------------------------------------------------------------------------- /pytorch_pretrained/convert_tf_checkpoint_to_pytorch.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Convert BERT checkpoint.""" 16 | 17 | from __future__ import absolute_import 18 | from __future__ import division 19 | from __future__ import print_function 20 | 21 | import os 22 | import re 23 | import argparse 24 | import tensorflow as tf 25 | import torch 26 | import numpy as np 27 | 28 | from pytorch_pretrained_bert.modeling import BertConfig, BertForPreTraining, load_tf_weights_in_bert 29 | 30 | def convert_tf_checkpoint_to_pytorch(tf_checkpoint_path, bert_config_file, pytorch_dump_path): 31 | # Initialise PyTorch model 32 | config = BertConfig.from_json_file(bert_config_file) 33 | print("Building PyTorch model from configuration: {}".format(str(config))) 34 | model = BertForPreTraining(config) 35 | 36 | # Load weights from tf checkpoint 37 | load_tf_weights_in_bert(model, tf_checkpoint_path) 38 | 39 | # Save pytorch-model 40 | print("Save PyTorch model to {}".format(pytorch_dump_path)) 41 | torch.save(model.state_dict(), pytorch_dump_path) 42 | 43 | 44 | if __name__ == "__main__": 45 | parser = argparse.ArgumentParser() 46 | ## Required parameters 47 | parser.add_argument("--tf_checkpoint_path", 48 | default = None, 49 | type = str, 50 | required = True, 51 | help = "Path the TensorFlow checkpoint path.") 52 | parser.add_argument("--bert_config_file", 53 | default = None, 54 | type = str, 55 | required = True, 56 | help = "The Config json file corresponding to the pre-trained BERT model. \n" 57 | "This specifies the model architecture.") 58 | parser.add_argument("--pytorch_dump_path", 59 | default = None, 60 | type = str, 61 | required = True, 62 | help = "Path to the output PyTorch model.") 63 | args = parser.parse_args() 64 | convert_tf_checkpoint_to_pytorch(args.tf_checkpoint_path, 65 | args.bert_config_file, 66 | args.pytorch_dump_path) 67 | -------------------------------------------------------------------------------- /pytorch_pretrained/convert_transfo_xl_checkpoint_to_pytorch.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Convert Transformer XL checkpoint and datasets.""" 16 | 17 | from __future__ import absolute_import, division, print_function 18 | 19 | import argparse 20 | import os 21 | import sys 22 | from io import open 23 | 24 | import torch 25 | 26 | import pytorch_pretrained_bert.tokenization_transfo_xl as data_utils 27 | from pytorch_pretrained_bert.modeling_transfo_xl import (CONFIG_NAME, 28 | WEIGHTS_NAME, 29 | TransfoXLConfig, 30 | TransfoXLLMHeadModel, 31 | load_tf_weights_in_transfo_xl) 32 | from pytorch_pretrained_bert.tokenization_transfo_xl import (CORPUS_NAME, 33 | VOCAB_NAME) 34 | 35 | if sys.version_info[0] == 2: 36 | import cPickle as pickle 37 | else: 38 | import pickle 39 | 40 | # We do this to be able to load python 2 datasets pickles 41 | # See e.g. https://stackoverflow.com/questions/2121874/python-pickling-after-changing-a-modules-directory/2121918#2121918 42 | data_utils.Vocab = data_utils.TransfoXLTokenizer 43 | data_utils.Corpus = data_utils.TransfoXLCorpus 44 | sys.modules['data_utils'] = data_utils 45 | sys.modules['vocabulary'] = data_utils 46 | 47 | def convert_transfo_xl_checkpoint_to_pytorch(tf_checkpoint_path, 48 | transfo_xl_config_file, 49 | pytorch_dump_folder_path, 50 | transfo_xl_dataset_file): 51 | if transfo_xl_dataset_file: 52 | # Convert a pre-processed corpus (see original TensorFlow repo) 53 | with open(transfo_xl_dataset_file, "rb") as fp: 54 | corpus = pickle.load(fp, encoding="latin1") 55 | # Save vocabulary and dataset cache as Dictionaries (should be better than pickles for the long-term) 56 | pytorch_vocab_dump_path = pytorch_dump_folder_path + '/' + VOCAB_NAME 57 | print("Save vocabulary to {}".format(pytorch_vocab_dump_path)) 58 | corpus_vocab_dict = corpus.vocab.__dict__ 59 | torch.save(corpus_vocab_dict, pytorch_vocab_dump_path) 60 | 61 | corpus_dict_no_vocab = corpus.__dict__ 62 | corpus_dict_no_vocab.pop('vocab', None) 63 | pytorch_dataset_dump_path = pytorch_dump_folder_path + '/' + CORPUS_NAME 64 | print("Save dataset to {}".format(pytorch_dataset_dump_path)) 65 | torch.save(corpus_dict_no_vocab, pytorch_dataset_dump_path) 66 | 67 | if tf_checkpoint_path: 68 | # Convert a pre-trained TensorFlow model 69 | config_path = os.path.abspath(transfo_xl_config_file) 70 | tf_path = os.path.abspath(tf_checkpoint_path) 71 | 72 | print("Converting Transformer XL checkpoint from {} with Config at {}".format(tf_path, config_path)) 73 | # Initialise PyTorch model 74 | if transfo_xl_config_file == "": 75 | config = TransfoXLConfig() 76 | else: 77 | config = TransfoXLConfig(transfo_xl_config_file) 78 | print("Building PyTorch model from configuration: {}".format(str(config))) 79 | model = TransfoXLLMHeadModel(config) 80 | 81 | model = load_tf_weights_in_transfo_xl(model, config, tf_path) 82 | # Save pytorch-model 83 | pytorch_weights_dump_path = os.path.join(pytorch_dump_folder_path, WEIGHTS_NAME) 84 | pytorch_config_dump_path = os.path.join(pytorch_dump_folder_path, CONFIG_NAME) 85 | print("Save PyTorch model to {}".format(os.path.abspath(pytorch_weights_dump_path))) 86 | torch.save(model.state_dict(), pytorch_weights_dump_path) 87 | print("Save configuration file to {}".format(os.path.abspath(pytorch_config_dump_path))) 88 | with open(pytorch_config_dump_path, "w", encoding="utf-8") as f: 89 | f.write(config.to_json_string()) 90 | 91 | 92 | if __name__ == "__main__": 93 | parser = argparse.ArgumentParser() 94 | parser.add_argument("--pytorch_dump_folder_path", 95 | default = None, 96 | type = str, 97 | required = True, 98 | help = "Path to the folder to store the PyTorch model or dataset/vocab.") 99 | parser.add_argument("--tf_checkpoint_path", 100 | default = "", 101 | type = str, 102 | help = "An optional path to a TensorFlow checkpoint path to be converted.") 103 | parser.add_argument("--transfo_xl_config_file", 104 | default = "", 105 | type = str, 106 | help = "An optional Config json file corresponding to the pre-trained BERT model. \n" 107 | "This specifies the model architecture.") 108 | parser.add_argument("--transfo_xl_dataset_file", 109 | default = "", 110 | type = str, 111 | help = "An optional dataset file to be converted in a vocabulary.") 112 | args = parser.parse_args() 113 | convert_transfo_xl_checkpoint_to_pytorch(args.tf_checkpoint_path, 114 | args.transfo_xl_config_file, 115 | args.pytorch_dump_folder_path, 116 | args.transfo_xl_dataset_file) 117 | -------------------------------------------------------------------------------- /pytorch_pretrained/file_utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities for working with the local dataset cache. 3 | This file is adapted from the AllenNLP library at https://github.com/allenai/allennlp 4 | Copyright by the AllenNLP authors. 5 | """ 6 | from __future__ import (absolute_import, division, print_function, unicode_literals) 7 | 8 | import sys 9 | import json 10 | import logging 11 | import os 12 | import shutil 13 | import tempfile 14 | import fnmatch 15 | from functools import wraps 16 | from hashlib import sha256 17 | import sys 18 | from io import open 19 | 20 | import boto3 21 | import requests 22 | from botocore.exceptions import ClientError 23 | from tqdm import tqdm 24 | 25 | try: 26 | from urllib.parse import urlparse 27 | except ImportError: 28 | from urlparse import urlparse 29 | 30 | try: 31 | from pathlib import Path 32 | PYTORCH_PRETRAINED_BERT_CACHE = Path(os.getenv('PYTORCH_PRETRAINED_BERT_CACHE', 33 | Path.home() / '.pytorch_pretrained_bert')) 34 | except (AttributeError, ImportError): 35 | PYTORCH_PRETRAINED_BERT_CACHE = os.getenv('PYTORCH_PRETRAINED_BERT_CACHE', 36 | os.path.join(os.path.expanduser("~"), '.pytorch_pretrained_bert')) 37 | 38 | CONFIG_NAME = "Config.json" 39 | WEIGHTS_NAME = "pytorch_model.bin" 40 | 41 | logger = logging.getLogger(__name__) # pylint: disable=invalid-name 42 | 43 | 44 | def url_to_filename(url, etag=None): 45 | """ 46 | Convert `url` into a hashed filename in a repeatable way. 47 | If `etag` is specified, append its hash to the url's, delimited 48 | by a period. 49 | """ 50 | url_bytes = url.encode('utf-8') 51 | url_hash = sha256(url_bytes) 52 | filename = url_hash.hexdigest() 53 | 54 | if etag: 55 | etag_bytes = etag.encode('utf-8') 56 | etag_hash = sha256(etag_bytes) 57 | filename += '.' + etag_hash.hexdigest() 58 | 59 | return filename 60 | 61 | 62 | def filename_to_url(filename, cache_dir=None): 63 | """ 64 | Return the url and etag (which may be ``None``) stored for `filename`. 65 | Raise ``EnvironmentError`` if `filename` or its stored metadata do not exist. 66 | """ 67 | if cache_dir is None: 68 | cache_dir = PYTORCH_PRETRAINED_BERT_CACHE 69 | if sys.version_info[0] == 3 and isinstance(cache_dir, Path): 70 | cache_dir = str(cache_dir) 71 | 72 | cache_path = os.path.join(cache_dir, filename) 73 | if not os.path.exists(cache_path): 74 | raise EnvironmentError("file {} not found".format(cache_path)) 75 | 76 | meta_path = cache_path + '.json' 77 | if not os.path.exists(meta_path): 78 | raise EnvironmentError("file {} not found".format(meta_path)) 79 | 80 | with open(meta_path, encoding="utf-8") as meta_file: 81 | metadata = json.load(meta_file) 82 | url = metadata['url'] 83 | etag = metadata['etag'] 84 | 85 | return url, etag 86 | 87 | 88 | def cached_path(url_or_filename, cache_dir=None): 89 | """ 90 | Given something that might be a URL (or might be a local path), 91 | determine which. If it's a URL, download the file and cache it, and 92 | return the path to the cached file. If it's already a local path, 93 | make sure the file exists and then return the path. 94 | """ 95 | if cache_dir is None: 96 | cache_dir = PYTORCH_PRETRAINED_BERT_CACHE 97 | if sys.version_info[0] == 3 and isinstance(url_or_filename, Path): 98 | url_or_filename = str(url_or_filename) 99 | if sys.version_info[0] == 3 and isinstance(cache_dir, Path): 100 | cache_dir = str(cache_dir) 101 | 102 | parsed = urlparse(url_or_filename) 103 | 104 | if parsed.scheme in ('http', 'https', 's3'): 105 | # URL, so get it from the cache (downloading if necessary) 106 | return get_from_cache(url_or_filename, cache_dir) 107 | elif os.path.exists(url_or_filename): 108 | # File, and it exists. 109 | return url_or_filename 110 | elif parsed.scheme == '': 111 | # File, but it doesn't exist. 112 | raise EnvironmentError("file {} not found".format(url_or_filename)) 113 | else: 114 | # Something unknown 115 | raise ValueError("unable to parse {} as a URL or as a local path".format(url_or_filename)) 116 | 117 | 118 | def split_s3_path(url): 119 | """Split a full s3 path into the bucket name and path.""" 120 | parsed = urlparse(url) 121 | if not parsed.netloc or not parsed.path: 122 | raise ValueError("bad s3 path {}".format(url)) 123 | bucket_name = parsed.netloc 124 | s3_path = parsed.path 125 | # Remove '/' at beginning of path. 126 | if s3_path.startswith("/"): 127 | s3_path = s3_path[1:] 128 | return bucket_name, s3_path 129 | 130 | 131 | def s3_request(func): 132 | """ 133 | Wrapper function for s3 requests in order to create more helpful error 134 | messages. 135 | """ 136 | 137 | @wraps(func) 138 | def wrapper(url, *args, **kwargs): 139 | try: 140 | return func(url, *args, **kwargs) 141 | except ClientError as exc: 142 | if int(exc.response["Error"]["Code"]) == 404: 143 | raise EnvironmentError("file {} not found".format(url)) 144 | else: 145 | raise 146 | 147 | return wrapper 148 | 149 | 150 | @s3_request 151 | def s3_etag(url): 152 | """Check ETag on S3 object.""" 153 | s3_resource = boto3.resource("s3") 154 | bucket_name, s3_path = split_s3_path(url) 155 | s3_object = s3_resource.Object(bucket_name, s3_path) 156 | return s3_object.e_tag 157 | 158 | 159 | @s3_request 160 | def s3_get(url, temp_file): 161 | """Pull a file directly from S3.""" 162 | s3_resource = boto3.resource("s3") 163 | bucket_name, s3_path = split_s3_path(url) 164 | s3_resource.Bucket(bucket_name).download_fileobj(s3_path, temp_file) 165 | 166 | 167 | def http_get(url, temp_file): 168 | req = requests.get(url, stream=True) 169 | content_length = req.headers.get('Content-Length') 170 | total = int(content_length) if content_length is not None else None 171 | progress = tqdm(unit="B", total=total) 172 | for chunk in req.iter_content(chunk_size=1024): 173 | if chunk: # filter out keep-alive new chunks 174 | progress.update(len(chunk)) 175 | temp_file.write(chunk) 176 | progress.close() 177 | 178 | 179 | def get_from_cache(url, cache_dir=None): 180 | """ 181 | Given a URL, look for the corresponding dataset in the local cache. 182 | If it's not there, download it. Then return the path to the cached file. 183 | """ 184 | if cache_dir is None: 185 | cache_dir = PYTORCH_PRETRAINED_BERT_CACHE 186 | if sys.version_info[0] == 3 and isinstance(cache_dir, Path): 187 | cache_dir = str(cache_dir) 188 | 189 | if not os.path.exists(cache_dir): 190 | os.makedirs(cache_dir) 191 | 192 | # Get eTag to add to filename, if it exists. 193 | if url.startswith("s3://"): 194 | etag = s3_etag(url) 195 | else: 196 | try: 197 | response = requests.head(url, allow_redirects=True) 198 | if response.status_code != 200: 199 | etag = None 200 | else: 201 | etag = response.headers.get("ETag") 202 | except EnvironmentError: 203 | etag = None 204 | 205 | if sys.version_info[0] == 2 and etag is not None: 206 | etag = etag.decode('utf-8') 207 | filename = url_to_filename(url, etag) 208 | 209 | # get cache path to put the file 210 | cache_path = os.path.join(cache_dir, filename) 211 | 212 | # If we don't have a connection (etag is None) and can't identify the file 213 | # try to get the last downloaded one 214 | if not os.path.exists(cache_path) and etag is None: 215 | matching_files = fnmatch.filter(os.listdir(cache_dir), filename + '.*') 216 | matching_files = list(filter(lambda s: not s.endswith('.json'), matching_files)) 217 | if matching_files: 218 | cache_path = os.path.join(cache_dir, matching_files[-1]) 219 | 220 | if not os.path.exists(cache_path): 221 | # Download to temporary file, then copy to cache dir once finished. 222 | # Otherwise you get corrupt cache entries if the download gets interrupted. 223 | with tempfile.NamedTemporaryFile() as temp_file: 224 | logger.info("%s not found in cache, downloading to %s", url, temp_file.name) 225 | 226 | # GET file object 227 | if url.startswith("s3://"): 228 | s3_get(url, temp_file) 229 | else: 230 | http_get(url, temp_file) 231 | 232 | # we are copying the file before closing it, so flush to avoid truncation 233 | temp_file.flush() 234 | # shutil.copyfileobj() starts at the current position, so go to the start 235 | temp_file.seek(0) 236 | 237 | logger.info("copying %s to cache at %s", temp_file.name, cache_path) 238 | with open(cache_path, 'wb') as cache_file: 239 | shutil.copyfileobj(temp_file, cache_file) 240 | 241 | logger.info("creating metadata file for %s", cache_path) 242 | meta = {'url': url, 'etag': etag} 243 | meta_path = cache_path + '.json' 244 | with open(meta_path, 'w') as meta_file: 245 | output_string = json.dumps(meta) 246 | if sys.version_info[0] == 2 and isinstance(output_string, str): 247 | output_string = unicode(output_string, 'utf-8') # The beauty of python 2 248 | meta_file.write(output_string) 249 | 250 | logger.info("removing temp file %s", temp_file.name) 251 | 252 | return cache_path 253 | 254 | 255 | def read_set_from_file(filename): 256 | ''' 257 | Extract a de-duped collection (set) of text from a file. 258 | Expected file format is one item per line. 259 | ''' 260 | collection = set() 261 | with open(filename, 'r', encoding='utf-8') as file_: 262 | for line in file_: 263 | collection.add(line.rstrip()) 264 | return collection 265 | 266 | 267 | def get_file_extension(path, dot=True, lower=True): 268 | ext = os.path.splitext(path)[1] 269 | ext = ext if dot else ext[1:] 270 | return ext.lower() if lower else ext 271 | -------------------------------------------------------------------------------- /pytorch_pretrained/modeling_transfo_xl_utilities.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 Google AI, Google Brain and Carnegie Mellon University Authors and the HuggingFace Inc. team. 3 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | """ Utilities for PyTorch Transformer XL model. 17 | Directly adapted from https://github.com/kimiyoung/transformer-xl. 18 | """ 19 | 20 | from collections import defaultdict 21 | 22 | import numpy as np 23 | 24 | import torch 25 | import torch.nn as nn 26 | import torch.nn.functional as F 27 | 28 | # CUDA_MAJOR = int(torch.version.cuda.split('.')[0]) 29 | # CUDA_MINOR = int(torch.version.cuda.split('.')[1]) 30 | 31 | class ProjectedAdaptiveLogSoftmax(nn.Module): 32 | def __init__(self, n_token, d_embed, d_proj, cutoffs, div_val=1, 33 | keep_order=False): 34 | super(ProjectedAdaptiveLogSoftmax, self).__init__() 35 | 36 | self.n_token = n_token 37 | self.d_embed = d_embed 38 | self.d_proj = d_proj 39 | 40 | self.cutoffs = cutoffs + [n_token] 41 | self.cutoff_ends = [0] + self.cutoffs 42 | self.div_val = div_val 43 | 44 | self.shortlist_size = self.cutoffs[0] 45 | self.n_clusters = len(self.cutoffs) - 1 46 | self.head_size = self.shortlist_size + self.n_clusters 47 | 48 | if self.n_clusters > 0: 49 | self.cluster_weight = nn.Parameter(torch.zeros(self.n_clusters, self.d_embed)) 50 | self.cluster_bias = nn.Parameter(torch.zeros(self.n_clusters)) 51 | 52 | self.out_layers = nn.ModuleList() 53 | self.out_projs = nn.ParameterList() 54 | 55 | if div_val == 1: 56 | for i in range(len(self.cutoffs)): 57 | if d_proj != d_embed: 58 | self.out_projs.append( 59 | nn.Parameter(torch.Tensor(d_proj, d_embed)) 60 | ) 61 | else: 62 | self.out_projs.append(None) 63 | 64 | self.out_layers.append(nn.Linear(d_embed, n_token)) 65 | else: 66 | for i in range(len(self.cutoffs)): 67 | l_idx, r_idx = self.cutoff_ends[i], self.cutoff_ends[i+1] 68 | d_emb_i = d_embed // (div_val ** i) 69 | 70 | self.out_projs.append( 71 | nn.Parameter(torch.Tensor(d_proj, d_emb_i)) 72 | ) 73 | 74 | self.out_layers.append(nn.Linear(d_emb_i, r_idx-l_idx)) 75 | 76 | self.keep_order = keep_order 77 | 78 | def _compute_logit(self, hidden, weight, bias, proj): 79 | if proj is None: 80 | logit = F.linear(hidden, weight, bias=bias) 81 | else: 82 | # if CUDA_MAJOR <= 9 and CUDA_MINOR <= 1: 83 | proj_hid = F.linear(hidden, proj.t().contiguous()) 84 | logit = F.linear(proj_hid, weight, bias=bias) 85 | # else: 86 | # logit = torch.einsum('bd,de,ev->bv', (hidden, proj, weight.t())) 87 | # if bias is not None: 88 | # logit = logit + bias 89 | 90 | return logit 91 | 92 | def forward(self, hidden, target=None, keep_order=False): 93 | ''' 94 | Params: 95 | hidden :: [len*bsz x d_proj] 96 | target :: [len*bsz] 97 | Return: 98 | if target is None: 99 | out :: [len*bsz] Negative Log likelihood 100 | else: 101 | out :: [len*bsz x n_tokens] Log probabilities of tokens over the vocabulary 102 | We could replace this implementation by the native PyTorch one 103 | if their's had an option to set bias on all clusters in the native one. 104 | here: https://github.com/pytorch/pytorch/blob/dbe6a7a9ff1a364a8706bf5df58a1ca96d2fd9da/torch/nn/modules/adaptive.py#L138 105 | ''' 106 | 107 | if target is not None: 108 | target = target.view(-1) 109 | if hidden.size(0) != target.size(0): 110 | raise RuntimeError('Input and target should have the same size ' 111 | 'in the batch dimension.') 112 | 113 | if self.n_clusters == 0: 114 | logit = self._compute_logit(hidden, self.out_layers[0].weight, 115 | self.out_layers[0].bias, self.out_projs[0]) 116 | if target is not None: 117 | output = -F.log_softmax(logit, dim=-1) \ 118 | .gather(1, target.unsqueeze(1)).squeeze(1) 119 | else: 120 | output = F.log_softmax(logit, dim=-1) 121 | else: 122 | # construct weights and biases 123 | weights, biases = [], [] 124 | for i in range(len(self.cutoffs)): 125 | if self.div_val == 1: 126 | l_idx, r_idx = self.cutoff_ends[i], self.cutoff_ends[i + 1] 127 | weight_i = self.out_layers[0].weight[l_idx:r_idx] 128 | bias_i = self.out_layers[0].bias[l_idx:r_idx] 129 | else: 130 | weight_i = self.out_layers[i].weight 131 | bias_i = self.out_layers[i].bias 132 | 133 | if i == 0: 134 | weight_i = torch.cat( 135 | [weight_i, self.cluster_weight], dim=0) 136 | bias_i = torch.cat( 137 | [bias_i, self.cluster_bias], dim=0) 138 | 139 | weights.append(weight_i) 140 | biases.append(bias_i) 141 | 142 | head_weight, head_bias, head_proj = weights[0], biases[0], self.out_projs[0] 143 | 144 | head_logit = self._compute_logit(hidden, head_weight, head_bias, head_proj) 145 | head_logprob = F.log_softmax(head_logit, dim=1) 146 | 147 | if target is None: 148 | out = hidden.new_empty((head_logit.size(0), self.n_token)) 149 | else: 150 | out = torch.zeros_like(target, dtype=hidden.dtype, device=hidden.device) 151 | 152 | offset = 0 153 | cutoff_values = [0] + self.cutoffs 154 | for i in range(len(cutoff_values) - 1): 155 | l_idx, r_idx = cutoff_values[i], cutoff_values[i + 1] 156 | 157 | if target is not None: 158 | mask_i = (target >= l_idx) & (target < r_idx) 159 | indices_i = mask_i.nonzero().squeeze() 160 | 161 | if indices_i.numel() == 0: 162 | continue 163 | 164 | target_i = target.index_select(0, indices_i) - l_idx 165 | head_logprob_i = head_logprob.index_select(0, indices_i) 166 | hidden_i = hidden.index_select(0, indices_i) 167 | else: 168 | hidden_i = hidden 169 | 170 | if i == 0: 171 | if target is not None: 172 | logprob_i = head_logprob_i.gather(1, target_i[:, None]).squeeze(1) 173 | else: 174 | out[:, :self.cutoffs[0]] = head_logprob[:, :self.cutoffs[0]] 175 | else: 176 | weight_i, bias_i, proj_i = weights[i], biases[i], self.out_projs[i] 177 | 178 | tail_logit_i = self._compute_logit(hidden_i, weight_i, bias_i, proj_i) 179 | tail_logprob_i = F.log_softmax(tail_logit_i, dim=1) 180 | cluster_prob_idx = self.cutoffs[0] + i - 1 # No probability for the head cluster 181 | if target is not None: 182 | logprob_i = head_logprob_i[:, cluster_prob_idx] \ 183 | + tail_logprob_i.gather(1, target_i[:, None]).squeeze(1) 184 | else: 185 | logprob_i = head_logprob[:, cluster_prob_idx, None] + tail_logprob_i 186 | out[:, l_idx:r_idx] = logprob_i 187 | 188 | if target is not None: 189 | if (hasattr(self, 'keep_order') and self.keep_order) or keep_order: 190 | out.index_copy_(0, indices_i, -logprob_i) 191 | else: 192 | out[offset:offset+logprob_i.size(0)].copy_(-logprob_i) 193 | offset += logprob_i.size(0) 194 | 195 | return out 196 | 197 | 198 | def log_prob(self, hidden): 199 | r""" Computes Log probabilities for all :math:`n\_classes` 200 | From: https://github.com/pytorch/pytorch/blob/master/torch/nn/modules/adaptive.py 201 | Args: 202 | hidden (Tensor): a minibatch of examples 203 | Returns: 204 | Log-probabilities of for each class :math:`c` 205 | in range :math:`0 <= c <= n\_classes`, where :math:`n\_classes` is a 206 | parameter passed to ``AdaptiveLogSoftmaxWithLoss`` constructor. 207 | Shape: 208 | - Input: :math:`(N, in\_features)` 209 | - Output: :math:`(N, n\_classes)` 210 | """ 211 | if self.n_clusters == 0: 212 | logit = self._compute_logit(hidden, self.out_layers[0].weight, 213 | self.out_layers[0].bias, self.out_projs[0]) 214 | return F.log_softmax(logit, dim=-1) 215 | else: 216 | # construct weights and biases 217 | weights, biases = [], [] 218 | for i in range(len(self.cutoffs)): 219 | if self.div_val == 1: 220 | l_idx, r_idx = self.cutoff_ends[i], self.cutoff_ends[i + 1] 221 | weight_i = self.out_layers[0].weight[l_idx:r_idx] 222 | bias_i = self.out_layers[0].bias[l_idx:r_idx] 223 | else: 224 | weight_i = self.out_layers[i].weight 225 | bias_i = self.out_layers[i].bias 226 | 227 | if i == 0: 228 | weight_i = torch.cat( 229 | [weight_i, self.cluster_weight], dim=0) 230 | bias_i = torch.cat( 231 | [bias_i, self.cluster_bias], dim=0) 232 | 233 | weights.append(weight_i) 234 | biases.append(bias_i) 235 | 236 | head_weight, head_bias, head_proj = weights[0], biases[0], self.out_projs[0] 237 | head_logit = self._compute_logit(hidden, head_weight, head_bias, head_proj) 238 | 239 | out = hidden.new_empty((head_logit.size(0), self.n_token)) 240 | head_logprob = F.log_softmax(head_logit, dim=1) 241 | 242 | cutoff_values = [0] + self.cutoffs 243 | for i in range(len(cutoff_values) - 1): 244 | start_idx, stop_idx = cutoff_values[i], cutoff_values[i + 1] 245 | 246 | if i == 0: 247 | out[:, :self.cutoffs[0]] = head_logprob[:, :self.cutoffs[0]] 248 | else: 249 | weight_i, bias_i, proj_i = weights[i], biases[i], self.out_projs[i] 250 | 251 | tail_logit_i = self._compute_logit(hidden, weight_i, bias_i, proj_i) 252 | tail_logprob_i = F.log_softmax(tail_logit_i, dim=1) 253 | 254 | logprob_i = head_logprob[:, -i] + tail_logprob_i 255 | out[:, start_idx, stop_idx] = logprob_i 256 | 257 | return out 258 | 259 | 260 | class LogUniformSampler(object): 261 | def __init__(self, range_max, n_sample): 262 | """ 263 | Reference : https://github.com/tensorflow/tensorflow/blob/r1.10/tensorflow/python/ops/candidate_sampling_ops.py 264 | `P(class) = (Log(class + 2) - Log(class + 1)) / Log(range_max + 1)` 265 | 266 | expected count can be approximated by 1 - (1 - p)^n 267 | and we use a numerically stable version -expm1(num_tries * log1p(-p)) 268 | 269 | Our implementation fixes num_tries at 2 * n_sample, and the actual #samples will vary from run to run 270 | """ 271 | with torch.no_grad(): 272 | self.range_max = range_max 273 | log_indices = torch.arange(1., range_max+2., 1.).log_() 274 | self.dist = (log_indices[1:] - log_indices[:-1]) / log_indices[-1] 275 | # print('P', self.dist.numpy().tolist()[-30:]) 276 | 277 | self.log_q = (- (-self.dist.double().log1p_() * 2 * n_sample).expm1_()).log_().float() 278 | 279 | self.n_sample = n_sample 280 | 281 | def sample(self, labels): 282 | """ 283 | labels: [b1, b2] 284 | Return 285 | true_log_probs: [b1, b2] 286 | samp_log_probs: [n_sample] 287 | neg_samples: [n_sample] 288 | """ 289 | 290 | # neg_samples = torch.empty(0).long() 291 | n_sample = self.n_sample 292 | n_tries = 2 * n_sample 293 | 294 | with torch.no_grad(): 295 | neg_samples = torch.multinomial(self.dist, n_tries, replacement=True).unique() 296 | device = labels.device 297 | neg_samples = neg_samples.to(device) 298 | true_log_probs = self.log_q[labels].to(device) 299 | samp_log_probs = self.log_q[neg_samples].to(device) 300 | return true_log_probs, samp_log_probs, neg_samples 301 | 302 | def sample_logits(embedding, bias, labels, inputs, sampler): 303 | """ 304 | embedding: an nn.Embedding layer 305 | bias: [n_vocab] 306 | labels: [b1, b2] 307 | inputs: [b1, b2, n_emb] 308 | sampler: you may use a LogUniformSampler 309 | Return 310 | logits: [b1, b2, 1 + n_sample] 311 | """ 312 | true_log_probs, samp_log_probs, neg_samples = sampler.sample(labels) 313 | n_sample = neg_samples.size(0) 314 | b1, b2 = labels.size(0), labels.size(1) 315 | all_ids = torch.cat([labels.view(-1), neg_samples]) 316 | all_w = embedding(all_ids) 317 | true_w = all_w[: -n_sample].view(b1, b2, -1) 318 | sample_w = all_w[- n_sample:].view(n_sample, -1) 319 | 320 | all_b = bias[all_ids] 321 | true_b = all_b[: -n_sample].view(b1, b2) 322 | sample_b = all_b[- n_sample:] 323 | 324 | hit = (labels[:, :, None] == neg_samples).detach() 325 | 326 | true_logits = torch.einsum('ijk,ijk->ij', 327 | [true_w, inputs]) + true_b - true_log_probs 328 | sample_logits = torch.einsum('lk,ijk->ijl', 329 | [sample_w, inputs]) + sample_b - samp_log_probs 330 | sample_logits.masked_fill_(hit, -1e30) 331 | logits = torch.cat([true_logits[:, :, None], sample_logits], -1) 332 | 333 | return logits 334 | 335 | 336 | # class LogUniformSampler(object): 337 | # def __init__(self, range_max, unique=False): 338 | # """ 339 | # Reference : https://github.com/tensorflow/tensorflow/blob/r1.10/tensorflow/python/ops/candidate_sampling_ops.py 340 | # `P(class) = (Log(class + 2) - Log(class + 1)) / Log(range_max + 1)` 341 | # """ 342 | # self.range_max = range_max 343 | # log_indices = torch.arange(1., range_max+2., 1.).log_() 344 | # self.dist = (log_indices[1:] - log_indices[:-1]) / log_indices[-1] 345 | 346 | # self.unique = unique 347 | 348 | # if self.unique: 349 | # self.exclude_mask = torch.ByteTensor(range_max).fill_(0) 350 | 351 | # def sample(self, n_sample, labels): 352 | # pos_sample, new_labels = labels.unique(return_inverse=True) 353 | # n_pos_sample = pos_sample.size(0) 354 | # n_neg_sample = n_sample - n_pos_sample 355 | 356 | # if self.unique: 357 | # self.exclude_mask.index_fill_(0, pos_sample, 1) 358 | # sample_dist = self.dist.clone().masked_fill_(self.exclude_mask, 0) 359 | # self.exclude_mask.index_fill_(0, pos_sample, 0) 360 | # else: 361 | # sample_dist = self.dist 362 | 363 | # neg_sample = torch.multinomial(sample_dist, n_neg_sample) 364 | 365 | # sample = torch.cat([pos_sample, neg_sample]) 366 | # sample_prob = self.dist[sample] 367 | 368 | # return new_labels, sample, sample_prob 369 | 370 | 371 | if __name__ == '__main__': 372 | S, B = 3, 4 373 | n_vocab = 10000 374 | n_sample = 5 375 | H = 32 376 | 377 | labels = torch.LongTensor(S, B).random_(0, n_vocab) 378 | 379 | # sampler = LogUniformSampler(n_vocab, unique=False) 380 | # new_labels, sample, sample_prob = sampler.sample(n_sample, labels) 381 | 382 | sampler = LogUniformSampler(n_vocab, n_sample)#, unique=True) 383 | # true_probs, samp_probs, neg_samples = sampler.sample(n_sample, labels) 384 | 385 | # print('true_probs', true_probs.numpy().tolist()) 386 | # print('samp_probs', samp_probs.numpy().tolist()) 387 | # print('neg_samples', neg_samples.numpy().tolist()) 388 | 389 | # print('sum', torch.sum(sampler.dist).item()) 390 | 391 | # assert torch.all(torch.sort(sample.unique())[0].eq(torch.sort(sample)[0])).item() 392 | 393 | embedding = nn.Embedding(n_vocab, H) 394 | bias = torch.zeros(n_vocab) 395 | inputs = torch.Tensor(S, B, H).normal_() 396 | 397 | logits, out_labels = sample_logits(embedding, bias, labels, inputs, sampler, n_sample) 398 | print('logits', logits.detach().numpy().tolist()) 399 | print('logits shape', logits.size()) 400 | print('out_labels', out_labels.detach().numpy().tolist()) 401 | print('out_labels shape', out_labels.size()) 402 | 403 | -------------------------------------------------------------------------------- /pytorch_pretrained/optimization.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """PyTorch optimization for BERT model.""" 16 | 17 | import math 18 | import torch 19 | from torch.optim import Optimizer 20 | from torch.optim.optimizer import required 21 | from torch.nn.utils import clip_grad_norm_ 22 | import logging 23 | import abc 24 | import sys 25 | 26 | logger = logging.getLogger(__name__) 27 | 28 | 29 | if sys.version_info >= (3, 4): 30 | ABC = abc.ABC 31 | else: 32 | ABC = abc.ABCMeta('ABC', (), {}) 33 | 34 | 35 | class _LRSchedule(ABC): 36 | """ Parent of all LRSchedules here. """ 37 | warn_t_total = False # is set to True for schedules where progressing beyond t_total steps doesn't make sense 38 | def __init__(self, warmup=0.002, t_total=-1, **kw): 39 | """ 40 | :param warmup: what fraction of t_total steps will be used for linear warmup 41 | :param t_total: how many training steps (updates) are planned 42 | :param kw: 43 | """ 44 | super(_LRSchedule, self).__init__(**kw) 45 | if t_total < 0: 46 | logger.warning("t_total value of {} results in schedule not being applied".format(t_total)) 47 | if not 0.0 <= warmup < 1.0 and not warmup == -1: 48 | raise ValueError("Invalid warmup: {} - should be in [0.0, 1.0[ or -1".format(warmup)) 49 | warmup = max(warmup, 0.) 50 | self.warmup, self.t_total = float(warmup), float(t_total) 51 | self.warned_for_t_total_at_progress = -1 52 | 53 | def get_lr(self, step, nowarn=False): 54 | """ 55 | :param step: which of t_total steps we're on 56 | :param nowarn: set to True to suppress warning regarding training beyond specified 't_total' steps 57 | :return: learning rate multiplier for current update 58 | """ 59 | if self.t_total < 0: 60 | return 1. 61 | progress = float(step) / self.t_total 62 | ret = self.get_lr_(progress) 63 | # warning for exceeding t_total (only active with warmup_linear 64 | if not nowarn and self.warn_t_total and progress > 1. and progress > self.warned_for_t_total_at_progress: 65 | logger.warning( 66 | "Training beyond specified 't_total'. Learning rate multiplier set to {}. Please set 't_total' of {} correctly." 67 | .format(ret, self.__class__.__name__)) 68 | self.warned_for_t_total_at_progress = progress 69 | # end warning 70 | return ret 71 | 72 | @abc.abstractmethod 73 | def get_lr_(self, progress): 74 | """ 75 | :param progress: value between 0 and 1 (unless going beyond t_total steps) specifying training progress 76 | :return: learning rate multiplier for current update 77 | """ 78 | return 1. 79 | 80 | 81 | class ConstantLR(_LRSchedule): 82 | def get_lr_(self, progress): 83 | return 1. 84 | 85 | 86 | class WarmupCosineSchedule(_LRSchedule): 87 | """ 88 | Linearly increases learning rate from 0 to 1 over `warmup` fraction of training steps. 89 | Decreases learning rate from 1. to 0. over remaining `1 - warmup` steps following a cosine curve. 90 | If `cycles` (default=0.5) is different from default, learning rate follows cosine function after warmup. 91 | """ 92 | warn_t_total = True 93 | def __init__(self, warmup=0.002, t_total=-1, cycles=.5, **kw): 94 | """ 95 | :param warmup: see LRSchedule 96 | :param t_total: see LRSchedule 97 | :param cycles: number of cycles. Default: 0.5, corresponding to cosine decay from 1. at progress==warmup and 0 at progress==1. 98 | :param kw: 99 | """ 100 | super(WarmupCosineSchedule, self).__init__(warmup=warmup, t_total=t_total, **kw) 101 | self.cycles = cycles 102 | 103 | def get_lr_(self, progress): 104 | if progress < self.warmup: 105 | return progress / self.warmup 106 | else: 107 | progress = (progress - self.warmup) / (1 - self.warmup) # progress after warmup 108 | return 0.5 * (1. + math.cos(math.pi * self.cycles * 2 * progress)) 109 | 110 | 111 | class WarmupCosineWithHardRestartsSchedule(WarmupCosineSchedule): 112 | """ 113 | Linearly increases learning rate from 0 to 1 over `warmup` fraction of training steps. 114 | If `cycles` (default=1.) is different from default, learning rate follows `cycles` times a cosine decaying 115 | learning rate (with hard restarts). 116 | """ 117 | def __init__(self, warmup=0.002, t_total=-1, cycles=1., **kw): 118 | super(WarmupCosineWithHardRestartsSchedule, self).__init__(warmup=warmup, t_total=t_total, cycles=cycles, **kw) 119 | assert(cycles >= 1.) 120 | 121 | def get_lr_(self, progress): 122 | if progress < self.warmup: 123 | return progress / self.warmup 124 | else: 125 | progress = (progress - self.warmup) / (1 - self.warmup) # progress after warmup 126 | ret = 0.5 * (1. + math.cos(math.pi * ((self.cycles * progress) % 1))) 127 | return ret 128 | 129 | 130 | class WarmupCosineWithWarmupRestartsSchedule(WarmupCosineWithHardRestartsSchedule): 131 | """ 132 | All training progress is divided in `cycles` (default=1.) parts of equal length. 133 | Every part follows a schedule with the first `warmup` fraction of the training steps linearly increasing from 0. to 1., 134 | followed by a learning rate decreasing from 1. to 0. following a cosine curve. 135 | """ 136 | def __init__(self, warmup=0.002, t_total=-1, cycles=1., **kw): 137 | assert(warmup * cycles < 1.) 138 | warmup = warmup * cycles if warmup >= 0 else warmup 139 | super(WarmupCosineWithWarmupRestartsSchedule, self).__init__(warmup=warmup, t_total=t_total, cycles=cycles, **kw) 140 | 141 | def get_lr_(self, progress): 142 | progress = progress * self.cycles % 1. 143 | if progress < self.warmup: 144 | return progress / self.warmup 145 | else: 146 | progress = (progress - self.warmup) / (1 - self.warmup) # progress after warmup 147 | ret = 0.5 * (1. + math.cos(math.pi * progress)) 148 | return ret 149 | 150 | 151 | class WarmupConstantSchedule(_LRSchedule): 152 | """ 153 | Linearly increases learning rate from 0 to 1 over `warmup` fraction of training steps. 154 | Keeps learning rate equal to 1. after warmup. 155 | """ 156 | def get_lr_(self, progress): 157 | if progress < self.warmup: 158 | return progress / self.warmup 159 | return 1. 160 | 161 | 162 | class WarmupLinearSchedule(_LRSchedule): 163 | """ 164 | Linearly increases learning rate from 0 to 1 over `warmup` fraction of training steps. 165 | Linearly decreases learning rate from 1. to 0. over remaining `1 - warmup` steps. 166 | """ 167 | warn_t_total = True 168 | def get_lr_(self, progress): 169 | if progress < self.warmup: 170 | return progress / self.warmup 171 | return max((progress - 1.) / (self.warmup - 1.), 0.) 172 | 173 | 174 | SCHEDULES = { 175 | None: ConstantLR, 176 | "none": ConstantLR, 177 | "warmup_cosine": WarmupCosineSchedule, 178 | "warmup_constant": WarmupConstantSchedule, 179 | "warmup_linear": WarmupLinearSchedule 180 | } 181 | 182 | 183 | class BertAdam(Optimizer): 184 | """Implements BERT version of Adam algorithm with weight decay fix. 185 | Params: 186 | lr: learning rate 187 | warmup: portion of t_total for the warmup, -1 means no warmup. Default: -1 188 | t_total: total number of training steps for the learning 189 | rate schedule, -1 means constant learning rate of 1. (no warmup regardless of warmup setting). Default: -1 190 | schedule: schedule to use for the warmup (see above). 191 | Can be `'warmup_linear'`, `'warmup_constant'`, `'warmup_cosine'`, `'none'`, `None` or a `_LRSchedule` object (see below). 192 | If `None` or `'none'`, learning rate is always kept constant. 193 | Default : `'warmup_linear'` 194 | b1: Adams b1. Default: 0.9 195 | b2: Adams b2. Default: 0.999 196 | e: Adams epsilon. Default: 1e-6 197 | weight_decay: Weight decay. Default: 0.01 198 | max_grad_norm: Maximum norm for the gradients (-1 means no clipping). Default: 1.0 199 | """ 200 | def __init__(self, params, lr=required, warmup=-1, t_total=-1, schedule='warmup_linear', 201 | b1=0.9, b2=0.999, e=1e-6, weight_decay=0.01, max_grad_norm=1.0, **kwargs): 202 | if lr is not required and lr < 0.0: 203 | raise ValueError("Invalid learning rate: {} - should be >= 0.0".format(lr)) 204 | if not isinstance(schedule, _LRSchedule) and schedule not in SCHEDULES: 205 | raise ValueError("Invalid schedule parameter: {}".format(schedule)) 206 | if not 0.0 <= b1 < 1.0: 207 | raise ValueError("Invalid b1 parameter: {} - should be in [0.0, 1.0[".format(b1)) 208 | if not 0.0 <= b2 < 1.0: 209 | raise ValueError("Invalid b2 parameter: {} - should be in [0.0, 1.0[".format(b2)) 210 | if not e >= 0.0: 211 | raise ValueError("Invalid epsilon value: {} - should be >= 0.0".format(e)) 212 | # initialize schedule object 213 | if not isinstance(schedule, _LRSchedule): 214 | schedule_type = SCHEDULES[schedule] 215 | schedule = schedule_type(warmup=warmup, t_total=t_total) 216 | else: 217 | if warmup != -1 or t_total != -1: 218 | logger.warning("warmup and t_total on the optimizer are ineffective when _LRSchedule object is provided as schedule. " 219 | "Please specify custom warmup and t_total in _LRSchedule object.") 220 | defaults = dict(lr=lr, schedule=schedule, 221 | b1=b1, b2=b2, e=e, weight_decay=weight_decay, 222 | max_grad_norm=max_grad_norm) 223 | super(BertAdam, self).__init__(params, defaults) 224 | 225 | def get_lr(self): 226 | lr = [] 227 | for group in self.param_groups: 228 | for p in group['params']: 229 | state = self.state[p] 230 | if len(state) == 0: 231 | return [0] 232 | lr_scheduled = group['lr'] 233 | lr_scheduled *= group['schedule'].get_lr(state['step']) 234 | lr.append(lr_scheduled) 235 | return lr 236 | 237 | def step(self, closure=None): 238 | """Performs a single optimization step. 239 | 240 | Arguments: 241 | closure (callable, optional): A closure that reevaluates the model 242 | and returns the loss. 243 | """ 244 | loss = None 245 | if closure is not None: 246 | loss = closure() 247 | 248 | for group in self.param_groups: 249 | for p in group['params']: 250 | if p.grad is None: 251 | continue 252 | grad = p.grad.data 253 | if grad.is_sparse: 254 | raise RuntimeError('Adam does not support sparse gradients, please consider SparseAdam instead') 255 | 256 | state = self.state[p] 257 | 258 | # State initialization 259 | if len(state) == 0: 260 | state['step'] = 0 261 | # Exponential moving average of gradient values 262 | state['next_m'] = torch.zeros_like(p.data) 263 | # Exponential moving average of squared gradient values 264 | state['next_v'] = torch.zeros_like(p.data) 265 | 266 | next_m, next_v = state['next_m'], state['next_v'] 267 | beta1, beta2 = group['b1'], group['b2'] 268 | 269 | # Add grad clipping 270 | if group['max_grad_norm'] > 0: 271 | clip_grad_norm_(p, group['max_grad_norm']) 272 | 273 | # Decay the first and second moment running average coefficient 274 | # In-place operations to update the averages at the same time 275 | next_m.mul_(beta1).add_(1 - beta1, grad) 276 | next_v.mul_(beta2).addcmul_(1 - beta2, grad, grad) 277 | update = next_m / (next_v.sqrt() + group['e']) 278 | 279 | # Just adding the square of the weights to the loss function is *not* 280 | # the correct way of using L2 regularization/weight decay with Adam, 281 | # since that will interact with the m and v parameters in strange ways. 282 | # 283 | # Instead we want to decay the weights in a manner that doesn't interact 284 | # with the m/v parameters. This is equivalent to adding the square 285 | # of the weights to the loss with plain (non-momentum) SGD. 286 | if group['weight_decay'] > 0.0: 287 | update += group['weight_decay'] * p.data 288 | 289 | lr_scheduled = group['lr'] 290 | lr_scheduled *= group['schedule'].get_lr(state['step']) 291 | 292 | update_with_lr = lr_scheduled * update 293 | p.data.add_(-update_with_lr) 294 | 295 | state['step'] += 1 296 | 297 | # step_size = lr_scheduled * math.sqrt(bias_correction2) / bias_correction1 298 | # No bias correction 299 | # bias_correction1 = 1 - beta1 ** state['step'] 300 | # bias_correction2 = 1 - beta2 ** state['step'] 301 | 302 | return loss 303 | -------------------------------------------------------------------------------- /pytorch_pretrained/optimization_openai.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """PyTorch optimization for OpenAI GPT model.""" 16 | 17 | import math 18 | import torch 19 | from torch.optim import Optimizer 20 | from torch.optim.optimizer import required 21 | from torch.nn.utils import clip_grad_norm_ 22 | import logging 23 | from .optimization import SCHEDULES, _LRSchedule, WarmupCosineWithWarmupRestartsSchedule, \ 24 | WarmupCosineWithHardRestartsSchedule, WarmupCosineSchedule, WarmupLinearSchedule, WarmupConstantSchedule 25 | 26 | logger = logging.getLogger(__name__) 27 | 28 | 29 | class OpenAIAdam(Optimizer): 30 | """Implements Open AI version of Adam algorithm with weight decay fix. 31 | """ 32 | def __init__(self, params, lr=required, schedule='warmup_linear', warmup=-1, t_total=-1, 33 | b1=0.9, b2=0.999, e=1e-8, weight_decay=0, 34 | vector_l2=False, max_grad_norm=-1, **kwargs): 35 | if lr is not required and lr < 0.0: 36 | raise ValueError("Invalid learning rate: {} - should be >= 0.0".format(lr)) 37 | if not isinstance(schedule, _LRSchedule) and schedule not in SCHEDULES: 38 | raise ValueError("Invalid schedule parameter: {}".format(schedule)) 39 | if not 0.0 <= b1 < 1.0: 40 | raise ValueError("Invalid b1 parameter: {} - should be in [0.0, 1.0[".format(b1)) 41 | if not 0.0 <= b2 < 1.0: 42 | raise ValueError("Invalid b2 parameter: {} - should be in [0.0, 1.0[".format(b2)) 43 | if not e >= 0.0: 44 | raise ValueError("Invalid epsilon value: {} - should be >= 0.0".format(e)) 45 | # initialize schedule object 46 | if not isinstance(schedule, _LRSchedule): 47 | schedule_type = SCHEDULES[schedule] 48 | schedule = schedule_type(warmup=warmup, t_total=t_total) 49 | else: 50 | if warmup != -1 or t_total != -1: 51 | logger.warning("warmup and t_total on the optimizer are ineffective when _LRSchedule object is provided as schedule. " 52 | "Please specify custom warmup and t_total in _LRSchedule object.") 53 | defaults = dict(lr=lr, schedule=schedule, 54 | b1=b1, b2=b2, e=e, weight_decay=weight_decay, vector_l2=vector_l2, 55 | max_grad_norm=max_grad_norm) 56 | super(OpenAIAdam, self).__init__(params, defaults) 57 | 58 | def get_lr(self): 59 | lr = [] 60 | for group in self.param_groups: 61 | for p in group['params']: 62 | state = self.state[p] 63 | if len(state) == 0: 64 | return [0] 65 | lr_scheduled = group['lr'] 66 | lr_scheduled *= group['schedule'].get_lr(state['step']) 67 | lr.append(lr_scheduled) 68 | return lr 69 | 70 | def step(self, closure=None): 71 | """Performs a single optimization step. 72 | 73 | Arguments: 74 | closure (callable, optional): A closure that reevaluates the model 75 | and returns the loss. 76 | """ 77 | loss = None 78 | if closure is not None: 79 | loss = closure() 80 | 81 | for group in self.param_groups: 82 | for p in group['params']: 83 | if p.grad is None: 84 | continue 85 | grad = p.grad.data 86 | if grad.is_sparse: 87 | raise RuntimeError('Adam does not support sparse gradients, please consider SparseAdam instead') 88 | 89 | state = self.state[p] 90 | 91 | # State initialization 92 | if len(state) == 0: 93 | state['step'] = 0 94 | # Exponential moving average of gradient values 95 | state['exp_avg'] = torch.zeros_like(p.data) 96 | # Exponential moving average of squared gradient values 97 | state['exp_avg_sq'] = torch.zeros_like(p.data) 98 | 99 | exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq'] 100 | beta1, beta2 = group['b1'], group['b2'] 101 | 102 | state['step'] += 1 103 | 104 | # Add grad clipping 105 | if group['max_grad_norm'] > 0: 106 | clip_grad_norm_(p, group['max_grad_norm']) 107 | 108 | # Decay the first and second moment running average coefficient 109 | exp_avg.mul_(beta1).add_(1 - beta1, grad) 110 | exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad) 111 | denom = exp_avg_sq.sqrt().add_(group['e']) 112 | 113 | bias_correction1 = 1 - beta1 ** state['step'] 114 | bias_correction2 = 1 - beta2 ** state['step'] 115 | 116 | lr_scheduled = group['lr'] 117 | lr_scheduled *= group['schedule'].get_lr(state['step']) 118 | 119 | step_size = lr_scheduled * math.sqrt(bias_correction2) / bias_correction1 120 | 121 | p.data.addcdiv_(-step_size, exp_avg, denom) 122 | 123 | # Add weight decay at the end (fixed version) 124 | if (len(p.size()) > 1 or group['vector_l2']) and group['weight_decay'] > 0: 125 | p.data.add_(-lr_scheduled * group['weight_decay'], p.data) 126 | 127 | return loss 128 | -------------------------------------------------------------------------------- /pytorch_pretrained/tokenization.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Tokenization classes.""" 16 | 17 | from __future__ import absolute_import, division, print_function, unicode_literals 18 | 19 | import collections 20 | import logging 21 | import os 22 | import unicodedata 23 | from io import open 24 | 25 | from .file_utils import cached_path 26 | 27 | logger = logging.getLogger(__name__) 28 | 29 | PRETRAINED_VOCAB_ARCHIVE_MAP = { 30 | 'bert-base-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", 31 | 'bert-large-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt", 32 | 'bert-base-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-cased-vocab.txt", 33 | 'bert-large-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-cased-vocab.txt", 34 | 'bert-base-multilingual-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-uncased-vocab.txt", 35 | 'bert-base-multilingual-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-vocab.txt", 36 | 'bert-base-chinese': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-vocab.txt", 37 | } 38 | PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP = { 39 | 'bert-base-uncased': 512, 40 | 'bert-large-uncased': 512, 41 | 'bert-base-cased': 512, 42 | 'bert-large-cased': 512, 43 | 'bert-base-multilingual-uncased': 512, 44 | 'bert-base-multilingual-cased': 512, 45 | 'bert-base-chinese': 512, 46 | } 47 | VOCAB_NAME = 'vocab.txt' 48 | 49 | 50 | def load_vocab(vocab_file): 51 | """Loads a vocabulary file into a dictionary.""" 52 | vocab = collections.OrderedDict() 53 | index = 0 54 | with open(vocab_file, "r", encoding="utf-8") as reader: 55 | while True: 56 | token = reader.readline() 57 | if not token: 58 | break 59 | token = token.strip() 60 | vocab[token] = index 61 | index += 1 62 | return vocab 63 | 64 | 65 | def whitespace_tokenize(text): 66 | """Runs basic whitespace cleaning and splitting on a piece of text.""" 67 | text = text.strip() 68 | if not text: 69 | return [] 70 | tokens = text.split() 71 | return tokens 72 | 73 | 74 | class BertTokenizer(object): 75 | """Runs end-to-end tokenization: punctuation splitting + wordpiece""" 76 | 77 | def __init__(self, vocab_file, do_lower_case=True, max_len=None, do_basic_tokenize=True, 78 | never_split=("[UNK]", "[SEP]", "[PAD]", "[CLS]", "[MASK]")): 79 | """Constructs a BertTokenizer. 80 | 81 | Args: 82 | vocab_file: Path to a one-wordpiece-per-line vocabulary file 83 | do_lower_case: Whether to lower case the input 84 | Only has an effect when do_wordpiece_only=False 85 | do_basic_tokenize: Whether to do basic tokenization before wordpiece. 86 | max_len: An artificial maximum length to truncate tokenized sequences to; 87 | Effective maximum length is always the minimum of this 88 | value (if specified) and the underlying BERT model's 89 | sequence length. 90 | never_split: List of tokens which will never be split during tokenization. 91 | Only has an effect when do_wordpiece_only=False 92 | """ 93 | if not os.path.isfile(vocab_file): 94 | raise ValueError( 95 | "Can't find a vocabulary file at path '{}'. To load the vocabulary from a Google pretrained " 96 | "model use `tokenizer = BertTokenizer.from_pretrained(PRETRAINED_MODEL_NAME)`".format(vocab_file)) 97 | self.vocab = load_vocab(vocab_file) 98 | self.ids_to_tokens = collections.OrderedDict( 99 | [(ids, tok) for tok, ids in self.vocab.items()]) 100 | self.do_basic_tokenize = do_basic_tokenize 101 | if do_basic_tokenize: 102 | self.basic_tokenizer = BasicTokenizer(do_lower_case=do_lower_case, 103 | never_split=never_split) 104 | self.wordpiece_tokenizer = WordpieceTokenizer(vocab=self.vocab) 105 | self.max_len = max_len if max_len is not None else int(1e12) 106 | 107 | def tokenize(self, text): 108 | split_tokens = [] 109 | if self.do_basic_tokenize: 110 | for token in self.basic_tokenizer.tokenize(text): 111 | for sub_token in self.wordpiece_tokenizer.tokenize(token): 112 | split_tokens.append(sub_token) 113 | else: 114 | split_tokens = self.wordpiece_tokenizer.tokenize(text) 115 | return split_tokens 116 | 117 | def convert_tokens_to_ids(self, tokens): 118 | """Converts a sequence of tokens into ids using the vocab.""" 119 | ids = [] 120 | for token in tokens: 121 | ids.append(self.vocab[token]) 122 | if len(ids) > self.max_len: 123 | logger.warning( 124 | "Token indices sequence length is longer than the specified maximum " 125 | " sequence length for this BERT model ({} > {}). Running this" 126 | " sequence through BERT will result in indexing errors".format(len(ids), self.max_len) 127 | ) 128 | return ids 129 | 130 | def convert_ids_to_tokens(self, ids): 131 | """Converts a sequence of ids in wordpiece tokens using the vocab.""" 132 | tokens = [] 133 | for i in ids: 134 | tokens.append(self.ids_to_tokens[i]) 135 | return tokens 136 | 137 | def save_vocabulary(self, vocab_path): 138 | """Save the tokenizer vocabulary to a directory or file.""" 139 | index = 0 140 | if os.path.isdir(vocab_path): 141 | vocab_file = os.path.join(vocab_path, VOCAB_NAME) 142 | with open(vocab_file, "w", encoding="utf-8") as writer: 143 | for token, token_index in sorted(self.vocab.items(), key=lambda kv: kv[1]): 144 | if index != token_index: 145 | logger.warning("Saving vocabulary to {}: vocabulary indices are not consecutive." 146 | " Please check that the vocabulary is not corrupted!".format(vocab_file)) 147 | index = token_index 148 | writer.write(token + u'\n') 149 | index += 1 150 | return vocab_file 151 | 152 | @classmethod 153 | def from_pretrained(cls, pretrained_model_name_or_path, cache_dir=None, *inputs, **kwargs): 154 | """ 155 | Instantiate a PreTrainedBertModel from a pre-trained model file. 156 | Download and cache the pre-trained model file if needed. 157 | """ 158 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_ARCHIVE_MAP: 159 | vocab_file = PRETRAINED_VOCAB_ARCHIVE_MAP[pretrained_model_name_or_path] 160 | if '-cased' in pretrained_model_name_or_path and kwargs.get('do_lower_case', True): 161 | logger.warning("The pre-trained model you are loading is a cased model but you have not set " 162 | "`do_lower_case` to False. We are setting `do_lower_case=False` for you but " 163 | "you may want to check this behavior.") 164 | kwargs['do_lower_case'] = False 165 | elif '-cased' not in pretrained_model_name_or_path and not kwargs.get('do_lower_case', True): 166 | logger.warning("The pre-trained model you are loading is an uncased model but you have set " 167 | "`do_lower_case` to False. We are setting `do_lower_case=True` for you " 168 | "but you may want to check this behavior.") 169 | kwargs['do_lower_case'] = True 170 | else: 171 | vocab_file = pretrained_model_name_or_path 172 | if os.path.isdir(vocab_file): 173 | vocab_file = os.path.join(vocab_file, VOCAB_NAME) 174 | # redirect to the cache, if necessary 175 | try: 176 | resolved_vocab_file = cached_path(vocab_file, cache_dir=cache_dir) 177 | except EnvironmentError: 178 | logger.error( 179 | "Model name '{}' was not found in model name list ({}). " 180 | "We assumed '{}' was a path or url but couldn't find any file " 181 | "associated to this path or url.".format( 182 | pretrained_model_name_or_path, 183 | ', '.join(PRETRAINED_VOCAB_ARCHIVE_MAP.keys()), 184 | vocab_file)) 185 | return None 186 | if resolved_vocab_file == vocab_file: 187 | logger.info("loading vocabulary file {}".format(vocab_file)) 188 | else: 189 | logger.info("loading vocabulary file {} from cache at {}".format( 190 | vocab_file, resolved_vocab_file)) 191 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP: 192 | # if we're using a pretrained model, ensure the tokenizer wont index sequences longer 193 | # than the number of positional embeddings 194 | max_len = PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP[pretrained_model_name_or_path] 195 | kwargs['max_len'] = min(kwargs.get('max_len', int(1e12)), max_len) 196 | # Instantiate tokenizer. 197 | tokenizer = cls(resolved_vocab_file, *inputs, **kwargs) 198 | return tokenizer 199 | 200 | 201 | class BasicTokenizer(object): 202 | """Runs basic tokenization (punctuation splitting, lower casing, etc.).""" 203 | 204 | def __init__(self, 205 | do_lower_case=True, 206 | never_split=("[UNK]", "[SEP]", "[PAD]", "[CLS]", "[MASK]")): 207 | """Constructs a BasicTokenizer. 208 | 209 | Args: 210 | do_lower_case: Whether to lower case the input. 211 | """ 212 | self.do_lower_case = do_lower_case 213 | self.never_split = never_split 214 | 215 | def tokenize(self, text): 216 | """Tokenizes a piece of text.""" 217 | text = self._clean_text(text) 218 | # This was added on November 1st, 2018 for the multilingual and Chinese 219 | # Models. This is also applied to the English Models now, but it doesn't 220 | # matter since the English Models were not trained on any Chinese Datas 221 | # and generally don't have any Chinese Datas in them (there are Chinese 222 | # characters in the vocabulary because Wikipedia does have some Chinese 223 | # words in the English Wikipedia.). 224 | text = self._tokenize_chinese_chars(text) 225 | orig_tokens = whitespace_tokenize(text) 226 | split_tokens = [] 227 | for token in orig_tokens: 228 | if self.do_lower_case and token not in self.never_split: 229 | token = token.lower() 230 | token = self._run_strip_accents(token) 231 | split_tokens.extend(self._run_split_on_punc(token)) 232 | 233 | output_tokens = whitespace_tokenize(" ".join(split_tokens)) 234 | return output_tokens 235 | 236 | def _run_strip_accents(self, text): 237 | """Strips accents from a piece of text.""" 238 | text = unicodedata.normalize("NFD", text) 239 | output = [] 240 | for char in text: 241 | cat = unicodedata.category(char) 242 | if cat == "Mn": 243 | continue 244 | output.append(char) 245 | return "".join(output) 246 | 247 | def _run_split_on_punc(self, text): 248 | """Splits punctuation on a piece of text.""" 249 | if text in self.never_split: 250 | return [text] 251 | chars = list(text) 252 | i = 0 253 | start_new_word = True 254 | output = [] 255 | while i < len(chars): 256 | char = chars[i] 257 | if _is_punctuation(char): 258 | output.append([char]) 259 | start_new_word = True 260 | else: 261 | if start_new_word: 262 | output.append([]) 263 | start_new_word = False 264 | output[-1].append(char) 265 | i += 1 266 | 267 | return ["".join(x) for x in output] 268 | 269 | def _tokenize_chinese_chars(self, text): 270 | """Adds whitespace around any CJK character.""" 271 | output = [] 272 | for char in text: 273 | cp = ord(char) 274 | if self._is_chinese_char(cp): 275 | output.append(" ") 276 | output.append(char) 277 | output.append(" ") 278 | else: 279 | output.append(char) 280 | return "".join(output) 281 | 282 | def _is_chinese_char(self, cp): 283 | """Checks whether CP is the codepoint of a CJK character.""" 284 | # This defines a "chinese character" as anything in the CJK Unicode block: 285 | # https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block) 286 | # 287 | # Note that the CJK Unicode block is NOT all Japanese and Korean characters, 288 | # despite its name. The modern Korean Hangul alphabet is a different block, 289 | # as is Japanese Hiragana and Katakana. Those alphabets are used to write 290 | # space-separated words, so they are not treated specially and handled 291 | # like the all of the other languages. 292 | if ((cp >= 0x4E00 and cp <= 0x9FFF) or # 293 | (cp >= 0x3400 and cp <= 0x4DBF) or # 294 | (cp >= 0x20000 and cp <= 0x2A6DF) or # 295 | (cp >= 0x2A700 and cp <= 0x2B73F) or # 296 | (cp >= 0x2B740 and cp <= 0x2B81F) or # 297 | (cp >= 0x2B820 and cp <= 0x2CEAF) or 298 | (cp >= 0xF900 and cp <= 0xFAFF) or # 299 | (cp >= 0x2F800 and cp <= 0x2FA1F)): # 300 | return True 301 | 302 | return False 303 | 304 | def _clean_text(self, text): 305 | """Performs invalid character removal and whitespace cleanup on text.""" 306 | output = [] 307 | for char in text: 308 | cp = ord(char) 309 | if cp == 0 or cp == 0xfffd or _is_control(char): 310 | continue 311 | if _is_whitespace(char): 312 | output.append(" ") 313 | else: 314 | output.append(char) 315 | return "".join(output) 316 | 317 | 318 | class WordpieceTokenizer(object): 319 | """Runs WordPiece tokenization.""" 320 | 321 | def __init__(self, vocab, unk_token="[UNK]", max_input_chars_per_word=100): 322 | self.vocab = vocab 323 | self.unk_token = unk_token 324 | self.max_input_chars_per_word = max_input_chars_per_word 325 | 326 | def tokenize(self, text): 327 | """Tokenizes a piece of text into its word pieces. 328 | 329 | This uses a greedy longest-match-first algorithm to perform tokenization 330 | using the given vocabulary. 331 | 332 | For example: 333 | input = "unaffable" 334 | output = ["un", "##aff", "##able"] 335 | 336 | Args: 337 | text: A single token or whitespace separated tokens. This should have 338 | already been passed through `BasicTokenizer`. 339 | 340 | Returns: 341 | A list of wordpiece tokens. 342 | """ 343 | 344 | output_tokens = [] 345 | for token in whitespace_tokenize(text): 346 | chars = list(token) 347 | if len(chars) > self.max_input_chars_per_word: 348 | output_tokens.append(self.unk_token) 349 | continue 350 | 351 | is_bad = False 352 | start = 0 353 | sub_tokens = [] 354 | while start < len(chars): 355 | end = len(chars) 356 | cur_substr = None 357 | while start < end: 358 | substr = "".join(chars[start:end]) 359 | if start > 0: 360 | substr = "##" + substr 361 | if substr in self.vocab: 362 | cur_substr = substr 363 | break 364 | end -= 1 365 | if cur_substr is None: 366 | is_bad = True 367 | break 368 | sub_tokens.append(cur_substr) 369 | start = end 370 | 371 | if is_bad: 372 | output_tokens.append(self.unk_token) 373 | else: 374 | output_tokens.extend(sub_tokens) 375 | return output_tokens 376 | 377 | 378 | def _is_whitespace(char): 379 | """Checks whether `chars` is a whitespace character.""" 380 | # \t, \n, and \r are technically contorl characters but we treat them 381 | # as whitespace since they are generally considered as such. 382 | if char == " " or char == "\t" or char == "\n" or char == "\r": 383 | return True 384 | cat = unicodedata.category(char) 385 | if cat == "Zs": 386 | return True 387 | return False 388 | 389 | 390 | def _is_control(char): 391 | """Checks whether `chars` is a control character.""" 392 | # These are technically control characters but we count them as whitespace 393 | # characters. 394 | if char == "\t" or char == "\n" or char == "\r": 395 | return False 396 | cat = unicodedata.category(char) 397 | if cat.startswith("C"): 398 | return True 399 | return False 400 | 401 | 402 | def _is_punctuation(char): 403 | """Checks whether `chars` is a punctuation character.""" 404 | cp = ord(char) 405 | # We treat all non-letter/number ASCII as punctuation. 406 | # Characters such as "^", "$", and "`" are not in the Unicode 407 | # Punctuation class but we treat them as punctuation anyways, for 408 | # consistency. 409 | if ((cp >= 33 and cp <= 47) or (cp >= 58 and cp <= 64) or 410 | (cp >= 91 and cp <= 96) or (cp >= 123 and cp <= 126)): 411 | return True 412 | cat = unicodedata.category(char) 413 | if cat.startswith("P"): 414 | return True 415 | return False 416 | -------------------------------------------------------------------------------- /pytorch_pretrained/tokenization_gpt2.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Tokenization classes for OpenAI GPT.""" 16 | from __future__ import (absolute_import, division, print_function, 17 | unicode_literals) 18 | 19 | import sys 20 | import json 21 | import logging 22 | import os 23 | import regex as re 24 | from io import open 25 | 26 | try: 27 | from functools import lru_cache 28 | except ImportError: 29 | # Just a dummy decorator to get the checks to run on python2 30 | # because honestly I don't want to support a byte-level unicode BPE tokenizer on python 2 right now. 31 | def lru_cache(): 32 | return lambda func: func 33 | 34 | from .file_utils import cached_path 35 | 36 | logger = logging.getLogger(__name__) 37 | 38 | PRETRAINED_VOCAB_ARCHIVE_MAP = { 39 | 'gpt2': "https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-vocab.json", 40 | } 41 | PRETRAINED_MERGES_ARCHIVE_MAP = { 42 | 'gpt2': "https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-merges.txt", 43 | } 44 | PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP = { 45 | 'gpt2': 1024, 46 | } 47 | VOCAB_NAME = 'vocab.json' 48 | MERGES_NAME = 'merges.txt' 49 | SPECIAL_TOKENS_NAME = 'special_tokens.txt' 50 | 51 | @lru_cache() 52 | def bytes_to_unicode(): 53 | """ 54 | Returns list of utf-8 byte and a corresponding list of unicode strings. 55 | The reversible bpe codes work on unicode strings. 56 | This means you need a large # of unicode characters in your vocab if you want to avoid UNKs. 57 | When you're at something like a 10B token dataset you end up needing around 5K for decent coverage. 58 | This is a signficant percentage of your normal, say, 32K bpe vocab. 59 | To avoid that, we want lookup tables between utf-8 bytes and unicode strings. 60 | And avoids mapping to whitespace/control characters the bpe code barfs on. 61 | """ 62 | _chr = unichr if sys.version_info[0] == 2 else chr 63 | bs = list(range(ord("!"), ord("~")+1))+list(range(ord("¡"), ord("¬")+1))+list(range(ord("®"), ord("ÿ")+1)) 64 | cs = bs[:] 65 | n = 0 66 | for b in range(2**8): 67 | if b not in bs: 68 | bs.append(b) 69 | cs.append(2**8+n) 70 | n += 1 71 | cs = [_chr(n) for n in cs] 72 | return dict(zip(bs, cs)) 73 | 74 | def get_pairs(word): 75 | """Return set of symbol pairs in a word. 76 | 77 | Word is represented as tuple of symbols (symbols being variable-length strings). 78 | """ 79 | pairs = set() 80 | prev_char = word[0] 81 | for char in word[1:]: 82 | pairs.add((prev_char, char)) 83 | prev_char = char 84 | return pairs 85 | 86 | class GPT2Tokenizer(object): 87 | """ 88 | GPT-2 BPE tokenizer. Peculiarities: 89 | - Byte-level BPE 90 | """ 91 | @classmethod 92 | def from_pretrained(cls, pretrained_model_name_or_path, cache_dir=None, *inputs, **kwargs): 93 | """ 94 | Instantiate a PreTrainedBertModel from a pre-trained model file. 95 | Download and cache the pre-trained model file if needed. 96 | """ 97 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_ARCHIVE_MAP: 98 | vocab_file = PRETRAINED_VOCAB_ARCHIVE_MAP[pretrained_model_name_or_path] 99 | merges_file = PRETRAINED_MERGES_ARCHIVE_MAP[pretrained_model_name_or_path] 100 | special_tokens_file = None 101 | else: 102 | vocab_file = os.path.join(pretrained_model_name_or_path, VOCAB_NAME) 103 | merges_file = os.path.join(pretrained_model_name_or_path, MERGES_NAME) 104 | special_tokens_file = os.path.join(pretrained_model_name_or_path, SPECIAL_TOKENS_NAME) 105 | if not os.path.exists(special_tokens_file): 106 | special_tokens_file = None 107 | else: 108 | logger.info("loading special tokens file {}".format(special_tokens_file)) 109 | # redirect to the cache, if necessary 110 | try: 111 | resolved_vocab_file = cached_path(vocab_file, cache_dir=cache_dir) 112 | resolved_merges_file = cached_path(merges_file, cache_dir=cache_dir) 113 | except EnvironmentError: 114 | logger.error( 115 | "Model name '{}' was not found in model name list ({}). " 116 | "We assumed '{}' was a path or url but couldn't find files {} and {} " 117 | "at this path or url.".format( 118 | pretrained_model_name_or_path, 119 | ', '.join(PRETRAINED_VOCAB_ARCHIVE_MAP.keys()), 120 | pretrained_model_name_or_path, 121 | vocab_file, merges_file)) 122 | return None 123 | if resolved_vocab_file == vocab_file and resolved_merges_file == merges_file: 124 | logger.info("loading vocabulary file {}".format(vocab_file)) 125 | logger.info("loading merges file {}".format(merges_file)) 126 | else: 127 | logger.info("loading vocabulary file {} from cache at {}".format( 128 | vocab_file, resolved_vocab_file)) 129 | logger.info("loading merges file {} from cache at {}".format( 130 | merges_file, resolved_merges_file)) 131 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP: 132 | # if we're using a pretrained model, ensure the tokenizer wont index sequences longer 133 | # than the number of positional embeddings 134 | max_len = PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP[pretrained_model_name_or_path] 135 | kwargs['max_len'] = min(kwargs.get('max_len', int(1e12)), max_len) 136 | # Instantiate tokenizer. 137 | if special_tokens_file and 'special_tokens' not in kwargs: 138 | special_tokens = open(special_tokens_file, encoding='utf-8').read().split('\n')[:-1] 139 | else: 140 | special_tokens = kwargs.pop('special_tokens', []) 141 | tokenizer = cls(resolved_vocab_file, resolved_merges_file, special_tokens=special_tokens, *inputs, **kwargs) 142 | return tokenizer 143 | 144 | def __init__(self, vocab_file, merges_file, errors='replace', special_tokens=None, max_len=None): 145 | self.max_len = max_len if max_len is not None else int(1e12) 146 | self.encoder = json.load(open(vocab_file)) 147 | self.decoder = {v:k for k,v in self.encoder.items()} 148 | self.errors = errors # how to handle errors in decoding 149 | self.byte_encoder = bytes_to_unicode() 150 | self.byte_decoder = {v:k for k, v in self.byte_encoder.items()} 151 | bpe_data = open(merges_file, encoding='utf-8').read().split('\n')[1:-1] 152 | bpe_merges = [tuple(merge.split()) for merge in bpe_data] 153 | self.bpe_ranks = dict(zip(bpe_merges, range(len(bpe_merges)))) 154 | self.cache = {} 155 | 156 | # Should haved added re.IGNORECASE so BPE merges can happen for capitalized versions of contractions 157 | self.pat = re.compile(r"""'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+""") 158 | 159 | self.special_tokens = {} 160 | self.special_tokens_decoder = {} 161 | self.set_special_tokens(special_tokens) 162 | 163 | def __len__(self): 164 | return len(self.encoder) + len(self.special_tokens) 165 | 166 | def set_special_tokens(self, special_tokens): 167 | """ Add a list of additional tokens to the encoder. 168 | The additional tokens are indexed starting from the last index of the 169 | current vocabulary in the order of the `special_tokens` list. 170 | """ 171 | if not special_tokens: 172 | self.special_tokens = {} 173 | self.special_tokens_decoder = {} 174 | return 175 | self.special_tokens = dict((tok, len(self.encoder) + i) for i, tok in enumerate(special_tokens)) 176 | self.special_tokens_decoder = {v:k for k, v in self.special_tokens.items()} 177 | logger.info("Special tokens {}".format(self.special_tokens)) 178 | 179 | def bpe(self, token): 180 | if token in self.cache: 181 | return self.cache[token] 182 | word = tuple(token) 183 | pairs = get_pairs(word) 184 | 185 | if not pairs: 186 | return token 187 | 188 | while True: 189 | bigram = min(pairs, key = lambda pair: self.bpe_ranks.get(pair, float('inf'))) 190 | if bigram not in self.bpe_ranks: 191 | break 192 | first, second = bigram 193 | new_word = [] 194 | i = 0 195 | while i < len(word): 196 | try: 197 | j = word.index(first, i) 198 | new_word.extend(word[i:j]) 199 | i = j 200 | except: 201 | new_word.extend(word[i:]) 202 | break 203 | 204 | if word[i] == first and i < len(word)-1 and word[i+1] == second: 205 | new_word.append(first+second) 206 | i += 2 207 | else: 208 | new_word.append(word[i]) 209 | i += 1 210 | new_word = tuple(new_word) 211 | word = new_word 212 | if len(word) == 1: 213 | break 214 | else: 215 | pairs = get_pairs(word) 216 | word = ' '.join(word) 217 | self.cache[token] = word 218 | return word 219 | 220 | def tokenize(self, text): 221 | """ Tokenize a string. """ 222 | bpe_tokens = [] 223 | for token in re.findall(self.pat, text): 224 | token = ''.join(self.byte_encoder[ord(b)] for b in token) 225 | bpe_tokens.extend(bpe_token for bpe_token in self.bpe(token).split(' ')) 226 | return bpe_tokens 227 | 228 | def convert_tokens_to_ids(self, tokens): 229 | """ Converts a sequence of tokens into ids using the vocab. """ 230 | ids = [] 231 | if isinstance(tokens, str) or (sys.version_info[0] == 2 and isinstance(tokens, unicode)): 232 | if tokens in self.special_tokens: 233 | return self.special_tokens[tokens] 234 | else: 235 | return self.encoder.get(tokens, 0) 236 | for token in tokens: 237 | if token in self.special_tokens: 238 | ids.append(self.special_tokens[token]) 239 | else: 240 | ids.append(self.encoder.get(token, 0)) 241 | if len(ids) > self.max_len: 242 | logger.warning( 243 | "Token indices sequence length is longer than the specified maximum " 244 | " sequence length for this OpenAI GPT model ({} > {}). Running this" 245 | " sequence through the model will result in indexing errors".format(len(ids), self.max_len) 246 | ) 247 | return ids 248 | 249 | def convert_ids_to_tokens(self, ids, skip_special_tokens=False): 250 | """Converts a sequence of ids in BPE tokens using the vocab.""" 251 | tokens = [] 252 | for i in ids: 253 | if i in self.special_tokens_decoder: 254 | if not skip_special_tokens: 255 | tokens.append(self.special_tokens_decoder[i]) 256 | else: 257 | tokens.append(self.decoder[i]) 258 | return tokens 259 | 260 | def encode(self, text): 261 | return self.convert_tokens_to_ids(self.tokenize(text)) 262 | 263 | def decode(self, tokens): 264 | text = ''.join([self.decoder[token] for token in tokens]) 265 | text = bytearray([self.byte_decoder[c] for c in text]).decode('utf-8', errors=self.errors) 266 | return text 267 | 268 | def save_vocabulary(self, vocab_path): 269 | """Save the tokenizer vocabulary and merge files to a directory.""" 270 | if not os.path.isdir(vocab_path): 271 | logger.error("Vocabulary path ({}) should be a directory".format(vocab_path)) 272 | return 273 | vocab_file = os.path.join(vocab_path, VOCAB_NAME) 274 | merge_file = os.path.join(vocab_path, MERGES_NAME) 275 | special_tokens_file = os.path.join(vocab_path, SPECIAL_TOKENS_NAME) 276 | 277 | with open(vocab_file, 'w', encoding='utf-8') as f: 278 | f.write(json.dumps(self.encoder, ensure_ascii=False)) 279 | 280 | index = 0 281 | with open(merge_file, "w", encoding="utf-8") as writer: 282 | writer.write(u'#version: 0.2\n') 283 | for bpe_tokens, token_index in sorted(self.bpe_ranks.items(), key=lambda kv: kv[1]): 284 | if index != token_index: 285 | logger.warning("Saving vocabulary to {}: BPE merge indices are not consecutive." 286 | " Please check that the tokenizer is not corrupted!".format(merge_file)) 287 | index = token_index 288 | writer.write(' '.join(bpe_tokens) + u'\n') 289 | index += 1 290 | 291 | index = len(self.encoder) 292 | with open(special_tokens_file, 'w', encoding='utf-8') as writer: 293 | for token, token_index in sorted(self.special_tokens.items(), key=lambda kv: kv[1]): 294 | if index != token_index: 295 | logger.warning("Saving special tokens vocabulary to {}: BPE indices are not consecutive." 296 | " Please check that the tokenizer is not corrupted!".format(special_tokens_file)) 297 | index = token_index 298 | writer.write(token + u'\n') 299 | index += 1 300 | 301 | return vocab_file, merge_file, special_tokens_file 302 | -------------------------------------------------------------------------------- /pytorch_pretrained/tokenization_openai.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | """Tokenization classes for OpenAI GPT.""" 16 | from __future__ import (absolute_import, division, print_function, 17 | unicode_literals) 18 | 19 | import json 20 | import logging 21 | import os 22 | import re 23 | import sys 24 | from io import open 25 | 26 | from tqdm import tqdm 27 | 28 | from .file_utils import cached_path 29 | from .tokenization import BasicTokenizer 30 | 31 | logger = logging.getLogger(__name__) 32 | 33 | PRETRAINED_VOCAB_ARCHIVE_MAP = { 34 | 'openai-gpt': "https://s3.amazonaws.com/models.huggingface.co/bert/openai-gpt-vocab.json", 35 | } 36 | PRETRAINED_MERGES_ARCHIVE_MAP = { 37 | 'openai-gpt': "https://s3.amazonaws.com/models.huggingface.co/bert/openai-gpt-merges.txt", 38 | } 39 | PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP = { 40 | 'openai-gpt': 512, 41 | } 42 | VOCAB_NAME = 'vocab.json' 43 | MERGES_NAME = 'merges.txt' 44 | SPECIAL_TOKENS_NAME = 'special_tokens.txt' 45 | 46 | def get_pairs(word): 47 | """ 48 | Return set of symbol pairs in a word. 49 | word is represented as tuple of symbols (symbols being variable-length strings) 50 | """ 51 | pairs = set() 52 | prev_char = word[0] 53 | for char in word[1:]: 54 | pairs.add((prev_char, char)) 55 | prev_char = char 56 | return pairs 57 | 58 | def text_standardize(text): 59 | """ 60 | fixes some issues the spacy tokenizer had on books corpus 61 | also does some whitespace standardization 62 | """ 63 | text = text.replace('—', '-') 64 | text = text.replace('–', '-') 65 | text = text.replace('―', '-') 66 | text = text.replace('…', '...') 67 | text = text.replace('´', "'") 68 | text = re.sub(r'''(-+|~+|!+|"+|;+|\?+|\++|,+|\)+|\(+|\\+|\/+|\*+|\[+|\]+|}+|{+|\|+|_+)''', r' \1 ', text) 69 | text = re.sub(r'\s*\n\s*', ' \n ', text) 70 | text = re.sub(r'[^\S\n]+', ' ', text) 71 | return text.strip() 72 | 73 | class OpenAIGPTTokenizer(object): 74 | """ 75 | BPE tokenizer. Peculiarities: 76 | - lower case all inputs 77 | - uses SpaCy tokenizer and ftfy for pre-BPE tokenization if they are installed, fallback to BERT's BasicTokenizer if not. 78 | - argument special_tokens and function set_special_tokens: 79 | can be used to add additional symbols (ex: "__classify__") to a vocabulary. 80 | """ 81 | @classmethod 82 | def from_pretrained(cls, pretrained_model_name_or_path, cache_dir=None, *inputs, **kwargs): 83 | """ 84 | Instantiate a PreTrainedBertModel from a pre-trained model file. 85 | Download and cache the pre-trained model file if needed. 86 | """ 87 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_ARCHIVE_MAP: 88 | vocab_file = PRETRAINED_VOCAB_ARCHIVE_MAP[pretrained_model_name_or_path] 89 | merges_file = PRETRAINED_MERGES_ARCHIVE_MAP[pretrained_model_name_or_path] 90 | special_tokens_file = None 91 | else: 92 | vocab_file = os.path.join(pretrained_model_name_or_path, VOCAB_NAME) 93 | merges_file = os.path.join(pretrained_model_name_or_path, MERGES_NAME) 94 | special_tokens_file = os.path.join(pretrained_model_name_or_path, SPECIAL_TOKENS_NAME) 95 | if not os.path.exists(special_tokens_file): 96 | special_tokens_file = None 97 | else: 98 | logger.info("loading special tokens file {}".format(special_tokens_file)) 99 | # redirect to the cache, if necessary 100 | try: 101 | resolved_vocab_file = cached_path(vocab_file, cache_dir=cache_dir) 102 | resolved_merges_file = cached_path(merges_file, cache_dir=cache_dir) 103 | except EnvironmentError: 104 | logger.error( 105 | "Model name '{}' was not found in model name list ({}). " 106 | "We assumed '{}' was a path or url but couldn't find files {} and {} " 107 | "at this path or url.".format( 108 | pretrained_model_name_or_path, 109 | ', '.join(PRETRAINED_VOCAB_ARCHIVE_MAP.keys()), 110 | pretrained_model_name_or_path, 111 | vocab_file, merges_file)) 112 | return None 113 | if resolved_vocab_file == vocab_file and resolved_merges_file == merges_file: 114 | logger.info("loading vocabulary file {}".format(vocab_file)) 115 | logger.info("loading merges file {}".format(merges_file)) 116 | else: 117 | logger.info("loading vocabulary file {} from cache at {}".format( 118 | vocab_file, resolved_vocab_file)) 119 | logger.info("loading merges file {} from cache at {}".format( 120 | merges_file, resolved_merges_file)) 121 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP: 122 | # if we're using a pretrained model, ensure the tokenizer wont index sequences longer 123 | # than the number of positional embeddings 124 | max_len = PRETRAINED_VOCAB_POSITIONAL_EMBEDDINGS_SIZE_MAP[pretrained_model_name_or_path] 125 | kwargs['max_len'] = min(kwargs.get('max_len', int(1e12)), max_len) 126 | # Instantiate tokenizer. 127 | if special_tokens_file and 'special_tokens' not in kwargs: 128 | special_tokens = open(special_tokens_file, encoding='utf-8').read().split('\n')[:-1] 129 | else: 130 | special_tokens = kwargs.pop('special_tokens', []) 131 | tokenizer = cls(resolved_vocab_file, resolved_merges_file, special_tokens=special_tokens, *inputs, **kwargs) 132 | return tokenizer 133 | 134 | def __init__(self, vocab_file, merges_file, special_tokens=None, max_len=None): 135 | try: 136 | import ftfy 137 | import spacy 138 | self.nlp = spacy.load('en', disable=['parser', 'tagger', 'ner', 'textcat']) 139 | self.fix_text = ftfy.fix_text 140 | except ImportError: 141 | logger.warning("ftfy or spacy is not installed using BERT BasicTokenizer instead of SpaCy & ftfy.") 142 | self.nlp = BasicTokenizer(do_lower_case=True, 143 | never_split=special_tokens if special_tokens is not None else []) 144 | self.fix_text = None 145 | 146 | self.max_len = max_len if max_len is not None else int(1e12) 147 | self.encoder = json.load(open(vocab_file, encoding="utf-8")) 148 | self.decoder = {v:k for k,v in self.encoder.items()} 149 | merges = open(merges_file, encoding='utf-8').read().split('\n')[1:-1] 150 | merges = [tuple(merge.split()) for merge in merges] 151 | self.bpe_ranks = dict(zip(merges, range(len(merges)))) 152 | self.cache = {} 153 | self.special_tokens = {} 154 | self.special_tokens_decoder = {} 155 | self.set_special_tokens(special_tokens) 156 | 157 | def __len__(self): 158 | return len(self.encoder) + len(self.special_tokens) 159 | 160 | def set_special_tokens(self, special_tokens): 161 | """ Add a list of additional tokens to the encoder. 162 | The additional tokens are indexed starting from the last index of the 163 | current vocabulary in the order of the `special_tokens` list. 164 | """ 165 | if not special_tokens: 166 | self.special_tokens = {} 167 | self.special_tokens_decoder = {} 168 | return 169 | self.special_tokens = dict((tok, len(self.encoder) + i) for i, tok in enumerate(special_tokens)) 170 | self.special_tokens_decoder = {v:k for k, v in self.special_tokens.items()} 171 | if self.fix_text is None: 172 | # Using BERT's BasicTokenizer: we can update the tokenizer 173 | self.nlp.never_split = special_tokens 174 | logger.info("Special tokens {}".format(self.special_tokens)) 175 | 176 | def bpe(self, token): 177 | word = tuple(token[:-1]) + (token[-1] + '',) 178 | if token in self.cache: 179 | return self.cache[token] 180 | pairs = get_pairs(word) 181 | 182 | if not pairs: 183 | return token+'' 184 | 185 | while True: 186 | bigram = min(pairs, key=lambda pair: self.bpe_ranks.get(pair, float('inf'))) 187 | if bigram not in self.bpe_ranks: 188 | break 189 | first, second = bigram 190 | new_word = [] 191 | i = 0 192 | while i < len(word): 193 | try: 194 | j = word.index(first, i) 195 | new_word.extend(word[i:j]) 196 | i = j 197 | except: 198 | new_word.extend(word[i:]) 199 | break 200 | 201 | if word[i] == first and i < len(word)-1 and word[i+1] == second: 202 | new_word.append(first+second) 203 | i += 2 204 | else: 205 | new_word.append(word[i]) 206 | i += 1 207 | new_word = tuple(new_word) 208 | word = new_word 209 | if len(word) == 1: 210 | break 211 | else: 212 | pairs = get_pairs(word) 213 | word = ' '.join(word) 214 | if word == '\n ': 215 | word = '\n' 216 | self.cache[token] = word 217 | return word 218 | 219 | def tokenize(self, text): 220 | """ Tokenize a string. """ 221 | split_tokens = [] 222 | if self.fix_text is None: 223 | # Using BERT's BasicTokenizer 224 | text = self.nlp.tokenize(text) 225 | for token in text: 226 | split_tokens.extend([t for t in self.bpe(token).split(' ')]) 227 | else: 228 | # Using SpaCy & ftfy (original tokenization process of OpenAI GPT) 229 | text = self.nlp(text_standardize(self.fix_text(text))) 230 | for token in text: 231 | split_tokens.extend([t for t in self.bpe(token.text.lower()).split(' ')]) 232 | return split_tokens 233 | 234 | def convert_tokens_to_ids(self, tokens): 235 | """ Converts a sequence of tokens into ids using the vocab. """ 236 | ids = [] 237 | if isinstance(tokens, str) or (sys.version_info[0] == 2 and isinstance(tokens, unicode)): 238 | if tokens in self.special_tokens: 239 | return self.special_tokens[tokens] 240 | else: 241 | return self.encoder.get(tokens, 0) 242 | for token in tokens: 243 | if token in self.special_tokens: 244 | ids.append(self.special_tokens[token]) 245 | else: 246 | ids.append(self.encoder.get(token, 0)) 247 | if len(ids) > self.max_len: 248 | logger.warning( 249 | "Token indices sequence length is longer than the specified maximum " 250 | " sequence length for this OpenAI GPT model ({} > {}). Running this" 251 | " sequence through the model will result in indexing errors".format(len(ids), self.max_len) 252 | ) 253 | return ids 254 | 255 | def convert_ids_to_tokens(self, ids, skip_special_tokens=False): 256 | """Converts a sequence of ids in BPE tokens using the vocab.""" 257 | tokens = [] 258 | for i in ids: 259 | if i in self.special_tokens_decoder: 260 | if not skip_special_tokens: 261 | tokens.append(self.special_tokens_decoder[i]) 262 | else: 263 | tokens.append(self.decoder[i]) 264 | return tokens 265 | 266 | def encode(self, text): 267 | return self.convert_tokens_to_ids(self.tokenize(text)) 268 | 269 | def decode(self, ids, skip_special_tokens=False, clean_up_tokenization_spaces=True): 270 | """Converts a sequence of ids in a string.""" 271 | tokens = self.convert_ids_to_tokens(ids, skip_special_tokens=skip_special_tokens) 272 | out_string = ''.join(tokens).replace('', ' ').strip() 273 | if clean_up_tokenization_spaces: 274 | out_string = out_string.replace('', '') 275 | out_string = out_string.replace(' .', '.').replace(' ?', '?').replace(' !', '!').replace(' ,', ',').replace(' ,', ',' 276 | ).replace(" ' ", "'").replace(" n't", "n't").replace(" 'm", "'m").replace(" do not", " don't" 277 | ).replace(" 's", "'s").replace(" 've", "'ve").replace(" 're", "'re") 278 | return out_string 279 | 280 | def save_vocabulary(self, vocab_path): 281 | """Save the tokenizer vocabulary and merge files to a directory.""" 282 | if not os.path.isdir(vocab_path): 283 | logger.error("Vocabulary path ({}) should be a directory".format(vocab_path)) 284 | return 285 | vocab_file = os.path.join(vocab_path, VOCAB_NAME) 286 | merge_file = os.path.join(vocab_path, MERGES_NAME) 287 | special_tokens_file = os.path.join(vocab_path, SPECIAL_TOKENS_NAME) 288 | 289 | with open(vocab_file, 'w', encoding='utf-8') as f: 290 | f.write(json.dumps(self.encoder, ensure_ascii=False)) 291 | 292 | index = 0 293 | with open(merge_file, "w", encoding="utf-8") as writer: 294 | writer.write(u'#version: 0.2\n') 295 | for bpe_tokens, token_index in sorted(self.bpe_ranks.items(), key=lambda kv: kv[1]): 296 | if index != token_index: 297 | logger.warning("Saving vocabulary to {}: BPE merge indices are not consecutive." 298 | " Please check that the tokenizer is not corrupted!".format(merge_file)) 299 | index = token_index 300 | writer.write(' '.join(bpe_tokens) + u'\n') 301 | index += 1 302 | 303 | index = len(self.encoder) 304 | with open(special_tokens_file, 'w', encoding='utf-8') as writer: 305 | for token, token_index in sorted(self.special_tokens.items(), key=lambda kv: kv[1]): 306 | if index != token_index: 307 | logger.warning("Saving special tokens vocabulary to {}: BPE indices are not consecutive." 308 | " Please check that the tokenizer is not corrupted!".format(special_tokens_file)) 309 | index = token_index 310 | writer.write(token + u'\n') 311 | index += 1 312 | 313 | return vocab_file, merge_file, special_tokens_file 314 | -------------------------------------------------------------------------------- /pytorch_pretrained/tokenization_transfo_xl.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # Copyright 2018 Google AI, Google Brain and Carnegie Mellon University Authors and the HuggingFace Inc. team. 3 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | """ Tokenization classes for Transformer XL model. 17 | Adapted from https://github.com/kimiyoung/transformer-xl. 18 | """ 19 | from __future__ import (absolute_import, division, print_function, 20 | unicode_literals) 21 | 22 | import glob 23 | import logging 24 | import os 25 | import sys 26 | from collections import Counter, OrderedDict 27 | from io import open 28 | import unicodedata 29 | 30 | import torch 31 | import numpy as np 32 | 33 | from .file_utils import cached_path 34 | 35 | if sys.version_info[0] == 2: 36 | import cPickle as pickle 37 | else: 38 | import pickle 39 | 40 | 41 | logger = logging.getLogger(__name__) 42 | 43 | PRETRAINED_VOCAB_ARCHIVE_MAP = { 44 | 'transfo-xl-wt103': "https://s3.amazonaws.com/models.huggingface.co/bert/transfo-xl-wt103-vocab.bin", 45 | } 46 | VOCAB_NAME = 'vocab.bin' 47 | 48 | PRETRAINED_CORPUS_ARCHIVE_MAP = { 49 | 'transfo-xl-wt103': "https://s3.amazonaws.com/models.huggingface.co/bert/transfo-xl-wt103-corpus.bin", 50 | } 51 | CORPUS_NAME = 'corpus.bin' 52 | 53 | class TransfoXLTokenizer(object): 54 | """ 55 | Transformer-XL tokenizer adapted from Vocab class in https://github.com/kimiyoung/transformer-xl 56 | """ 57 | @classmethod 58 | def from_pretrained(cls, pretrained_model_name_or_path, cache_dir=None, *inputs, **kwargs): 59 | """ 60 | Instantiate a TransfoXLTokenizer. 61 | The TransfoXLTokenizer. 62 | """ 63 | if pretrained_model_name_or_path in PRETRAINED_VOCAB_ARCHIVE_MAP: 64 | vocab_file = PRETRAINED_VOCAB_ARCHIVE_MAP[pretrained_model_name_or_path] 65 | else: 66 | if os.path.isdir(pretrained_model_name_or_path): 67 | vocab_file = os.path.join(pretrained_model_name_or_path, VOCAB_NAME) 68 | else: 69 | vocab_file = pretrained_model_name_or_path 70 | # redirect to the cache, if necessary 71 | try: 72 | resolved_vocab_file = cached_path(vocab_file, cache_dir=cache_dir) 73 | except EnvironmentError: 74 | logger.error( 75 | "Model name '{}' was not found in model name list ({}). " 76 | "We assumed '{}' was a path or url but couldn't find files {} " 77 | "at this path or url.".format( 78 | pretrained_model_name_or_path, 79 | ', '.join(PRETRAINED_VOCAB_ARCHIVE_MAP.keys()), 80 | pretrained_model_name_or_path, 81 | vocab_file)) 82 | return None 83 | if resolved_vocab_file == vocab_file: 84 | logger.info("loading vocabulary file {}".format(vocab_file)) 85 | else: 86 | logger.info("loading vocabulary file {} from cache at {}".format( 87 | vocab_file, resolved_vocab_file)) 88 | 89 | # Instantiate tokenizer. 90 | tokenizer = cls(*inputs, **kwargs) 91 | vocab_dict = torch.load(resolved_vocab_file) 92 | for key, value in vocab_dict.items(): 93 | tokenizer.__dict__[key] = value 94 | return tokenizer 95 | 96 | def __init__(self, special=[], min_freq=0, max_size=None, lower_case=False, 97 | delimiter=None, vocab_file=None, never_split=("", "", "")): 98 | self.counter = Counter() 99 | self.special = special 100 | self.min_freq = min_freq 101 | self.max_size = max_size 102 | self.lower_case = lower_case 103 | self.delimiter = delimiter 104 | self.vocab_file = vocab_file 105 | self.never_split = never_split 106 | 107 | def count_file(self, path, verbose=False, add_eos=False): 108 | if verbose: print('counting file {} ...'.format(path)) 109 | assert os.path.exists(path) 110 | 111 | sents = [] 112 | with open(path, 'r', encoding='utf-8') as f: 113 | for idx, line in enumerate(f): 114 | if verbose and idx > 0 and idx % 500000 == 0: 115 | print(' line {}'.format(idx)) 116 | symbols = self.tokenize(line, add_eos=add_eos) 117 | self.counter.update(symbols) 118 | sents.append(symbols) 119 | 120 | return sents 121 | 122 | def count_sents(self, sents, verbose=False): 123 | """ 124 | sents : a list of sentences, each a list of tokenized symbols 125 | """ 126 | if verbose: print('counting {} sents ...'.format(len(sents))) 127 | for idx, symbols in enumerate(sents): 128 | if verbose and idx > 0 and idx % 500000 == 0: 129 | print(' line {}'.format(idx)) 130 | self.counter.update(symbols) 131 | 132 | def _build_from_file(self, vocab_file): 133 | self.idx2sym = [] 134 | self.sym2idx = OrderedDict() 135 | 136 | with open(vocab_file, 'r', encoding='utf-8') as f: 137 | for line in f: 138 | symb = line.strip().split()[0] 139 | self.add_symbol(symb) 140 | if '' in self.sym2idx: 141 | self.unk_idx = self.sym2idx[''] 142 | elif '' in self.sym2idx: 143 | self.unk_idx = self.sym2idx[''] 144 | else: 145 | raise ValueError('No token in vocabulary') 146 | 147 | def save_vocabulary(self, vocab_path): 148 | """Save the tokenizer vocabulary to a directory or file.""" 149 | index = 0 150 | if os.path.isdir(vocab_path): 151 | vocab_file = os.path.join(vocab_path, VOCAB_NAME) 152 | torch.save(self.__dict__, vocab_file) 153 | return vocab_file 154 | 155 | def build_vocab(self): 156 | if self.vocab_file: 157 | print('building vocab from {}'.format(self.vocab_file)) 158 | self._build_from_file(self.vocab_file) 159 | print('final vocab size {}'.format(len(self))) 160 | else: 161 | print('building vocab with min_freq={}, max_size={}'.format( 162 | self.min_freq, self.max_size)) 163 | self.idx2sym = [] 164 | self.sym2idx = OrderedDict() 165 | 166 | for sym in self.special: 167 | self.add_special(sym) 168 | 169 | for sym, cnt in self.counter.most_common(self.max_size): 170 | if cnt < self.min_freq: break 171 | self.add_symbol(sym) 172 | 173 | print('final vocab size {} from {} unique tokens'.format( 174 | len(self), len(self.counter))) 175 | 176 | def encode_file(self, path, ordered=False, verbose=False, add_eos=True, 177 | add_double_eos=False): 178 | if verbose: print('encoding file {} ...'.format(path)) 179 | assert os.path.exists(path) 180 | encoded = [] 181 | with open(path, 'r', encoding='utf-8') as f: 182 | for idx, line in enumerate(f): 183 | if verbose and idx > 0 and idx % 500000 == 0: 184 | print(' line {}'.format(idx)) 185 | symbols = self.tokenize(line, add_eos=add_eos, 186 | add_double_eos=add_double_eos) 187 | encoded.append(self.convert_to_tensor(symbols)) 188 | 189 | if ordered: 190 | encoded = torch.cat(encoded) 191 | 192 | return encoded 193 | 194 | def encode_sents(self, sents, ordered=False, verbose=False): 195 | if verbose: print('encoding {} sents ...'.format(len(sents))) 196 | encoded = [] 197 | for idx, symbols in enumerate(sents): 198 | if verbose and idx > 0 and idx % 500000 == 0: 199 | print(' line {}'.format(idx)) 200 | encoded.append(self.convert_to_tensor(symbols)) 201 | 202 | if ordered: 203 | encoded = torch.cat(encoded) 204 | 205 | return encoded 206 | 207 | def add_special(self, sym): 208 | if sym not in self.sym2idx: 209 | self.idx2sym.append(sym) 210 | self.sym2idx[sym] = len(self.idx2sym) - 1 211 | setattr(self, '{}_idx'.format(sym.strip('<>')), self.sym2idx[sym]) 212 | 213 | def add_symbol(self, sym): 214 | if sym not in self.sym2idx: 215 | self.idx2sym.append(sym) 216 | self.sym2idx[sym] = len(self.idx2sym) - 1 217 | 218 | def get_sym(self, idx): 219 | assert 0 <= idx < len(self), 'Index {} out of vocabulary range'.format(idx) 220 | return self.idx2sym[idx] 221 | 222 | def get_idx(self, sym): 223 | if sym in self.sym2idx: 224 | return self.sym2idx[sym] 225 | else: 226 | # print('encounter unk {}'.format(sym)) 227 | # assert '' not in sym 228 | if hasattr(self, 'unk_idx'): 229 | return self.sym2idx.get(sym, self.unk_idx) 230 | # Backward compatibility with pre-trained Models 231 | elif '' in self.sym2idx: 232 | return self.sym2idx[''] 233 | elif '' in self.sym2idx: 234 | return self.sym2idx[''] 235 | else: 236 | raise ValueError('Token not in vocabulary and no token in vocabulary for replacement') 237 | 238 | def convert_ids_to_tokens(self, indices): 239 | """Converts a sequence of indices in symbols using the vocab.""" 240 | return [self.get_sym(idx) for idx in indices] 241 | 242 | def convert_tokens_to_ids(self, symbols): 243 | """Converts a sequence of symbols into ids using the vocab.""" 244 | return [self.get_idx(sym) for sym in symbols] 245 | 246 | def convert_to_tensor(self, symbols): 247 | return torch.LongTensor(self.convert_tokens_to_ids(symbols)) 248 | 249 | def decode(self, indices, exclude=None): 250 | """Converts a sequence of indices in a string.""" 251 | if exclude is None: 252 | return ' '.join([self.get_sym(idx) for idx in indices]) 253 | else: 254 | return ' '.join([self.get_sym(idx) for idx in indices if idx not in exclude]) 255 | 256 | def __len__(self): 257 | return len(self.idx2sym) 258 | 259 | def tokenize(self, line, add_eos=False, add_double_eos=False): 260 | line = line.strip() 261 | # convert to lower case 262 | if self.lower_case: 263 | line = line.lower() 264 | 265 | # empty delimiter '' will evaluate False 266 | if self.delimiter == '': 267 | symbols = line 268 | else: 269 | symbols = line.split(self.delimiter) 270 | 271 | if add_double_eos: # lm1b 272 | return [''] + symbols + [''] 273 | elif add_eos: 274 | return symbols + [''] 275 | else: 276 | return symbols 277 | 278 | 279 | class LMOrderedIterator(object): 280 | def __init__(self, data, bsz, bptt, device='cpu', ext_len=None): 281 | """ 282 | Datas -- LongTensor -- the LongTensor is strictly ordered 283 | """ 284 | self.bsz = bsz 285 | self.bptt = bptt 286 | self.ext_len = ext_len if ext_len is not None else 0 287 | 288 | self.device = device 289 | 290 | # Work out how cleanly we can divide the dataset into bsz parts. 291 | self.n_step = data.size(0) // bsz 292 | 293 | # Trim off any extra elements that wouldn't cleanly fit (remainders). 294 | data = data.narrow(0, 0, self.n_step * bsz) 295 | 296 | # Evenly divide the Datas across the bsz batches. 297 | self.data = data.view(bsz, -1).t().contiguous().to(device) 298 | 299 | # Number of mini-batches 300 | self.n_batch = (self.n_step + self.bptt - 1) // self.bptt 301 | 302 | def get_batch(self, i, bptt=None): 303 | if bptt is None: bptt = self.bptt 304 | seq_len = min(bptt, self.data.size(0) - 1 - i) 305 | 306 | end_idx = i + seq_len 307 | beg_idx = max(0, i - self.ext_len) 308 | 309 | data = self.data[beg_idx:end_idx] 310 | target = self.data[i+1:i+1+seq_len] 311 | 312 | data_out = data.transpose(0, 1).contiguous().to(self.device) 313 | target_out = target.transpose(0, 1).contiguous().to(self.device) 314 | 315 | return data_out, target_out, seq_len 316 | 317 | def get_fixlen_iter(self, start=0): 318 | for i in range(start, self.data.size(0) - 1, self.bptt): 319 | yield self.get_batch(i) 320 | 321 | def get_varlen_iter(self, start=0, std=5, min_len=5, max_deviation=3): 322 | max_len = self.bptt + max_deviation * std 323 | i = start 324 | while True: 325 | bptt = self.bptt if np.random.random() < 0.95 else self.bptt / 2. 326 | bptt = min(max_len, max(min_len, int(np.random.normal(bptt, std)))) 327 | data, target, seq_len = self.get_batch(i, bptt) 328 | i += seq_len 329 | yield data, target, seq_len 330 | if i >= self.data.size(0) - 2: 331 | break 332 | 333 | def __iter__(self): 334 | return self.get_fixlen_iter() 335 | 336 | 337 | class LMShuffledIterator(object): 338 | def __init__(self, data, bsz, bptt, device='cpu', ext_len=None, shuffle=False): 339 | """ 340 | Datas -- list[LongTensor] -- there is no order among the LongTensors 341 | """ 342 | self.data = data 343 | 344 | self.bsz = bsz 345 | self.bptt = bptt 346 | self.ext_len = ext_len if ext_len is not None else 0 347 | 348 | self.device = device 349 | self.shuffle = shuffle 350 | 351 | def get_sent_stream(self): 352 | # index iterator 353 | epoch_indices = np.random.permutation(len(self.data)) if self.shuffle \ 354 | else np.array(range(len(self.data))) 355 | 356 | # sentence iterator 357 | for idx in epoch_indices: 358 | yield self.data[idx] 359 | 360 | def stream_iterator(self, sent_stream): 361 | # streams for each Datas in the batch 362 | streams = [None] * self.bsz 363 | 364 | data = torch.LongTensor(self.bptt, self.bsz) 365 | target = torch.LongTensor(self.bptt, self.bsz) 366 | 367 | n_retain = 0 368 | 369 | while True: 370 | # Datas : [n_retain+bptt x bsz] 371 | # target : [bptt x bsz] 372 | data[n_retain:].fill_(-1) 373 | target.fill_(-1) 374 | 375 | valid_batch = True 376 | 377 | for i in range(self.bsz): 378 | n_filled = 0 379 | try: 380 | while n_filled < self.bptt: 381 | if streams[i] is None or len(streams[i]) <= 1: 382 | streams[i] = next(sent_stream) 383 | # number of new tokens to fill in 384 | n_new = min(len(streams[i]) - 1, self.bptt - n_filled) 385 | # first n_retain tokens are retained from last batch 386 | data[n_retain+n_filled:n_retain+n_filled+n_new, i] = \ 387 | streams[i][:n_new] 388 | target[n_filled:n_filled+n_new, i] = \ 389 | streams[i][1:n_new+1] 390 | streams[i] = streams[i][n_new:] 391 | n_filled += n_new 392 | except StopIteration: 393 | valid_batch = False 394 | break 395 | 396 | if not valid_batch: 397 | return 398 | 399 | data_out = data.transpose(0, 1).contiguous().to(self.device) 400 | target_out = target.transpose(0, 1).contiguous().to(self.device) 401 | 402 | yield data_out, target_out, self.bptt 403 | 404 | n_retain = min(data.size(0), self.ext_len) 405 | if n_retain > 0: 406 | data[:n_retain] = data[-n_retain:] 407 | data.resize_(n_retain + self.bptt, data.size(1)) 408 | 409 | def __iter__(self): 410 | # sent_stream is an iterator 411 | sent_stream = self.get_sent_stream() 412 | 413 | for batch in self.stream_iterator(sent_stream): 414 | yield batch 415 | 416 | 417 | class LMMultiFileIterator(LMShuffledIterator): 418 | def __init__(self, paths, vocab, bsz, bptt, device='cpu', ext_len=None, 419 | shuffle=False): 420 | 421 | self.paths = paths 422 | self.vocab = vocab 423 | 424 | self.bsz = bsz 425 | self.bptt = bptt 426 | self.ext_len = ext_len if ext_len is not None else 0 427 | 428 | self.device = device 429 | self.shuffle = shuffle 430 | 431 | def get_sent_stream(self, path): 432 | sents = self.vocab.encode_file(path, add_double_eos=True) 433 | if self.shuffle: 434 | np.random.shuffle(sents) 435 | sent_stream = iter(sents) 436 | 437 | return sent_stream 438 | 439 | def __iter__(self): 440 | if self.shuffle: 441 | np.random.shuffle(self.paths) 442 | 443 | for path in self.paths: 444 | # sent_stream is an iterator 445 | sent_stream = self.get_sent_stream(path) 446 | for batch in self.stream_iterator(sent_stream): 447 | yield batch 448 | 449 | 450 | class TransfoXLCorpus(object): 451 | @classmethod 452 | def from_pretrained(cls, pretrained_model_name_or_path, cache_dir=None, *inputs, **kwargs): 453 | """ 454 | Instantiate a pre-processed corpus. 455 | """ 456 | vocab = TransfoXLTokenizer.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs) 457 | if pretrained_model_name_or_path in PRETRAINED_CORPUS_ARCHIVE_MAP: 458 | corpus_file = PRETRAINED_CORPUS_ARCHIVE_MAP[pretrained_model_name_or_path] 459 | else: 460 | corpus_file = os.path.join(pretrained_model_name_or_path, CORPUS_NAME) 461 | # redirect to the cache, if necessary 462 | try: 463 | resolved_corpus_file = cached_path(corpus_file, cache_dir=cache_dir) 464 | except EnvironmentError: 465 | logger.error( 466 | "Corpus '{}' was not found in corpus list ({}). " 467 | "We assumed '{}' was a path or url but couldn't find files {} " 468 | "at this path or url.".format( 469 | pretrained_model_name_or_path, 470 | ', '.join(PRETRAINED_VOCAB_ARCHIVE_MAP.keys()), 471 | pretrained_model_name_or_path, 472 | corpus_file)) 473 | return None 474 | if resolved_corpus_file == corpus_file: 475 | logger.info("loading corpus file {}".format(corpus_file)) 476 | else: 477 | logger.info("loading corpus file {} from cache at {}".format( 478 | corpus_file, resolved_corpus_file)) 479 | 480 | # Instantiate tokenizer. 481 | corpus = cls(*inputs, **kwargs) 482 | corpus_dict = torch.load(resolved_corpus_file) 483 | for key, value in corpus_dict.items(): 484 | corpus.__dict__[key] = value 485 | corpus.vocab = vocab 486 | if corpus.train is not None: 487 | corpus.train = torch.tensor(corpus.train, dtype=torch.long) 488 | if corpus.valid is not None: 489 | corpus.valid = torch.tensor(corpus.valid, dtype=torch.long) 490 | if corpus.test is not None: 491 | corpus.test = torch.tensor(corpus.test, dtype=torch.long) 492 | return corpus 493 | 494 | def __init__(self, *args, **kwargs): 495 | self.vocab = TransfoXLTokenizer(*args, **kwargs) 496 | self.dataset = None 497 | self.train = None 498 | self.valid = None 499 | self.test = None 500 | 501 | def build_corpus(self, path, dataset): 502 | self.dataset = dataset 503 | 504 | if self.dataset in ['ptb', 'wt2', 'enwik8', 'text8']: 505 | self.vocab.count_file(os.path.join(path, 'train.txt')) 506 | self.vocab.count_file(os.path.join(path, 'valid.txt')) 507 | self.vocab.count_file(os.path.join(path, 'test.txt')) 508 | elif self.dataset == 'wt103': 509 | self.vocab.count_file(os.path.join(path, 'train.txt')) 510 | elif self.dataset == 'lm1b': 511 | train_path_pattern = os.path.join( 512 | path, '1-billion-word-language-modeling-benchmark-r13output', 513 | 'training-monolingual.tokenized.shuffled', 'news.en-*') 514 | train_paths = glob.glob(train_path_pattern) 515 | # the vocab will load from file when build_vocab() is called 516 | 517 | self.vocab.build_vocab() 518 | 519 | if self.dataset in ['ptb', 'wt2', 'wt103']: 520 | self.train = self.vocab.encode_file( 521 | os.path.join(path, 'train.txt'), ordered=True) 522 | self.valid = self.vocab.encode_file( 523 | os.path.join(path, 'valid.txt'), ordered=True) 524 | self.test = self.vocab.encode_file( 525 | os.path.join(path, 'test.txt'), ordered=True) 526 | elif self.dataset in ['enwik8', 'text8']: 527 | self.train = self.vocab.encode_file( 528 | os.path.join(path, 'train.txt'), ordered=True, add_eos=False) 529 | self.valid = self.vocab.encode_file( 530 | os.path.join(path, 'valid.txt'), ordered=True, add_eos=False) 531 | self.test = self.vocab.encode_file( 532 | os.path.join(path, 'test.txt'), ordered=True, add_eos=False) 533 | elif self.dataset == 'lm1b': 534 | self.train = train_paths 535 | self.valid = self.vocab.encode_file( 536 | os.path.join(path, 'valid.txt'), ordered=False, add_double_eos=True) 537 | self.test = self.vocab.encode_file( 538 | os.path.join(path, 'test.txt'), ordered=False, add_double_eos=True) 539 | 540 | def get_iterator(self, split, *args, **kwargs): 541 | if split == 'train': 542 | if self.dataset in ['ptb', 'wt2', 'wt103', 'enwik8', 'text8']: 543 | data_iter = LMOrderedIterator(self.train, *args, **kwargs) 544 | elif self.dataset == 'lm1b': 545 | kwargs['shuffle'] = True 546 | data_iter = LMMultiFileIterator(self.train, self.vocab, *args, **kwargs) 547 | elif split in ['valid', 'test']: 548 | data = self.valid if split == 'valid' else self.test 549 | if self.dataset in ['ptb', 'wt2', 'wt103', 'enwik8', 'text8']: 550 | data_iter = LMOrderedIterator(data, *args, **kwargs) 551 | elif self.dataset == 'lm1b': 552 | data_iter = LMShuffledIterator(data, *args, **kwargs) 553 | 554 | return data_iter 555 | 556 | 557 | def get_lm_corpus(datadir, dataset): 558 | fn = os.path.join(datadir, 'cache.pt') 559 | fn_pickle = os.path.join(datadir, 'cache.pkl') 560 | if os.path.exists(fn): 561 | print('Loading cached dataset...') 562 | corpus = torch.load(fn_pickle) 563 | elif os.path.exists(fn): 564 | print('Loading cached dataset from pickle...') 565 | with open(fn, "rb") as fp: 566 | corpus = pickle.load(fp) 567 | else: 568 | print('Producing dataset {}...'.format(dataset)) 569 | kwargs = {} 570 | if dataset in ['wt103', 'wt2']: 571 | kwargs['special'] = [''] 572 | kwargs['lower_case'] = False 573 | elif dataset == 'ptb': 574 | kwargs['special'] = [''] 575 | kwargs['lower_case'] = True 576 | elif dataset == 'lm1b': 577 | kwargs['special'] = [] 578 | kwargs['lower_case'] = False 579 | kwargs['vocab_file'] = os.path.join(datadir, '1b_word_vocab.txt') 580 | elif dataset in ['enwik8', 'text8']: 581 | pass 582 | 583 | corpus = TransfoXLCorpus(datadir, dataset, **kwargs) 584 | torch.save(corpus, fn) 585 | 586 | return corpus 587 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | import time 3 | import torch 4 | import numpy as np 5 | from train_eval import train 6 | from importlib import import_module 7 | import argparse 8 | from utils import built_train_dataset, built_dev_dataset, get_time_dif 9 | import os 10 | os.environ["CUDA_VISIBLE_DEVICES"] = '0' 11 | 12 | 13 | parser = argparse.ArgumentParser(description='Chinese Ner Pytorch') 14 | parser.add_argument('--doing', type=str, required=True, help='choose a action: train,test,predict') 15 | parser.add_argument('--model', type=str, required=True, help='choose a model: Bert,Albert,Xlnet,Gpt-2') 16 | args = parser.parse_args() 17 | 18 | 19 | if __name__ == '__main__': 20 | 21 | model_name = args.model 22 | x = import_module('Models.' + model_name) 23 | config = x.Config() 24 | np.random.seed(1) 25 | torch.manual_seed(1) 26 | torch.cuda.manual_seed_all(1) 27 | torch.backends.cudnn.deterministic = True # 保证每次结果一样 28 | 29 | start_time = time.time() 30 | print("Loading Datas...") 31 | train_dataset = built_train_dataset(config) 32 | dev_dataset = built_dev_dataset(config) 33 | time_dif = get_time_dif(start_time) 34 | print("Time usage:", time_dif) 35 | 36 | if args.doing=='train': 37 | model = x.Model(config).to(config.device) 38 | train(config, model, train_dataset, dev_dataset) 39 | if args.doing=='predict': 40 | model = x.Model(config).to(config.device) 41 | predict(config,model,) 42 | -------------------------------------------------------------------------------- /train_eval.py: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | import numpy as np 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | from sklearn import metrics 7 | import time 8 | from sklearn.metrics import f1_score, classification_report 9 | 10 | from pytorch_pretrained import BertTokenizer 11 | from pytorch_pretrained.optimization import * 12 | from utils import * 13 | 14 | 15 | def train(config, model, train_dataset, dev_dataset): 16 | start_time = time.time() 17 | optimizer = torch.optim.Adam(model.parameters(), lr=config.learning_rate) 18 | total_batch = 0 # 记录进行到多少batch 19 | for epoch in range(config.num_epochs): 20 | for i, batch in enumerate(train_dataset): 21 | spend_time=get_time_dif(start_time) 22 | model.zero_grad() 23 | model.train() 24 | batch= tuple(_.to(config.device) for _ in batch) 25 | input_id,input_mask,label,output_mask = batch 26 | encode=model(batch) 27 | loss=model.loss(encode,input_mask,label) 28 | loss.backward() 29 | optimizer.step() 30 | if total_batch % 50 == 0: 31 | print('step: {} | epoch: {}| loss: {:.4f}| time: {}|' 32 | .format(total_batch, epoch, loss.item(),spend_time)) 33 | total_batch+=1 34 | dev(model,epoch,dev_dataset) 35 | torch.save(model.state_dict(),config.save_path) 36 | 37 | 38 | 39 | 40 | def dev(model,epoch,dev_dataset): 41 | model.eval() 42 | count=0 43 | length = 0 44 | y_predicts,y_labels=[],[] 45 | eval_loss,eval_acc,eval_f1=0,0,0 46 | with torch.no_grad(): 47 | for i,batch in enumerate(dev_dataset): 48 | input_ids, input_mask, label_ids, output_mask = batch 49 | length+=input_ids.size(0) 50 | encode = model(batch) 51 | eval_los = model.loss(encode,output_mask,label_ids) 52 | eval_loss = eval_los + eval_loss 53 | count += 1 54 | 55 | predicts = model.predict(encode, output_mask) 56 | y_predicts.append(predicts) 57 | 58 | label_ids = label_ids.view(1, -1) 59 | label_ids = label_ids[label_ids != -1] 60 | y_labels.append(label_ids) 61 | 62 | eval_predicted = torch.cat(y_predicts, dim=0) 63 | eval_labeled = torch.cat(y_labels, dim=0) 64 | model.acc_f1(eval_predicted, eval_labeled) 65 | model.class_report(eval_predicted, eval_labeled) 66 | print('eval epoch : {}| loss : {}'.format(epoch,eval_loss/length)) 67 | 68 | 69 | # def predict(model,config,input_str=""): 70 | # model.eval() # 取消batchnorm和dropout,用于评估阶段 71 | # model.to(config.device) 72 | # VOCAB = config.bert_path # your path for model and vocab 73 | # tokenizer = BertTokenizer.from_pretrained(VOCAB) 74 | # while True: 75 | # with torch.no_grad(): 76 | # input_str = input("请输入文本: ") 77 | # input_ids = tokenizer.encode(input_str,add_special_tokens=True) # add_spicial_tokens=True,为自动为sentence加上[CLS]和[SEP] 78 | # input_mask = [1] * len(input_ids) 79 | # output_mask = [0] + [1] * (len(input_ids) - 2) + [0] # 用于屏蔽特殊token 80 | # 81 | # input_ids_tensor = torch.LongTensor(input_ids).reshape(1, -1) 82 | # input_mask_tensor = torch.LongTensor(input_mask).reshape(1, -1) 83 | # output_mask_tensor = torch.LongTensor(output_mask).reshape(1, -1) 84 | # input_ids_tensor = input_ids_tensor.to(DEVICE) 85 | # input_mask_tensor = input_mask_tensor.to(DEVICE) 86 | # output_mask_tensor = output_mask_tensor.to(DEVICE) 87 | # 88 | # bert_encode = self.model(input_ids_tensor, input_mask_tensor) 89 | # predicts = self.model.predict(bert_encode, output_mask_tensor) 90 | # 91 | # print('paths:{}'.format(predicts)) 92 | # entities = [] 93 | # for tag in self.tags: 94 | # tags = get_tags(predicts[0], tag, self.model.tag_map) 95 | # entities += format_result(tags, input_str, tag) 96 | # print(entities) 97 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | import torch 3 | import os 4 | import numpy as np 5 | from sklearn.metrics import f1_score, classification_report 6 | from tqdm import tqdm 7 | import time 8 | from datetime import timedelta 9 | from torch.utils.data import TensorDataset, DataLoader 10 | import datetime 11 | 12 | 13 | 14 | PAD, CLS, SEP = '[PAD]', '[CLS]', '[SEP]' # padding符号, bert中句子开头,结尾符号 15 | 16 | 17 | class InputFeatures(object): 18 | def __init__(self, input_id, label_id, input_mask,output_mask): 19 | self.input_id = input_id 20 | self.label_id = label_id 21 | self.input_mask = input_mask 22 | self.output_mask = output_mask 23 | 24 | def build_dataset(config): 25 | 26 | def load_dataset(data_path,label_path,pad_size,label_dic,tokenizer): 27 | """ 28 | :param data_path:文本数据路径 29 | :param label_path:标签数据路径 30 | :param pad_size:每个句子最大长度 31 | :param label_dic:词性种类表 32 | :return: 33 | """ 34 | 35 | result=[] 36 | with open(data_path, 'r', encoding='utf-8') as df: 37 | with open(label_path, 'r', encoding='utf-8') as lf: 38 | train_data=df.readlines() 39 | train_label=lf.readlines() 40 | for word , label in zip(train_data,train_label): 41 | tokens=word.split() 42 | label=label.split() 43 | 44 | if len(tokens) > pad_size - 2: # 大于最大长度进行截断 45 | tokens = tokens[0:(pad_size - 2)] 46 | label = label[0:(pad_size - 2)] 47 | 48 | # token to index 49 | tokens_c_s = '[CLS] ' + ''.join(tokens) + ' [SEP]' 50 | label_c_s = ' '.join(label) 51 | 52 | tokenized_text=tokenizer.tokenize(tokens_c_s) 53 | input_ids=tokenizer.convert_tokens_to_ids(tokenized_text) 54 | 55 | label_ids=[label_dic[i] for i in label_c_s.split()] 56 | input_mask=[1]*len(input_ids) 57 | 58 | if len(input_ids) < pad_size: 59 | input_id = input_ids + ([0]*(pad_size-len(input_ids))) 60 | input_mask += ([0]*(pad_size-len(input_ids))) 61 | if len(label_ids) < pad_size: 62 | label_id = label_ids+([-1]*(pad_size-len(label_ids))) 63 | 64 | output_mask=[1]*len(tokens) 65 | output_mask=[0]+output_mask+[0] 66 | if len(output_mask) < pad_size: 67 | output_mask +=([0]*(pad_size-len(output_mask))) 68 | 69 | assert len(input_id) == pad_size 70 | assert len(input_mask) == pad_size 71 | assert len(label_id) == pad_size 72 | assert len(output_mask) == pad_size 73 | 74 | # 处理后数据 75 | # ------------------------------------------- 76 | # 原始: 我 是 中 国 人 77 | # 分词: [CLS] 我 是 中 国 人 [SEP] 78 | # input_id: 101 2 12 13 16 14 102 0 0 0 79 | # input_mask: 1 1 1 1 1 1 1 0 0 0 80 | # label_id: T T 0 0 0 -1 -1 -1 -1 -1 81 | # output_mask: 0 1 1 1 1 1 0 0 0 0 82 | 83 | feature = InputFeatures(input_id=input_id,label_id=label_id,input_mask=input_mask,output_mask=output_mask) 84 | result.append(feature) 85 | return result 86 | data=load_dataset(config.train_data_path,config.train_label_path,config.pad_size,config.vocab_class,config.tokenizer) 87 | train_ids = torch.LongTensor([_.input_id for _ in data]) 88 | train_masks = torch.LongTensor([_.input_mask for _ in data]) 89 | train_tags = torch.LongTensor([_.label_id for _ in data]) 90 | output_masks = torch.LongTensor([_.output_mask for _ in data]) 91 | train_dataset = TensorDataset(train_ids, train_masks, train_tags, output_masks) 92 | return train_dataset 93 | 94 | def built_train_dataset(config): 95 | train_dataset=build_dataset(config) 96 | return DataLoader(train_dataset,shuffle=True,batch_size=config.batch_size) 97 | 98 | 99 | def built_dev_dataset(config): 100 | dev_dataset=build_dataset(config) 101 | return DataLoader(dev_dataset,shuffle=False,batch_size=config.batch_size) 102 | 103 | # def save_model(model, epoch, path='result', **kwargs): 104 | # """ 105 | # 默认保留所有模型 106 | # :param model: 模型 107 | # :param path: 保存路径 108 | # :param loss: 校验损失 109 | # :param last_loss: 最佳epoch损失 110 | # :param kwargs: every_epoch or best_epoch 111 | # :return: 112 | # """ 113 | # if not os.path.exists(path): 114 | # os.mkdir(path) 115 | # if kwargs.get('name', None) is None: 116 | # cur_time = datetime.datetime.now().strftime('%Y-%m-%d#%H:%M:%S') 117 | # name = cur_time + '--epoch:{}'.format(epoch) 118 | # full_name = os.path.join(path, name) 119 | # torch.save(model.state_dict(), full_name) 120 | # print('Saved model at epoch {} successfully'.format(epoch)) 121 | # with open('{}/checkpoint'.format(path), 'w') as file: 122 | # file.write(name) 123 | # print('Write to checkpoint') 124 | # 125 | # 126 | # def load_model(model, path='result', **kwargs): 127 | # if kwargs.get('name', None) is None: 128 | # with open('{}/checkpoint'.format(path)) as file: 129 | # content = file.read().strip() 130 | # name = os.path.join(path, content) 131 | # else: 132 | # name=kwargs['name'] 133 | # name = os.path.join(path,name) 134 | # model.load_state_dict(torch.load(name, map_location=lambda storage, loc: storage)) 135 | # print('load model {} successfully'.format(name)) 136 | # return model 137 | 138 | 139 | def get_time_dif(start_time): 140 | """获取已使用时间""" 141 | end_time = time.time() 142 | time_dif = end_time - start_time 143 | return timedelta(seconds=int(round(time_dif))) 144 | 145 | 146 | --------------------------------------------------------------------------------