基于深度学习的文本分类3
文章目录
介绍:这一节的主要内容是bert的使用。bert主要内容是预训练与微调,预训练可以得到词之间的关系,可以直接用于特征提取以及预测上下文,微调在预训练的基础上实现文本分类等功能,并对预训练中的参数进行微调。
主要内容:
(1)了解Transformer的原理和基于预训练语言模型(Bert)的词表示
(2)学会Bert的使用,具体包括pretrain和finetune(预训练与微调)
一个手把手教原理和实现的up主视频,超赞!!!!就是手把手教论文细节!和他的有详细注释的github代码以及知乎专栏
part1:文本表示方法4 — 编码器:Transformer
transformer block:
(1)自向量与位置编码
(2)自注意力机制
(3)残差连接(resnet)与layer normolization
(4)feed forward
具体看这里
最后讲这些block堆叠组合(一般12个layer)
(1)位置编码
借助sin cos用以表示文字之间的位置关系(因为bert里面没有像LSTM一样的前后迭代的过程)
这样对于一个词:
表示位置的编码+文字本身的嵌入编码=文字的初始embedding(或者理解为初始的特征也行?)
(2)自注意力机制
把embedding dimension平等分成h块
h是embedding dimension分成的份数
得到三个矩阵:Q,K,V维度:[batch size,h,sequence length,embedding dim/h ]
self_attention:
Q
⋅
K
T
Q\cdot K^T
Q⋅KT
K的转置只转置后面两维,这样做出来的内积能够表示出前后的距离关系(因为sequence length所在的维度表现了语句元的位置关系)
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dkQKT)V
d k \sqrt{d_k} dk是为了使得注意力矩阵标准化
(3)残差连接
(4)feed forward
两层线性变换后用激活函数激活再传入(3)
part2:两种预训练的方式
(1)Masked LM (masked language model)
15%的内容(token)做掩码:
(1)80%几率换成[mask]
(2)10%几率换成其它的任意词
(3)10%几率不改变
用模型预测这些被掩盖的内容,计算这些内容的loss
X
h
i
d
d
e
n
X_{hidden}
Xhidden=[batch_size,seq_len,embedding_dim]
W
v
o
c
a
b
:
W_{vocab}:
Wvocab:[embedding_dim,vocab_size] (vocab_size是字典中所有词的个数)
X
h
i
d
d
e
n
⋅
W
v
o
c
a
b
X_{hidden}\cdot W_{vocab}
Xhidden⋅Wvocab对vocab_size softmax
(2)Next Sentence Prediction
在原语句中加入以下部分:
每个句子的
开头[cls]:开始符
结尾[seq]:句子间间隔符
input中对每个词的嵌入(类似于词向量)有:
[tokem embedding]:每个字的嵌入
[segment embedding]:每句话的嵌入
[position embedding]:位置的嵌入
最后取
X
h
i
d
d
e
n
X_{hidden}
Xhidden中的[:,0,:]来代表每一个句子,得到结果cls_vector=[batch_size,embedding_dim]
输出分类依据:
s
i
g
m
o
i
d
(
L
i
n
e
a
r
(
c
l
s
v
e
c
t
o
r
)
)
sigmoid(Linear(cls_vector))
sigmoid(Linear(clsvector))
part3:微调
使用方法
对于模型的使用方面有以下情况:
(1)使用自己的数据集进行预训练(适用于专业性较强或数据集已经过编码的情况)
这时候参考下面模型训练的部分,需要自己做分词,构造词典,进行预训练
(2)调用官方的预训练模型,后面就只需要进行微调
(1)模型训练
里面的内容包含:
(1)怎样分词
(2)bert模型训练
(3)构造特征
内容具体而全面,代码简洁易懂,在这里就不做复述了。
(2)微调
微调的过程可以理解为原来的预训练模型得到了词语的特征和关联,预训练结束后房子的大致形状已经确定了,现在在原来的房子里面加电线水管,通水电煤气进行测试,测试过程中除了装管道还需要对房子的一些部分做修改,这就是对测试集的X,Y进行拟合调整参数(之前的预训练只使用了X)。
官方预训练模型,其中包含多种大的小的,中文的英文的预训练模型,进去选择点集下载
非官方例子,(基于keras),强烈安利
(1)文本分类
(2)关系抽取
(3)主体抽取
这里只说明一下其中的文本分类部分:
主要就是在预训练模型的基础上加入一个全连接层&sigmoid函数进行分类
from keras_bert import load_trained_model_from_checkpoint
#导入模型
bert_model = load_trained_model_from_checkpoint(config_path, checkpoint_path, seq_len=None)
#让原来的模型可训练
for l in bert_model.layers:
l.trainable = True
#设定输入格式,每个词的输入有两部分
#(第一部分是这个词的词向量,x1代表这一部分的维度;另一部分x2是segment_id代表句子的id,即这个词属于哪一个句子)
#上面两个维度使用Tokenizer中的encode函数能直接输出
#实际上还可以加上第三个维度来体现词在句子中的位置.
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(1, activation='sigmoid')(x)
#x1_in是预训练输入的维度
#x2_in是
model = Model([x1_in, x2_in], p)
model.compile(
loss='binary_crossentropy',#二分类的情况,多分类用交叉熵
optimizer=Adam(1e-5), # 用足够小的学习率
metrics=['accuracy']
)
model.summary()
ps:由于算力问题&不想再装包了就不写这个的demo了
对于大量数据加速计算可以使用TPU,现在在colab上可以氪金用辽。