当前位置:   article > 正文

Bert文本分类(基于keras-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、代码实现

  1. import pandas as pd
  2. import codecs, gc
  3. import numpy as np
  4. from sklearn.model_selection import KFold
  5. from keras_bert import load_trained_model_from_checkpoint, Tokenizer
  6. from keras.metrics import top_k_categorical_accuracy
  7. from keras.layers import *
  8. from keras.callbacks import *
  9. from keras.models import Model
  10. import keras.backend as K
  11. from keras.optimizers import Adam
  12. from keras.utils import to_categorical
  13. #读取训练集和测试集
  14. train_df=pd.read_csv('data/data_train.csv', sep='\t', names=['id', 'type', 'contents', 'labels']).astype(str)
  15. test_df=pd.read_csv('data/data_test.csv', sep='\t', names=['id', 'type', 'contents']).astype(str)
  16. maxlen = 100 #设置序列长度为120,要保证序列长度不超过512
  17. #预训练好的模型
  18. config_path = 'chinese_roberta_wwm_large_ext_L-24_H-1024_A-16/bert_config.json'
  19. checkpoint_path = 'chinese_roberta_wwm_large_ext_L-24_H-1024_A-16/bert_model.ckpt'
  20. dict_path = 'chinese_roberta_wwm_large_ext_L-24_H-1024_A-16/vocab.txt'
  21. #将词表中的词编号转换为字典
  22. token_dict = {}
  23. with codecs.open(dict_path, 'r', 'utf8') as reader:
  24. for line in reader:
  25. token = line.strip()
  26. token_dict[token] = len(token_dict)
  27. #重写tokenizer
  28. class OurTokenizer(Tokenizer):
  29. def _tokenize(self, text):
  30. R = []
  31. for c in text:
  32. if c in self._token_dict:
  33. R.append(c)
  34. elif self._is_space(c):
  35. R.append('[unused1]') # 用[unused1]来表示空格类字符
  36. else:
  37. R.append('[UNK]') # 不在列表的字符用[UNK]表示
  38. return R
  39. tokenizer = OurTokenizer(token_dict)
  40. #让每条文本的长度相同,用0填充
  41. def seq_padding(X, padding=0):
  42. L = [len(x) for x in X]
  43. ML = max(L)
  44. return np.array([
  45. np.concatenate([x, [padding] * (ML - len(x))]) if len(x) < ML else x for x in X
  46. ])
  47. #data_generator只是一种为了节约内存的数据方式
  48. class data_generator:
  49. def __init__(self, data, batch_size=32, shuffle=True):
  50. self.data = data
  51. self.batch_size = batch_size
  52. self.shuffle = shuffle
  53. self.steps = len(self.data) // self.batch_size
  54. if len(self.data) % self.batch_size != 0:
  55. self.steps += 1
  56. def __len__(self):
  57. return self.steps
  58. def __iter__(self):
  59. while True:
  60. idxs = list(range(len(self.data)))
  61. if self.shuffle:
  62. np.random.shuffle(idxs)
  63. X1, X2, Y = [], [], []
  64. for i in idxs:
  65. d = self.data[i]
  66. text = d[0][:maxlen]
  67. x1, x2 = tokenizer.encode(first=text)
  68. y = d[1]
  69. X1.append(x1)
  70. X2.append(x2)
  71. Y.append([y])
  72. if len(X1) == self.batch_size or i == idxs[-1]:
  73. X1 = seq_padding(X1)
  74. X2 = seq_padding(X2)
  75. Y = seq_padding(Y)
  76. yield [X1, X2], Y[:, 0, :]
  77. [X1, X2, Y] = [], [], []
  78. #计算top-k正确率,当预测值的前k个值中存在目标类别即认为预测正确
  79. def acc_top2(y_true, y_pred):
  80. return top_k_categorical_accuracy(y_true, y_pred, k=2)
  81. #bert模型设置
  82. def build_bert(nclass):
  83. bert_model = load_trained_model_from_checkpoint(config_path, checkpoint_path, seq_len=None) #加载预训练模型
  84. for l in bert_model.layers:
  85. l.trainable = True
  86. x1_in = Input(shape=(None,))
  87. x2_in = Input(shape=(None,))
  88. x = bert_model([x1_in, x2_in])
  89. x = Lambda(lambda x: x[:, 0])(x) # 取出[CLS]对应的向量用来做分类
  90. p = Dense(nclass, activation='softmax')(x)
  91. model = Model([x1_in, x2_in], p)
  92. model.compile(loss='categorical_crossentropy',
  93. optimizer=Adam(1e-5), #用足够小的学习率
  94. metrics=['accuracy', acc_top2])
  95. print(model.summary())
  96. return model
  97. #训练数据、测试数据和标签转化为模型输入格式
  98. DATA_LIST = []
  99. for data_row in train_df.iloc[:].itertuples():
  100. DATA_LIST.append((data_row.contents, to_categorical(data_row.labels, 3)))
  101. DATA_LIST = np.array(DATA_LIST)
  102. DATA_LIST_TEST = []
  103. for data_row in test_df.iloc[:].itertuples():
  104. DATA_LIST_TEST.append((data_row.contents, to_categorical(0, 3)))
  105. DATA_LIST_TEST = np.array(DATA_LIST_TEST)
  106. #交叉验证训练和测试模型
  107. def run_cv(nfold, data, data_labels, data_test):
  108. kf = KFold(n_splits=nfold, shuffle=True, random_state=520).split(data)
  109. train_model_pred = np.zeros((len(data), 3))
  110. test_model_pred = np.zeros((len(data_test), 3))
  111. for i, (train_fold, test_fold) in enumerate(kf):
  112. X_train, X_valid, = data[train_fold, :], data[test_fold, :]
  113. model = build_bert(3)
  114. early_stopping = EarlyStopping(monitor='val_acc', patience=3) #早停法,防止过拟合
  115. plateau = ReduceLROnPlateau(monitor="val_acc", verbose=1, mode='max', factor=0.5, patience=2) #当评价指标不在提升时,减少学习率
  116. checkpoint = ModelCheckpoint('./bert_dump/' + str(i) + '.hdf5', monitor='val_acc',verbose=2, save_best_only=True, mode='max', save_weights_only=True) #保存最好的模型
  117. train_D = data_generator(X_train, shuffle=True)
  118. valid_D = data_generator(X_valid, shuffle=True)
  119. test_D = data_generator(data_test, shuffle=False)
  120. #模型训练
  121. model.fit_generator(
  122. train_D.__iter__(),
  123. steps_per_epoch=len(train_D),
  124. epochs=5,
  125. validation_data=valid_D.__iter__(),
  126. validation_steps=len(valid_D),
  127. callbacks=[early_stopping, plateau, checkpoint],
  128. )
  129. # model.load_weights('./bert_dump/' + str(i) + '.hdf5')
  130. # return model
  131. train_model_pred[test_fold, :] = model.predict_generator(valid_D.__iter__(), steps=len(valid_D), verbose=1)
  132. test_model_pred += model.predict_generator(test_D.__iter__(), steps=len(test_D), verbose=1)
  133. del model
  134. gc.collect() #清理内存
  135. K.clear_session() #clear_session就是清除一个session
  136. # break
  137. return train_model_pred, test_model_pred
  138. #n折交叉验证
  139. train_model_pred, test_model_pred = run_cv(2, DATA_LIST, None, DATA_LIST_TEST)
  140. test_pred = [np.argmax(x) for x in test_model_pred]
  141. #将测试集预测结果写入文件
  142. output=pd.DataFrame({'id':test_df.id,'sentiment':test_pred})
  143. output.to_csv('data/results.csv', index=None)

3、分类过程与结果

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

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

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

Bert文本分类(keras-bert实现)源代码及数据集资源下载:

项目实战-Bert文本分类(keras-bert实现)源代码及数据集.zip-自然语言处理文档类资源-CSDN下载

本人博文NLP学习内容目录:

一、NLP基础学习

1、NLP学习路线总结

2、TF-IDF算法介绍及实现

3、NLTK使用方法总结

4、英文自然语言预处理方法总结及实现

5、中文自然语言预处理方法总结及实现

6、NLP常见语言模型总结

7、NLP数据增强方法总结及实现

8、TextRank算法介绍及实现

9、NLP关键词提取方法总结及实现

10、NLP词向量和句向量方法总结及实现

11、NLP句子相似性方法总结及实现

12、NLP中文句法分析

二、NLP项目实战

1、项目实战-英文文本分类-电影评论情感判别

2、项目实战-中文文本分类-商品评论情感判别

3、项目实战-XGBoost与LightGBM文本分类

4、项目实战-TextCNN文本分类实战

5、项目实战-Bert文本分类实战

6、项目实战-NLP中文句子类型判别和分类实战

交流学习资料共享欢迎入群:955817470(群一),801295159(群二)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/235618
推荐阅读
相关标签
  

闽ICP备14008679号