Keras项目-英文语料的文本分类实战

  • 一、机器学习模型
    • 1.1 数据简介
    • 1.2 数据读取与预处理
    • 1.3 数据切分与逻辑回归模型构建
  • 二、全连接神经网络模型
    • 2.1 模型训练
    • 2.2 模型结果展示
  • 三、WordEmebeding-全连接神经网络
    • 3.1数据序列化
    • 3.2 Embedding Layer Model
    • 3.3 特征提取
  • 四、Word2Vec-全连接神经网络
    • 4.1获取每个词的词向量
    • 4.2 模型训练
    • 4.3 继续训练词向量
  • 五、LSTM文本分类模型
  • 六、CNN文本分类模型
  • 七、模型调优
    • 7.1定义参数范围
    • 7.2 模型调优

一、机器学习模型

1.1 数据简介

读取数据,本次使用的数据集是英文数据集。
都是已经标注好的情感2分类数据集,1为积极,0为消极。


三个数据集都存在data文件夹下,需要遍历文件夹取得相应数据集

1.2 数据读取与预处理

将文本读取进来

import pandas as pd"""
数据读取,其中0表示消极,1表示积极
"""filepath_dict = {'yelp':   'data/yelp_labelled.txt','amazon': 'data/amazon_cells_labelled.txt','imdb':   'data/imdb_labelled.txt'}df_list = []for source, filepath in filepath_dict.items():df = pd.read_csv(filepath, names=['sentence', 'label'], sep='\t')df['source'] = source  df_list.append(df)df = pd.concat(df_list)
print(df.head())
sentence  label source
0                           Wow... Loved this place.      1   yelp
1                                 Crust is not good.      0   yelp
2          Not tasty and the texture was just nasty.      0   yelp
3  Stopped by during the late May bank holiday of...      1   yelp
4  The selection on the menu was great and so wer...      1   yelp

读取数据之后,需要将数据转化为对应的向量,计算机是不识别文字,只认识数字,所以需要将文字转化为对应的数字,计算机才能进行计算。

最为传统的将文字转为数字的模型就是池袋模型,本文先使用池袋模型对文字进行编码

假设有这么2段话:sentences = ['John likes ice cream, ‘John hates chocolate.’]

vectorizer.vocabulary_就是将文字转为数字位置编码

vectorizer.transform(sentences).toarray() 转为对应池袋模型的ndarray矩阵
可以看出出现的词为1,不出现为0,出现一次加1

"""
文本数据特征
"""
sentences = ['John likes ice cream cream', 'John hates chocolate chocolate.']
from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer(min_df=0, lowercase=False)
vectorizer.fit(sentences)
print (vectorizer.vocabulary_)
print (vectorizer.transform(sentences).toarray())
{'John': 0, 'likes': 5, 'ice': 4, 'cream': 2, 'hates': 3, 'chocolate': 1}
[[1 0 2 0 1 1][1 2 0 1 0 0]]

可以通过池袋模型对文本特征进行最简单的特征提取,将每一个文本都转为了对应的向量

1.3 数据切分与逻辑回归模型构建

先将数据集按照测试集与验证集,按照一定比例切分,设定好随机种子的值,以便于查看调参的结果。

先使用一个数据集进行实验

"""
数据集切分
"""
from sklearn.model_selection import train_test_split
df_yelp = df[df['source'] == 'yelp']
sentences = df_yelp['sentence'].values
y = df_yelp['label'].values
sentences_train, sentences_test, y_train, y_test = train_test_split(sentences, y, test_size=0.25, random_state=1000)

划分好数据集后,需要将文本特征转化为向量特征,就按照上文介绍的池袋模型,将文本向量化

"""
特征制作
"""
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()
vectorizer.fit(sentences_train)
X_train = vectorizer.transform(sentences_train)
X_test  = vectorizer.transform(sentences_test)

制作好数据输出后,就可以输出给模型进行学习,模型训练效果的好坏很大一部分取决于数据特征的处理。本次实验以机器学习的逻辑回归模型作为基础模型,来对比深度学习模型效果

"""
基础模型
"""
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression()
classifier.fit(X_train, y_train)
score = classifier.score(X_test, y_test)
print("Accuracy:", score)

Accuracy: 0.796

综合对比三分数据集的实验结果

"""
综合对比3份数据
"""
for source in df['source'].unique():df_source = df[df['source'] == source]sentences = df_source['sentence'].valuesy = df_source['label'].valuessentences_train, sentences_test, y_train, y_test = train_test_split(sentences, y, test_size=0.25, random_state=1000)vectorizer = CountVectorizer()vectorizer.fit(sentences_train)X_train = vectorizer.transform(sentences_train)X_test  = vectorizer.transform(sentences_test)classifier = LogisticRegression()classifier.fit(X_train, y_train)score = classifier.score(X_test, y_test)print('Accuracy for {} data: {:.4f}'.format(source, score))

Accuracy for yelp data: 0.7960
Accuracy for amazon data: 0.7960
Accuracy for imdb data: 0.7487

逻辑回归模型的训练结果的准确率大概都在80%左右。

二、全连接神经网络模型

2.1 模型训练

上文通过池袋模型特征学习得到的文本特征,有一个缺点,那就是特别的稀疏,大部分的数据都是0。

在sklearn中对于这么稀疏的数据,在表述的时候为节省内存,就会用位置信息记录有数值的信息。比如(254,1)就代表在254列这个位置的值为1。

而深度学习模型,keras并不支持之种的表达格式,因为深度学习网络每一层输出的数据应该维度都是相同的,需要正常的向量格式。

所以需要将X_train,X_test做一个转换

定义神经网络输出的维度input_dim是多少,就是等于每一条X的维度

网络定义比较简单,第一层就得到10特征,第二层就得到1个结果。

"""
神经网络模型
"""
from keras.models import Sequential
from keras import layers# 稀疏矩阵转换
X_train = X_train.toarray() #标准数据
X_test = X_test.toarray()#定义神经网络输出的维度是多少,就是每一条X的维度
input_dim = X_train.shape[1]  # Number of features#--------------------------------------定义网络-----------------------
model = Sequential()
#结构
model.add(layers.Dense(10, input_dim=input_dim, activation='relu'))
#表示处于0,1的概念
model.add(layers.Dense(1, activation='sigmoid'))
#模型优化
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
#训练
history = model.fit(X_train, y_train,epochs=100,verbose=False, #不打印训练结果validation_data=(X_test, y_test),batch_size=10) #性能好可以设置大一点,效果可能会更好#------------------------模型评估---------------------------
#保存loss和accurary
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))

