利用Keras实现的CNN进行文本分类

17 篇文章 0 订阅
12 篇文章 1 订阅

利用Keras实现的CNN进行文本分类

上一篇博文已经分析了CNN如何应用在文本分类中:
https://blog.csdn.net/qq_43012160/article/details/96572537
这一篇我们来讲一讲怎么用keras实现一个CNN并用它来文本分类。
先放一张原理图:
在这里插入图片描述

数据集和源码:

链接:https://pan.baidu.com/s/1XWBOcCMvHRuZEGdkKDr-fQ
提取码:o7st

pycharm提升代码可读性的一些小技巧

因为python是弱类型语言,很多时候我们在看到不熟悉的代码的时候(特别是没有注释的时候)看起来会非常的难受。就比如一个函数,因为没有C++java那样显式的参数表,有时候都不知道传什么参进去。其实通过pycharm是可以通过设置来看函数的参数表的:
从菜单打开Files->Settings,打开下图界面,勾上Parameter Info里的第一项设置在这里插入图片描述
再打开下图界面,勾上Other里的Show quick documentation…在这里插入图片描述
然后把鼠标放在想看到函数上,就有函数的参数表和介绍了:
在这里插入图片描述

引入要用到的包和数据的预处理

import pandas as pd
import numpy as np
import jieba
from keras import models
from keras import layers
from keras.utils.np_utils import to_categorical
from keras.preprocessing.text import Tokenizer
from sklearn.preprocessing import LabelEncoder
from sklearn.feature_extraction.text import CountVectorizer
from gensim.models import word2vec
from keras.preprocessing.sequence import pad_sequences
from keras.layers import *
from keras.models import Model
from sklearn import metrics
from keras.models import load_model

#读入数据集
train_data = pd.read_csv('mytrain.csv', lineterminator='\n')
test_data=pd.read_csv('testCSV.csv', lineterminator='\n')

#数据的预处理:
#利用LabelEncoder对数据标签进行规格化处理
def encodeLabel(data):
    listLable=[]
    for lable in data['lable']:
        listLable.append(lable)
    #到这里都是把lable整合到一起,下面是规格化处理
    le = LabelEncoder()
    resultLable=le.fit_transform(listLable)
    return resultLable

trainLable=encodeLabel(train_data)
testLable=encodeLabel(test_data)

#这里出来是所有review的集合:
def getReview(data):
    listReview=[]
    le = LabelEncoder()
    for review in data['review']:
        listReview.append(review)
    return listReview

trainReview=getReview(train_data)
testReview=getReview(test_data)

分词、编码与word2vec

因为后面是要用对每个词Embedding(这里选用的word2vec)的,所以肯定要对输入进来的句子进行分词,分词之后构成了一个不包括停止词的词袋vocab:

stoplist=[None,'.', ':', '-', '+', '/', ',','0','1','2','3','4','5','6','7','8','9','0']

#分词:
def wordCut(Review):
    Mat=[]
    for rec in Review:
        seten=[]
        sentence = list(map(lambda x: x.strip().lower() if len(x.strip().lower()) > 0 else None, jieba.cut(rec)))  # 每句话里的单词拿出来
        for wd in sentence:
           if not(wd in stoplist):seten.append(wd)
        Mat.append(seten)
    return Mat

trainCut=wordCut(trainReview)
testCut=wordCut(testReview)
wordCut=trainCut+testCut
#求句子最大长度
maxLen=0
for sentence in wordCut:
    length=0
    for wd in sentence:
        if not(wd in stoplist):length=length+1
    if (length>maxLen):maxLen=length

#fit_on_texts函数可以将输入的文本中的每个词编号,编号是根据词频的,词频越大,编号越小
tokenizer=Tokenizer()
tokenizer.fit_on_texts(wordCut)
vocab = tokenizer.word_index  # 得到每个词的编号,这里的vocab已经剔除掉stoplist了

