之前在BERT实战——基于Keras一文中介绍了两个库 keras_bert 和 bert4keras

但是由于 bert4keras 处于开发阶段,有些函数名称和位置等等发生了变化,那篇文章只用了 bert4keras 进行情感分析

于是这里新开了一篇文章将 2 个库都用一遍, bert4keras 也使用最新版本

本文所用bert4keras时间:2019-11-09

害怕 bert4keras 后续继续变化,需要稳定的可以先采用 keras_bert

数据集:

原始Github链接:https://github.com/bojone/bert4keras/tree/master/examples/datasets

个人网盘:链接: https://pan.baidu.com/s/1OAhNbRYpU1HW25_vChdRng 提取码: uxax

1.使用keras_bert

配置一些超参数,导入需要的包和设置文件路径

import json
import numpy as np
import pandas as pdfrom keras_bert import load_trained_model_from_checkpoint, Tokenizer
# 超参数
maxlen = 100
batch_size = 16
droup_out_rate = 0.5
learning_rate = 1e-5
epochs = 15 path_prefix = "./test"
# 预训练模型目录
config_path = path_prefix + "/chinese_L-12_H-768_A-12/bert_config.json"
checkpoint_path = path_prefix + "/chinese_L-12_H-768_A-12/bert_model.ckpt"
dict_path = path_prefix + "/chinese_L-12_H-768_A-12/vocab.txt"

读取数据和构造训练样本

# 读取数据
neg = pd.read_excel(path_prefix + "/data/neg.xls", header=None)
pos = pd.read_excel(path_prefix + "/data/pos.xls", header=None) # 构建训练数据
data = [] for d in neg[0]:
data.append((d, 0)) for d in pos[0]:
data.append((d, 1))

读取字典

# 读取字典
token_dict = load_vocabulary(dict_path)
# 建立分词器
tokenizer = Tokenizer(token_dict)

拆分为训练集和测试集

# 按照9:1的比例划分训练集和验证集
random_order = list(range(len(data)))
np.random.shuffle(random_order)
train_data = [data[j] for i, j in enumerate(random_order) if i % 10 != 0]
valid_data = [data[j] for i, j in enumerate(random_order) if i % 10 == 0]

序列padding 和 训练用的生成器

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
]) class data_generator:
def __init__(self, data, batch_size=batch_size):
self.data = data
self.batch_size = batch_size
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)))
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
[X1, X2, Y] = [], [], []

读取 bert 模型并增加一个全连接层用于预测

from keras.layers import *
from keras.models import Model
import keras.backend as K
from keras.optimizers import Adam # trainable设置True对Bert进行微调
# 默认不对Bert模型进行调参
bert_model = load_trained_model_from_checkpoint(config_path, checkpoint_path, , 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)
x = Dropout(droup_out_rate)(x)
p = Dense(1, activation='sigmoid')(x) model = Model([x1_in, x2_in], p)
model.compile(
loss='binary_crossentropy',
optimizer=Adam(learning_rate),
metrics=['accuracy']
)
model.summary()

开始训练

train_D = data_generator(train_data)
valid_D = data_generator(valid_data) model.fit_generator(
train_D.__iter__(),
steps_per_epoch=len(train_D),
epochs=epochs,
validation_data=valid_D.__iter__(),
validation_steps=len(valid_D)
)

2.使用bert4keras

为防止 bert4keras 又调整,导致代码和最新版本不适配,这里记录更新时间

更新时间:2019-11-09

配置超参数,导入需要的包和设置预训练模型的路径

import json
import numpy as np
import pandas as pd
import os
from bert4keras.bert import build_bert_model
from bert4keras.backend import set_gelu
from bert4keras.utils import Tokenizer, load_vocab
set_gelu('tanh') # 切换gelu版本 #超参数
maxlen = 100
batch_size = 16
droup_out_rate = 0.5
learning_rate = 1e-5
epochs = 15
path_prefix = "./test"
# 预训练模型路径
config_path = path_prefix + "/chinese_L-12_H-768_A-12/bert_config.json"
checkpoint_path = path_prefix + "/chinese_L-12_H-768_A-12/bert_model.ckpt"
dict_path = path_prefix + "/chinese_L-12_H-768_A-12/vocab.txt"