可以看出网络有点过拟合了

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
dense_1 (Dense)              (None, 10)                25060
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 11
=================================================================
Total params: 25,071
Trainable params: 25,071
Non-trainable params: 0
_________________________________________________________________
Training Accuracy: 1.0000
Testing Accuracy:  0.7914

2.2 模型结果展示

定义一个画图函数,用来查看模型训练过程

"""
结果展示
"""
import matplotlib.pyplot as plt
plt.style.use('ggplot')def plot_history(history,name):acc = history.history['accuracy']val_acc = history.history['val_accuracy']loss = history.history['loss']val_loss = history.history['val_loss']x = range(1, len(acc) + 1)plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)plt.plot(x, acc, 'b', label='Training acc')plt.plot(x, val_acc, 'r', label='Validation acc')plt.title('Training and validation accuracy')plt.legend()plt.subplot(1, 2, 2)plt.plot(x, loss, 'b', label='Training loss')plt.plot(x, val_loss, 'r', label='Validation loss')plt.title('Training and validation loss')plt.legend()#plt.show()plt.savefig(str(name)+'.png')plot_history(history,name='base_nn')

模型只是初步的模型,并未调优。

三、WordEmebeding-全连接神经网络

3.1数据序列化

刚才的深度学习网络,还存在一些问题,首先,池袋模型的特征表达效果有限。

其次,刚才是以一句话作为整体,细粒度上还不够,并未深入探讨词的贡献程度,词之间的相互关系。

所以,引入需要对刚才的全连接网络进行升级一下,考虑一下词之间的关系。

用Keras中的Tokenizer将词转换为相应的索引

vocab_size 代表语料库的大小,一般都需要进行加1操作,可能是由于从0开始计数的原因。vocab_size 通过训练过后的tokenizer.word_index的长度获取,就是语料库中有多少个不重复的单词。

"""
Word Embeddings
"""
from keras.preprocessing.text import Tokenizertokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(sentences_train)#将词转为索引
X_train = tokenizer.texts_to_sequences(sentences_train)
X_test = tokenizer.texts_to_sequences(sentences_test)vocab_size = len(tokenizer.word_index) + 1  # Adding 1 because of reserved 0 indexprint(sentences_train[2])
print(X_train[2])
I am a fan of his ... This movie sucked really bad.
[7, 150, 2, 932, 4, 49, 6, 11, 563, 45, 30]

