精华内容
下载资源
问答
  • bert中文分类实例win10

    千次阅读 热门讨论 2019-01-10 10:42:01
    bert分类实例,在本地win10下 我的bert分类项目地址(有数据,本地win10可运行):https://github.com/yongzhuo/bert,但是预测调用好像不方便, 我另外一个项目bert分类实例,可predict,很方便:...

    bert分类实例,在本地win10下

    我的bert分类项目地址(有数据,本地win10可运行):https://github.com/yongzhuo/bert,但是预测调用好像不方便,

    我另外一个项目bert分类实例,可predict,很方便:https://github.com/yongzhuo/nlp_xiaojiang/tree/master/ClassificationText/bert

    备注:   model.ckpt-15.data-00000-of-00001有400M传不上github,

               这个chinese_L-12_H-768_A-12预先训练好的模型先去谷歌下载替换吧

    如果下载不了,也可以去百度云,我放了一个上去前往链接: https://pan.baidu.com/s/1I3vydhmFEQ9nuPG2fDou8Q 提取码: rket

    运行直接 run_classifier.py  就可以了

    环境:tensorflow 1.11及以上

    展开全文
  • 实验中对中文34个topic进行实践(包括:时政,娱乐,体育等),在对run_classifier.py代码中的预处理环节需要加入NewsProcessor模块,及类似于MrpcProcessor,但是需要对中文的编码进行适当修改
  • bert简介


    0. bert简介

    • BERT(Bidirectional Encoder Representation from Transformers)是google-research在2018年10月提出的一种预训练模型,在11种不同NLP测试中创出SOTA表现,成为NLP发展史上里程碑式的模型成就。
    • 本篇文章从实践入手,带领大家进行Bert的中文文本分类模型的训练和推理的使用教程。

    1. bert结构

    1. bert中文分类模型训练

    bert训练主要分为两个阶段:预训练阶段和 Fine-tuning 阶段。

    什么是预训练?
    BERT是一个预训练的模型,那么什么是预训练呢?举例子进行简单的介绍
    假设已有A训练集,先用A对网络进行预训练,在A任务上学会网络参数,然后保存以备后用,当来一个新的任务B,采取相同的网络结构,网络参数初始化的时候可以加载A学习好的参数,其他的高层参数随机初始化,之后用B任务的训练数据来训练网络,当加载的参数保持不变时,称为"frozen",当加载的参数随着B任务的训练进行不断的改变,称为“fine-tuning”,即更好地把参数进行调整使得更适合当前的B任务
    优点:当任务B的训练数据较少时,很难很好的训练网络,但是获得了A训练的参数,会比仅仅使用B训练的参数更优

    预训练
    预训练阶段与 Word2Vec,ELMo 等类似,是在大型数据集上根据一些预训练任务训练得到。预训练需要巨大的运算资源,google官方预训练一个语言模型,需要在 4 到 16 个 Cloud TPU 训练四天的时间,幸运的是,google官方开源了许多预训练模型,包括中文预训练模型。大多数 NLP 研究人员永远不需要从头开始预训练他们自己的模型。

    微调
    Fine-tuning 阶段是后续用于一些下游任务的时候,在预训练模型基础之上进行微调,例如文本分类,词性标注,问答系统等,BERT 无需调整结构就可以在不同的任务上进行微调。


    1 下载bert项目代码

    https://github.com/google-research/bert
    

    代码结构

    • 预训练
      在开源的代码中,预训练的入口是在run_pretraining.py。
    • 微调
      而微调的入口针对不同的任务分别在run_classifier.py和run_squad.py。
      其中run_classifier.py用于文本分类任务的训练。
      而run_squad.py用于阅读理解任务的训练。
      在这里插入图片描述

    2 下载中文预训练模型

    对于中文而言,google公布了一个参数较小的BERT预训练模型。

    • 模型下载地址
    https://github.com/google-research/bert/blob/master/multilingual.md
    
    • 进入下载页面,选择:BERT-Base, Chinese进行下载。

    在这里插入图片描述

    • 下载完成后,解压至与run_classifier.py同一级目录。

    • 模型文件说明
      在这里插入图片描述
      bert_model.ckpt:存储得模型变量
      vocab.txt:中文文本采用的字典,
      bert_config.json:是bert在训练时,可选调整的一些配置参数。


    3 制作中文训练数据集

    对中文文本数据进行分类模型的训练,需要编写程序对训练数据进行处理,使其按照要求传入bert模型进行训练,而BERT代码中processor类就是负责对模型的输入数据进行处理。

    们以分类任务为例,介绍如何修改processor类来运行自己数据集上的fine-tune。在run_classsifier.py文件中我们可以看到,google对于一些公开数据集已经写了一些processor,如XnliProcessor,MnliProcessor,MrpcProcessor和ColaProcessor。这给我们提供了一个很好的示例,指导我们如何针对自己的数据集来写processor。

    class kedataProcessor(DataProcessor):
      """Processor for the XNLI data set."""
    
      def get_train_examples(self, data_dir):
          return self._create_examples(
    
              self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")
    
      def get_dev_examples(self, data_dir):
          return self._create_examples(
              self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")
    
      def get_test_examples(self, data_dir):
          return self._create_examples(
              self._read_tsv(os.path.join(data_dir, "test.tsv")), "test")
    
      def get_labels(self):
          # 这里返回的为具体的你的分类的类别
          labelf = open(FLAGS.data_dir+'\label.csv', 'r', newline='', encoding = 'gb2312')
          labeldata = csv.reader(labelf, delimiter="\t")
          labelList=[]
          for line in labeldata:
              label=line[1]
              labelList.append(label)
    
          return labelList
    
      def _create_examples(self, lines, set_type):
          """Creates examples for the training and dev sets."""
          examples = []
          for (i, line) in enumerate(lines):
              guid = "%s-%s" % (set_type, i)
              text_a = tokenization.convert_to_unicode(line[1])
              label = tokenization.convert_to_unicode(line[0])
              # print('guid:',guid," text:",text_a,' label:',label)
              examples.append(
                  InputExample(guid=guid, text_a=text_a, text_b=None, label=label))
    
          return examples
    
    

    自定义的processor里需要继承DataProcessor,并重载获取label的get_labels和获取单个输入的get_train_examples,get_dev_examples和get_test_examples函数。其分别会在main函数的FLAGS.do_train、FLAGS.do_eval和FLAGS.do_predict阶段被调用。
    这三个函数的内容是相差无几的,区别只在于需要指定各自读入文件的地址。

    以get_train_examples为例,函数需要返回一个由InputExample类组成的list。InputExample类是一个很简单的类,只有初始化函数,需要传入的参数中guid是用来区分每个example的,可以按照train-%d’%(i)的方式进行定义。text_a是一串字符串,text_b则是另一串字符串。在进行后续输入处理后(BERT代码中已包含,不需要自己完成) text_a和text_b将组合成[CLS] text_a [SEP] text_b [SEP]的形式传入模型。最后一个参数label也是字符串的形式,label的内容需要保证出现在get_labels函数返回的list里。

    举一个例子,假设我们想要处理一个能够判断句子相似度的模型,现在在data_dir的路径下有一个名为train.csv的输入文件,如果我们现在输入文件的格式如下csv形式:

    肯定	嗯,对,是。
    求职状态_已找到工作	呃,我有工作了谢谢。
    中性	哦,你您说吧。
    询问岗位地址	嗯那,那你们就是上班的话,是就近安排吗,我看有很多你们那个
    肯定	在听得见我说话吗。
    中性	啊,你说你说。
    智能助理	的用户暂时无法接听你的电话,短信通知请挂机语音留言,请按一如需人工帮助,请按零
    没听清什么事	干啥呀什么事情?
    在忙	哦,等会我现在在去面试的路上。
    否定	嗯,现在没有了,不好意思啊。
    

    label.csv

    0	打错了	226
    1	打过电话	127
    2	拒绝来电	177
    3	电话号码获取	19
    4	反问听见与否	55
    5	非机主	285
    6	否定	4477
    7	福利_其他	15
    8	福利_食宿	47
    9	福利_五险一金	83
    10	岗位_年龄要求	58
    

    修改processor字典
    修改完成processor后,需要在在原本main函数的processor字典里,加入修改后的processor类,即可在运行参数里指定调用该processor。

    processors = {
          "cola": ColaProcessor,
          "mnli": MnliProcessor,
          "mrpc": MrpcProcessor,
          "xnli": XnliProcessor,
          "kedata": kedataProcessor,
      }
    

    运行run_classifier.py
    之后就可以直接运行run_classsifier.py进行模型的训练。在运行时需要制定一些参数,一个较为完整的运行参数如下所示:

    BERT_BASE_DIR=/path/to/bert/chinese_L-12_H-768_A-12 #全局变量 下载的预训练bert地址
    MY_DATASET=/path/to/kedata #全局变量 数据集所在地址
    
    python run_classifier.py \
      --task_name=kedata \ #自己添加processor在processors字典里的key名
      --do_train=true \
      --do_eval=true \
      --dopredict=true \
      --data_dir=$MY_DATASET \
      --vocab_file=$BERT_BASE_DIR/vocab.txt \
      --bert_config_file=$BERT_BASE_DIR/bert_config.json \
      --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
      --max_seq_length=128 \ #模型参数
      --train_batch_size=32 \
      --learning_rate=5e-5 \
      --num_train_epochs=2.0 \
      --output_dir=/tmp/selfsim_output/ #模型输出路径
    

    2. bert模型推理

    1.tensorflow推理

    在这里插入图片描述

    • 问题:
      用Estimater.predict总是把模型重新load一遍,这样工程业务根本没法用。
    • 解决方案:
    1. 使用python的生成器,让程序“误以为”有很多序列需要预测,这里构造yield形式即可;
    2. 利用tf.data.Dataset.from_generator,加载生成器,声明好数据结构和类型;
    3. 利用class类的实例变量self的全局性,通过self.inputs把数据“喂给到”生成器内部,这样就保证了数据的“源源不断”;
    4. 程序需要close的机制,用于保证停掉生成器的工作。
    from tokenization import FullTokenizer, validate_case_matches_checkpoint
    from modeling import BertConfig
    from run_classifier import model_fn_builder
    import tensorflow as tf
    from tensorflow.python.estimator.estimator import Estimator
    from tensorflow.python.estimator.run_config import RunConfig
    from run_classifier import FLAGS,InputExample,convert_single_example
    import csv
    import os
    import numpy as np
    
    
    class model(object):
        def __init__(self, labelfile,vocabfile,bert_config_file,init_checkpoint,ckptdir,max_seq_length):
            self.label = self.loadLabel(labelfile)
            self.closed = False
            self.first_run = True
            self.bert_config_file=bert_config_file
            self.ckptdir=ckptdir
    
            self.tokenizer = FullTokenizer(
                vocab_file=vocabfile,
                do_lower_case=True)
            self.init_checkpoint = init_checkpoint
            self.seq_length = max_seq_length
            self.text = None
            self.num_examples = None
            self.predictions = None
            self.estimator = self.get_estimator()
    
        def loadLabel(sel, labelfile):
            labelf = open(labelfile, 'r', newline='', encoding='gbk')
            labeldata = csv.reader(labelf, delimiter="\t")
            labelList = []
            for line in labeldata:
                label = line[1]
                labelList.append(label)
            return labelList
    
        def get_estimator(self):
            validate_case_matches_checkpoint(True, self.init_checkpoint)
            bert_config = BertConfig.from_json_file(self.bert_config_file)  # 载入bert自定义配置
            if FLAGS.max_seq_length > bert_config.max_position_embeddings:  # 验证配置信息准确性
                raise ValueError(
                    "Cannot use sequence length %d because the BERT pre_model "
                    "was only trained up to sequence length %d" %
                    (self.seq_length, bert_config.max_position_embeddings))
            run_config = RunConfig(
                model_dir=self.ckptdir,
                save_checkpoints_steps=FLAGS.save_checkpoints_steps,
                session_config=None
            )
    
            model_fn = model_fn_builder(  # 估计器函数,提供Estimator使用的model_fn,内部使用EstimatorSpec构建的
                bert_config=bert_config,
                num_labels=len(self.label),
                init_checkpoint=self.init_checkpoint,
                learning_rate=FLAGS.learning_rate,
                num_train_steps=0,
                num_warmup_steps=0,
                use_tpu=FLAGS.use_tpu,
                use_one_hot_embeddings=FLAGS.use_tpu)
            estimator = Estimator(  # 实例化估计器
                model_fn=model_fn,
                config=run_config,
                warm_start_from=self.init_checkpoint  # 新增预热
            )
            return estimator
    
        def get_feature(self, index, text):
            example = InputExample(f"text_{index}", text, None, self.label[0])
            feature = convert_single_example(index, example, self.label, self.seq_length, self.tokenizer)
            return feature.input_ids, feature.input_mask, feature.segment_ids, feature.label_id
    
        def create_generator(self):
            """构建生成器"""
            while not self.closed:
                self.num_examples = len(self.text)
                features = (self.get_feature(*f) for f in enumerate(self.text))
    
                yield dict(zip(("input_ids", "input_mask", "segment_ids", "label_ids"), zip(*features)))
    
        def input_fn_builder(self):
            """用于预测单独对预测数据进行创建,不基于文件数据"""
            dataset = tf.data.Dataset.from_generator(
                self.create_generator,
                output_types={'input_ids': tf.int32,
                              'input_mask': tf.int32,
                              'segment_ids': tf.int32,
                              'label_ids': tf.int32},
                output_shapes={
                    'label_ids': (None),
                    'input_ids': (None, None),
                    'input_mask': (None, None),
                    'segment_ids': (None, None)}
            )
            return dataset
    
        def predict(self, text):
            self.text = text
            if self.first_run:
                self.predictions = self.estimator.predict(
                    input_fn=self.input_fn_builder, yield_single_examples=True)
                self.first_run = False
    
            probabilities = next(self.predictions)
            # 获取最大值索引
            index = np.argmax(probabilities["probabilities"])
            label = self.label[index]
            # return [self.label[i] for i in probabilities["probabilities"].argmax(axis=1)]
    
            return label
    
        def close(self):
            self.closed = True
    pythonfile=os.path.realpath(os.path.realpath(__file__))
    pardir=os.path.abspath(os.path.join(pythonfile,os.path.pardir))
    labelfile=os.path.join(pardir,'ckpt/label.csv')
    init_checkpoint=os.path.join(pardir,'chinese_L-12_H-768_A-12/bert_model.ckpt')
    vocabfile=os.path.join(pardir,'chinese_L-12_H-768_A-12/vocab.txt')
    bert_config_file=os.path.join(pardir,'chinese_L-12_H-768_A-12/bert_config.json')
    ckptdir=os.path.join(pardir,'ckpt/')
    max_seq_length=128
    def getModel():
        bert = model(labelfile,vocabfile,bert_config_file,init_checkpoint,ckptdir,max_seq_length)
        bert.predict([""])
        return bert
    
    if __name__=="__main__":
        bert=getModel()
        for i in range(1000):
            label=bert.predict(["打错了"])
    

    2. onnxruntime推理

    ONNX Runtime是一个高性能的机器学习模型推理引擎。它与PyTorch、TensorFlow以及许多其他支持ONNX标准的框架和工具兼容。ONNX Runtime设计了一个开放和可扩展的体系结构,通过利用内置的图形优化和跨CPU、GPU和边缘设备的各种硬件加速功能,可以轻松地优化和加速推理。ONNX Runtime可以很容易地插入到你的技术堆栈中,因为它可以在Linux、Windows、Mac和Android上工作,并且为Python、c#、c++、C和Java提供了方便的api。

    为加快bert的推理时间,部署到服务器上,可食用onnxruntime进行推理加速。

    1. checkpoint格式转换为saveModel格式

    在这里插入图片描述

    from tokenization import FullTokenizer, validate_case_matches_checkpoint
    from modeling import BertConfig
    from run_classifier import model_fn_builder
    import tensorflow as tf
    from tensorflow.python.estimator.estimator import Estimator
    from tensorflow.python.estimator.run_config import RunConfig
    from run_classifier import FLAGS
    import csv
    
    class Fast(object):
        def __init__(self, labelfile,vocabfile,bert_config_file,init_checkpoint,ckptdir):
            self.label = self.loadLabel(labelfile)
            self.closed = False
            self.first_run = True
            self.bert_config_file=bert_config_file
            self.ckptdir=ckptdir
    
            self.tokenizer = FullTokenizer(
                vocab_file=vocabfile,
                do_lower_case=True)
            self.init_checkpoint = init_checkpoint
            # self.seq_length = FLAGS.max_seq_length
            self.seq_length = 128
            self.text = None
            self.num_examples = None
            self.predictions = None
            self.estimator = self.get_estimator()
    
        def loadLabel(sel, labelfile):
            labelf = open(labelfile, 'r', newline='', encoding='gbk')
            labeldata = csv.reader(labelf, delimiter="\t")
            labelList = []
            # for i in range(60):
            #    labelList.append(i)
            for line in labeldata:
                label = line[1]
                labelList.append(label)
            return labelList
    
        def get_estimator(self):
            validate_case_matches_checkpoint(True, self.init_checkpoint)
            print("FLAGS.bert_config_file:",FLAGS.bert_config_file)
            bert_config = BertConfig.from_json_file(self.bert_config_file)  # 载入bert自定义配置
            if FLAGS.max_seq_length > bert_config.max_position_embeddings:  # 验证配置信息准确性
                raise ValueError(
                    "Cannot use sequence length %d because the BERT pre_model "
                    "was only trained up to sequence length %d" %
                    (self.seq_length, bert_config.max_position_embeddings))
            print("FLAGS.save_checkpoints_steps:",FLAGS.save_checkpoints_steps)
            run_config = RunConfig(
                model_dir=self.ckptdir,
                save_checkpoints_steps=FLAGS.save_checkpoints_steps,
                session_config=None
            )
    
            model_fn = model_fn_builder(  # 估计器函数,提供Estimator使用的model_fn,内部使用EstimatorSpec构建的
                bert_config=bert_config,
                num_labels=len(self.label),
                init_checkpoint=self.init_checkpoint,
                learning_rate=FLAGS.learning_rate,
                num_train_steps=0,
                num_warmup_steps=0,
                use_tpu=FLAGS.use_tpu,
                use_one_hot_embeddings=FLAGS.use_tpu)
            print("model_fn:",model_fn)
            estimator = Estimator(  # 实例化估计器
                model_fn=model_fn,
                config=run_config,
                warm_start_from=self.init_checkpoint  # 新增预热
            )
            print("estimator.params:",estimator.params)
            print("estimator:",estimator)
            return estimator
    
        def serving_input_fn(self):
            receiver_tensors = {
                'input_ids': tf.compat.v1.placeholder(dtype=tf.int64, shape=[None, self.seq_length], name='input_ids'),
                'input_mask': tf.compat.v1.placeholder(dtype=tf.int64, shape=[None, self.seq_length], name='input_mask'),
                'segment_ids': tf.compat.v1.placeholder(dtype=tf.int64, shape=[None, self.seq_length], name='segment_ids'),
                'label_ids': tf.compat.v1.placeholder(dtype=tf.int64, shape=[None], name="label_ids")
            }
    
            return tf.estimator.export.ServingInputReceiver(features= receiver_tensors ,receiver_tensors=receiver_tensors)
        def transModel(self):
    
            self.estimator.export_saved_model('./savemodel',self.serving_input_fn)
    
    
    
    labelfile='./ckpt/label.csv'
    init_checkpoint='./chinese_L-12_H-768_A-12/bert_model.ckpt'
    vocabfile='./chinese_L-12_H-768_A-12/vocab.txt'
    bert_config_file='./chinese_L-12_H-768_A-12/bert_config.json'
    ckptdir='./ckpt/'
    model = Fast(labelfile,vocabfile,bert_config_file,init_checkpoint,ckptdir)
    model.transModel()
    

    2. saveModel格式转换为onnx格式

    import os
    
    pbdir="1631247382"
    onnxname="model.onnx"
    cmdstr="python -m tf2onnx.convert --saved-model ./savemodel/{pbdir} --output ./onnx/{onnxname}".format(pbdir=pbdir,onnxname=onnxname)
    
    os.system(cmdstr)
    
    

    3. 使用onnxruntime推理onnx格式模型

    在这里插入图片描述

    import onnxruntime as ort
    from tokenization import FullTokenizer
    from run_classifier import convert_single_example
    from run_classifier import InputExample
    import time
    import numpy as np
    import csv
    
    import os
    
    class model(object):
        def __init__(self, vocab_file,labelfile,modelfile,max_seq_length):
            self.closed = False
            self.first_run = True
            self.tokenizer = FullTokenizer(
                vocab_file=vocab_file,
                do_lower_case=True)
            self.seq_length = max_seq_length
            self.label = self.loadLabel(labelfile)
    
            so = ort.SessionOptions()
    
            #so.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
            # so.execution_mode = ort.ExecutionMode.ORT_PARALLEL
    
            so.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
    
            #self.model = ort.InferenceSession(modelfile,sess_options=so,providers=['CPUExecutionProvider'])
            self.model = ort.InferenceSession(modelfile,sess_options=so,providers=['CUDAExecutionProvider'])
            #self.model.set_providers(['CUDAExecutionProvider'], [{'device_id': device_id,"gpu_mem_limit" :  3  *  1024  *  1024  *  1024}])
            # self.model.set_providers(['CUDAExecutionProvider'], [{'device_id': device_id }])
    
    
        def loadLabel(sel,labelfile):
            labelf = open(labelfile, 'r', newline='',encoding='gbk')
            labeldata = csv.reader(labelf, delimiter="\t")
            labelList = []
            #for i in range(60):
            #    labelList.append(i)
            for line in labeldata:
               label = line[1]
               labelList.append(label)
            return labelList
    
        def get_feature(self, index, text):
            example = InputExample(f"text_{index}", text, None, self.label[0])
            feature = convert_single_example(index, example, self.label, self.seq_length, self.tokenizer)
            return feature.input_ids, feature.input_mask, feature.segment_ids, feature.label_id
    
    
        def predict(self, text):
            dataList=[]
            input_ids_L=[]
            input_mask_L=[]
            segment_ids_L=[]
            label_ids_L=[]
            for i in range(len(text)):
                input_ids,input_mask,segment_ids,label_ids=self.get_feature(i,text[i])
                input_ids_L.append(input_ids)
                input_mask_L.append(input_mask)
                segment_ids_L.append(segment_ids)
                label_ids_L.append(label_ids)
    
            data = {
                "input_ids:0": np.array(input_ids_L, dtype=np.int64),
                "input_mask:0": np.array(input_mask_L, dtype=np.int64),
                "label_ids:0": np.array(label_ids_L, dtype=np.int64),
                "segment_ids:0": np.array(segment_ids_L, dtype=np.int64)
            }
            dataList.append(data)
            result = self.model.run(output_names=["loss/Softmax:0"], input_feed=data)
            label_l=[]
            for i in range(len(text)):
                # 获取最大值索引
                maxProbabilities=max(result[0][i])
    
                index=np.argmax(result[0][i])
    
                label=self.label[index]
                item={"label":label,"score":maxProbabilities}
                label_l.append(label)
    
            return label_l
    
    
    pythonfile=os.path.realpath(os.path.realpath(__file__))
    pardir=os.path.abspath(os.path.join(pythonfile,os.path.pardir))
    datadir=os.path.join(pardir,'zhaopin')
    
    labelfile=os.path.join(datadir,'label.csv')
    modelfile=os.path.join(datadir,'model.onnx')
    vocabfile=os.path.join(pardir,'vocab.txt')
    max_seq_length=128
    
    
    def getModel():
        bert = model(vocabfile,labelfile,modelfile ,max_seq_length)
        return bert
    
    if __name__=="__main__":
        bert=getModel()
        for i in range(1000):
            time1=time.time()
            bert.predict(["已经打过电话了"])
    
    展开全文
  • 报错: ResourceExhaustedError:OOM when ...今天跑bert分类训练的时候遇到的bug 我的bert分类项目地址(有数据,本地win10可运行):https://github.com/yongzhuo/bert 我另外一个项目bert分类实例,可predict...

    报错: ResourceExhaustedError:OOM when allocating tensor of shape [21128,768] and type float

    今天跑bert分类训练的时候遇到的bug

    我的bert分类项目地址(有数据,本地win10可运行):https://github.com/yongzhuo/bert

    我另外一个项目bert分类实例,可predict,很方便:https://github.com/yongzhuo/nlp_xiaojiang/tree/master/ClassificationText/bert

    参考的是 小数据福音!BERT在极小数据下带来显著提升的开源实现

                  这个网址: http://www.sohu.com/a/278070440_500659

    过程:

    1.按照它的方式处理数据,开始时候跑的是20万+的数据,报错OOM

    2.首先是调小batch_size,直至2还是报错,哭。再调小max_seq_length=50,还是不行,哭

    3.查了一些资料,

            1.ResourceExhaustedError (see above for traceback): OOM when allocating tensor

             地址:https://github.com/google-research/bert/issues/118

           2.ResourceExhaustedError:OOM when allocating tensor of shape [3840,4096] and type float (Out of memory Issue)

            地址:https://stackoverflow.com/questions/44971481/resourceexhaustederroroom-when-allocating-tensor-of-shape-3840-4096-and-type

            还是没有解决,但了解到是存储不够的原因了。

    4.想把TPUEstimator改为Estimator,因为显卡存储不够,但内存是有16G的,改成CPU运行就好了;可惜水平不够,改不了

    5.怎么办呢,让TPUEstimator运行cpu不就行了,于是增加

    os.environ["CUDA_VISIBLE_DEVICES"] = "100"#没法取到显卡gpu,就走cpu了(猜测)
    

    6.问题解决

    我的bert分类项目地址(有数据,本地win10可运行):https://github.com/yongzhuo/bert

    展开全文
  • BERT文本分类数据

    2021-01-11 21:27:54
    BERT文本分类代码对应的数据
  • Bert文本分类(基于keras-bert实现)

    万次阅读 多人点赞 2019-10-25 17:48:34
    中文预训练模型下载 当Bert遇上Keras:这可能是Bert最简单的打开姿势 keras-bert 不同模型的性能对比如下(可根据自己的数据选择合适的模型,模型越大需要训练的时间越长) 模型 开发集 测试集...

    目录

    一、Bert 预训练模型准备

    二、Bert 模型文本分类

    1、数据准备

    2、代码实现

    3、分类过程与结果


    一、Bert 预训练模型准备

    中文预训练模型下载      当Bert遇上Keras:这可能是Bert最简单的打开姿势      keras-bert

    不同模型的性能对比如下(可根据自己的数据选择合适的模型,模型越大需要训练的时间越长)

    模型开发集测试集
    BERT83.1 (82.7) / 89.9 (89.6)82.2 (81.6) / 89.2 (88.8)
    ERNIE73.2 (73.0) / 83.9 (83.8)71.9 (71.4) / 82.5 (82.3)
    BERT-wwm84.3 (83.4) / 90.5 (90.2)82.8 (81.8) / 89.7 (89.0)
    BERT-wwm-ext85.0 (84.5) / 91.2 (90.9)83.6 (83.0) / 90.4 (89.9)
    RoBERTa-wwm-ext86.6 (85.9) / 92.5 (92.2)85.6 (85.2) / 92.0 (91.7)
    RoBERTa-wwm-ext-large89.6 (89.1) / 94.8 (94.4)89.6 (88.9) / 94.5 (94.1)

    二、Bert 模型文本分类

    1、数据准备

    使用的仍是用户评论情感极性判别的数据

    训练集:data_train.csv ,样本数为82025,情感极性标签(0:负面、1:中性、2:正面) 

    测试集:data_test.csv ,样本数为35157

    评论数据主要包括:食品餐饮类,旅游住宿类,金融服务类,医疗服务类,物流快递类;部分数据如下:

    2、代码实现

    import pandas as pd
    import codecs, gc
    import numpy as np
    from sklearn.model_selection import KFold
    from keras_bert import load_trained_model_from_checkpoint, Tokenizer
    from keras.metrics import top_k_categorical_accuracy
    from keras.layers import *
    from keras.callbacks import *
    from keras.models import Model
    import keras.backend as K
    from keras.optimizers import Adam
    from keras.utils import to_categorical
    
    #读取训练集和测试集
    train_df=pd.read_csv('data/data_train.csv', sep='\t', names=['id', 'type', 'contents', 'labels']).astype(str)
    test_df=pd.read_csv('data/data_test.csv', sep='\t', names=['id', 'type', 'contents']).astype(str)
    
    maxlen = 100  #设置序列长度为120,要保证序列长度不超过512
    
    #预训练好的模型
    config_path = 'chinese_roberta_wwm_large_ext_L-24_H-1024_A-16/bert_config.json'
    checkpoint_path = 'chinese_roberta_wwm_large_ext_L-24_H-1024_A-16/bert_model.ckpt'
    dict_path = 'chinese_roberta_wwm_large_ext_L-24_H-1024_A-16/vocab.txt'
    
    #将词表中的词编号转换为字典
    token_dict = {}
    with codecs.open(dict_path, 'r', 'utf8') as reader:
        for line in reader:
            token = line.strip()
            token_dict[token] = len(token_dict)
    
    #重写tokenizer        
    class OurTokenizer(Tokenizer):
        def _tokenize(self, text):
            R = []
            for c in text:
                if c in self._token_dict:
                    R.append(c)
                elif self._is_space(c):
                    R.append('[unused1]')  # 用[unused1]来表示空格类字符
                else:
                    R.append('[UNK]')  # 不在列表的字符用[UNK]表示
            return R
    tokenizer = OurTokenizer(token_dict)
    
    #让每条文本的长度相同,用0填充
    def seq_padding(X, padding=0):
        L = [len(x) for x in X]
        ML = max(L)
        return np.array([
            np.concatenate([x, [padding] * (ML - len(x))]) if len(x) < ML else x for x in X
        ])
    
    #data_generator只是一种为了节约内存的数据方式
    class data_generator:
        def __init__(self, data, batch_size=32, shuffle=True):
            self.data = data
            self.batch_size = batch_size
            self.shuffle = shuffle
            self.steps = len(self.data) // self.batch_size
            if len(self.data) % self.batch_size != 0:
                self.steps += 1
    
        def __len__(self):
            return self.steps
    
        def __iter__(self):
            while True:
                idxs = list(range(len(self.data)))
    
                if self.shuffle:
                    np.random.shuffle(idxs)
    
                X1, X2, Y = [], [], []
                for i in idxs:
                    d = self.data[i]
                    text = d[0][:maxlen]
                    x1, x2 = tokenizer.encode(first=text)
                    y = d[1]
                    X1.append(x1)
                    X2.append(x2)
                    Y.append([y])
                    if len(X1) == self.batch_size or i == idxs[-1]:
                        X1 = seq_padding(X1)
                        X2 = seq_padding(X2)
                        Y = seq_padding(Y)
                        yield [X1, X2], Y[:, 0, :]
                        [X1, X2, Y] = [], [], []
    
    #计算top-k正确率,当预测值的前k个值中存在目标类别即认为预测正确                 
    def acc_top2(y_true, y_pred):
        return top_k_categorical_accuracy(y_true, y_pred, k=2)
    
    #bert模型设置
    def build_bert(nclass):
        bert_model = load_trained_model_from_checkpoint(config_path, checkpoint_path, seq_len=None)  #加载预训练模型
    
        for l in bert_model.layers:
            l.trainable = True
    
        x1_in = Input(shape=(None,))
        x2_in = Input(shape=(None,))
    
        x = bert_model([x1_in, x2_in])
        x = Lambda(lambda x: x[:, 0])(x) # 取出[CLS]对应的向量用来做分类
        p = Dense(nclass, activation='softmax')(x)
    
        model = Model([x1_in, x2_in], p)
        model.compile(loss='categorical_crossentropy',
                      optimizer=Adam(1e-5),    #用足够小的学习率
                      metrics=['accuracy', acc_top2])
        print(model.summary())
        return model
    
    #训练数据、测试数据和标签转化为模型输入格式
    DATA_LIST = []
    for data_row in train_df.iloc[:].itertuples():
        DATA_LIST.append((data_row.contents, to_categorical(data_row.labels, 3)))
    DATA_LIST = np.array(DATA_LIST)
    
    DATA_LIST_TEST = []
    for data_row in test_df.iloc[:].itertuples():
        DATA_LIST_TEST.append((data_row.contents, to_categorical(0, 3)))
    DATA_LIST_TEST = np.array(DATA_LIST_TEST)
    
    #交叉验证训练和测试模型
    def run_cv(nfold, data, data_labels, data_test):
        kf = KFold(n_splits=nfold, shuffle=True, random_state=520).split(data)
        train_model_pred = np.zeros((len(data), 3))
        test_model_pred = np.zeros((len(data_test), 3))
    
        for i, (train_fold, test_fold) in enumerate(kf):
            X_train, X_valid, = data[train_fold, :], data[test_fold, :]
    
            model = build_bert(3)
            early_stopping = EarlyStopping(monitor='val_acc', patience=3)   #早停法,防止过拟合
            plateau = ReduceLROnPlateau(monitor="val_acc", verbose=1, mode='max', factor=0.5, patience=2) #当评价指标不在提升时,减少学习率
            checkpoint = ModelCheckpoint('./bert_dump/' + str(i) + '.hdf5', monitor='val_acc',verbose=2, save_best_only=True, mode='max', save_weights_only=True) #保存最好的模型
    
            train_D = data_generator(X_train, shuffle=True)
            valid_D = data_generator(X_valid, shuffle=True)
            test_D = data_generator(data_test, shuffle=False)
            #模型训练
            model.fit_generator(
                train_D.__iter__(),
                steps_per_epoch=len(train_D),
                epochs=5,
                validation_data=valid_D.__iter__(),
                validation_steps=len(valid_D),
                callbacks=[early_stopping, plateau, checkpoint],
            )
    
            # model.load_weights('./bert_dump/' + str(i) + '.hdf5')
    
            # return model
            train_model_pred[test_fold, :] = model.predict_generator(valid_D.__iter__(), steps=len(valid_D), verbose=1)
            test_model_pred += model.predict_generator(test_D.__iter__(), steps=len(test_D), verbose=1)
    
            del model
            gc.collect()   #清理内存
            K.clear_session()   #clear_session就是清除一个session
            # break
    
        return train_model_pred, test_model_pred
    
    #n折交叉验证
    train_model_pred, test_model_pred = run_cv(2, DATA_LIST, None, DATA_LIST_TEST)
    
    test_pred = [np.argmax(x) for x in test_model_pred]
    
    #将测试集预测结果写入文件
    output=pd.DataFrame({'id':test_df.id,'sentiment':test_pred})
    output.to_csv('data/results.csv', index=None)
    
    

    3、分类过程与结果

    在服务器上跑了两天,终于完成了……

    最终提交结果F1-score达到了94.90%,比使用的其他模型效果都好。

    直接看排名结果,一下子上升到了第一,哈哈哈

     

     

    展开全文
  • 项目主要是利用BERT实现中文的情感分类 主要实现包括: bert 模型的实现 利用起进行情感分类 需要版本 python3 和tensorflow 大于1.10
  • BERT文本分类实战

    千次阅读 2019-07-25 22:07:44
    本文介绍了基于Bert对文本分类任务进行了Fine-tune,详细介绍了如何使用bert对文本进行训练,完成了文本分类任务,从训练到预测的全教程。欢迎转载,转载请注明出处。
  • 基于pytorch的 BERT中文文本分类

    万次阅读 2019-05-05 16:46:09
    转载一篇基于 pytorch 的BERT文本分类: https://blog.csdn.net/Real_Brilliant/article/details/84880528
  • NLP之BERT中文文本分类超详细教程

    万次阅读 多人点赞 2019-04-24 14:38:35
    bert模型是Google在2018年10月发布的语言表示模型,Bert在NLP领域横扫了11项任务的最优结果,可以说是现今最近NLP中最重要的突破。Bert模型的全称是Bidirectional Encoder Representations from Transformers,是...
  • Bert实现中文文本分类

    千次阅读 2020-02-17 12:44:11
    1,NLP之BERT中文文本分类 基本上有了一些介绍,但是缺少具体例子和明确的指明文件路径(应该给出例子) 2,如何使用BERT实现中文的文本分类 优点是有一个训练和测试集的流程图(可参考) 3,使用Bert预训练模型文本...
  • BERT简介及中文分类

    万次阅读 多人点赞 2018-12-21 16:58:42
    文章目录BERT是什么BERT调优句子(对)分类任务分类器预测中文分类实践下载中文预训练模型修改run_classifier.py训练预测 介绍来自bert的github资料翻译,水平有限 BERT是什么 BERT是一种预训练语言表示的方法,这...
  • BERT 文本分类 实操

    千次阅读 2019-07-30 10:05:47
    本文目录0. 准备工作1. 数据集的准备2. 增加自定义数据类3....文本相似度任务具体见: BERT介绍及中文文本相似度任务实践 文本相似度任务和文本分类任务的区别在于数据集的准备以及run_classifier.p...
  • 自然语言处理动手学Bert文本分类,本套课程基于Pytorch最新1.4版本来实现利用Bert实现中文文本分类任务,延续动手学系列课程风格,全程手敲代码,跟着杨博一行一行代码撸起来。
  • NLP之BERT中文文本分类超详细教程.pdf
  • BERT文本分类使用指南

    万次阅读 热门讨论 2018-12-21 16:19:27
    本文档介绍了如何使用BERT实现多类别文本分类任务,适合稍微了解BERT和文本分类的同学参考。 (一) 下载 首先,在github上clone谷歌的BERT项目,或者直接下载。项目地址 然后,下载中文预训练模型,地址 (二) ...
  • Bert模型全称Bidirectional Encoder Representations from Transformers,主要分为两个部分:1训练语言模型(language model)的预训练(pretrain)部分,2训练具体任务(task)的fine-tune部分。Bert在NLP领域横扫了...
  • 1.下载bert源代码和中文预训练模型 bert代码 模型下载 Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters 2.准备样本 依旧采用上一节中使用的ai挑战赛用户评论信息。对于自己...
  • 那么豆瓣评论与豆瓣评分之间是否有一定的联系,我们可以训练BERT中文分类模型,通过输入豆瓣评论输出输出预测的豆瓣评分,观察其与真实的豆瓣评分是否有差别。 在这个项目中,我们需要做: 文本的预处理 模型训练...
  • 最近在重温bert,对bert中文文本多分类的效果很好奇,并将其与传统的非pre-train模型进行对比,除此之外,由于选用的是12层的base版的bert,还从第0层开始到12层,对每一层的输出进行了校验和测试。想看看每一层的...
  • 中文模型下载:BERT-Base, Chinese: Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters 最终结果 最后一层和倒数第二层: last shape:(1, 14, 768), last2 shape: (1, 14, 768...
  • 简单高效的Bert中文文本分类模型开发和部署
  • NLP Bert 文本分类

    2020-06-27 19:01:22
    BERT模型也出来很久了,之前看了论文学习过它的大致模型(可以参考前些日子写的笔记NLP大杀器BERT模型解读),但是一直有杂七杂八的事拖着没有具体去实现过真实效果如何。今天就趁机来动手写一写实战,顺便复现一下...
  • Pytorch之Bert中文文本分类(二)

    千次阅读 2019-09-29 16:12:13
    本文主要是针对入门级别的Bert使用,包括英文文本分类中文文本分类。 这部分主要使用Bert进行情感分析,属于中文文本分类,同样使用BertForSequenceClassification 数据集中包括三个情感分类等级[-1,0,1] 流程和...
  • Bert中文文本分类全网最详细教程+源码+数据集

    万次阅读 多人点赞 2019-09-03 12:06:59
    Bert是当前最先进的自然语言处理工具之一。最起码要会使用这个强大的工具。 为了童鞋们能顺利运行,我把数据集改小了。 开始吧 一,运行环境 需要下载两个包,然后解压,但要记住位置,后面要使用到。 1)Bert下载...
  • 建立bert文本分类的流程 首先对数据用sample(frac = 1.0)随机打乱 from sklearn.preprocessing import LabelEncoder train_data = train_data.sample(frac = 1.0) lbl = LabelEncoder().fit(train_data['LABEL']) ...
  • 中文预训练模型下载 当Bert遇上Keras:这可能是Bert最简单的打开姿势 keras-bert Bert 模型文本分类 1、数据准备 在GitHub中有酒店评论的数据 训练集: 测试集: 2、代码实现 ''' 提示:受GPU性能的影响,...
  • BERT 处理中文分类和相似度

    千次阅读 2020-05-23 16:43:22
    https://terrifyzhao.github.io/2018/11/29/使用BERT中文文本相似度计算.html 简介 最近Google推出了NLP大杀器BERTBERT(Transformer双向编码器表示)是Google AI语言研究人员最近发表的一篇论文。它通过在各种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,186
精华内容 1,674
关键字:

bert中文分类