项目实训(十)--ernie

项目实训(十)

本文讲一下ernie的个人理解

ernie

改进

ernie基于BERT模型,做的进一步的优化,在中文的NLP任务上得到了state-of-the-art的结果。它主要的改进是在mask的机制上做了改进,它的mask不是基本的word piece的mask,而是在pretrainning阶段增加了外部的知识,由三种level的mask组成,分别是basic-level masking(word piece)+ phrase level masking(WWM style) + entity level masking。

我使用的ernie是基于bert进行了改动,使其更加符合中文语境。
简单讲就是在划分输入的粒度级别上进行了修改。
bert是在字符级别进行编码,而应用到中文这种划分可能就不是太合适。ernie在划分上进行了改进,采用中文的词作为最小划分粒度进行处理。

Knowlege Masking

intuition: 模型在预测未知词的时候,没有考虑到外部知识。但是如果我们在mask的时候,加入了外部的知识,模型可以获得更可靠的语言表示。
例如: 哈利波特是J.K.罗琳写的小说。 单独预测 哈[MASK]波特 或者 J.K.[MASK]琳 对于模型都很简单,但是模型不能学到哈利波特和J.K. 罗琳的关系。如果把哈利波特直接MASK掉的话,那模型可以根据作者,就预测到小说这个实体,实现了知识的学习。

和BERT的区别

在这里插入图片描述
ERNIE的mask的策略是通过三个阶段学习的,在第一个阶段,采用的是BERT的模式,用的是basic-level masking,然后在加入词组的mask(phrase-level masking), 然后在加入实体级别entity-level的mask。
basic level masking 在预训练中,第一阶段是先采用基本层级的masking就是随机mask掉中文中的一个字。
phrase level masking 第二阶段是采用词组级别的masking。我们mask掉句子中一部分词组,然后让模型预测这些词组,在这个阶段,词组的信息就被encoding到word embedding中了。
entity level masking 在第三阶段, 命名实体,例如说 人命,机构名,商品名等,在这个阶段被mask掉,模型在训练完成后,也就学习到了这些实体的信息。

代码实现

配置参数

    def __init__(self, dataset):
        self.model_name = 'ERNIE'
        # self.train_path = dataset + '/data/ans_train.txt'                                # 训练集
        # self.dev_path = dataset + '/data/testcase.csv'                                    # 验证集
        self.test_path = dataset + '/data/a_ans_test.txt'  # 测试集
        self.class_list = [x.strip() for x in open(
            dataset + '/data/class2.txt').readlines()]  # 类别名单
        self.save_path = dataset + '/saved_dict/' + self.model_name + '.ckpt'  # 模型训练结果
        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  # 设备

        self.require_improvement = 1000  # 若超过1000batch效果还没提升,则提前结束训练
        self.num_classes = len(self.class_list)  # 类别数,标签的种类数
        self.num_epochs = 1  # epoch数
        self.batch_size = 32  # mini-batch大小
        self.pad_size = 32  # 每句话处理成的长度(短填长切)
        self.learning_rate = 3e-5  # 学习率
        self.bert_path = './ERNIE_pretrain'  # 模型所在位置
        self.tokenizer = BertTokenizer.from_pretrained(self.bert_path)  # 加载分词器
        # print(self.tokenizer)
        self.hidden_size = 768  # 隐藏单元个数

模型


    def __init__(self, config):
        super(Model, self).__init__()
        # 调用预训练模型
        self.bert = BertModel.from_pretrained(config.bert_path)
        # requires_grad是Pytorch中通用数据结构Tensor的一个属性,用于说明当前量是否需要在计算中保留对应的梯度信息
        for param in self.bert.parameters():
            param.requires_grad = True
        #
        self.fc = nn.Linear(config.hidden_size, config.num_classes)

    def forward(self, x):
        context = x[0]  # 输入的句子
        mask = x[2]  # 对padding部分进行mask,和句子一个size,padding部分用0表示,如:[1, 1, 1, 1, 0, 0]
        # .bert()返回
        # result = (
        #     [encoder_0_output, encoder_1_output, ..., encoder_11_output],
        #     pool_output
        # )
        # 只取最后一个encoder层的输出
        _, pooled = self.bert(context, attention_mask=mask, output_all_encoded_layers=False)
        # 调用全连接层
        out = self.fc(pooled)
        return out

网络初始化

# 权重初始化,默认xavier
def init_network(model, method='xavier', exclude='embedding', seed=123):
    for name, w in model.named_parameters():
        if exclude not in name:
            if len(w.size()) < 2:
                continue
            if 'weight' in name:
                if method == 'xavier':
                    nn.init.xavier_normal_(w)
                elif method == 'kaiming':
                    nn.init.kaiming_normal_(w)
                else:
                    nn.init.normal_(w)
            elif 'bias' in name:
                nn.init.constant_(w, 0)
            else:
                pass

参考

https://zhuanlan.zhihu.com/p/103190005
https://www.zhihu.com/people/huwenxingnlp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值