然后就是喜闻乐见的Embedding(word2vec)了,word2vec本身也是使用前馈神经网络进行训练的,所以不妨在训练之后保存模型,以后用只要加载就好了:

#word2vec的训练:
# 设置词语向量维度
num_featrues = 300
# 保证被考虑词语的最低频度
min_word_count = 5
# 设置并行化训练使用CPU计算核心数量
num_workers =4
# 设置词语上下文窗口大小
context = 5

model = word2vec.Word2Vec(wordCut, workers=num_workers, size=num_featrues, min_count=min_word_count, window=context)
model.init_sims(replace=True)
# 输入一个路径,保存训练好的模型,其中./data/model目录事先要存在
model.save("E:/python/model/CNNw2vModel2")
print(model)
#加载模型,如果之前word2vec已经训练好了直接用这句就好了:
w2v_model = word2vec.Word2Vec.load("E:/python/model/CNNw2vModel2")

之后我们解决一下句子长短不一的问题:利用pad_sequences函数使句子规格化,这里maxLen是我统计的句子最大长度,超过自定义的maxlen长度的句子会被截短,不足的会在前面补0:

#特征数字编号
trainID = tokenizer.texts_to_sequences(trainCut)
testID = tokenizer.texts_to_sequences(testCut)
trainSeq=pad_sequences(trainID,maxlen=maxLen)
testSeq=pad_sequences(testID,maxlen=maxLen)

#标签的独热编码
trainCate = to_categorical(trainLable, num_classes=2)  # 将标签转换为one-hot编码
testCate= to_categorical(testLable, num_classes=2)  # 将标签转换为one-hot编码

CNN的搭建与模型的训练

因为要调用Embedding函数进行embedding,把词转化为词向量,而我们是使用word2vec方法,所以需要对Embedding函数的默认矩阵做一下自定义:

#利用训练后的word2vec自定义Embedding的训练矩阵,每行代表一个词(结合独热码和矩阵乘法理解)
embedding_matrix = np.zeros((len(vocab) + 1, 300))
for word, i in vocab.items():
    try:
        embedding_vector = w2v_model[str(word)]
        embedding_matrix[i] = embedding_vector
    except KeyError:
        continue

#训练模型
def TextCNN_model_1(x_train_padded_seqs, trainCate, x_test_padded_seqs, testCate):
    main_input = Input(shape=(maxLen,), dtype='float64')
    # 词嵌入(使用预训练word2vec的词向量,自定义权重矩阵,300是输出的词向量维度)
    embedder = Embedding(len(vocab) + 1, 300, input_length=maxLen, weights=[embedding_matrix], trainable=False)
    embed = embedder(main_input)
    # 卷积核个数为128,词窗大小分别为2,3,4,6
    cnn1 = Conv1D(128, 2, padding='same', strides=1, activation='relu')(embed)
    cnn1 = MaxPooling1D(pool_size=maxLen-1)(cnn1)
    cnn2 = Conv1D(128, 3, padding='same', strides=1, activation='relu')(embed)
    cnn2 = MaxPooling1D(pool_size=maxLen-2)(cnn2)
    cnn3 = Conv1D(128, 4, padding='same', strides=1, activation='relu')(embed)
    cnn3 = MaxPooling1D(pool_size=maxLen-3)(cnn3)
    cnn4 = Conv1D(128, 6, padding='same', strides=1, activation='relu')(embed)
    cnn4 = MaxPooling1D(pool_size=maxLen-5)(cnn4)
    # 合并三个模型的输出向量
    cnn = concatenate([cnn1, cnn2, cnn3,cnn4], axis=-1)
    flat = Flatten()(cnn)
    drop = Dropout(0.2)(flat)
    #输出层第一个参数2是分类类别数
    main_output = Dense(2, activation='softmax')(drop)
    model = Model(inputs=main_input, outputs=main_output)
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    #epochs是迭代次数
    model.fit(x_train_padded_seqs, trainCate, batch_size=800, epochs=7)
    #保存模型
    model.save("E:/python/model/TextCNN6")

 #主程序调用训练模型:
