如何将文字转会为数值:

将文字转成向量,用one-hot进行编码。

但是one-hot有两个问题:

  • 维度太高,比如汉字就得用21128维的向量表示
  • 无法表示两个汉字是否接近

因此使用线性变化将高维向量转成一维,如下图所示

这样可以用模型提取特征值,完成各种输出任务:

输出是多分类

输出是二分类

输出是序列

如何提取每个字词在整体语境中的特征:

有一种方法是运用记忆单元(传家宝),串行的记录整个句子的特征。如:CNN

但这会带来一些问题:句子相关词相隔太远怎么办?

LSTM可以禁止某些字词修改记忆单元,从而提升效果。

但还有一个更重要的问题:文章太长,串行结构太慢

引入自注意力机制

下图是自注意力机制的总体模型:

什么是注意力:

对于一句话中的一个字,提取其特征值不仅要注意自身,也要将一部分注意力分配给同一句话的其他字。

注意力靠两个部分完成:我怎么注意别人,我怎么让别人注意

在该模型中是分别通过W^{q}W^{k}两个矩阵乘以自身完成。

上图中的a_{1{.2}}就是a^{1}包含全局注意力的特征值。

如上图所示,就提取出了每个输入值归一化后的特征值。

为了确保输入数据和输出数据形状等个方面相匹配还要加上一个W^{v}

这样就构建了一个完全并行运算的有全局信息的特征值提取方法:

接下来用矩阵方程性质进行描述(注意下图中的矩阵描述方法与线性代数中的矩阵有所不同)

得到每个字的query,key和value向量

query和key相乘得到每个字对于其他字的注意力。

最终会形成一个n*n的矩阵(n_{i{j}}表示第i个字对第j个字的注意力

然后做一个softmax的处理

最后与value相乘再相加得到全局特征值

有哪些需要训练的参数:

了解内容:

加层数:

位置信息

文字是一段序列,文字相同,顺序不同,内容完全不同

将位置信息也加入到输入数据中:

要经过一个线性变换变成输入数据的长度

这是的输入数据称为一个token

transformer模型的结构:

通过结合迁移训练的方法

如何进行预训练:

字遮罩训练和句子连续标签训练:

bert的结构:

bert来自一个芝麻屋中的角色:

embedding:使用one-hot

注解:Segment Embedding是表明文字属于那一句话;在input中有一些特殊的token,CLS是专门用来做分类的,它会记录全局的信息,从而拥有全局的特征,而SEP表示一个句子的结束

pooling

上图是一些常用的pooling方法,其他方法比如再用一层注意力机制,找到那个注意力最高的做输出

Bert实战

实战bert对文本情感进行分类:

实际上该分类任务只需要在图片分类中做出两个大修改,一个是数据的预处理,一个是替换模型

数据预处理

首先将文字处理为向量:

Input ids为one-hot编码,这里用数字替代,实际实现是用bert模型自带的词表进行的转换。

Mask:遮挡,用于指出每次输入的句子中那部分为填充

Seq_ids:表名输入的短句属于哪一个句子

数据处理代码:

input = self.tokenizer(
            text, 
            return_tensors="pt", #返回张量格式("pt"=PyTorch, "tf"=TensorFlow, "np"=NumPy)
            truncation=True,        #超过 max_length 时截断文本
            padding="max_length",    #填充到 max_length 指定长度
            max_length=128         #最大序列长度(包括特殊Token如 [CLS]、[SEP])
        )

处理后的数据
 

input_ids = input["input_ids"].to(self.device)
        token_type_ids = input['token_type_ids'].to(self.device)
        attention_mask = input['attention_mask'].to(self.device)

定义模型

处理完后进行模型输入:

注意这里的输入已经由线性变换统一转成了768维,然后相加。

有两个地方不一样:

  1. 没有Mask,因为Mask直接乘上了Input ids经过线性变换转换成了TokenEmbeddings
  2. 多了一个PositionEmbedings,因为位置直接用下标转换即可,并不用特别对数据做处理。

输入模型:

sequence_out, pooler_out = self.bert(input_ids=input_ids,
                        token_type_ids=token_type_ids,
                        attention_mask=attention_mask,
                        return_dict=False)      #return_dict

定义模型:

        self.bert = BertModel.from_pretrained(bert_path)
        # config = BertConfig.from_pretrained(bert_path)
        # self.bert = BertModel(config) 只加载了其中的模型部分



        self.device = device
        self.cls_head = nn.Linear(768, num_class)
        self.tokenizer = BertTokenizer.from_pretrained(bert_path)

其他部分大致等于图片分类

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