将文本转为相应的词的索引之后,还存在一个问题,那就是每个文本的长度都不一样,而深度学习网络需要每个文本的长度都是一致的,所以还需要对文本进行长度一致的标准化。

最简单的就是统计语料中文本的普遍长度是多少,本文设置为30,太长的就切割,太短的就填充0

"""
补齐
"""
from keras.preprocessing.sequence import pad_sequencesmaxlen = 30
X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)
X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)
print(X_train[0, :])

[170 116 390 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0]

3.2 Embedding Layer Model

input_dim,一般就是语料库中不重复单词的大小

output_dim,就是文本映射成多少维度的向量,自己定义将每个词映射成多少维

keras.layers.Embedding(input_dim,output_dim,embeddings_initializer=‘uniform’,embeddings_regularizer=None, activity_regularizer=None,embeddings_constraint=None,mask_zero=False,input_length=None)

input_dim: int > 0。词汇表大小, 即,最大整数 index + 1。
output_dim: int >= 0。词向量的维度。

在keras中,数据是以张量的形式表示的,张量的形状称之为shape,表示从最外层向量逐步到达最底层向量的降维解包过程。比如,一个一阶的张量[1,2,3]的shape是(3,);
一个二阶的张量[[1,2,3],[4,5,6]]的shape是(2,3);一个三阶的张量[[[1],[2],[3]],[[4],[5],[6]]]的shape是(2,3,1)。

input_shape就是指输入张量的shape。例如,input_dim=784,说明输入是一个784维的向量,这相当于一个一阶的张量,它的shape就是(784,)。因此,input_shape=(784,)。

input_dim = input_shape(input_dim,)

input_dim, input_length = input_shape(input_length, input_dim)

通俗来说,input_length就是输入数据的长度,Input_dim就是数据的维度。比如一条数据内容是: “人人车” , one hot编码后是 [[1 0] [1 0] [0 1]]表示 ,则 batch_size = 3, input_dim = 2.

