【NLP】文本分类算法-基于字符级的无词嵌入双向循环神经网络(双向 GRU)

本文介绍了在风控场景下如何利用双向GRU进行文本分类,通过处理文本数据,构建RNN模型,特别是双向GRU,用于捕捉序列中的长期依赖关系。作者分享了详细的模型构建和训练过程,并展示了模型在风险弹幕数据集上的优秀表现,达到了0.9669的准确率,证明了深度学习在序列任务中的优势。
摘要由CSDN通过智能技术生成

7da2a653dfee08addc9455e497910ecd.jpeg

大家好,我是小伍哥,文本数据的处理,对于一个风控策略或者算法,我觉得是必须要掌握的技能,有人说,我的风控并不涉及到文本?我觉得这片面了,在非内容风控领域,文本知识也是非常有用的。

用户昵称、地址啥的,这种绝大部分风控场景都能遇到;关系网络的节点向量化,基本也是文本处理的思路;行为序列,也能用文本的知识去处理,能捕捉非常有趣模式。

在这里开个系:20大风控文本分类算法,去年就已经写的差不多了,现在整理好慢慢更新,本系列主要介绍了风控场景下文本分类的基本方法,对抗文本变异,包括传统的词袋模型、循环神经网络,也有常用于计算机视觉任务的卷积神经网络,以及 RNN + CNN,试验完一遍,基本能搞定大部分的文本分类以及文本变异对抗问题。

今天是第 4 讲,主要关注语句的序列关系,使用双向GRU对文本进行分类,逻辑回归写了3期了,估计大家看厌烦了, 今天跳跃下,直接跳到双向RNN,后面在写单向的RNN,有应用需求的,可以直接应用双向的,效果比较好,学习的,还是需要从简单RNN,LSTM再到GRU。

一、原理介绍

RNN 可能看起来很可怕,尽管它们因为复杂而难以理解,但非常有趣。RNN 模型封装了一个非常漂亮的设计,以克服传统神经网络在处理序列数据(文本、时间序列、视频、DNA 序列等)时的短板。

RNN 是一系列神经网络的模块,它们彼此连接像锁链一样,每一个都将消息向后传递,强烈推荐大家从 Colah 的博客中深入了解它的内部机制,下面的图就来源于此。

0a895614bdb06df07d25e4602a920b2f.png

我们要处理的序列类型是文本数据。对意义而言,单词顺序很重要。RNN 考虑到了这一点,它可以捕捉长期依赖关系。

二、数据集和预处理

本文用一个风险弹幕数据集做实验,该数据集包含19670条明细数据,每一行都用 1(垃圾文本)和 0(正常文本)进行了标记。

数据集地址:https://github.com/LebronGG/textcnn/blob/master/data/cnews/train.txt,自己需要简单处理下,负向-1,正向-0即可。也可以后台回复【弹幕】获取

目标:针对直播间中存在的大量涉黄涉暴弹幕,进行垃圾分类,将弹幕中不合法的内容进行识别并屏蔽。

正常弹幕示例

新人主播,各位老板多多关注ᚠᚠᚠ    0

50077你卖我    0

看看五雷咒的威力    0

垃圾弹幕示例

网站++沜买的私聊我    1

安 KMD555 买-P-微    1

抠逼加薇2928046748抠逼加薇2928046748抠逼。   1

fdb688a6365d9b2d6aad897f82b52ec8.png

数据读取和查看

import os 
import pandas as pd
path  = '/Users/wuzhengxiang/Documents/DataSets/TextCnn'
os.chdir(path)
data = pd.read_csv('text_all.csv')


#对数据进行随机打乱
data = data.sample(frac=1, random_state=42)
print(data.shape)
(19670, 2)


#查看0-1的比例,可以看出来,数据集基本上平衡
data['label'].value_counts()
1    9882
0    9788


#查看前10行的数据
data.head(10)
                         text  label
17036        郑 29526 Q 77544      1
5426                    葩葩葩l      0
14173            网站盘需要买的私聊我.      1
14582               买家秀和卖家秀?0
1730                  1776看v      0
1444              我又没送你谢我干啥ᚠ      0
10439            7645 55562筘      0
2448   伽韦 sx111505 珂视频箹   Ku      1
10423            影薇 w2753636      1
11782      胸还没有寒磊的 大ᚠ  还奶子疼!0

三、模型构建

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.text import text_to_word_sequence
from keras.preprocessing.sequence import pad_sequences


from keras.models import Model 
from keras.models import Sequential


from keras.layers import Input, Dense, Embedding, Conv1D, Conv2D, MaxPooling1D, MaxPool2D
from keras.layers import Reshape, Flatten, Dropout, Concatenate
from keras.layers import SpatialDropout1D, concatenate
from keras.layers import GRU, Bidirectional, GlobalAveragePooling1D, GlobalMaxPooling1D


from keras.callbacks import Callback
from keras.optimizers import Adam


from keras.callbacks import ModelCheckpoint, EarlyStopping
from keras.models import load_model
from keras.utils.vis_utils import plot_model




#进行分字处理
import os
import pandas as pd
path  = '/Users/wuzhengxiang/Documents/DataSets/TextCnn'
os.chdir(path)
text_all = pd.read_csv('text_all.csv')


data = text_all
data['text'] = text_all['text'].apply(lambda x: ' '.join(x))
data.head()


x_train, x_test, y_train, y_test=\
     train_test_split(data['text'], 
                      data['label'], 
                      test_size=0.2, 
                      random_state=42
                      )
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)




x_train[45]
'\ufeff + C 名 看 P , 是 威 哦 ❤   ❤'




