文章目录
一.导言
在实战这块,我们已经具备了一些入门基本的原理和神经网络的整体过程的理解,在训练中为了节省时间,实战以keras进行演示,以便更快地获得模型运行性能并加以分析。如果有时间,后面也会用原生来书写一遍,以便加深对神经网络的认识。
二.电影评论二分类实战
2.1 步骤
导入库 -> 获取数据 -> 建立模型 -> 训练 -> 精度评估 -> 是否改进模型
2.2 导入库
from keras import models
from keras import layers
from tensorflow.keras import optimizers
from keras import losses, metrics
import matplotlib.pyplot as plt
import numpy as np
from keras.datasets import imdb
2.3 获取数据
2.3.1 导入数据
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words = 10000)
# 输出单词索引
train_data[0]
部分结果:
2.3.2 数据处理
因为电影评论数据加载进来为单词的索引,所以我们需要进行变换来查看语句是什么。
# 2.解码成英文单词
word_index = imdb.get_word_index() # 字典 key-value: 单词-索引
# word_index
# 反转成 索引-单词形式
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
# reverse_word_index
# 解码 i-3 是因为 前三个索引 0,1,2 是 ‘padding'(填充)、'start of sequence'(序列开始)、unknown(未知词)分别保留的索引, 没有找到就输出?
decoded_review = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]])
decoded_review
结果:
我们会发现通过上述操作,我们就转换成了单词。
2.3.3 向量化数据
我们最终训练的是矩阵,所以上述变换只是用于查看原句子的内容,我们还需要一种常用的方法向量化 将每行的句子按照索引(索引对应向量的列号为1,反之为0) 进行处理
# 定义一个向量化语句函数,将其转换成二进制形式(类比热编码) 10000是因为我们导入的数据词数为10000
def vectorize_sequences(sequences, dimension=10000):
results = np.zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
# 将results[i] 索引设置为1
results[i, sequence] = 1.
return results
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)
x_train
结果:
2.3.4 处理监督数据(label data)
我们也需要将监督数据转成向量化。
y_train = np.asarray(train_labels).astype(np.float32)
y_test = np.asarray(test_labels).astype(np.float32)
为了更好的理解,我们先打印下监督数据结果:
2.4 建立模型
以下建立了输入层,隐藏层,输出层。
model = models.Sequential()
# 输入层 神经元单元16个 激活函数relu
model.add(layers.Dense(16, activation='relu', input_shape=(10000, )))
# 隐藏层 神经元单元16个 激活函数relu
model.add(layers.Dense(16, activation='relu'))
# 输出层 神经元单元1个 激活函数sigmoid
model.add(layers.Dense(1, activation='sigmoid'))
#编译 梯度下降选择RMSprop,二叉交叉熵函数 显示精度
# model.compile(optimizer='rmsprop',loss='binary_crossentropy', metrics=['accuracy'])
# 通过配置优化器来实现 采用RMSprop梯度下降优化算法,损失函数采用二叉交叉熵函数, 评估标准选用精度
model.compile(optimizer=optimizers.RMSprop(lr=0.001),loss='binary_crossentropy', metrics=['accuracy'])
2.5 模型训练
# 留出验证集
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]
# 训练模型
history = model.fit(partial_x_train,partial_y_train,epochs=20,batch_size=512,validation_data=(x_val,y_val))
history_dict = history.history
history_dict.keys()
结果:
2.6 模型评估
2.6.1 训练损失和验证损失
history_dict = history.history
loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']
epochs = range(1, len(loss_values) + 1)
# bo表示绘制蓝色圆点, b绘制蓝色实线
plt.plot(epochs, loss_values, 'bo', label='Training loss')
plt.plot(epochs, val_loss_values, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
结果:
我们发现,随着训练的进行,训练集的损失逐渐减小,验证集的损失逐渐增大。
2.6.2 训练精度和验证精度
#清空图像
plt.clf()
acc = history_dict['accuracy']
val_acc = history_dict['val_accuracy']
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
结果:
我们发现,通过图中表明,训练集精度逐渐增大,验证集精度逐渐减小。
2.6.3 模型评估结果
我们发现,随着训练的进行,模型在第3轮之后出现了过拟合,因此我们需要改进模型使之达到效果。
2.7 改进模型
重新训练模型。
# 重新训练一个模型并计算结果
model = models.Sequential()
# 输入层
model.add(layers.Dense(16, activation='relu', input_shape=(10000, )))
# 隐藏层
model.add(layers.Dense(16, activation='relu'))
# 输出层
model.add(layers.Dense(1, activation='sigmoid'))
# 模型编译
model.compile(optimizer='rmsprop',loss='binary_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train,epochs=4,batch_size=512)
results = model.evaluate(x_test, y_test)
results
测试数据评估:
# 利用上述结果预测
test_result = model.predict(x_test)
np.sum(test_result > 0.9)
最后得到 7817(总数25000)个预测精度达到0.9。
2.8 总结
通过最常用的方法我们达到了上述效果,如果通过最先进的方法,可以达到99% 以上精度。