"""
Embedding Layer
"""
from keras.models import Sequential
from keras import layersembedding_dim = 50model = Sequential()
model.add(layers.Embedding(input_dim=vocab_size,  #输入为语料库的大小再+1output_dim=embedding_dim, #将其input_length=maxlen))
model.add(layers.Flatten())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model.summary()

其中embedding_1 (Embedding) (None, 30, 50) :

None就是预料文本的有多少个,一般不做定义。30代表每条文本有多少个词,我们上面定义了30个词,50代表每个词训练层50维。

embedding_1 (Embedding) (None, 30, 50) 是一个3维的,全连接是一个2维的特征提取,所以需要将3维的转化为2维度的数据。可以将每个词向量进行拼接拉长,转化为2维度的向量。如下所示

拉长后,就变成30*50=1500了

Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_1 (Embedding)      (None, 30, 50)            128750
_________________________________________________________________
flatten_1 (Flatten)          (None, 1500)              0
_________________________________________________________________
dense_3 (Dense)              (None, 10)                15010
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 11
=================================================================
Total params: 143,771
Trainable params: 143,771
Non-trainable params: 0

模型训练

"""
重新训练
"""
history = model.fit(X_train, y_train,epochs=20,verbose=False,validation_data=(X_test, y_test),batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history,name='base_Embedding Layer')

Training Accuracy: 1.0000
Testing Accuracy: 0.6203

发现模型性能结果还不如机器学习,还未进行调优

3.3 特征提取

上文的方法将词进行叠在一起,导致词的特征太多,学习起来效果还不如原来的模型。所以还需要一个特征提取的方法。

用了一个全局特征提取GlobalMaxPool1D(),这是一个1维的maxpooling,将每一列找最大的,就pooling成1个值。所以(30,50)就变成了(,50)了

再接入全连接层

"""
pooling特征压缩
"""
from keras.models import Sequential
from keras import layersembedding_dim = 50model = Sequential()
model.add(layers.Embedding(input_dim=vocab_size, output_dim=embedding_dim, input_length=maxlen))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model.summary()history = model.fit(X_train, y_train,epochs=50,verbose=False,validation_data=(X_test, y_test),batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history,name='pooling')
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_2 (Embedding)      (None, 30, 50)            128750
_________________________________________________________________
global_max_pooling1d_1 (Glob (None, 50)                0
_________________________________________________________________
dense_5 (Dense)              (None, 10)                510
_________________________________________________________________
dense_6 (Dense)              (None, 1)                 11
=================================================================
Total params: 129,271
Trainable params: 129,271
Non-trainable params: 0
_________________________________________________________________
D:\Anaconda3\envs\tf3\lib\site-packages\tensorflow_core\python\framework\indexed_slices.py:424: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory."Converting sparse IndexedSlices to a dense Tensor of unknown shape. "
Training Accuracy: 1.0000
Testing Accuracy:  0.7647

四、Word2Vec-全连接神经网络

4.1获取每个词的词向量

对于上文的word2beding是被认为定义成50维的,每条文本都被训练层30*50的文本向量表达,但是这个50是我们自己人为随机定义的,然后交给网络去训练,在训练过程中实现对每个词向量表达的调整。

但是这个有个问题,我们不知道网络训练的词向量的效果到底如何,不知道是否50维度就可以很好的表达出每个词在上下文中的含义。

所以我们可以预先用别人训练好的词向量模型,获取到每个词的向量的最佳表达,来提升模型的性能。

读取本地的glove词向量模型,来读取每个词的词向量,需要传入词向量位置,词编码字典tokenizer.word_index,词向量维度embedding_dim,本地的词向量是多少维度的embedding_dim就定义为多少维。

需要那些词,就取出那些词,预先构造一个都是0的embedding_matrix,将每个词的向量都按tokenizer.word_index顺序的填充进去。

"""
词向量模型
"""
import numpy as np
#过滤无关词语
def create_embedding_matrix(filepath, word_index, embedding_dim):vocab_size = len(word_index) + 1  # keras文档中指定需要+1embedding_matrix = np.zeros((vocab_size, embedding_dim))with open(filepath,encoding='utf-8') as f:for line in f:word, *vector = line.split()if word in word_index:idx = word_index[word] embedding_matrix[idx] = np.array(vector, dtype=np.float32)[:embedding_dim]return embedding_matrix
embedding_dim = 50
embedding_matrix = create_embedding_matrix('data/glove.6B.50d.txt',tokenizer.word_index, embedding_dim)

4.2 模型训练

和上面的模型训练差不多,修改了两个参数weights=[embedding_matrix],trainable=False。embedding_matrix是传入相应的词向量模型,trainable=False表示是否对传入的词向量再次进行训练。

"""
重新训练
"""
model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, weights=[embedding_matrix], input_length=maxlen, trainable=False))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model.summary()history = model.fit(X_train, y_train,epochs=50,verbose=False,validation_data=(X_test, y_test),batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history,name='wordvec')
Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_3 (Embedding)      (None, 30, 50)            128750
_________________________________________________________________
global_max_pooling1d_2 (Glob (None, 50)                0
_________________________________________________________________
dense_7 (Dense)              (None, 10)                510
_________________________________________________________________
dense_8 (Dense)              (None, 1)                 11
=================================================================
Total params: 129,271
Trainable params: 521
Non-trainable params: 128,750
_________________________________________________________________
Training Accuracy: 0.7914
Testing Accuracy:  0.7380

训练次数还不够,模型还没到一个拟合的状态

4.3 继续训练词向量

别人训练的词向量模型,可以是基于通用的任务,对于当前任务的适用性可能还不高,可以自己在别人训练的基础上,继续进行训练,更加适合自己领域下的词向量模型。

将trainable=True就行

"""
训练Embedding Layer
"""
model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, weights=[embedding_matrix], input_length=maxlen, trainable=True))
model.add(layers.GlobalMaxPool1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model.summary()
history = model.fit(X_train, y_train,epochs=50,verbose=False,validation_data=(X_test, y_test),batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history,name='wordvec_train=True')
Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_3 (Embedding)      (None, 30, 50)            128750
_________________________________________________________________
global_max_pooling1d_2 (Glob (None, 50)                0
_________________________________________________________________
dense_7 (Dense)              (None, 10)                510
_________________________________________________________________
dense_8 (Dense)              (None, 1)                 11
=================================================================
Total params: 129,271
Trainable params: 521
Non-trainable params: 128,750
_________________________________________________________________
Training Accuracy: 0.7914
Testing Accuracy:  0.7380

继续学习,有过拟合风险,还未加入drop层;结构可能越来越好,也可能越来约差。

五、LSTM文本分类模型

LSTM是按个对每个词向量进行计算,需要传入序列的数字,所以不需要Pooling。

用LSTM代替GlobalMaxPool1D来提取特征。

下面的LSTM中是第二层,所以不需要定义Input-dim,直接定义先得到多少个输出特征。

其中return_sequences=False,表示只要最后一个结果y30,return_sequences=True,表示也需要中间结果,那就是y1-y30。

如果后面再连接一个LSTM,就需要设置为True

"""
LSTM模型
"""
from keras.layers import Dense, Activation, Dropout, LSTM
from keras.optimizers import Adam
model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, weights=[embedding_matrix], input_length=maxlen, #maxlentrainable=True))
model.add(LSTM(64, return_sequences=False))
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))opt = Adam(lr=0.001)
model.compile(optimizer=opt,loss='binary_crossentropy',metrics=['accuracy'])
model.summary()
history = model.fit(X_train, y_train,epochs=50,validation_data=(X_test, y_test),batch_size=64)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history,name='LSTM')

