文本分类的14种算法(6):
文本分类深度学习框架(keras)的环境配置与基本操作
下面会介绍的算法属于深度学习算法,会用到keras包,代码也会做一些改动
包的安装
深度学习的模型一般用keras框架跑,而keras框架需要tensorflow作为基础,所以要装一下keras和tensorflow两个包,直接在pycharm里搜索和安装keras和tensorflow:
File->Settings->Project Interpreter,点右边栏最上面的加号(Latest version右边那个)添加包,添一个keras和一个tensorflow(我用的非gpu版的,就不带后缀):
之后跑还是会报错,会有5个W0716报错告诉你The name xxx is deprecated,please use xxx.xxx instead这样的报错。这是因为pycharm自己提供的tensorflow版本太低了,里面用的这些函数太旧了,keras已经不支持了。其实解决也很简单,5处报错在2个文件里,把报错地方的函数名xxx换成他要你use instead的函数名xxx.xxx就可以了。改完5处函数名再跑就不会出错了。
就是相当于人工打个补丁,到源文件里替换一下已经淘汰的函数(名)。
代码的扩充
之前代码里我们自己写的评测函数和它的调用就可以删掉了。
#评测函数:
def classificate(estimator, trainReview, trainLable, testReview, testLable):
start = time.time()
#模型训练,fit通常都是指模型的学习、训练过程
print('训练:')
model = estimator
model.fit(trainReview, trainLable)
print(model)
#模型预测:
print('预测:')
pred_model = model.predict(testReview)
print(pred_model)
#算法评估
print('评估:')
score = metrics.accuracy_score(testLable, pred_model)
matrix = metrics.confusion_matrix(testLable, pred_model)
report = metrics.classification_report(testLable, pred_model)
print('>>>准确率\n', score)
print('\n>>>混淆矩阵\n', matrix)
print('\n>>>召回率\n', report)
end = time.time()
t = end - start
print('\n>>>算法消耗时间为:', t, '秒\n')
#算法调用:
gbm =lg.LGBMClassifier()
classificate(gbm, trainCount, trainLable, testCount, testLable)
先计个时、记录一下特征维度,再把标签矩阵转化成独热编码矩阵。什么是独热编码矩阵呢,就比如一组规格化编码之后的标签[0,1,2.3,2],独热编码之后就把他变成了只有以为为1其他位都为0的5个二进制向量,根据为1的那一位所在位置的不同就可以区分其所代表的编码:
[[1.0.0.0],
[0.1.0.0],
[0.0.1.0],
[0.0.0.1],
[0.0.1.0]]
# 求标签的独热编码矩阵
trainCate = to_categorical(trainLable)
testCate = to_categorical(testLable)
然后就是喜闻乐见的构建神经网络了:
# 1 创建神经网络
network = models.Sequential()
# 2 添加神经连接层
# 第一层必须有并且一定是 [输入层], 必选
network.add(layers.Dense( # 添加带有 relu 激活函数的全连接层
units=100,
activation='relu',
# 输入维度即数据集特征维度
input_shape=(feature_num, )
))
# 介于第一层和最后一层之间的称为 [隐藏层],可选
network.add(layers.Dense( # 添加带有 relu 激活函数的全连接层
units=100,
activation='relu'
))
# 最后一层必须有并且一定是 [输出层], 必选
network.add(layers.Dense( # 添加带有 softmax 激活函数的全连接层
units=2, #输出层感知器个数即标签维度/类数
activation='softmax'
))
# 3 编译神经网络
network.compile(loss='categorical_crossentropy', # 分类交叉熵损失函数
optimizer='rmsprop',
metrics=['accuracy'] # 准确率度量
)
# 4 开始训练神经网络
network.fit(trainCount, # 训练集特征
trainCate, # 训练集标签
epochs=5, # 迭代次数
batch_size=100, # 指定进行梯度下降时每个batch包含的样本数
validation_data=(testCount, testCate) # 验证测试集数据
)
由于输出层的感知器数量肯定是和输出类别数相等的,所以最后一层输出层的units=2,即本例中的标签类别数为2(Positive\Negative),标签维度为2.
预测集的训练与评估:
#利用模型进行预测
pred = network.predict(testCount)
score = network.evaluate(testCount,
testCate,
batch_size=32)
end = time.time()
usingTime=end-start
print('时间:',usingTime,'s; 得分:',score)
Keras中model.evaluate()返回的是损失值和我们选定的指标值,这个选定是在compile里的metrics参数操作的,比如这个代码的compile函数,metrics选的就是准确度accuracy:
# 3 编译神经网络
network.compile(loss='categorical_crossentropy', # 分类交叉熵损失函数
optimizer='rmsprop',
metrics=['accuracy'] # 准确率度量,也是选定evaluate的指标值为准确度
)
跑一下前馈神经网络:
耗时46s,选用的是分类交叉熵损失函数,损失值约为1.09,准确率78%左右。
前馈神经网络
前馈神经网络是一种最简单的神经网络,各神经元分层排列。每个神经元只与前一层的神经元相连。接收前一层的输出,并输出给下一层.各层间没有反馈。
之前说的多层感知器就是一种将输入的多个数据集映射到单一的输出的数据集上的前馈神经网络(不过MLP好像是可以后馈的),常见的前馈神经网络还有BP网络和RBF网络。
多层感知器的神经单元采用的是阈函数所以无法处理线性分类问题(它输出来的值总是散的),所以就有了BP神经网络,BP神经网络的神经元采用的是Sigmoid函数,输出0~1之间的连续量。且BP神经网络包括信号的前向传播和误差的反向传播两个过程,即计算误差输出时按从输入到输出的方向进行,而调整权值和阈值则从输出到输入的方向进行。通过误差的反向传导使上一层的神经元调整阈值与连接权重,使误差沿梯度方向下降,从而降低误差。
LSTM
我们做阅读题总强调语境,但是上面说的所有算法,他们都没法对历史时间片的信息进行合适的分析,于是循环神经网络RNN应运而生,它的每一层不仅输出给下一层,同时还输出一个隐状态,给当前层在处理下一个样本时使用。RNN的感知器大概长这样:
RNN虽然可以有效的处理时序数据,拥有类似于“记忆”的功能,能够处理历史信息,但是RNN在处理长期依赖(时间序列上距离较远的节点)时会遇到巨大的困难,因为计算距离较远的节点之间的联系时会涉及雅可比矩阵的多次相乘,这会带来梯度消失(经常发生)或者梯度膨胀(较少发生)的问题。为解决这些问题,出现了门限RNN,其中最具代表性的即LSTM。
长短时记忆网络的思路比较简单。原始RNN的隐藏层只有一个状态,即h,它对于短期的输入非常敏感。那么,我们就再增加一个状态,即c,让它来保存长期的状态。
新增加的状态c,称为单元状态(cell state)。我们把上图按照时间维度展开:
即LSTM使用多个状态单元保存不同时间间距的历史信息,且利用权重对其进行调整。
除了多状态保存,LSTM的巧妙之处还在于通过增加输入门限,遗忘门限和输出门限,使得自循环的权重是变化的,这样一来在模型参数固定的情况下,不同时刻的积分尺度可以动态改变,从而避免了梯度消失或者梯度膨胀的问题。且LSTM允许在不同时刻改变该系数。
援引这篇文章:https://blog.youkuaiyun.com/mzpmzk/article/details/80548927的图:
也就是利用权重和门限来控制不同时间间距的历史信息对当前时间片的影响:
放下代码,跑的挺慢的:
lstm_network = models.Sequential()
# 2 添加神经连接层
lstm_network.add(layers.Embedding(input_dim=feature_num, # 添加嵌入层
output_dim=28))
lstm_network.add(layers.LSTM(units=28)) # 添加 28 个单元的 LSTM 神经层
lstm_network.add(layers.Dense(units=2,
activation='sigmoid')) # 添加 sigmoid 分类激活函数的全连接层
# 3 编译神经网络
lstm_network.compile(loss='binary_crossentropy',
optimizer='Adam',
metrics=['accuracy'] # 准确率度量,也是选定evaluate的指标值为准确度
)
# 4 开始训练神经网络
lstm_network.fit(trainCount, # 训练集特征
trainCate, # 训练集标签
epochs=5, # 迭代次数
batch_size=28, # 指定进行梯度下降时每个batch包含的样本数
validation_data=(testCount, testCate) # 验证测试集数据
)
至此14种文本分类算法就介绍完了,后面会出一个总结。