我们使用的数据集为tesnflow2自带的的电影评论数据集imdb
加载数据集,第一次加载的时候可能要到外网下载数据,比较慢,我放在网盘里,下载链接:https://pan.baidu.com/s/1tq_kO3tlDmwn-CMTCBrpLw
提取码:4r7f
下载后将其拷贝到
data = keras.datasets.imdb
#限定读取的单词个数
max_word = 10000
(x_train, y_train), (x_test, y_test) = data.load_data(num_words=max_word)
查看数据shape
x_train.shape, y_train.shape
输出:((25000,), (25000,))
查看标签
print(y_train)
print(y_train.max())
print(y_train.min())
输出:
[1 0 0 ... 0 1 0]
1
0
嗯,是个二分类问题。
神经网络输入数据的长度最好相同,我们来看看训练数据的长度
data_lens = [len(x) for x in x_train]
print(max(data_lens))
print(min(data_lens))
输出:
2494
11
长度不同,我们下一步要使其长度相同,并且文本训练成密集向量,不懂的请自行查询相关资料,理论不多做介绍,本文注重实现过程。我们查看下数据的长度分布
import matplotlib.pyplot as plt
import numpy as np
p_x = np.linspace(0,2494,len(data_lens))
p_y = data_lens
plt.scatter(p_x,p_y)
我们把长度固定为一个大于平均长度的值,平均长度为
np.mean(data_lens)
输出:238.71364
好吧,那就取300 吧
x_train = keras.preprocessing.sequence.pad_sequences(x_train,300)
x_test = keras.preprocessing.sequence.pad_sequences(x_test,300)
开始模型搭建,文本的密集化采用tensorflow2 model中的函数完成
model = keras.models.Sequential()
#把文本训练成密集向量,数据维度(max_word,300)->(max_word,300,50)
model.add(layers.Embedding(max_word,50,input_length=300))
#添加扁平化层,将数据扁平化,数据维度(max_word,300,50)->(max_word,300*50),方便传递给全连接层
model.add(layers.Flatten())
#添加全连接层
model.add(layers.Dense(128,activation='relu'))
#添加输出层
model.add(layers.Dense(1))
#二分类问题激活函数选sigmoid
model.add(layers.Activation('sigmoid'))
#查看构建的模型
model.summary()
输出:
开始模型的编译和训练
model.compile(optimizer = keras.optimizers.Adam(lr=0.001) #设置优化器和学习率lr
,loss = 'binary_crossentropy' #损失函数二元交叉熵 ]
,metrics = ['acc'] #评价指标正确率acc
)
model.fit(x_train
,y_train
,epochs=10 #训练次数
,batch_size = 128
,validation_data = (x_test,y_test)
)
Train on 25000 samples, validate on 25000 samples Epoch 1/10 25000/25000 [==============================] - 7s 278us/sample - loss: 0.4376 - acc: 0.7748 - val_loss: 0.2951 - val_acc: 0.8735
Epoch 2/10 25000/25000 [==============================] - 6s 246us/sample - loss: 0.1181 - acc: 0.9600 - val_loss: 0.3628 - val_acc: 0.8563
Epoch 3/10 25000/25000 [==============================] - 6s 228us/sample - loss: 0.0171 - acc: 0.9972 - val_loss: 0.4186 - val_acc: 0.8649
Epoch 4/10 25000/25000 [==============================] - 6s 235us/sample - loss: 0.0026 - acc: 0.9999 - val_loss: 0.4444 - val_acc: 0.8678
Epoch 5/10 25000/25000 [==============================] - 6s 234us/sample - loss: 0.0010 - acc: 1.0000 - val_loss: 0.4723 - val_acc: 0.8694
Epoch 6/10 25000/25000 [==============================] - 6s 238us/sample - loss: 5.7669e-04 - acc: 1.0000 - val_loss: 0.4912 - val_acc: 0.8698
Epoch 7/10 25000/25000 [==============================] - 6s 238us/sample - loss: 3.7859e-04 - acc: 1.0000 - val_loss: 0.5088 - val_acc: 0.8702
Epoch 8/10 25000/25000 [==============================] - 6s 233us/sample - loss: 2.6826e-04 - acc: 1.0000 - val_loss: 0.5232 - val_acc: 0.8705
Epoch 9/10 25000/25000 [==============================] - 6s 248us/sample - loss: 1.9853e-04 - acc: 1.0000 - val_loss: 0.5364 - val_acc: 0.8701
Epoch 10/10 25000/25000 [==============================] - 7s 262us/sample - loss: 1.5131e-04 - acc: 1.0000 - val_loss: 0.5492 - val_acc: 0.8708
可以看出,在训练集上acc很快达到1,在测试集上acc先增大后减小,画个图更方便观察二者
可以看出模型在训练集上表现甚好,在测试集上表现不尽人意,产生了过拟合。
解决过拟合问题,除了增大数据量外我们还常用两种方法:1、增加dropout层 2、添加L1或L2正则化 3、交叉验证
现在对模型进行修改
model = tf.keras.models.Sequential()
#把文本训练成密集向量,数据维度(max_word,300)->(max_word,300,50)
model.add(tf.keras.layers.Embedding(max_word,50,input_length=300))
#添加扁平化层,将数据扁平化,数据维度(max_word,300,50)->(max_word,300*50),方便传递给全连接层
#model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.GlobalAveragePooling1D())
#添加全连接层
model.add(tf.keras.layers.Dense(128,activation='relu',kernel_regularizer=tf.keras.regularizers.Regularizer())) #添加正则化
#添加Dropout层
model.add(tf.keras.layers.Dropout(0.8))
#添加输出层
model.add(tf.keras.layers.Dense(1))
#二分类问题激活函数选sigmoid
model.add(tf.keras.layers.Activation('sigmoid'))
改造后的结果:
两线交点acc大约为0.89,表现好了些,更多的优化改进这里暂不探讨了,ok,到此为止。