GlobalMaxPool1D来提取特征

Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_5 (Embedding)      (None, 30, 50)            128750
_________________________________________________________________
lstm_1 (LSTM)                (None, 64)                29440
_________________________________________________________________
dense_11 (Dense)             (None, 10)                650
_________________________________________________________________
dense_12 (Dense)             (None, 1)                 11
=================================================================
Total params: 158,851
Trainable params: 158,851
Non-trainable params: 0
_________________________________________________________________

Epoch 50/50
561/561 [==============================] - 0s 248us/step - loss: 0.0120 - accuracy: 0.9982 - val_loss: 1.0881 - val_accuracy: 0.7861
Training Accuracy: 0.9982
Testing Accuracy: 0.7861

六、CNN文本分类模型

用卷积神经网络来提取文本数据

其中设置layers.Conv1D(128, 5, activation=‘relu’),一维的卷积核。

128表示用不同的128卷积特征图去卷积文本向量,所以每个卷积核对得到1个特征图

1维5表示卷积核的长度,原本长度为30的词的向量,卷积后变成30-5+1=26个。

"""
CNN模型
"""
embedding_dim = 50
model = Sequential()
model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
model.add(layers.Conv1D(128, 5, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(10, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])
model.summary()history = model.fit(X_train, y_train,epochs=10,verbose=True,validation_data=(X_test, y_test),batch_size=10)
loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))
plot_history(history,name='CNN')
Model: "sequential_7"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_6 (Embedding)      (None, 30, 50)            128750
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 26, 128)           32128
_________________________________________________________________
global_max_pooling1d_4 (Glob (None, 128)               0
_________________________________________________________________
dense_13 (Dense)             (None, 10)                1290
_________________________________________________________________
dense_14 (Dense)             (None, 1)                 11
=================================================================
Total params: 162,179
Trainable params: 162,179
Non-trainable params: 0

Epoch 10/10
561/561 [==============================] - 0s 433us/step - loss: 0.0039 - accuracy: 1.0000 - val_loss: 0.7069 - val_accuracy: 0.7754
Training Accuracy: 1.0000
Testing Accuracy: 0.7754

七、模型调优

7.1定义参数范围

模型中有很多参数,对于参数的不同,都可能提升模型的性能。

先定于一个模型架构,定义好相应的参数,构建成函数的形式 create_mode。

在对相应的参数来设置一个可变范围
例如设定filter的个数,卷积kernel的 长度,文本训练的embeding的大小等。
param_grid = dict(num_filters=[32, 64, 128],
kernel_size=[3, 5, 7],
embedding_dim=[50],
maxlen=[30])

"""
调参
"""
def create_model(num_filters, kernel_size, vocab_size, embedding_dim, maxlen):model = Sequential()model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))model.add(layers.Conv1D(num_filters, kernel_size, activation='relu'))model.add(layers.GlobalMaxPooling1D())model.add(layers.Dense(10, activation='relu'))model.add(layers.Dense(1, activation='sigmoid'))model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])return model
param_grid = dict(num_filters=[32, 64, 128],kernel_size=[3, 5, 7],embedding_dim=[50],maxlen=[30])

7.2 模型调优