MAX_NB_WORDS = 80000
tokenizer=Tokenizer(num_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(x_train)




tokenizer.texts_to_sequences([x_train[38]])




train_sequences = tokenizer.texts_to_sequences(x_train)
test_sequences  = tokenizer.texts_to_sequences(x_test)




MAX_LENGTH = 35
padded_train_sequences = pad_sequences(train_sequences, maxlen=MAX_LENGTH)
padded_test_sequences  = pad_sequences(test_sequences,  maxlen=MAX_LENGTH)


padded_train_sequences
array([[  0,   0,   0, ...,   2,   8,   2],
       [  0,   0,   0, ..., 387, 443,  16],
       [  0,   0,   0, ...,  64,  59,  11],
       ...,
       [  0,   0,   0, ...,  27,  27,  27],
       [  0,   0,   0, ...,   3,   9,  71],
       [  0,   0,   0, ...,   1,  16,  16]], dtype=int32)
padded_train_sequences.shape
(15736, 35)


import numpy as np


def get_simple_rnn_model():
    embedding_dim = 300
    embedding_matrix = np.random.random((MAX_NB_WORDS, embedding_dim))
    inp = Input(shape=(MAX_LENGTH, ))
    x = Embedding(input_dim = MAX_NB_WORDS, 
                  output_dim = embedding_dim, 
                  input_length = MAX_LENGTH, 
                  weights=[embedding_matrix], trainable=True)(inp)
    x = SpatialDropout1D(0.3)(x)
    x = Bidirectional(GRU(100, return_sequences=True))(x)
    avg_pool = GlobalAveragePooling1D()(x)
    max_pool = GlobalMaxPooling1D()(x)
    conc = concatenate([avg_pool, max_pool])
    outp = Dense(1, activation="sigmoid")(conc)


    model = Model(inputs=inp, outputs=outp)
    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])
    return model
rnn_simple_model = get_simple_rnn_model()


plot_model(rnn_simple_model, 
           #to_file='C:\\Users\\伍正祥\\Desktop\\NLP任务实验\\rnn_simple_model.png', 
           show_shapes=True, 
           show_layer_names=True
          )




filepath="weights-improvement-{epoch:02d}-{val_acc:.4f}.hdf5"
checkpoint = ModelCheckpoint(filepath, 
                             monitor='val_acc', 
                             verbose=1, 
                             save_best_only=True,
                             mode='max'
                            )


batch_size = 256
epochs = 2
history = rnn_simple_model.fit(
                   x = padded_train_sequences, 
                   y = y_train, 
                   validation_data = (padded_test_sequences, y_test), 
                   batch_size = 256, 
                   #callbacks=[checkpoint], 
                   epochs = 5, 
                   verbose=1
           )


#best_rnn_simple_model = load_model('weights-improvement-01-0.8262.hdf5')


y_pred_rnn_simple = rnn_simple_model.predict(padded_test_sequences, 
                                                  verbose=1, batch_size=2048)


y_pred_rnn_simple = pd.DataFrame(y_pred_rnn_simple, columns=['prediction'])
y_pred_rnn_simple['prediction'] = y_pred_rnn_simple['prediction'].map(lambda p: 1 if p >= 0.5 else 0)


#y_pred_rnn_simple.to_csv('./predictions/y_pred_rnn_simple.csv', index=False)
#y_pred_rnn_simple = pd.read_csv('./predictions/y_pred_rnn_simple.csv')


print(accuracy_score(y_test, y_pred_rnn_simple))
0.9669547534316217


df = pd.DataFrame({'text':x_test,'label':y_test,'pred':y_pred_rnn_simple})
df[df['label']!=df['pred']]

相比于第二个模型(拼音+ngram+逻辑回归)的0.95602,这个一下子就干到了0.9669,可以看到深度学习还是非常勇猛的,在序列领域,RNN有着不可取代的地位。后续我们继续考虑变异情况,再考虑用深度学习来试验,看看能做到多少的准确率。

四、模型解释

1)模型打印

plot_model 可以打印模型的框架,我们的框架如下,可以看到,使用了一个双项的GRU,然后进行了两种不同的池化方式进行池化在拼接起来。

a9aa423471a96e2677e94496e5874f0d.png

2)模型训练过程

我们可以看看训练过程的损失下降和准确率上升,通过曲线,可以优化我们的训练过程。

import matplotlib.pyplot as plt
# 画出损失函数曲线
plt.plot(history.history['loss'],    'bo',)
plt.plot(history.history['accuracy'], 'b',)
plt.title('train loss')
plt.ylabel('acc')
plt.xlabel('epoch')
plt.legend()

# 画出损失函数曲线
plt.plot(history.history['val_loss'],    'bo',)
plt.plot(history.history['val_accuracy'], 'b',)
plt.title('val loss')
plt.ylabel('acc')
plt.xlabel('epoch')
plt.legend()

可以看到整个下降曲线还是很平滑的,如果我们轮数增加,准确率还有上升的可能性,大家可以测试下,有点非机器,一训练就开始发热了,

f79134bebf7be430a326caedd24a3b59.png

7bdc328a87595e7ca694c33c56eb6b50.png

先写到这里了,大家可以看到,深度学习,对于解决语言问题,还是很有优势的,就这么简简单单的一段代码,准确率有了非常大的提升,后面的文章,我们继续深入研究各种风控识别算法。

···  END  ···

 
 

07f34c42cfccbd129391f7de15e1694c.jpeg

 
 
 
 
 
 
 
 
往期精彩回顾




适合初学者入门人工智能的路线及资料下载(图文+视频)机器学习入门系列下载机器学习及深度学习笔记等资料打印《统计学习方法》的代码复现专辑机器学习交流qq群955171419,加入微信群请扫码

1553cdd0b0efbfaa5fcaf3c2e5cbcd52.png

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值