读取数据和构造训练样本

# 读取数据
neg = pd.read_excel(path_prefix + "/data/neg.xls", header=None)
pos = pd.read_excel(path_prefix + "/data/pos.xls", header=None) data, tokens = [], {}
# 读取词典
_token_dict = load_vocab(dict_path)
# 建立临时分词器
_tokenizer = Tokenizer(_token_dict) for d in neg[0]:
data.append((d, 0))
for t in _tokenizer.tokenize(d):
tokens[t] = tokens.get(t, 0) + 1 for d in pos[0]:
data.append((d, 1))
for t in _tokenizer.tokenize(d):
tokens[t] = tokens.get(t, 0) + 1

精简字典,只留下本任务用到的字

tokens = {i: j for i, j in tokens.items() if j >= 4}
# token_dict是本任务需要用到的字
# keep_words是在bert中保留的字表
token_dict, keep_words = {}, [] for t in ['[PAD]', '[UNK]', '[CLS]', '[SEP]']:
token_dict[t] = len(token_dict)
keep_words.append(_token_dict[t]) for t in tokens:
if t in _token_dict and t not in token_dict:
token_dict[t] = len(token_dict)
keep_words.append(_token_dict[t]) # 建立分词器
tokenizer = Tokenizer(token_dict)

拆分训练集和测试集

if not os.path.exists('./random_order.json'):
random_order = list(range(len(data)))
np.random.shuffle(random_order)
json.dump(
random_order,
open('./random_order.json', 'w'),
indent=4
)
else:
random_order = json.load(open('./random_order.json')) # 按照9:1的比例划分训练集和验证集
train_data = [data[j] for i, j in enumerate(random_order) if i % 10 != 0]
valid_data = [data[j] for i, j in enumerate(random_order) if i % 10 == 0]