用sklearn来的RandomizedSearchCV,和keras的KerasClassifier随机搜索来调参数
在KerasClassifier传入定义的函数模型,以及其他参数,verbose=False表示不显示迭代。

KerasClassifier(build_fn=create_model,
epochs=epochs, batch_size=64,
verbose=False)

RandomizedSearchCV中传入得到的KerasClassifier模型,以及参数统计,n_iter=5表示随机选择5次,定义好交叉验证等参数。

RandomizedSearchCV(estimator=model, param_distributions=param_grid,
cv=3, verbose=1, n_iter=5)

最后进行训练,获取最优的参数,并保存下来。

from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import RandomizedSearchCV# 超参数
epochs = 20
embedding_dim = 50
maxlen = 30
output_file = 'data/output.txt'# 参数选择
for source, frame in df.groupby('source'):print('Running grid search for data set :', source)#----------------------------数据预处理-----------------------------sentences = df['sentence'].valuesy = df['label'].valuessentences_train, sentences_test, y_train, y_test = train_test_split(sentences, y, test_size=0.25, random_state=1000)tokenizer = Tokenizer(num_words=5000)tokenizer.fit_on_texts(sentences_train)X_train = tokenizer.texts_to_sequences(sentences_train)X_test = tokenizer.texts_to_sequences(sentences_test)vocab_size = len(tokenizer.word_index) + 1X_train = pad_sequences(X_train, padding='post', maxlen=maxlen)X_test = pad_sequences(X_test, padding='post', maxlen=maxlen)# ----------------------------参数空间--------------------param_grid = dict(num_filters=[32, 64, 128],kernel_size=[3, 5, 7],vocab_size=[vocab_size],embedding_dim=[embedding_dim],maxlen=[maxlen])model = KerasClassifier(build_fn=create_model,epochs=epochs, batch_size=64,verbose=False)grid = RandomizedSearchCV(estimator=model, param_distributions=param_grid,cv=3, verbose=1, n_iter=5)grid_result = grid.fit(X_train, y_train)# 测试结果test_accuracy = grid.score(X_test, y_test)with open(output_file, 'a') as f:s = ('Running {} data set\nBest Accuracy : ''{:.4f}\n{}\nTest Accuracy : {:.4f}\n\n')output_string = s.format(source,grid_result.best_score_,grid_result.best_params_,test_accuracy)print(output_string)f.write(output_string)
Running grid search for data set : amazon
Fitting 3 folds for each of 5 candidates, totalling 15 fits
Running amazon data set
Best Accuracy : 0.8083
{'vocab_size': 4603, 'num_filters': 128, 'maxlen': 30, 'kernel_size': 3, 'embedding_dim': 50}
Test Accuracy : 0.8253Running grid search for data set : imdb
Fitting 3 folds for each of 5 candidates, totalling 15 fitsRunning imdb data set
Best Accuracy : 0.8122
{'vocab_size': 4603, 'num_filters': 32, 'maxlen': 30, 'kernel_size': 3, 'embedding_dim': 50}
Test Accuracy : 0.8355Running grid search for data set : yelp
Fitting 3 folds for each of 5 candidates, totalling 15 fits
Running yelp data set
Best Accuracy : 0.8030
{'vocab_size': 4603, 'num_filters': 64, 'maxlen': 30, 'kernel_size': 3, 'embedding_dim': 50}
Test Accuracy : 0.8108

