精华内容
下载资源
问答
  • 数据探索是有效的命名实体识别的重要组成部分,因为系统通常会产生常见的意外错误,一旦发现这些错误便可以轻松修复。 尽管任务表面上很简单,但是自动命名实体识别系统仍然会犯很多错误,除非经过针对使用案例量身...
  • 文章目录一、Huggingface-transformers介绍二、文件组成三、config四、Tokenizer五、基本模型BertModel六、序列标注任务实战(命名实体识别)1.加载各类包(略)2.载入训练参数3.模型初始4....


    一、Huggingface-transformers介绍

    transformers(以前称为pytorch-transformers和pytorch-pretrained-bert)提供用于自然语言理解(NLU)和自然语言生成(NLG)的BERT家族通用结构(BERT,GPT-2,RoBERTa,XLM,DistilBert,XLNet等),包含超过32种、涵盖100多种语言的预训练模型。同时提供TensorFlow 2.0和PyTorch之间的高互通性。项目安装非常便捷,使用pip命令即可。使用transformers前需要下载好pytorch(版本>=1.0)或者tensorflow2.0。下面以pytorch为例,来演示使用方法

    pip install transformers
    

    github:https://github.com/huggingface/transformers

    通过此次源码分享,你将了解:

    • transformers加载bert的方法,及相关类的源码
    • 以命名实体识别和阅读理解为例,展示如何使用transformers实现下游任务

    transformer项目组成介绍
    examples中是项目提供的各种任务的例子。src/transformers/文件夹是项目涉及各类函数的地址。

    transformer1.png

    token-classification是序列标注例子所在的文件夹,其中run_ner.py是此次分享的命名实体识别程序文件。
    transformer2.png

    二、文件组成

    pytroch 版本的bert主要有三个文件组成:

    • 词表文件(Tokenizer) —— vocab.txt
    • 配置文件 —— bert_config.json
    • 模型文件 —— *.bin

    file

    三、config

    bert_config.json为Bert配置文件,存放了BertModel的配置,控制模型的名称、最终输出的样式、隐藏层宽度和深度、激活函数的类别等。将Config类导出时文件格式为 json格式,就像下面这样:

    {
        "attention_probs_dropout_prob": 0.1, 
        "directionality": "bidi", 
        "hidden_act": "gelu", 
        "hidden_dropout_prob": 0.1, 
        "hidden_size": 768, 
        "initializer_range": 0.02, 
        "intermediate_size": 3072, 
        "max_position_embeddings": 512, 
        "num_attention_heads": 12, 
        "num_hidden_layers": 12, 
        "pooler_fc_size": 768, 
        "pooler_num_attention_heads": 12, 
        "pooler_num_fc_layers": 3, 
        "pooler_size_per_head": 128, 
        "pooler_type": "first_token_transform", 
        "type_vocab_size": 2, 
        "vocab_size": 21128
        }
    

    具体含义可以参考:https://huggingface.co/transformers/v2.1.1/model_doc/bert.html#bertconfig

    具体加载config的代码如下所示:

      from transformers import BertConfig
      #在v2.10.0中使用的自动识别的类,但在此次源码分享中仅以Bert模型为例
      #from transformers import  AutoConfig,
      config = BertConfig.from_pretrained(
          model_args.config_name if model_args.config_name else model_args.model_name_or_path,
          num_labels=num_labels,
          id2label=label_map,
          label2id={label: i for i, label in enumerate(labels)},
          cache_dir=model_args.cache_dir,
      )
    
    

    BertConfig 父类 PretrainedConfig 中的from_pretrained函数如下:

       def from_pretrained(cls, pretrained_model_name_or_path, **kwargs) -> 
           r"""
           Args:
               pretrained_model_name_or_path (:obj:`string`)    名称          
               cache_dir (:obj:`string`, `optional`)             缓存文件夹  
               kwargs (:obj:`Dict[str, any]`, `optional`)        其他参数用 `Dict[str, any]`的形式     
               force_download (:obj:`bool`, `optional`, defaults to :obj:`False`)  覆盖文件夹中之前下载文件             
               resume_download (:obj:`bool`, `optional`, defaults to :obj:`False`) 是否继续下载
               proxies (:obj:`Dict`, `optional`)  代理服务器地址
           Returns:
               :class:`PretrainedConfig`: An instance of a configuration object
    
           Examples::
               config 文件可以采取三种方式,bert名称、bert文件夹地址、config文件地址
               config = BertConfig.from_pretrained('bert-base-uncased')    # Download configuration from S3 and cache.
               config = BertConfig.from_pretrained('./test/saved_model/')  # E.g. config (or model) was saved using `save_pretrained('./test/saved_model/')`
               config = BertConfig.from_pretrained('./test/saved_model/my_configuration.json')
               config = BertConfig.from_pretrained('bert-base-uncased', output_attention=True, foo=False)
               assert config.output_attention == True
               config, unused_kwargs = BertConfig.from_pretrained('bert-base-uncased', output_attention=True,
                                                                  foo=False, return_unused_kwargs=True)
               assert config.output_attention == True
               assert unused_kwargs == {'foo': False}
           """
           config_dict, kwargs = cls.get_config_dict(pretrained_model_name_or_path, **kwargs)
           return cls.from_dict(config_dict, **kwargs)
       
    

    BertConfig源码如下所示,就是一个包含各种参数的类。虽然模型显示可以自加参数(**kwargs),但我的模型加载参数总出错,所以我的代码采用笨方法加载自己参数,效果是一样的。

    class BertConfig(PretrainedConfig):    
          pretrained_config_archive_map = BERT_PRETRAINED_CONFIG_ARCHIVE_MAP
          model_type = "bert"
          def __init__(
              self,
              vocab_size=30522,
              hidden_size=768,
              num_hidden_layers=12,
              num_attention_heads=12,
              intermediate_size=3072,
              hidden_act="gelu",
              hidden_dropout_prob=0.1,
              attention_probs_dropout_prob=0.1,
              max_position_embeddings=512,
              type_vocab_size=2,
              initializer_range=0.02,
              layer_norm_eps=1e-12,
              pad_token_id=0,
              **kwargs
          ):
              super().__init__(pad_token_id=pad_token_id, **kwargs)
    
              self.vocab_size = vocab_size
              self.hidden_size = hidden_size
              self.num_hidden_layers = num_hidden_layers
              self.num_attention_heads = num_attention_heads
              self.hidden_act = hidden_act
              self.intermediate_size = intermediate_size
              self.hidden_dropout_prob = hidden_dropout_prob
              self.attention_probs_dropout_prob = attention_probs_dropout_prob
              self.max_position_embeddings = max_position_embeddings
              self.type_vocab_size = type_vocab_size
              self.initializer_range = initializer_range
              self.layer_norm_eps = layer_norm_eps
              #此处可以添加自己模型需要的额外参数
              self.trigger_label = None
              self.device = None
    
    config.device = device
    

    四、Tokenizer

    这是一个将纯文本转换为编码的过程。注意,Tokenizer并不涉及将词转化为词向量的过程,仅仅是将纯文本分词,添加[MASK]标记、[SEP]、[CLS]标记,并转换为字典索引。Tokenizer类导出时将分为三个文件,也就是:

        from transformers import BertTokenizer
    
        tokenizer = BertTokenizer.from_pretrained(
            model_args.tokenizer_name if model_args.tokenizer_name else model_args.model_name_or_path,
            cache_dir=model_args.cache_dir,
            use_fast=model_args.use_fast,
            do_lower_case=args.do_lower_case
        )
    

    其父类PreTrainedTokenizer的from_pretrained方法与config类似。使用时,先利用tokenize将文本进行标准化转化,再利用convert_tokens_to_ids进行lookup操作转化为input_ids

    利用Tokenizer处理文本

    • 利用Tokenizer对单句进行分词和(标准化)编码
        In[1]:text = '我爱北京天安门,吢吣吤吥吧吩'
        In[2]:tokens = tokenizer.tokenize(text)     
        In[3]:input_ids = tokenizer.convert_tokens_to_ids(tokens)#使用tokenizer.encode也可以达成同样效果,encode是其父类定义的方法,分别调用以上两步。利用convert_ids_to_tokens函数即可达成ids转换成token。
        In[4]:print(tokens,'\n',input_ids)
        Out:['我', '爱', '北', '京', '天', '安', '门', ',', '[UNK]', '[UNK]', '[UNK]', '[UNK]', '吧', '吩'] 
            [2769, 4263, 1266, 776, 1921, 2128, 7305, 8024, 100, 100, 100, 100, 1416, 1418]    
    
    • 利用Tokenizer对多句进行分词和(标准化)编码
      # encode_plus返回所有编码信息
      In:sen_code = tokenizer.encode_plus("i like you", "but not him")
      Out : 
          {'input_ids': [101, 1045, 2066, 2017, 102, 2021, 2025, 2032, 102],
          'token_type_ids': [0, 0, 0, 0, 0, 1, 1, 1, 1],
          'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}   
    
    • 模型的所有分词器都是在PreTrainedTokenizer中实现的,分词的结果主要有以下内容:
    {
    input_ids: list[int],
    token_type_ids: list[int] if return_token_type_ids is True (default)
    attention_mask: list[int] if return_attention_mask is True (default)
    overflowing_tokens: list[int] if a max_length is specified and 		return_overflowing_tokens is True
    num_truncated_tokens: int if a max_length is specified and return_overflowing_tokens is True
    special_tokens_mask: list[int] if add_special_tokens if set to True and return_special_tokens_mask is True
    }
    
    • 编码解释:

      • ‘input_ids’:顾名思义,是单词在词典中的编码
      • ‘token_type_ids’, 区分两个句子的编码
      • ‘attention_mask’, 指定对哪些词进行self-Attention操作,意味pad部分为0
      • ‘overflowing_tokens’, 当指定最大长度时,溢出的单词
      • ‘num_truncated_tokens’, 溢出的token数量
      • ‘return_special_tokens_mask’,如果添加特殊标记,则这是[0,1]的列表,其中0指定特殊添加的标记,而1指定序列标记
    • special_tokens_map.json 特殊标记的定义方式:

    {"unk_token": "[UNK]", "sep_token": "[SEP]", "pad_token": "[PAD]", 
     "cls_token": "[CLS]", "mask_token": "[MASK]"}   
    

    五、基本模型BertModel

    基本模型,可以将其理解为将输入转化为bert向量的模型。项目在基本模型(如Berrt、GPT等)基础上,针对下游任务,还定义了诸如BertForQuestionAnswering、BertForTokenClassification等下游任务模型。从构造函数可以看到用到了embeddings,encoder和pooler。

    模型导出时将生成config.json和pytorch_model.bin参数文件。前者就是1中的配置文件,这和我们的直觉相同,即config和model应该是紧密联系在一起的两个类。后者其实和torch.save()存储得到的文件是相同的,这是因为Model都直接或者间接继承了Pytorch的Module类。从这里可以看出,HuggingFace在实现时很好地尊重了Pytorch的原生API。

    • 模型输入

    下面是允许输入到模型中的参数,模型至少需要有1个输入: input_ids 或 input_embeds。

    input_ids 就是一连串 token 在字典中的对应id。形状为 (batch_size, sequence_length)。
    token_type_ids 可选。就是 token 对应的句子id,值为0或1(0表示对应的token属于第一句,1表示属于第二句)。形状为(batch_size, sequence_length)。

    input_ids 就是一连串 token 在字典中的对应id。形状为 (batch_size, sequence_length)。Bert 的输入需要用 [CLS] 和 [SEP] 进行标记,开头用 [CLS],句子结尾用 [SEP],各类bert模型对应的输入格式如下所示:

    bert:       [CLS] + tokens + [SEP] + padding
    
    roberta:    [CLS] + prefix_space + tokens + [SEP] + padding
    
    distilbert: [CLS] + tokens + [SEP] + padding
    
    xlm:        [CLS] + tokens + [SEP] + padding
    
    xlnet:      padding + tokens + [SEP] + [CLS]
    

    token_type_ids 可选。就是 token 对应的句子id,值为0或1(0表示对应的token属于第一句,1表示属于第二句)。形状为(batch_size, sequence_length)。如为None则BertModel会默认全为0(即a句)。

    两个句子:

    tokens:[CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP]
    
    token_type_ids:0   0  0    0    0     0       0   0   1  1  1  1   1   1
    

    一个句子:

    tokens:[CLS] the dog is hairy . [SEP]
    
    token_type_ids:0   0   0   0  0     0   0
    

    attention_mask 可选。各元素的值为 0 或 1 ,避免在 padding 的 token 上计算 attention(1不进行masked,0则masked)。形状为(batch_size, sequence_length)。如为None则BertModel默认全为1。
    position_ids 可选。表示 token 在句子中的位置id。形状为(batch_size, sequence_length)。形状为(batch_size, sequence_length)。如为None则BertModel会自动生成。

    形如[0,1,2,......,seq_length - 1],
    

    head_mask 可选。各元素的值为 0 或 1 ,1 表示 head 有效,0无效。形状为(num_heads,)或(num_layers, num_heads)。
    input_embeds 可选。替代 input_ids,我们可以直接输入 Embedding 后的 Tensor。形状为(batch_size, sequence_length, embedding_dim)。
    encoder_hidden_states 可选。encoder 最后一层输出的隐藏状态序列,模型配置为 decoder 时使用。形状为(batch_size, sequence_length, hidden_size)。
    encoder_attention_mask 可选。避免在 padding 的 token 上计算 attention,模型配置为 decoder 时使用。形状为(batch_size, sequence_length)。

    以下部分参考Bert代码详解(一)

    • 构造函数__init__
        def __init__(self, config):
            super().__init__(config)
            self.config = config
    
            self.embeddings = BertEmbeddings(config)
            self.encoder = BertEncoder(config)
            self.pooler = BertPooler(config)
    
            self.init_weights()
    
    • BertEmbeddings(config)
      只看最后它的输出,返回拼接inputs_embedsposition_embeddingstoken_type_embeddings
          embeddings = inputs_embeds + position_embeddings + token_type_embeddings
          embeddings = self.LayerNorm(embeddings)
          embeddings = self.dropout(embeddings)
          return embeddings
    
    • BertEncoder(config)
      BertEncoder层建立了12个BertLayer层(large为24),然后将这12个层的输出以list形式进行输出。BertLayer层架构请见Bert代码详解(一)
        #BertEncoder层建立了整个transformer构架
        #Transformer构架参考:https://zhuanlan.zhihu.com/p/39034683        (BE CAUTIOUS!)
        #现在我假设大家都知道了这个架构,我这里沿袭了上面知乎中某些专有名词的称呼
        
        #........................................................................
        #Transformer中包含若干层(论文中base为12层,large为24层)encoder,每层encoder在代码中就是一个BertLayer。
        #所以下面的代码首先声明了一层layer,然后构造了num_hidden_layers(12 or 24)层相同的layer放在一个列表中,既是self.layer
        layer = BertLayer(config)
        self.layer = nn.ModuleList([copy.deepcopy(layer) for _ in range(config.num_hidden_layers)])
        #........................................................................
        
        #........................................................................
        #下面看其forward函数
        def forward(self, hidden_states, attention_mask, output_all_encoded_layers=True):
        #看其输入:
        #hidden_states:根据上面所讲,hidden_states就是embedding_output,其维度为[batch_size, seq_lenght, word_dimension],embedding出来后,多了一个dimension
        #attention_mask:维度[batch_size, 1, 1, seq_length]
        #(to be completed)
        #output_all_encoder_layers:此函数的输出模式,下面会详细讲解
        
        #这个函数到底做了什么了?其实很简单,就是做了一个循环,将每一个encoder的输出作为输入输给下一层的encoder,直到12(or24)层循环完毕
            all_encoder_layers = []
            #遍历所有的encoder,总共有12层或者24层
            for layer_module in self.layer:
                #每一层的输出hidden_states也是下一层layer_moudle(BertLayer)的输入,这样就连接起来了各层encoder。第一层的输入是embedding_output
                hidden_states = layer_module(hidden_states, attention_mask)
                #如果output_all_encoded_layers == True:则将每一层的结果添加到all_encoder_layers中
                if output_all_encoded_layers:
                    all_encoder_layers.append(hidden_states)
            #如果output_all_encoded_layers == False, 则只将最后一层的输出加到all_encoded_layers中
            if not output_all_encoded_layers:
                all_encoder_layers.append(hidden_states)
            return all_encoder_layers
        #所以output_all_encoded_layers是用来控制输出模式的。
        #这样整个transformer的框架就出来了,下面将讲述框架中的每一层encoder(即BertLayer)是怎么构造的
        #........................................................................
    
    • BertPooler层
      取出每一句的第一个单词,做全连接和激活。得到的输出可以用来分类等下游任务(即将每个句子的第一个单词的表示作为整个句子的表示)
    #pooler层的输入是transformer最后一层的输出,[batch_size, seq_length, hidden_size]
    def forward(self, hidden_states):
            # We "pool" the model by simply taking the hidden state corresponding
            # to the first token.
            
            #取出每一句的第一个单词,做全连接和激活。得到的输出可以用来分类等下游任务(即将每个句子的第一个单词的表示作为整个句子的表示)
            first_token_tensor = hidden_states[:, 0]
            pooled_output = self.dense(first_token_tensor)
            pooled_output = self.activation(pooled_output)
            return pooled_output
    
    • BertModel中forward函数
      依次调用BertEmbeddings、BertEncoder、BertPooler,最后返回的是encoder_outputs第1层(?不太确定,但从代码看是如此)+ pooled_output(即用一个词[cls]代表整句话)+ encoder_outputs其他层的输出 + attentions
    embedding_output = self.embeddings(
                input_ids=input_ids, position_ids=position_ids, token_type_ids=token_type_ids, inputs_embeds=inputs_embeds
            )
    encoder_outputs = self.encoder(
                embedding_output,
                attention_mask=extended_attention_mask,
                head_mask=head_mask,
                encoder_hidden_states=encoder_hidden_states,
                encoder_attention_mask=encoder_extended_attention_mask,
            )
    sequence_output = encoder_outputs[0]
    pooled_output = self.pooler(sequence_output)
    
    outputs = (sequence_output, pooled_output,) + encoder_outputs[
                1:
            ]  # add hidden_states and attentions if they are here
    return outputs  # sequence_output, pooled_output, (hidden_states), (attentions)
    

    六、序列标注任务实战(命名实体识别)

    以序列标注模型为例,各级bert模型继承关系

    Created with Raphaël 2.2.0加载各类的包(import)载入训练参数Bert模型初始化(config,Tokenizer,Model初始化)处理训练集和测试集开始训练

    1.加载各类包(略)

    2.载入训练参数

    新版本的transformers中的ner没有采用传统的parser模块,利用HfArgumentParser方法,将参数类转化为argparse参数,以便于在命令行中指定他们。这样按用途划分可以更好查找关注,或设置相关参数。

        #run_ner.py中97行
        #ModelArguments类为model/config/tokenizer涉及的参数
        #DataTrainingArguments类为数据涉及到的参数
        parser = HfArgumentParser((ModelArguments, DataTrainingArguments, TrainingArguments))
        if len(sys.argv) == 2 and sys.argv[1].endswith(".json"):
            # 训练时输入python run_ner.py *******.json,即从.json中读取参数。
            # 当sys.argv参数为2时,此时sys.argv[0]为自己本身,即"run_ner.py",sys.argv[1]为json文件
            
            model_args, data_args, training_args = parser.parse_json_file(json_file=os.path.abspath(sys.argv[1]))
        else:
            model_args, data_args, training_args = parser.parse_args_into_dataclasses()
    

    3.模型初始化

    参照三、四、五节内容。

      config = AutoConfig.from_pretrained(
            model_args.config_name if model_args.config_name else model_args.model_name_or_path,
            num_labels=num_labels,
            id2label=label_map,
            label2id={label: i for i, label in enumerate(labels)},
            cache_dir=model_args.cache_dir,
        )
      tokenizer = AutoTokenizer.from_pretrained(
            model_args.tokenizer_name if model_args.tokenizer_name else model_args.model_name_or_path,
            cache_dir=model_args.cache_dir,
            use_fast=model_args.use_fast,
        )
      model = AutoModelForTokenClassification.from_pretrained(
            model_args.model_name_or_path,
            from_tf=bool(".ckpt" in model_args.model_name_or_path),
            config=config,
            cache_dir=model_args.cache_dir,
        )
    
    导入Bert系列模型
    通过官网自动导入
    手动到官网下载模型信息并导入
    通过github,云盘等方式下载模型并导入

    当前transformers使用 AutoModelForTokenClassification(以序列标注任务为例)实现模型的自动加载(可以使自己程序显得高端、大气、上档次)。实现原理:利用该函数的’ from_pretrained() ‘方法负责返回正确的模型类实例,基于config对象的’ model_type ‘属性,当前输入并无此属性时,返回到在’ pretrained_model_name_or_path '字符串上使用模式匹配。在实现了自己的序列标注模型后,可以通过修改modeling_auto.pyMODEL_FOR_TOKEN_CLASSIFICATION_MAPPING关键字段来匹配自己的模型。

    MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING.png

    不过自动加载的方法在调试模型时并不适用,所以还是直接加载来的划算:

    from transformers import BertForTokenClassification #可以修改成自己的模型
    #from transformers.modeling_bert import BertForTokenClassification 序列标注bert模型原始位置
    
    model = BertForTokenClassification.from_pretrained(
            model_args.model_name_or_path, 
            from_tf=bool(".ckpt" in model_args.model_name_or_path),
            config=config, 
            cache_dir=model_args.cache_dir,
        )
    

    4.BertForTokenClassification

    BertForSequenceClassification(modeling_bert.py)是一个已经实现好的在 token 级别上进行文本分类的类,一般用来进行序列标注任务(在进行自己的命名实体识别任务时,可以新建子类继承该方法,进行其他任务也类似),相关类继承关系如下:

    Created with Raphaël 2.2.0PreTrainedModelBertPreTrainedModelBertModelForTokenClassification改写的序列标注模型

    BertForTokenClassification构造函数如下所示:

    def __init__(self, config):
        super(BertForTokenClassification, self).__init__(config)
        self.num_labels = config.num_labels #假设有10个标签
    
        self.bert = BertModel(config) #hidden_size维度为768
        self.dropout = nn.Dropout(config.hidden_dropout_prob)
        self.classifier = nn.Linear(config.hidden_size, config.num_labels)#该线性层为768*10
    
        self.init_weights()
    

    下面是 BertForTokenClassification 的中 forward() 函数的部分代码,它用到的是全部 token 上的输出。返回 loss + scores(即logits) + hidden_states + attentions

    def forward(
            self,
            input_ids=None,
            attention_mask=None,
            token_type_ids=None,
            position_ids=None,
            head_mask=None,
            inputs_embeds=None,
            labels=None,
        ):
            
          outputs = self.bert(
                input_ids,
                attention_mask=attention_mask,
                token_type_ids=token_type_ids,
                position_ids=position_ids,
                head_mask=head_mask,
                inputs_embeds=inputs_embeds,
            )#原则上用到前四个参数即可,也可直接取第几层输入,有论文表示第3层输出用于命名实体识别效果最好
    
            sequence_output = outputs[0] #假设输入为64*128*768
    
            sequence_output = self.dropout(sequence_output) 
            logits = self.classifier(sequence_output) # (64*128*768) * (768*10) = 64*128*10
    
            outputs = (logits,) + outputs[2:]  # add hidden states and attention if they are here
    
            if labels is not None: #给labels是训练
                loss_fct = CrossEntropyLoss() #交叉熵损失函数
                # Only keep active parts of the loss
                if attention_mask is not None:
                    active_loss = attention_mask.view(-1) == 1 #先把attention_mask展开,其中等于1为True,等于0为False,维度 64*128 = 8192
                    active_logits = logits.view(-1, self.num_labels) #把logits展开,维度为8192*10
                    active_labels = torch.where(
                        active_loss, labels.view(-1), torch.tensor(loss_fct.ignore_index).type_as(labels)
                    )#where三个参数,第一个为判断条件,第二个是复合条件设置值,第三个不符合条件设置值。loss_fct.ignore_index默认为-100,可以在初始化CrossEntropyLoss(ignore_index=-1)修改
                    loss = loss_fct(active_logits, active_labels)
                else: #不给labels是预测
                    loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
                outputs = (loss,) + outputs
    
            return outputs  # (loss), scores, (hidden_states), (attentions)
    

    5.处理数据

    利用NerDataset函数将命名实体数据集处理成第五节中提及的BertModel输入格式,如下图所示(bert),不同的bert模型需要处理成不同的格式,可以通过model_type参数进行调整。

    bert

    6.开始训练

    利用 Trainer.train 函数进行模型训练,Trainer 是一个简单但功能完整的PyTorch训练和eval循环方法,并针对 Transformers 进行了优化。简单介绍下流程

    1)将训练、验证、测试数据集传入DataLoader

    #测试集、验证集导入函数与此类似
    def get_train_dataloader(self) -> DataLoader:
                        ...
                        ...
                        ...
        data_loader = DataLoader(
                self.train_dataset,
                batch_size=self.args.train_batch_size,
                sampler=train_sampler,
                collate_fn=self.data_collator.collate_batch,
            )
        return data_loader
    

    2)设置优化函数

    optimizer, scheduler = self.get_optimizers(num_training_steps=t_total)
    

    3) 设置fp16精度、多gpu并行、分布式训练

    if self.args.fp16:
        if not is_apex_available():
            raise ImportError("Please install apex from https://www.github.com/nvidia/apex to use fp16 training.")
        model, optimizer = amp.initialize(model, optimizer, opt_level=self.args.fp16_opt_level)
    
    # multi-gpu training (should be after apex fp16 initialization)
    if self.args.n_gpu > 1:
        model = torch.nn.DataParallel(model)
    
    # Distributed training (should be after apex fp16 initialization)
    if self.args.local_rank != -1:
        model = torch.nn.parallel.DistributedDataParallel(
            model,
            device_ids=[self.args.local_rank],
            output_device=self.args.local_rank,
            find_unused_parameters=True,
        )
    

    transformers只加入了基本的常用操作,除此此外还可加入一些高阶训练技巧

    4)是否冻结训练参数

    no_decay = ["bias", "LayerNorm.weight"]
    bert_param_optimizer = list(model.bert.named_parameters())
    crf_param_optimizer = list(model.crf.named_parameters())
    linear_param_optimizer = list(model.classifier.named_parameters())
    optimizer_grouped_parameters = [
        {'params': [p for n, p in bert_param_optimizer if not any(nd in n for nd in no_decay)],
         'weight_decay': args.weight_decay, 'lr': args.learning_rate},
        {'params': [p for n, p in bert_param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0,
         'lr': args.learning_rate},
        {'params': [p for n, p in crf_param_optimizer if not any(nd in n for nd in no_decay)],
         'weight_decay': args.weight_decay,'lr': 0.001},
        {'params': [p for n, p in crf_param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0,
         'lr': 0.001},
        {'params': [p for n, p in linear_param_optimizer if not any(nd in n for nd in no_decay)],
         'weight_decay': args.weight_decay,'lr': 0.001},
        {'params': [p for n, p in linear_param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0,
         'lr': 0.001}
        ]
    

    5)学习率退火

    scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=args.warmup_steps,
                                                    num_training_steps=t_total)
    

    6)训练参数可视化

    自己加入tensorboardX进行可视化调节训练进程

    7)轮次训练迭代

    7.测试评估和预测

    参考文献

    1. HuggingFace-Transformers系列的介绍以及在下游任务中的使用
    2. 配置、使用transformers包
    3. bert模型简介、transformers中bert模型源码阅读、分类任务实战和难点总结
    4. 手把手教你用Pytorch-Transformers——部分源码解读及相关说明(一)
    5. Bert代码详解(一)
    展开全文
  • 业务数据可视化分析-> 标准数据格式转换-> 模型训练-> 在线预测-> 序列标准任务优化和拓展 作者:走在前方 博客:https://wenjie.blog.csdn.net/ 专注于文本分类、关键词抽取、文本摘要、FQA .

    本文主要通过不同的数据集来进行 NER 模型验证验证,以及指定一些通过训练 NER 任务的一套标准,通过两条路线进行分析和总结。
    (1)工业界场景-> 学术界 NER 论文-> BERT 实现 NER 方案以及源码分析
    (2)预料数据-> 业务数据可视化分析-> 标准数据格式转换-> 模型训练-> 在线预测-> 序列标准任务优化和拓展

    本文主要分享核心要点

    • 命名实体识别初识
      • 什么是 NER
      • NER 发展以及技术方案
    • 工业界应用场景
      • 人力资源检索系统
      • 电子病历系统
      • 聊天机器人对话系统
      • 其他(某团语音平台,某米音箱。。)
    • 学术界论文方案解读
      • BiLSTM-CRF
      • Att-BiLSTM-CRF
      • BERT
      • BERT-CRF
    • BERT 源码分析
      • 词潜入历史发展 word2vec、glove、ELMo、BERT
      • BERT 模型详细介绍
      • BERT 模型演变
    • NER 项目前准备工作
      • 数据库分析可视化 pyecharts、seaborn、matplotlib
      • NER 项目 CRF 模块
      • transformer 模型模块
      • NER 评估模块
    • 不同数据集实验
      • 案例 1:CoNLL2003 经典 NER 入门项目
      • 案例 2:航空旅游项目
      • 案例 3:新闻数据项目
      • 案例 4:NLP 比赛 音乐领域 NER 项目
      • 案例 5: 中文分词以及词性标注

    命名实体识别初识

    Named-entity recognition (NER) (also known as entity identification, entity chunking and entity extraction)

    命名实体识别(Named Entity Recognition,简称 NER),又称作“专名识别”,是指识别文本中具有特定意义的实体,主要包括人名、地名、机构名、专有名词等。简单的讲,就是识别自然文本中的实体指称的边界和类别。

    一些研究也涉及电影名、书名、项目名、研究领域名称、电子邮件地址、电话号码以及生物信息学领域的专有名词(如蛋白质、DNA、RNA 等)。甚至有一些工作不限定“实体”的类型,而是将其当做开放域的命名实体识别和分类。

    NER 一直是 NLP 领域中的研究热点,从早期基于词典和规则的方法,到传统机器学习的方法,到近年来基于深度学习的方法,NER 研究进展的 大概趋势大致如下图 所示。

    图片

    工业界应用场景

    简历自动检索系统

    https://dataturks.com/blog/named-entity-recognition-in-resumes.php

    图片

    图片

    人力资源检索系统,可以通过 NER 来完成,从三个方面提供给我们一些思路

    1。简历自动汇总

    2。优化搜索引擎算法

    3。强大的推荐系统

    4。简化客户支持

    • 简历自动汇总

    图片

    各公司人力资源部面临的一个关键挑战是评估一大堆求职者的简历。为了增加他们的亮点,申请者往往过于详细化他们的简历,其中大部分信息与评估者所寻求的无关。为了简化这一过程,通过我们的 NER 模型,我们可以方便地对简历进行快速评估,从而简化在一堆简历中筛选候选人所需的工作。

    • 优化搜索引擎算法

    图片

    为了设计一种搜索引擎算法,而不是在数百万篇在线文章和网站上搜索输入的查询,一种更有效的方法是对文章运行一次 NER 模型,并永久存储与之相关的实体。然后,可以将搜索查询中的关键标记与与网站文章关联的标记进行比较,以实现快速高效的搜索。

    • 强大的推荐系统

    图片

    NER 可用于开发推荐系统的算法,自动过滤我们可能感兴趣的相关内容,并据此指导我们根据以前的行为发现相关和未访问的相关内容。这可以通过提取与我们的历史或以前活动中的内容相关联的实体,并将它们与分配给其他未公开内容的标签进行比较,以筛选相关的实体来实现。

    • 简化客户支持

    图片

    NER 可用于识别客户投诉和反馈中的相关实体,如产品规格、部门或公司分支机构的详细信息,以便对反馈进行相应分类,并转发给负责识别产品的相应部门。

    电子病例命名实体识别

    电子病历结构化是让计算机理解病历、应用病历的基础。基于对病历的结构化,可以计算出症状、疾病、药品、检查检验等多个知识点之间的关系及其概率,构建医疗领域的知识图谱,进一步优化医生的工作. 对于给定的一组电子病历纯文本文档,识别并抽取出其中与医学临床相关的实体,并将它们归类到预先定义好的类别中。例如,我们可以识别含解剖部位、独立症状、症状描述、手术和药物等实体。

    图片

    举例说明,根据病例描述抽取信息:

    • 输入数据

    女性,88 岁,农民,双滦区应营子村人,主因右髋部摔伤后疼痛****肿胀,活动受限 5 小时于 2016-10-29;11:12 入院。

    • 输出结果

    右髋部 21 23 身体部位

    疼痛 27 28 症状和体征

    肿胀 29 30 症状和体征

    聊天机器人的对话系统

    图片图片图片

    图片图片

    对话系统在聊天机器人中应用以及发展历史

    • 1950: Turing Test
    • 1966: ELIZA, MIT chatbot
    • 1995: ALICE, pattern recognition chatbot
    • 2011-2012: Siri, Watson, Google Assistant
    • 2015: Amazon Alexa, Microsoft Cortana
    • 2016: Bot 元年:Microsoft Bot Framework, FB Messenger, Google Assistant …
    • 2017: 百度度秘,腾讯云小微,阿里小蜜 …

    对话系统主要包括三个方面的内容

    • NLU 自然语言理解

    对话系统中语义理解部分主要包括:领域分类、意图识别和槽位抽取。

    领域分类:针对一个 query 的短文本分类

    意图识别:也可以看成文本分类问题

    槽位抽取:可以看成 NER 技术领域的问题

    • 领域分类

    例如: 音乐、天气、指令。。。。

    • 意图识别(slot filling)

    对于音乐来说,比如:播放,暂停,下一首等。。。

    • 槽位填充(命名实体识别)

    例如: 播放一周周杰伦东风破。 {‘singer’:’'周杰伦 ,‘song’:'东风破 '}

    • DM 对话管理
    • NLG 自然语言生成

    2018 年 Alexa Prize Challenge 亚马逊举办的聊天机器人大赛

    2018 年冠军** **

    Gunrock: Building A Human-Like Social Bot By Leveraging Large Scale Real User Data

    图片

    系统的整体架构

    图片

    学术界论文方案解读

    BiLSTM-CRF vs Att-BiLSTM-CRF 论文

    BiLSTM-CRF 论文

    Attention+BiLSTM-CRF 论文

    BiLSTM-CRF baidu

    图片

    Att-BiLSTM-CRF

    图片

    接下来我们重点看下 Att-BiLSTM-CRF 这篇论文,我们重点了解。

    其中: 论文的代码

    • attention 的计算方法

    https://github.com/lingluodlut/Att-ChemdNER/blob/81db44f5cbd5bbbb1d1dee72a528280425de7bc9/src/nn.py#L628

    • Att-BiLSTM-CRF VS 其他模型效果对比

    该论文中提供了4个计算attention 的方法

    图片

    四种计算 attention 方法对比效果

    图片

    其他模型 VS Att-BiLSTM-CRf 对比

    图片

    BiLSTM-CRF VS Att-BiLSTM-CRF 架构

    图片

    The architectures of BiLSTM-CRF model and our Att-BiLSTM-CRF model.

    (A) The basic BiLSTM-CRF model.

    (B) Our Att-BiLSTM-CRF model. In the models, the BIO (Begin, Inside, Outside) tagging scheme are used. In the figure (B), only the attention weights of the target word are illustrated for clarity. The attention weight is larger when the word is more related to the target word, and the color of attention line is darker

    BERT vs BERT-CRF 论文

    2018 《 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》

    2020 《 A New Active Learning Strategy for Bert-CRF Based Named Entity Recognition》

    BERT 论文

    图片

    图片

    BERT-CRF 论文

    图片

    图片

    本论文我们主要关注几个核心点即可

    论文主要通过增加一些策略机制来进行一些实验的实验

    • 实验证明 Bert-BiLSTM-CRF 和 Bert-CRF 这两种方式没有太大的区别,反而 Bert-BiLSTM-CRF 增加 BiLSTM 层使得模型训练和推理速度变慢。
    • BERT BIO 编码格式输入(注意:pad 补充),这里同 BERT 原始论文保持一致

    图片

    • dropout 参数设置

    在 fc 层减少过拟合设置 dropout = 0.9 ,后续我们实验也可以尝试 。

    In the fully connected layer, we set the dropout rate to be 0.9 to prevent overfitting

    • 学习滤参数设置

    learning rate to 0.00001

    BERT 源码分析

    BERT系列预训练模型

    NER 项目准备

    NER 评估标准

    seqeval 是一个用于序列标记评估的 python 框架。seqeval 可以评估命名实体识别、词性标注、语义角色标注等分块任务的性能。

    seqeval 支持格式:IOB 和 IOBES

    seqeval 安装方法:pip install seqeval

    安装完成后,为保持使用我们把源码拷贝到自己的工程下。

    seqeval 代码使用

    from seqeval.metrics import accuracy_score
    from seqeval.metrics import classification_report
    from seqeval.metrics import f1_score
    y_true = [['O', 'O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]
    y_pred = [['O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]
    # score
    print( f1_score(y_true, y_pred) )
    # acc
    print(accuracy_score(y_true, y_pred))
    # report
    print( classification_report(y_true, y_pred) )
    

    上述代码运行的效果:

    0.5
    0.8
               precision    recall  f1-score   support
    
          PER       1.00      1.00      1.00         1
         MISC       0.00      0.00      0.00         1
    
    micro avg       0.50      0.50      0.50         2
    macro avg       0.50      0.50      0.50         2
    

    BERT 预训练模型下载

    **英文 BERT 预训练模型,预训练模型以及文件 rename 后 **

    bert-base-uncased

    ├── config.json
    
    ├── pytorch_model.bin
    
    └── vocab.txt
    

    **BERT 预训练中文模型,预训练模型以及文件 rename 后 **

    图片

    BERT CRF 模块

    直接使用 torchcrf

    pip install torchcf

    安装成功后,我们找到 torchcf 模块,拷贝自己的项目中即可直接使用了。

    transformers

    transformers下载 ,下载完成后,把项目拷贝到自己的项目中。

    数据分析可视化

    数据可视化可以帮助我们理解业务数据,重点选择 pyecharts、seaborn、matplotlib 工具库。

    CoNLL2003 数据集项目

    我们使用指定服务器,需要执行下面内容。

    https://blog.csdn.net/ShiMengRan107/article/details/100152211

    PS1='${debian_chroot:+($debian_chroot)}ailib@ubuntu:\w\$ '
    export PATH=/usr/share/anaconda3/bin:$PATH
    source activate
    conda activate torch1.4-gpu
    export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:$LD_LIBRARY_PATH  
    export CUDA_HOME=/usr/local/cuda-10.0:$CUDA_HOME  
    export PATH=/usr/local/cuda-10.0/bin:$PATH  
    export LD_LIBRARY_PATH=/usr/local/cuda-10.0/extras/CUPTI/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
    

    CoNLL2003 数据集[1]

    实体被标注为四种类型:

    LOC (location, 地名)

    ORG (organisation, 组织机构名)

    PER (person, 人名)

    MISC (miscellaneous, 其他)

    一条标注数据的组织形式如下:

    [word][POS tag][chunk tag][NER tag]
    

    DATA FORMAT

    The data files contain one word per line. Empty lines have been usedfor marking sentence boundaries and a line containing the keyword-DOCSTART- has been added to thebeginning of each article in order to mark article boundaries. Each non-empty line contains the following tokens:

    1. the current word

    2. the lemma of the word (German only)

    3. the part-of-speech (POS) tag generated by a tagger

    4. the chunk tag generated by a text chunker

    5. the named entity tag given by human annotators

    数据预处理

    原始数据处理

    提供 train.txt,dev.txt,test.txt 的数据格式如下

    
    -DOCSTART- -X- -X- O
    
    CRICKET NNP B-NP O
    - : O O
    LEICESTERSHIRE NNP B-NP B-ORG
    TAKE NNP I-NP O
    OVER IN B-PP O
    AT NNP B-NP O
    TOP NNP I-NP O
    AFTER NNP I-NP O
    INNINGS NNP I-NP O
    VICTORY NN I-NP O
    . . O O
    
    LONDON NNP B-NP B-LOC
    1996-08-30 CD I-NP O
    

    上述数据处理生成三个文件

    • seq.in 每行表示一个完整的句子,然后以空格分割
    CRICKET - LEICESTERSHIRE TAKE OVER AT TOP AFTER INNINGS VICTORY .
    LONDON 1996-08-30
    
    • seq.out 对应每个单词的 TAG,空格分割
    O O B-ORG O O O O O O O O
    B-LOC O
    
    • slot_label.txt NER 标签的类型,这里增加 PAD 和 UNK 两个特殊的标签
    PAD
    UNK
    O
    B-LOC
    I-LOC
    B-MISC
    I-MISC
    B-ORG
    I-ORG
    B-PER
    I-PER
    

    特征工程

    原始数据进行数字化表示

    图片

    定义保存 words 和 slot_labels 的类 ,我们把每个句子使用 InputExample 来表示

    class InputExample(object):
        """
        A single training/test example for simple sequence classification.
    
        Args:
            guid: Unique id for the example.
            words: list. The words of the sequence.
            slot_labels: (Optional) list. The slot labels of the example.
        """
    
        def __init__(self, guid, words, slot_labels=None):
            self.guid = guid
            self.words = words
            self.slot_labels = slot_labels
    

    模型训练

    图片

    python3 main.py \
    --model_name_or_path ../pretrained_models/bert-base-uncased/ \
    --task CoNLL-2003 \
    --model_type bert \
    --model_dir CoNLL-2003_model \
    --do_train --do_eval --use_crf \
    --num_train_epochs 5 \
    --train_batch_size 64 \
    --eval_batch_size 64 
    

    这里对几个重要的参数进行说明

    • model_name_or_path

    bert 的 pre_trained_model 的路径

    • task

    指定数据集处理器

    • model_type

    指定模型的类型,例如 bert,albert 等

    • do_train do_eval use_crf 分别为训练、验证和使用 crf 预测 tag
    • num_train_epoches 设置模型迭代的次数
    • train_batch_size,eval_batch_size 分别为训练和验证数据集每个批次加载的记录数

    在线服务预测

    在线服务启动

    python3 api.py \
    --model_name_or_path ../pretrained_models/bert-base-uncased/ \
    --task CoNLL-2003 \
    --model_type bert \
    --model_dir CoNLL-2003_model \
    --use_crf 
    

    这里我们使用的是 CoNLL2013 的数据集,如果是其它的数据,需要替换相应的目录

    这里对几个重要的参数进行说明

    • model_name_or_path

    bert 的 pre_trained_model 的路径

    • model_type

    指定模型的类型,例如 bert,albert 等

    • use_crf 使用 crf 预测 tag
    • num_train_epoches 设置模型迭代的次数
    • train_batch_size,eval_batch_size 分别为训练和验证数据集每个批次加载的记录数
    • no_cuda 如果设置使用 cpu 进行推理,不设置的话如果有 cuda 可以 gpu 下推理

    在线文本预测

    curl -H “Content-Type:application/json” -X POST --data ‘{“text”: “Steve went to Paris”}’ http://localhost:8000/predict

    返回结果

    { “errno”: 0, “errmsg”: “success”, “time”: 69, “data”: [{ “word”: “Steve”, “tag”: “B-PER” }, { “word”: “went”, “tag”: “O” }, { “word”: “to”, “tag”: “O” }, { “word”: “Paris”, “tag”: “B-LOC” }] }

    预测代码分析

    • 数据输入

    text = 'Steve went to Paris

    • 构建模型输入数据

    图片

    • 特征数据离散化处理
    tokenizer = load_tokenizer(args)
    text_dataset = load_examples(args, tokenizer, text)
    

    图片

    获取三个字段数据分别

    input_ids 文本中每个 token 在字典中表示

    attention_mask 存在 token 的设置 1,不足 max_seq_len 长度的内容设置 0

    token_type_ids 表示第一个句子,这全部 0

    • 预测 predict 函数定义(重点)

    图片

    航空旅游数据集项目

    ATIS (Airline Travel Information System)

    我们在完成 CoNLL2003 数据集下的 BERT-NER 训练和预测后,在进行别的数据集就非常容易了。关键在于我们的程序是通用的,唯一我们需要做的时候转换成一个数据集即可。

    ATIS 数据集分析

    首先,我们熟悉下处理成标准的格式数据(以后我们在处理 NER 问题时候,都可以处理成 CoNLL2003 中标准格式即可)

    seq.in

    seq.out

    slot_label.txt

    同时生成对应的 train、test、dev。 每个数据都对应上述 seq.in 和 seq.out,其中 slot_label.txt 是所有的 TAG 以及增加两个特殊的标签 PAD、UNK。

    然后,需要对 seq.in seq.out 进行处理,针对每个句子处理后生成 tokens、input_ids、attention_mask、token_type_ids、slot_labels。

    05/16/2020 23:19:06 - INFO - data_loader -   guid: dev-1
    05/16/2020 23:19:06 - INFO - data_loader -   tokens: [CLS] show me all round trip flights between houston and las vegas [SEP]
    05/16/2020 23:19:06 - INFO - data_loader -   input_ids: 101 2265 2033 2035 2461 4440 7599 2090 5395 1998 5869 7136 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    05/16/2020 23:19:06 - INFO - data_loader -   attention_mask: 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    05/16/2020 23:19:06 - INFO - data_loader -   token_type_ids: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    05/16/2020 23:19:06 - INFO - data_loader -   slot_labels: 0 2 2 2 98 99 2 2 73 2 114 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    

    我们分析后发现 slot_labels.txt 中每个标签数量差别很大,存在 TAG 分布不均衡问题。 我们在实际工作中如果入到这种问题,可以想办法补充,使其尽可能均衡(这里我们不在处理

    ATIS 模型训练

    模型采用 BERT-CRF 进行

    图片

    python3 main.py \
    --model_name_or_path ../pretrained_models/bert-base-uncased/ \
    --task atis \
    --model_type bert \
    --model_dir atis_model \
    --do_train --do_eval --use_crf \
    --num_train_epochs 15 \
    --train_batch_size 64 \
    --eval_batch_size 64 \
    --max_seq_len 32   
    

    我们这里训练 **15 **次迭代,训练完成后我们查看下效果。

    • 验证数据集效果

    图片

    • 测试数据集下的效果

    图片

    我们的 f1 在 dev 数据集达到 97%+,在 test 数据集下也达到 94%+。证明我们 BERT -CRF 在 NER 效果上还是不错的。

    注意:BERT-CRF 在 NER 领域效果已经非常好的了,我们唯一需要重点关注的是数据。如果使用过程某些地方需要处理,我们需要把 TAG 的数据进行扩展,是提升效果最重要的方法。切切记!!!

    ATIS 模型预测

    在线服务启动。 默认据服务器自动采用 cpu 还是 gpu 进行推理 (gpu 效果>> 好远 cpu)

    图片

    python3 api.py \
    --model_name_or_path ../pretrained_models/bert-base-uncased/ \
    --task atis \
    --model_type bert \
    --model_dir atis_model \
    --use_crf 
    

    启动完成后,我们来进行预测

    curl http://localhost:8000/predict \
    -H "Content-Type:application/json" \
    -X POST \
    --data '{"text": "i want to fly boston to san francisco","lang":"en"}'
    

    返回结果如

    {
    	"errno": 0,
    	"errmsg": "success",
    	"time": 13,
    	"data": [{
    			"word": "i",
    			"tag": "O"
    		},
    		{
    			"word": "want",
    			"tag": "O"
    		},
    		{
    			"word": "to",
    			"tag": "O"
    		},
    		{
    			"word": "fly",
    			"tag": "O"
    		},
    		{
    			"word": "boston",
    			"tag": "B-fromloc.city_name"
    		},
    		{
    			"word": "to",
    			"tag": "O"
    		},
    		{
    			"word": "san",
    			"tag": "B-toloc.city_name"
    		},
    		{
    			"word": "francisco",
    			"tag": "I-toloc.city_name"
    		}
    	]
    }
    
    

    返回的结果:(其中 time 是在 cpu 推理的情况下花费 58 毫秒,cuda 运行在 17ms 左右,可以满足上线的条件)

    同时我们看看服务端后端的日志记录

    127.0.0.1 - - [16/May/2020 23:00:28] "POST /predict HTTP/1.1" 200 -
    text =  i am flying from boston to the bay area
    seq_len =  9
    0	i	O
    1	am	O
    2	flying	O
    3	from	O
    4	boston	B-fromloc.city_name
    5	to	O
    6	the	O
    7	bay	I-toloc.city_name
    8	area	O
    

    MSRA 新闻数据集项目

    我们项目的数据集 中文数据集下载 ,点击下载即可,这个 MSRA-NER 数据集是在新闻语料上进行的序列标注。下载完成得到 dh_msra.zip,解压即可使用。

    BiLSTM_CRF tensorflow 实现一个版本 ,这是我从 github 上找的一个版本,大家可以学习。

    我们接下来会实现一个 BERT_CRF PyTorch 版本。主要考虑 PyTorch 语法简单易上手,BERT 在 NLP 领域各个比赛榜单都刷爆了。总之,BERT 重要,太重要了,学习 NLP 就必须掌握 BERT,并且在工业界得到了应用。

    数据分析

    对 dh_msra.zip 中文的数据集切分训练集、验证集、测试集。

    关于数据分析我们通过 pyecharts 进行一个可视化分析,便于我们的效果展示。 我们实际算法工作中关于数据分析以及特征提取占用我们 70%左右的时间,故了解我们的业务数据非常重要的。

    关于更多的 pyecharts 内容请参考

    Python数据可视化 pyecharts实战

    Python数据分析案例实战 视频课程

    • 数据 Example 分布

    图片

    这里给出训练数据、验证数据以及测试数据句子的长度

    • 标签类别数据分布
    from pyecharts import  options as opts
    from pyecharts.charts import Bar
    def bar_charts()->Bar():
        c = Bar()
        c.add_xaxis(xaxis_data=keys)
        c.add_yaxis(series_name='train_TAG-数量统计',yaxis_data=train_tags) 
        return c
    c = bar_charts()
    c.render_notebook()
    

    图片

    图片

    图片

    从上述 train、dev、test 发现,数据的 TAG

    • 文章句子长度分布

    通过分析自己业务句子的长度,可以在训练的时候 max_seq_len 进行设置合理的数值。

    图片图片

    通过上述分析:

    数据长度最大的长度整体在 80 左右,我们在通过 boxplot 那么我们在训练 bert 的时候 max_seq_len 可以设置 60 左右

    NER 模型训练

    python3 main.py  \
    --model_name_or_path ../pretrained_models/bert-base-chinese/ \
    --task  msra \
    --model_type  bert \
    --model_dir msra_bert_base_zh_model  \
    --do_train  --do_eval --use_crf   \
    --num_train_epochs  3 \
    --train_batch_size 64 \
    --eval_batch_size 64  \
    --max_seq_len 64 
    

    NVIDIA GeForce GTX 1080 12G 显存,我们 3 次迭代单卡运行 20 分钟 。如果大家是 cpu 环境下进行训练的话,可以自己抽取一部分小的数据进行训练,保障可以允许即可。如果机器资源允许的情况下,可以调大 train_batch_size ,可以加快训练的速度。训练结果如下:

    INFO - train -   ***** Eval [**dev**] results 
    INFO - train -              precision    recall  f1-score   support
          ORG       0.86      0.94      0.90      1601
          LOC       0.92      0.96      0.94      2562
          PER       0.97      0.97      0.97      1811
    micro avg       0.92      0.96      0.94      5974
    macro avg       0.92      0.96      0.94      5974
    
    INFO - train -     loss = 1.0743800858999122
    INFO - train -     sementic_frame_acc = 0.9231186685962374
    INFO - train -     slot_**f1 = 0.9369517094367467**
    INFO - train -     slot_precision = 0.918206652739836
    INFO - train -     slot_recall = 0.9564780716437897
    
    INFO - train -   ***** Eval [**test**] results *****
    INFO - train -              precision    recall  f1-score   support
          LOC       0.95      0.93      0.94      2935
          PER       0.96      0.96      0.96      1998
          ORG       0.85      0.91      0.88      1426
    micro avg       0.93      0.94      0.94      6359
    macro avg       0.93      0.94      0.94      6359
    INFO - train -     loss = 1.006102637312878
    INFO - train -     sementic_frame_acc = 0.9249547920433996
    INFO - train -     slot_**f1 = 0.9350995453832889**
    INFO - train -     slot_precision = 0.9321769026410377
    INFO - train -     slot_recall = 0.9380405724170467
    

    NER 模型在线预测

    我们通过 gpu 下训练的模型,也可以直接运行在 cpu 下。

    python3 api.py \
    --model_name_or_path ../pretrained_models/bert-base-chinese/ \
    --task  msra  \
    --model_type  bert  \
    --model_dir msra_bert_base_zh_model \
    --use_crf 
    

    注意:model_name_or_path 和 model_dir 换成自己预训练模型路径和模型文件路径

    预测效率对比:gpu 单条记录预测 13ms 左右,cpu 大概 60ms(和服务器配置有关系)。对于 cpu 下推理速度慢的问题我们也可以针对模型进行优化(比如:albert-tiny…)

    **在线预测命令行如下: **

    curl http://127.0.0.1:8000/predict \
    -H "Content-Type:application/json" \
    -X POST \
    --data '{"text": "沈福利毕业于北京工业大学,位于北京市朝阳区","lang":"zh"}'  
    

    图片

    返回结果 :

    
    {
    
      "errno": 0, 
    
      "errmsg": "success", 
    
    **  "time": 16, **
    
      "data": [
    
        {
    
          "word": "沈", 
    
          "tag": "B-PER"
    
        }, 
    
        {
    
          "word": "福", 
    
          "tag": "I-PER"
    
        }, 
    
        {
    
          "word": "利", 
    
          "tag": "I-PER"
    
        }, 
    
        {
    
          "word": "毕", 
    
          "tag": "O"
    
        }, 
    
        {
    
          "word": "业", 
    
          "tag": "O"
    
        }, 
    
        {
    
          "word": "于", 
    
          "tag": "O"
    
        }, 
    
        {
    
          "word": "北", 
    
          "tag": "B-ORG"
    
        }, 
    
        {
    
          "word": "京", 
    
          "tag": "I-ORG"
    
        }, 
    
        {
    
          "word": "工", 
    
          "tag": "I-ORG"
    
        }, 
    
        {
    
          "word": "业", 
    
          "tag": "I-ORG"
    
        }, 
    
        {
    
          "word": "大", 
    
          "tag": "I-ORG"
    
        }, 
    
        {
    
          "word": "学", 
    
          "tag": "I-ORG"
    
        }, 
    
        {
    
          "word": ",", 
    
          "tag": "O"
    
        }, 
    
        {
    
          "word": "位", 
    
          "tag": "O"
    
        }, 
    
        {
    
          "word": "于", 
    
          "tag": "O"
    
        }, 
    
        {
    
          "word": "北", 
    
          "tag": "B-LOC"
    
        }, 
    
        {
    
          "word": "京", 
    
          "tag": "I-LOC"
    
        }, 
    
        {
    
          "word": "市", 
    
          "tag": "I-LOC"
    
        }, 
    
        {
    
          "word": "朝", 
    
          "tag": "B-LOC"
    
        }, 
    
        {
    
          "word": "阳", 
    
          "tag": "I-LOC"
    
        }, 
    
        {
    
          "word": "区", 
    
          "tag": "I-LOC"
    
        }
    
      ]
    
    }
    

    我们看下后台服务器日志数据

    图片

    我们可以得出这样的结果:

    **沈福利**毕业于北京工业大学,位于北京市朝阳区

    我们就可以把每个类型的 TAG 都提取出来了。

    NLP 比赛 音乐领域语义理解

    数据是主要来自人机对话系统中音乐领域以及非音乐领域的真实用户请求记录。

    音乐类槽位填充项目

    中文分词以及词性标注

    针对中文分词以及词性标注问题实际上是一个序列标注任务,属于 NER 功能,下面我们简单了解下。一般选择的方案:BiLSTM-CRF 或者 BERT_CRF.。下面我们采用 BERT_CRF 来进行实验,实际使用的过程,规则字典+模型一起来完成的,我们这里学习下如何使用NER 模型来进行分词( 大家可以尝试bilstm_crf ,目前工业界常用,主要基于推测性能来考虑的 ) ,本文实验我们选择了几种词性进行( [‘N’, ‘V’, ‘NZ’, ‘W’, ‘VN’, ‘MQ’, ‘D’, ‘T’, ‘UDE1’, ‘A’, ‘P’, ‘NR’, ‘VI’, ‘NNT’, ‘NT’, ‘NS’, ‘M’, ‘F’, ‘C’, ‘RR’])

    数据分析

    对 people-2014 人民日报 POS 词性标注数据数据集切分训练集、验证集、测试集。

    关于数据分析我们通过 pyecharts 进行一个可视化分析,便于我们的效果展示。 我们实际算法工作中关于数据分析以及特征提取占用我们 70%左右的时间,故了解我们的业务数据非常重要的。

    关于更多的 pyecharts 内容请参考

    Python数据可视化 pyecharts实战

    Python数据分析案例实战 视频课程

    • 数据 Example 分布

    这里给出训练数据、验证数据以及测试数据句子的记录数

    图片

    • 标签类别数据分布

    图片

    图片

    图片

    从上述 train、dev、test 发现,数据的 TAG

    • 文章句子长度分布

    通过分析自己业务句子的长度,可以在训练的时候 max_seq_len 进行设置合理的数值。

    图片图片

    通过上述分析:

    数据长度最大的长度整体在 200 左右,我们在通过 boxplot 那么我们在训练 bert 的时候 max_seq_len 可以设置 200 左右(多数据分布在 64 左右,为加速训练速度,可以训练时候可以设置一个比较小的数值)

    NER 模型训练

    这里给出 ubuntu 环境下 pytorch 配置环境

    export PATH=/home/ubuntu/anaconda3/bin:$PATH

    export PATH=/usr/local/cuda-9.0/bin:$PATH

    export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATH

    export LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LIBRARY_PATH

    python3 main.py  \
    --model_name_or_path ../pretrained_models/bert-base-chinese/ \
    --task  people-2014  \
    --model_type  bert \
    --model_dir people2014_bert_base_zh_model  \
    --do_train  --do_eval --use_crf   \
    --num_train_epochs 3  \
    --train_batch_size 32 \
    --eval_batch_size 64  \
    --max_seq_len 64
    

    我们实验使用单卡 GTX1080ti GPU,每个迭代1.5 小时。这里训练3次迭代效果(大家可以可以尝试更多):

     INFO - train -              precision    recall  f1-score   support
    
           NT       0.89      0.90      0.90      7307
            V       0.99      0.98      0.99    165986
            D       0.99      0.99      0.99     61665
            T       0.99      0.99      0.99     28097
         UDE1       1.00      1.00      1.00     51574
            N       0.97      0.97      0.97    185587
           VN       0.98      0.98      0.98     45969
           NZ       0.90      0.90      0.90     69613
            P       1.00      1.00      1.00     47142
          NNT       0.98      0.99      0.98     18146
            F       0.99      0.99      0.99     23310
            M       0.99      0.98      0.98     12727
           VI       0.98      0.98      0.98     22278
           MQ       0.98      0.99      0.99     34141
           RR       1.00      1.00      1.00     17288
           NR       0.97      0.97      0.97     21167
            A       0.98      0.98      0.98     31482
            C       1.00      1.00      1.00     14431
           NS       0.96      0.96      0.96     17992
    
    micro avg       0.98      0.98      0.98    875902
    macro avg       0.98      0.98      0.98    875902
    
    INFO - train -     loss = 1.8359935450942124
    INFO - train -     sementic_frame_acc = 0.8029136970713302
    INFO - train -     slot_f1 = 0.9759650342340757
    INFO - train -     slot_precision = 0.9765579723812039
    INFO - train -     slot_recall = 0.975372815680293
    

    大家可以自己尝试更多的参数进行训练

    • 增大 num_train_epochs
    • max_seq_len 可以设置 256(通过数据分析发现)
    • 在进行这类序列任务,如果有多卡,可以利用多卡并行提高训练数据

    这里对主要的词性进行说明,更多可以参考 。 具体实际应用,大家可以标准更多地数据来进分词效果实验。

     NR(人名)    
     VI(动词)   
      DE1(的)    
      C( 连词)  
      V(动词)    
     NS(地名)    
     MQ     
      D       
      N(名词)    
      A(形容词)  
     NT(机构团体)
     NZ(其它专名)
     VN(名动词)  
       RR       
      T(时间词)  
      M(数词)    
      NNT       
      F(方位词)  
      P(介词)    
    

    NER 模型在线预测

    python3 api.py \
    --model_name_or_path ../pretrained_models/bert-base-chinese/ \
    --task  people-2014  \
    --model_type  bert  \
    --model_dir people2014_bert_base_zh_model  \
    --use_crf 
    

    注意:model_name_or_path 和 model_dir 换成自己预训练模型路径和模型文件路径

    预测效率对比:gpu 单条记录预测 13ms 左右,cpu 大概 60ms(和服务器配置有关系)。对于 cpu 下推理速度慢的问题我们也可以针对模型进行优化(比如:albert-tiny…)

    **在线预测命令行如下: **

    query = 从北京到上海怎么走

    识别介词:从

    识别地名:北京、上海

    其他名词:怎么走

    1)执行命令
    curl http://127.0.0.1:8000/predict -H "Content-Type:application/json" -X POST --data '{"text": "从北京到上海怎么走","lang":"zh"}'2) 返回结果
    text =  从北京到上海怎么走
    seq_len =  9
    0       从      S-P
    1       北      B-NS
    2       京      I-NS
    3       到      S-V
    4       上      B-NS
    5       海      I-NS
    6       怎      B-NZ
    7       么      I-NZ
    8       走      I-NZ
    
    • query = 我要去北京市海淀区中关村大街

    地名识别 NS: 北京市、海淀区

    专有名词: 中关村大街

    (1)执行命令
    curl http://127.0.0.1:8000/predict -H "Content-Type:application/json" -X POST --data '{"text": "我要去北京市海淀区中关村大街","lang":"zh"}'
    (2)返回结果
    text =  我要去北京市海淀区中关村大街
    seq_len =  14
    0       我      S-RR
    1       要      S-V
    2       去      O
    3       北      B-NS
    4       京      I-NS
    5       市      I-NS
    6       海      B-NS
    7       淀      I-NS
    8       区      I-NS
    9       中      B-NZ
    10      关      I-NZ
    11      村      I-NZ
    12      大      I-NZ
    13      街      I-NZ
    
    • query =播放一首周杰伦的歌曲

    动词: 播放

    人名:周杰伦

    普通名称: 歌曲

    (1) 执行命令
    curl http://127.0.0.1:8000/predict -H "Content-Type:application/json" -X POST --data '{"text": "播放一首周杰伦的歌曲","lang":"zh"}'
    (2)返回结果
    text =  播放一首周杰伦的歌
    seq_len =  9
    0       播      B-V
    1       放      I-V
    2       一      B-MQ
    3       首      I-MQ
    4       周      B-NR
    5       杰      I-NR
    6       伦      I-NR
    7       的      S-UDE1
    8       歌      B-N
    9       曲      I-N
    

    附录-拓展学习资料

    下面给大家提供一些学习资料,供大家自己学习,作为课堂外的内容。

    CoNLL-2003

    https://www.aclweb.org/anthology/W03-0419.pdf

    https://www.clips.uantwerpen.be/conll2003/ner/

    https://yuanxiaosc.github.io/2018/12/26/%E5%91%BD%E5%90%8D%E5%AE%9E%E4%BD%93%E8%AF%86%E5%88%ABCoNLL2003/

    https://github.com/yuanxiaosc/BERT-for-Sequence-Labeling-and-Text-Classification

    如何训练小模型

    NLPCC2020 NER 项目

    https://github.com/CLUEbenchmark/CLUENER2020

    https://www.cluebenchmarks.com/introduce.html

    https://www.cluebenchmarks.com/NLPCC.html

    https://zhuanlan.zhihu.com/p/102676719?utm_source=wechat_timeline

    把BERT的推断速度提升17倍

    下面我们做一些的尝试

    1/9 的 bert_base < 12M

    **数据 **

    • 160G+原始数据
    • 35G+的通用数据
    • 3700+预训练模型
    • 256 的预处理长度

    模型

    我们可以考虑 bert_base 修改 6 层看看效果 。

    “num_hidden_layers”: 12-> “num_hidden_layers”: 6

    “max_position_embeddings”: 512-> “max_position_embeddings”: 256

    v100-32G 8 卡混合精度训练

    wwm-mlm

    结果

    • loss 在 1.5->1.8 抖动

    2000qps 20gpu-> 2000qps 1gpu

    推理优化方案

    • Tensorflow serving Batching
    • FP16 量化
    • Faster Transformer

    中文版本 zh-albert

    我们直接使用 albert_zh 中已经转好的版本, 点击下载

    对话系统

    [1] 小爱:语音识别和 NLP 在语音交互中的实践

    [2] 美团对话理解技术及实践

    [3] 小米NLU2018

    展开全文
  • 简单NLP分析套路(1)----语料库积累...简单NLP分析套路(2)----分词,词频,命名实体识别与关键词抽取:https://cloud.tencent.com/developer/article/1384457 简单NLP分析套路(3)---- 可视化展现与语料收集整理: ...

    简单NLP分析套路(1)----语料库积累之3种简单爬虫应对大部分网站:
    https://cloud.tencent.com/developer/article/1384454

    简单NLP分析套路(2)----分词,词频,命名实体识别与关键词抽取:https://cloud.tencent.com/developer/article/1384457

    简单NLP分析套路(3)---- 可视化展现与语料收集整理:
    https://cloud.tencent.com/developer/article/1384469

    展开全文
  • 最近费尽千辛万苦构造了一份可以用(大概)的知识图谱,并且把要利用知识图谱做的领域命名实体识别和一些推荐的功能做成Web版的demo,顺带想实现一些可视化知识图谱的功能。 (凭啥知识图谱就只能在Neo4j里自嗨,不...
  • 它支持诸如精度,召回率和F1分数之类的标准指标,并在带注释的文档的上下文中可视化黄金标准和注释器结果。 实体的颜色编码使专家可以快速识别正确和不正确的注释以及Orbis也提供的与KB的相应链接。 由于Orbis使用...
  • 自然语言处理:关键短语和关键字提取,以及命名实体识别。 文本表示形式:TF-IDF,词频和自定义词嵌入(wip) 向量空间分析:聚类(K均值,Meanshift,DBSCAN和Hierarchical),主题建模(wip)和解释。 文本...
  • HarvestText Sow with little data seed, harvest much from a text ...(命名实体识别,依存句法分析,简易问答系统) 本README包含各个功能的典型例子,部分函数的详细用法可在文档中找到: 具体功能如下: 基本处理
  • 命名实体识别,依存句法分析,简易问答系统) 本README包含各个功能的典型示例,部分函数的详细用法可在文档中找到: 具体功能如下: 基本处理 可考虑指定词和类别的分词。充分考虑省略号,双引号等特殊标点的分句...
  • nlp的分类问题使用bert来解决,nlp的所有问题都可以抽象成分类问题,也就是nlp问题都可以用bert来解决,包括命名实体识别、实体关系抽取、实体链接(百度叫实体链指)等。有兴趣可以看这个基于bert的实体关系抽取,...

    从业这么多年,说说对机器学习算法的认识。
    关于分类问题,结构化数据的分类回归问题都可以用xgboost来解决;nlp的所有问题都可以抽象成分类问题,也就是nlp问题都可以用bert来解决,包括命名实体识别、实体关系抽取、实体链接(百度叫实体链指)等。有兴趣可以看这个基于bert的实体关系抽取,点我

    这里说说xgboost怎么玩。


    官网博客,点我

    1.安装

    mac安装,我直接:pip install xgboost安装报错(mac安装坑挺深),conda安装:conda install py-xgboost 就没有问题了,依赖什么的都会一起安装,省事。
    在这里插入图片描述
    要结合matplotlib画图工具一起使用的话一定要:conda install matplotlib进行安装,xgboost使用conda 安装,matplotlib再使用pip安装的话会出现环境污染问题,conda list查看环境情况会发现有两个版本的numpy、scipy,这是因为pip安装的源和conda安装的源不一样,默认版本不一样,不要混着使用。
    在这里插入图片描述

    2.运行报错:AttributeError: module ‘xgboost’ has no attribute ‘DMatrix’

    修改文件名,你的文件名很可能是xgboost.py

    3.输入数据格式 :libsvm

    libsvm 使用的训练数据和检验数据文件格式如下:

    [label] [index1]:[value1] [index2]:[value2] …
    [label] [index1]:[value1] [index2]:[value2] …
    

    label 目标值,就是说 class(属于哪一类),就是你要分类的种类,通常是一些整数。
    index 是有顺序的索引,通常是连续的整数。就是指特征编号,必须按照升序排列
    value 就是特征值,用来 train 的数据,通常是一堆实数组成。

    详细见:地址,点我

    4.mushroom数据

    每个样本描述了蘑菇的22个属性,比如形状、气味等等(将22维原始特征用加工后变成了126维特征并存为libsvm格式),然后给出了这个蘑菇是否可食用。其中6513个样本做训练,1611个样本做测试。

    libsvm格式数据下载(训练测试数据都在这里):下载地址,点我

    5.跑一个最简单的demo

    # coding=utf-8
    import xgboost as xgb
    import numpy as np
    
    if __name__ == '__main__':
        # 读取数据
        data_train = xgb.DMatrix('agaricus_train.txt')
        data_test = xgb.DMatrix('agaricus_test.txt')
    
        # 设定相关参数,训练模型
        param = {'max_depth': 2, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic'}
        n_round = 10
        model = xgb.train(param, data_train, num_boost_round=n_round)
    
        # 预测结果
        y_predict = model.predict(data_test)
        # 实际标签
        y_true = data_test.get_label()
        
        print('y_predict:', y_predict)
        print('y_true:', y_true)
    

    终端输出(可以看到预测结果和标签结果是一致的,阈值设置0.5即可):
    在这里插入图片描述

    6.可选目标函数(objective)

    二分类问题一般选择:reg:logistic
    多分类问题一般选择:multi:softmax

    “reg:linear” —— 线性回归。
    “reg:logistic”—— 逻辑回归。
    “binary:logistic”—— 二分类的逻辑回归问题,输出为概率。
    “binary:logitraw”—— 二分类的逻辑回归问题,输出的结果为wTx。
    “count:poisson”—— 计数问题的poisson回归,输出结果为poisson分布。在poisson回归中,max_delta_step的缺省值为0.7(used to safeguard optimization)
    “multi:softmax” –让XGBoost采用softmax目标函数处理多分类问题,同时需要设置参数num_class(类别个数)
    “multi:softprob” –和softmax一样,但是输出的是ndata * nclass的向量,可以将该向量reshape成ndata行nclass列的矩阵。没行数据表示样本所属于每个类别的概率。
    “rank:pairwise” –set XGBoost to do ranking task by minimizing the pairwise loss
    

    7.输出评价指标

    如果不知道这些指标怎么计算,这篇博客帮你搞明白:
    文章地址,点它:搞懂回归和分类模型的评价指标的计算:混淆矩阵,ROC,AUC,KS,SSE,R-square,Adjusted R-Square

    from sklearn import metrics
    print ('AUC: %.4f' % metrics.roc_auc_score(y_true,y_predict_prob))  # y_predict_prob是概率值
    print ('ACC: %.4f' % metrics.accuracy_score(y_true,y_predict))
    print ('Recall: %.4f' % metrics.recall_score(y_true,y_predict))
    print ('F1-score: %.4f' %metrics.f1_score(y_true,y_predict))
    print ('Precesion: %.4f' %metrics.precision_score(y_true,y_predict))
    print(metrics.confusion_matrix(y_true,y_predict))
    

    8.特征重要度可视化

    import os
    os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
    from xgboost import plot_importance
    from matplotlib import pyplot as plt
    plot_importance(model)
    plt.show()
    

    效果:
    在这里插入图片描述

    9.输出top-n重要特征

    feature_score = model.get_fscore()
    feature_score = dict(sorted(feature_score.items(), key=lambda x: x[1], reverse=True))
    

    输出:

    {'f29': 48, 'f6': 44, 'f2': 36, 'f4': 20, 'f179': 18, 'f133': 16, 'f95': 12, 'f7': 10, 'f71': 10, 'f12': 10, 'f5': 10, 'f96': 8, 'f21': 6, 'f81': 6, 'f43': 6, 'f141': 6, 'f115': 6, 'f27': 4, 'f132': 4, 'f74': 4, 'f1': 4, 'f83': 4, 'f121': 4, 'f178': 4, 'f84': 4, 'f93': 4, 'f99': 4, 'f124': 4, 'f118': 2, 'f88': 2, 'f46': 2, 'f201': 2, 'f199': 2, 'f151': 2, 'f101': 2, 'f54': 2, 'f0': 2, 'f41': 2, 'f144': 2, 'f36': 2, 'f225': 2, 'f117': 2, 'f98': 2, 'f80': 2, 'f17': 2, 'f25': 2, 'f55': 2, 'f146': 2, 'f128': 2, 'f44': 2}
    

    10.如何调参

    看这篇博客

    11.xgboost相比GBDT的改进

    算法层面

    主要是两点:
    1.损失函数的优化。xgboost损失函数是误差部分是二阶泰勒展开,GBDT 是一阶泰勒展开。因此损失函数近似的更精准。
    2.节点分裂策略的优化。实现了利用分捅/分位数方法,实现了全局和局部的近似分裂点算法,降低了计算量,并且在eps参数设置合理的情况下,能达到穷举法几乎一样的性能

    其他:
    3.传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)
    4.XGB加了正则项,普通GBDT没有。为了防止过拟合
    5.对每颗子树增加一个参数,使得每颗子树的权重降低,防止过拟合,这个参数叫shrinkage,相当于学习速率(xgboost中的eta)
    6.对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。
    7.列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。

    系统层面

    8.对每个特征进行分块(block)并排序,使得在寻找最佳分裂点的时候能够并行化计算。这是xgboost比一般GBDT更快的一个重要原因。
    9.通过设置合理的block的大小,充分利用了CPU缓存进行读取加速(cache-aware access)。使得数据读取的速度更快。因为太小的block的尺寸使得多线程中每个线程负载太小降低了并行效率。太大的block尺寸会导致CPU的缓存获取miss掉。
    10.block压缩与拆分。out-of-core 通过将block压缩(block compressoin)并存储到硬盘上,并且通过将block分区到多个硬盘上(block Sharding)实现了更大的IO 读写速度,因此,因为加入了硬盘存储block读写的部分不仅仅使得xgboost处理大数据量的能力有所提升,并且通过提高IO的吞吐量使得xgboost相比一般实利用这种技术实现大数据计算的框架更快。

    12.RF与GBDT之间的区别

    GBDT是一种boosting算法。boosting工作机制:先从初始训练集训练出一个基学习器,然后在根据基学习器的表现对训练样本分布进行调整,使得先前的基学习器做错的训练样本在后续获得更多关注(增加错误样本权重),然后基于调整后的样本分布训练下一个基学习器,如此重复,直到基学习器达到指定的T时,最终将T个基学习器进行加权结合,得出预测。

    随机森林是对bagging算法的一点改动,但是更能体现样本集之间的差异性。会提高最终预测结果的泛化能力。

    相同点

    都是由多棵树组成
    最终的结果都是由多棵树一起决定

    不同点

    1.组成随机森林的树可以分类树也可以是回归树,而GBDT只由回归树组成
    2.组成随机森林的树可以并行生成,而GBDT是串行生成
    3.随机森林的结果是多数表决,而GBDT则是多棵树累加之和表决的
    4.随机森林对异常值不敏感,而GBDT对异常值比较敏感
    5.随机森林是通过减少模型的方差来提高性能,而GBDT是减少模型的偏差来提高性能的
    6.随机森林不需要进行数据预处理,即特征归一化。而GBDT则需要进行特征归一化

    展开全文
  • 这个项目的代码基于这个红楼梦项目的 。现在只实现了all_relation.html 所有人物关系页面的部分,代码也比较乱,之后我会慢慢... <!... <!...--|-ltp.py 分词、词性标注、命名实体识别 --> <!--|- get_*.py
  • 谁招聘地图 通过对条目进行地理标记来创建HN招聘名单。 提取标头,使用RegEx和Stanford命名实体识别器查找地名,然后将其提交给Bing进行地理编码。 取得结果并使用Leaflet可视化结果。
  • brat标注工具知识总结

    2021-05-29 18:03:41
    目录医疗实体识别、关系抽取...这个项目中不仅提供了用于命名实体识别和关系抽取的医疗数据标注工具,还提供了标注规范文档和可用于测试标注工具的部分电子病历样例。 https://github.com/WILAB-HIT/Resources BRAT ...
  • 可视化和论文层次重点讲解seq2seq+attention 机制,通过本课程的学习。...为后续课程讲解项目打下基础,学习完课程后可以学习后续项目实战课程:命名实体识别、对话系统语义理解项目、知识图谱、FQA问答系统等。
  • 1、词向量引入词性 1.1、原理 1.2、预设词性特征 1.3、完整代码示例 1.4、效果比较及改进方向 2、词向量-->单位向量 ...应用场景:关键词抽取提升、命名实体识别提升… 大家可以根据自身业务场景来选择是否引入词性
  • 双向RNN用于命名实体识别 迁移学习和词嵌入步骤 词嵌入和人脸编码的关系 2.3 Properties of word embeddings 类比推理 使用词向量的推理 相似度衡量:余弦距离、欧氏距离 2.4 Embedding Matrix ...
  • 15.通用命名实体识别 16.领域命名实体识别 17.实体查询程序设计 18.关系查询程序设计 19.知识图谱数据可视化 20.推荐系统基本原理和实现机制 21.知识图谱与推荐系统融合的模式 22.基于KGE的开源推荐系统框架 23....
  • 本文教你用简单易学的工业级Python自然语言处理软件包Spacy,对自然语言文本做词性分析、命名实体识别、依赖关系刻画,以及词嵌入向量的计算和可视化。 盲维 我总爱重复一句芒格爱说的话: To the one with ...
  • 主要功能包括分词、词性标注、命名实体识别、用户词典功能,新词发现与关键词提取。 可以可视化界面操作和API方式调用。 哈工大LTP(推荐) 语言技术平台(LTP)是哈工大社会计算与信息检索研究中心开发的一整套中文...
  • 技术贴收藏

    2018-08-15 17:31:56
    深度学习篇: 一文弄懂神经网络中的反向传播法——BackPropagation 三个月教你从零入门深度学习 数据结构篇: 剑指offer python实现 66道算法题 ...序列标注:BiLSTM-CRF模型做基于字的中文命名实体识别 ...
  • TEXTOIR-Lee-源码

    2021-03-15 16:06:27
    尽管开发了一些用于命名实体识别,情感分析的工具包,但意图识别的相关工作很少,即使在开放世界的环境中也是如此。 因此,我们建立了一个文本开放意图识别平台来填补空白。 演示视频可在 :woman_and_man_holding_...
  • 开源NLP标注工具及NLP数据集

    千次阅读 2020-03-26 20:13:34
    开源NLP标注工具技术分享 数据堂 AI-Lab 一、什么是标注平台 自然语言处理标注工具是指通过可视化界面,以清晰、快捷的...命名实体识别(对文本实体进行标注,如人名、地名、实体名等等) 关系抽取任务(对文本中词...
  • 主要功能包括分词、词性标注、命名实体识别、用户词典功能,新词发现与关键词提取。 可以可视化界面操作和API方式调用。 哈工大LTP(推荐) http://www.ltp-cloud.com/ 语言技术平台(LTP)是哈工大社会计算
  • 1.1 词汇表征 ...命名实体识别示例 迁移学习及词嵌入 词嵌入与人脸编码的关系——很相似,只是不同的约定称呼而已 1.3 词嵌入的特性 词嵌入的特性:同类词间的差较小 寻找同类...
  • 机器学习日报 2017-02-25 特征学习顶会ICLR 2017...@199IT-互联网数据中心深度学习NLP套装:分词、词性标注、命名实体识别 @爱可可-爱生活概率与统计概念的可视化诠释 @爱可可-爱生活 @好东西传送门 出品,由@AI1
  • 简介 Andrew Ng 深度学习入门课程学习记录 序列模型 2 自然语言处理 2.1 词汇表征。 传统表示:one-hot。缺点是假设词语是相互独立的,难以刻画词语之间的相关性。...词嵌入的应用:命名实体识别、文本摘要
  • NLP学习 资料总结

    2020-01-11 16:59:12
    1.句法语义分析:对于给定的句子,进行分词、词性标记、命名实体识别和链接、句法分析、语义角色识别和多义词消歧。 2.信息抽取:从给定文本中抽取重要信息。通俗来说就是,了解谁在什么时候、什么原因、对谁做了...
  • 说到自然语言处理, 语言模型, 命名实体识别, 机器翻译, 可能很多人想到的LSTM等循环神经网络, 但目前其实LSTM起码在自然语言处理领域已经过时了, 在Stanford阅读理解数据集(SQuAD2.0)榜单里, 机器的成绩已经超人类...

空空如也

空空如也

1 2 3 4
收藏数 76
精华内容 30
关键字:

可视化命名实体识别