padding和生成器

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
]) class data_generator:
def __init__(self, data, batch_size=batch_size):
self.data = data
self.batch_size = batch_size
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)))
np.random.shuffle(idxs)
X1, X2, Y = [], [], []
for i in idxs:
d = self.data[i]
text = d[0][:maxlen]
x1, x2 = tokenizer.encode(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
[X1, X2, Y] = [], [], []

读取 bert 模型并增加一个全连接层用于预测

from keras.layers import *
from keras.models import Model
import keras.backend as K
from keras.optimizers import Adam model = build_bert_model(
config_path,
checkpoint_path,
# 只保留keep_words中的字,精简原字表
keep_words=keep_words,
) output = Lambda(lambda x: x[:, 0])(model.output)
output = Dropout(droup_out_rate)(output)
output = Dense(1, activation='sigmoid')(output)
model = Model(model.input, output) model.compile(
loss='binary_crossentropy',
optimizer=Adam(learning_rate),
metrics=['accuracy']
)
model.summary()

开始训练

train_D = data_generator(train_data)
valid_D = data_generator(valid_data) model.fit_generator(
train_D.__iter__(),
steps_per_epoch=len(train_D),
epochs=epochs,
validation_data=valid_D.__iter__(),
validation_steps=len(valid_D)
)

在Keras中用Bert进行情感分析的更多相关文章

  1. Keras下的文本情感分析简介。与MLP,RNN,LSTM模型下的文本情感测试

    # coding: utf-8 # In[1]: import urllib.request import os import tarfile # In[2]: url="http://ai ...

  2. LSTM 文本情感分析/序列分类 Keras

    LSTM 文本情感分析/序列分类 Keras 请参考 http://spaces.ac.cn/archives/3414/   neg.xls是这样的 pos.xls是这样的neg=pd.read_e ...

  3. 矩池云 | Tony老师解读Kaggle Twitter情感分析案例

    今天Tony老师给大家带来的案例是Kaggle上的Twitter的情感分析竞赛.在这个案例中,将使用预训练的模型BERT来完成对整个竞赛的数据分析. 导入需要的库 import numpy as np ...

  4. R语言︱情感分析—基于监督算法R语言实现(二)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:本文大多内容来自未出版的<数据 ...

  5. 文本情感分析(一):基于词袋模型(VSM、LSA、n-gram)的文本表示

    现在自然语言处理用深度学习做的比较多,我还没试过用传统的监督学习方法做分类器,比如SVM.Xgboost.随机森林,来训练模型.因此,用Kaggle上经典的电影评论情感分析题,来学习如何用传统机器学习 ...

  6. NLP入门(十)使用LSTM进行文本情感分析

    情感分析简介   文本情感分析(Sentiment Analysis)是自然语言处理(NLP)方法中常见的应用,也是一个有趣的基本任务,尤其是以提炼文本情绪内容为目的的分类.它是对带有情感色彩的主观性 ...

  7. 中文情感分析 glove+LSTM

    最近尝试了一下中文的情感分析. 主要使用了Glove和LSTM.语料数据集采用的是中文酒店评价语料 1.首先是训练Glove,获得词向量(这里是用的300d).这一步使用的是jieba分词和中文维基. ...

  8. Bert实战---情感分类

    1.情感分析语料预处理 使用酒店评论语料,正面评论和负面评论各5000条,用BERT参数这么大的模型, 训练会产生严重过拟合,,泛化能力差的情况, 这也是我们下面需要解决的问题; 2.sigmoid二 ...

  9. 机器学习 - LSTM应用之情感分析

    1. 概述 在情感分析的应用领域,例如判断某一句话是positive或者是negative的案例中,咱们可以通过传统的standard neuro network来作为解决方案,但是传统的神经网络在应 ...

随机推荐

  1. 03python面向对象编程2

    3.继承 如果你要编写的类是另一个现成类的特殊版本,可使用继承.一个类继承另一个类时,它将自动获得另一个类的所有属性和方法:原有的类称为父类,而新类称为子类.子类继承了其父类的所有属性和方法,同时还可 ...

  2. 长沙理工大学第十二届ACM大赛-重现赛 B 日历中的数字 (实现)

    链接:https://ac.nowcoder.com/acm/contest/1/B来源:牛客网 全屏查看题目   时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他 ...

  3. Ubuntu 16.04 安装摄像头驱动usb_cam

    !!需要在ROS平台上安装   ROS见 https://www.cnblogs.com/haijian/p/8782560.html cd ~/catkin_ws/src 下载usb_cam包 gi ...

  4. css 3D动画

    一.今天让我们来学习一下css 3D吧! 1.首先我们要学习好css3 3d一定要有一定的立体感! 2.再来那就聊聊原理吧! 3.css3 3d 顾名思义是由两个2d名片组成的 但不是让你建立连个2d ...

  5. DevExpress v19.1新版亮点——WinForms篇(二)

    行业领先的.NET界面控件DevExpress v19.1终于正式发布,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WinForms v19.1中新增的一些控 ...

  6. MySQL--缓存的使用注意

    几个参数 query_cache_type:为ON时开启,为OFF关闭,为DEMAND时则只有查询语句中有sql cache时才使用缓存 query_cache_size: 缓存的内存空间 query ...

  7. 深入理解MySql事务

    事务是MySQL等关系型数据库区别于NoSQL的重要方面,是保证数据一致性的重要手段.本文将首先介绍MySQL事务相关的基础概念,然后介绍事务的ACID特性,并分析其实现原理. MySQL博大精深,文 ...

  8. 模拟输入(ADC-A0)

    ESP8266具有内置的10位ADC,只有一个ADC通道(A0引脚),即只有一个ADC输入引脚可读取来自外部器件的模拟电压 ESP8266上的ADC通道和芯片供电电压复用,也就是说我们可以将其设置为测 ...

  9. Win10离线安装.NET Framework 3.5的方法补充(附cab格式离线安装包下载) - 转载

    MS酋长很早以前已经分享了<Win10离线安装.NET Framework 3.5的方法技巧>,同时分享了exe格式的.NET Framework 3.5离线安装包下载地址.但有部分网友反 ...

  10. luogu 2491 [SDOI2011]消防 / 1099 树网的核 单调队列 + 树上问题

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 300001 #define inf 1000000000 ...