人工智能框架实战精讲:Keras项目-英文语料的DNN、Word2Vec、CNN、LSTM文本分类实战与调参优化相关推荐

  1. 51单片机c语言应用开发三位一体实战精讲 pdf 119网盘,51单片机C语言应用开发三位一体实战精讲.pdf...

    燎舍黪曩饔黠抽璇漩 黏 地丛书 刘波文 ∷ :著 对 向 编 策划编辑 :胡晓柏 : 正 圭 飚翻 Ξ∶ 蓝设计 寸面设计 8Π 颥曩曩罂 内容简介 51系 (SO51/ATSg)为 工程 心 全书以 ...

  2. 基于CNN中文文本分类实战

    一.前言 之前写过一篇基于循环神经网络(RNN)的情感分类文章,这次我们换种思路,采用卷积神经网络(CNN)来进行文本分类任务.倘若对CNN如何在文本上进行卷积的可以移步博主的快速入门CNN在NLP中 ...

  3. [Python人工智能] 二十一.Word2Vec+CNN中文文本分类详解及与机器学习(RF\DTC\SVM\KNN\NB\LR)分类对比

    从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章分享了Keras实现RNN和LSTM的文本分类算法,并与传统的机器学习分类算法进行对比实验.这篇文章我们将继续巩固 ...

  4. 【BERT-多标签文本分类实战】之五——BERT模型库的挑选与Transformers

    ·请参考本系列目录:[BERT-多标签文本分类实战]之一--实战项目总览 ·下载本实战项目资源:>=点击此处=< [1] BERT模型库   从BERT模型一经Google出世,到tens ...

  5. Python机器学习全流程项目实战精讲(2018版)

    Python机器学习全流程项目实战精讲(2018版) 网盘地址:https://pan.baidu.com/s/16SSVq74YC07M0dW1iDekPg 提取码: vu7r 备用地址(腾讯微云) ...

  6. 视频教程-2019年人工智能热门案例精讲之P图美化照片-深度学习

    2019年人工智能热门案例精讲之P图美化照片 香港大学硕士.任职经历包括微软中国(Microsoft),今日头条研发中心,联想香港人工智能中心以及联合国亚太分部.现主要工作是利用深度学习实现基于知识图 ...

  7. 视频教程-2019年人工智能热门案例精讲之基于Azure热门案例-C/C++

    2019年人工智能热门案例精讲之基于Azure热门案例 香港大学硕士.任职经历包括微软中国(Microsoft),今日头条研发中心,联想香港人工智能中心以及联合国亚太分部.现主要工作是利用深度学习实现 ...

  8. 视频教程-PR教程-Premiere 2020影视剪辑实战精讲-其他

    PR教程-Premiere 2020影视剪辑实战精讲 Adobe平面设计与影视剪辑专家讲师.微软Office办公软件专家讲师.资深IT图书作者/策划人/出版人.深度/终身学习研究与实践者.Python ...

  9. 视频教程-19全新mysql教程零基础入门实战精讲mysql视频DBA数据库视频教程SQL教程-MySQL

    19全新mysql教程零基础入门实战精讲mysql视频DBA数据库视频教程SQL教程 7年的开发架构经验,曾就职于国内一线互联网公司,开发工程师,现在是某创业公司技术负责人, 擅长语言有node/ja ...

最新文章

  1. 深度学习将眼睛变成健康“指示器”
  2. model存储 swift_Swift语言IOS8开发战记10.Data Model
  3. Google Web Brower
  4. android.content.res.Resources$NotFoundException: String resource ID #0x0
  5. 【AD封装】 Type C 封装库 6Pin 24Pin分享下载(带3D视图)
  6. ArcGIS for Desktop入门教程_第六章_用ArcMap制作地图 - ArcGIS知乎-新一代ArcGIS问答社区...
  7. 太阳直射点纬度计算公式_地理小常识:买房小技巧,房屋朝向、楼层和太阳高度角的关系...
  8. CTF密码学——常见编解码及加解密总结
  9. 将esx虚拟机从一台服务器迁移,虚拟化应用支招:ESX VtoP迁移实战
  10. python 机器视觉测量_用Opencv python实现精密测量
  11. 计算机网络连接黄感叹号,电脑连接路由器网络连接显示黄色感叹号的解决办法...
  12. 主引导记录(MBR)
  13. 《武魂》物理引擎特效全解析
  14. android蓝牙键盘光标,如何将Android手机连接到无线蓝牙鼠标?
  15. 微信小程序分享朋友圈 详细教程及注意事项
  16. 虚拟机安装---模板机准备1(最小化安装)
  17. MVC过滤器使用实例
  18. deep learning 从自我学习到深层网络学习
  19. Python实现冒泡排序,从小到大输出(bubble)
  20. 几十个炫酷可视化数据分析网站你值得拥有

热门文章

  1. 【前端面试宝典】超基础的vue知识
  2. 三大面试技巧助你飞跃
  3. (已解决)ERROR 2013 (HY000):连接MySql出错
  4. 轻松自动化---selenium-webdriver(python) (八)
  5. mongdb 下载慢,解决
  6. 弱网测试学习记录(1)
  7. 同事离职做假证,顺利拿到大公司offer,15k一下子到了24k
  8. 关于STM32F407ZGT6的一些知识小结及串口1程序
  9. 推荐一个小巧强大的代码编辑器
  10. 粉丝来信:黑猫投诉对象给投诉错了,又无法撤销删除应该怎么办呢?