TextCNN_model_1(trainSeq, trainCate, testSeq, testCate)

在这里插入图片描述

加载模型、调用模型预测与对模型的评估

#预测与评估
mainModel = load_model('E:/python/model/TextCNN6')
result = mainModel.predict(testSeq)  # 预测样本属于每个类别的概率
score = mainModel.evaluate(testSeq,
                           testCate,
                           batch_size=32)
print(score)

运行结果:
在这里插入图片描述
正确率只有60%左右,不太尽如人意,后面还要继续调参。

调参小技巧

调用tensorflow和keras训练神经网络的时候,每训练一些数据,每进行一次迭代,控制台都会有相应的输出反馈,可以根据反馈的信息(loss是损失函数,acc是这组数据的准确率)进行CNN参数的优化。比如我原来是迭代的10次,后来跑了很多次(参数当然做过调整)发现基本上到第7、8次迭代正确率就不会上升了,后面就有可能过拟合了,于是就把迭代次数调到了7.
又比如设置卷积核窗口大小的时候,我最开始设置过16甚至84的窗口高度,后来想想实在不合常理,谁会说话的时候一个词和84个词之前的词有关键的逻辑关联呢(除了“但”、“不”这样的转折性关键词),所以就把窗口给缩小了,不过一些关键的转折性词可能确实会有这样的关系,后面可以再调调参试试。毕竟如果真没什么用也会被池化层maxPooling给筛掉。

本来我正确率就54%,给我这么一调调上了60%,虽然还是不高。。。

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
基于python编写的Keras深度学习框架开发,利用卷积神经网络CNN,快速识别图片并进行分类 卷积神经网络(Convolutional Neural Networks, CNNs 或 ConvNets)是一类深度神经网络,特别擅长处理图像相关的机器学习和深度学习任务。它们的名称来源于网络中使用了一种叫做卷积的数学运算。以下是卷积神经网络的一些关键组件和特性: 卷积层(Convolutional Layer): 卷积层是CNN的核心组件。它们通过一组可学习的滤波器(或称为卷积核、卷积器)在输入图像(或上一层的输出特征图)上滑动来工作。 滤波器和图像之间的卷积操作生成输出特征图,该特征图反映了滤波器所捕捉的局部图像特性(如边缘、角点等)。 通过使用多个滤波器,卷积层可以提取输入图像中的多种特征。 激活函数(Activation Function): 在卷积操作之后,通常会应用一个激活函数(如ReLU、Sigmoid或tanh)来增加网络的非线性。 池化层(Pooling Layer): 池化层通常位于卷积层之后,用于降低特征图的维度(空间尺寸),减少计算量和参数数量,同时保持特征的空间层次结构。 常见的池化操作包括最大池化(Max Pooling)和平均池化(Average Pooling)。 全连接层(Fully Connected Layer): 在CNN的末端,通常会有几层全连接层(也称为密集层或线性层)。这些层中的每个神经元都与前一层的所有神经元连接。 全连接层通常用于对提取的特征进行分类或回归。 训练过程: CNN的训练过程与其他深度学习模型类似,通过反向传播算法和梯度下降(或其变种)来优化网络参数(如滤波器权重和偏置)。 训练数据通常被分为多个批次(mini-batches),并在每个批次上迭代更新网络参数。 应用: CNN在计算机视觉领域有着广泛的应用,包括图像分类、目标检测、图像分割、人脸识别等。 它们也已被扩展到处理其他类型的数据,如文本(通过卷积一维序列)和音频(通过卷积时间序列)。 随着深度学习技术的发展,卷积神经网络的结构和设计也在不断演变,出现了许多新的变体和改进,如残差网络(ResNet)、深度卷积生成对抗网络(DCGAN)等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值