Tensorflow_08C_Keras 的数据增强与 Tensorboard 使用方法

Brief 概述

前面两章重点描述了使用 Keras 搭建模型的两种方式,并且妥善的储存模型到 .h5 文件中,等下一次使用的时候直接呼叫储存文档,就可以把整个模型,连同参数一起回传到新的模型中继续开始工作。

最后,既然 Keras 已经大致完好的被 Tensorflow 移植过来,那么 tf 最厉害的可视化工具 Tensorboard 肯定也不能落于人后,接下来将使用非常简单的方式,让我们能够随后开启 Tensorboard 观察我们模型定义的长相,并加上一系列的数据预处理,让模型训练的更完善。

p.s. 点击此 进入 keras 官网,点击此 进入 keras 的 GitHub 源代码。

 

Import Data 导入数据

构建神经网络之前,最重要的还是数据本身,而这里将继续沿用前面面几个章节中所使用的两个模型 MNIST 与 CIFAR10,和与其对应的函数代码,并简单打印出引入数据集图像对应标签的结果。

import gzip
from Code_Session.TF_04 import mnist as M
import pickle
from Code_Session.TF_05 import cifar2cnn as cc

MNIST Dataset

path_mnist = '/Users/kcl/Documents/Python_Projects/01_AI_Tutorials/_2_Image_Datasets/MNIST_data'
mnist = M.MNIST(val_ratio=0.0, data_dir=path_mnist)
print(mnist.img_train.shape)
(60000, 784)
mnist_img_train = M.format_images(mnist.img_train)
mnist_lab_train = mnist.lab_train
mnist_cls_name = [i for i in range(10)]
cc.plot_images(mnist_img_train, mnist.lab_train, mnist_cls_name, size=[3, 4])

 

CIFAR10 Dataset

path_cifar = '/Users/kcl/Documents/Python_Projects/cifar-10-batches-py'
img_train = cc.merge_batches('data', file_dir=path_cifar)
print(img_train.shape)
(50000, 3072)
file_dir = path_cifar + '/' + 'batches.meta'
def get_class_name(file_dir=file_dir):
    with open(file_dir, 'rb') as file:
        dic = pickle.load(file, encoding='bytes')
    return [w.decode('utf-8') for w in dic[b'label_names']]

cifar_img_train = cc.format_images(img_train)
cifar_lab_train = cc.merge_batches('labels', file_dir=path_cifar)
cc.plot_images(cifar_img_train, cifar_lab_train, 
               get_class_name(), size=[3, 4])

 

p.s. 如果对其中的代码有任何不熟悉,请详见前面几回合的内容。

接下来就可以从 Tensorflow 模块中呼叫 keras 搭建一个非常迅捷且轻便的神经网络模型。类似 keras 的 API 模块也有 PrettyTensor 与 layers,不过从 Tensorflow 官网的态度来看,它很可能将在未来被删减,而主推 keras,同时很多更新的功能 keras 也持续同步着,是一个相对稳健的高级 API,故值得一探究竟。

 

Load The Model as One Piece 整体模型的载入

new_model = K.models.load_model('save.h5')

Review the Trained Results

关于一个完整的神经网络,可以查看的内容非常多,而 Keras 也很贴心的帮使用者整理方法,可以很轻松的让我们看清每一层神经之间的参数量,同时使用函数呼叫指定层框架中的参数。

model.summary( )

首先是 summary 函数,调用它来查看我们在上面重新载入回来的模型架构,如下指令。

new_model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 28, 28, 1)         0         
_________________________________________________________________
layer1 (Conv2D)              (None, 28, 28, 16)        416       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 16)        0         
_________________________________________________________________
batch_normalization (BatchNo (None, 14, 14, 16)        64        
_________________________________________________________________
layer2 (Conv2D)              (None, 14, 14, 36)        14436     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 36)          0         
_________________________________________________________________
batch_normalization_1 (Batch (None, 7, 7, 36)          144       
_________________________________________________________________
flatten (Flatten)            (None, 1764)              0         
_________________________________________________________________
dense (Dense)                (None, 128)               225920    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 242,270
Trainable params: 242,166
Non-trainable params: 104
_________________________________________________________________

每层之间的参数变化总量都在这个函数的帮助下一览无遗。

 

Plot Wrong Predicted Images

接着我们可以使用重新載入的 model 框架中的 predict 函数预测输入数字图像的对应类别是什么,如下代码:

### Predict MNIST image
rand_img = mnist.img_test.reshape([-1, 28, 28, 1])[3:5004]
rand_lab = mnist.lab_test[3:5004]
lab_name = [i for i in range(10)]

### Predict CIFAR10 image
# rand_img = cifar_img_test[3:100]
# rand_lab = cc.load_binary_data('test_batch', 'labels', 
#                                file_dir=path_cifar).astype(np.int)[3:100]
# lab_name = get_class_name()

# ----------------------------------------------------------------------

pred_oh = new_model.predict(rand_img)

### Only when using MNIST dataset, turn this on
rand_img = rand_img.reshape([-1, 28, 28])

pred_lab = np.argmax(pred_oh, axis=1)
# print(pred_lab)
incorrect = (pred_lab != rand_lab)

cc.plot_images(rand_img[incorrect], rand_lab[incorrect], lab_name,
               size=[3, 4], pred_labels=pred_lab[incorrect])

 

 

Lookup Weights between Layers

  1. 首先使用 model.layers 方法呼叫所有的层,以列表 list 的方式回传
  2. 指定好选择的层之后,使用 get_weights() 函数同样呼叫所有该层的参数集,以列表的方式回传
  3. 指定好是哪一个参数集之后,即可得到一个以 numpy list 作为数据格式的结果

上面的三点说来话长,执行的时候也就不过是下面的一段话,如下代码:

new_model.layers[4].get_weights()[0].shape
(5, 5, 16, 36)

抠出指定层的指定节点之数字之后,需要进一步图像话观察或是特定区域分析权重大小的相关探讨,都将变得非常简单。


还有另一些方法可以呼叫没层的参数:K.backendK.models.Model 如果上面第一个方法行不通了,下面两个是可以尝试的切入点。

 

Tensorboard in Keras

既然 Keras 是依托于 Tensorflow 来执行一切算法与参数的传递,那么 Tensorboard 的使用肯定也是使用者马上能够联想上的一个重要工具,此一工具也非常完好的在 Keras 中被保留和使用,使用方式更是如出一辙的简单,一个函数 K.callbacks.TensorBoard() 调用即可完成所有的工作(点击此进入源代码),不过需要注意安插其他配套代码的位置与时机,流程如下:

  1. Construct a model using Sequential or Model function
  2. Add more layers within a constructed model
  3. Compile the model
  4. 1st additional step: Apply K.callbacks.TensorBoard() function
  5. 2nd additional step: Fit (train) the model with new argument "callbacks=[K...TensorBoard]"
  6. ... Same procedure ...

详细代码将于下面的 Data Preprocessing 环节一同展现,执行完后即得到一个新的文件,使用者即可在终端使用此文件开启文档在 Tensorboard 中查看结果。

 

Data Preprocessing in Keras

说到数据的前期处理,Keras 同样应该给出了它自己独有且简单方便的执行方法,其对应函数为 K.preprocessing.image.ImageDataGenerator(),其执行顺序如下流程:

  1. 前期预处理数据时,即使用此函数,并设定一系列参数
  2. 赋予设定好的函数一个对象,并使用对象的方法 .fit()
  3. 例行公事的架构神经网络
  4. 最后要使用 model.fit() 训练时,需改成 model.fit_generator()
  5. 正常执行模型评估

Step 1

此步骤也是耗时最久的一步,先跟 Keras 说明图像数据要被处理成什么样子,再指定是哪些数据要被处理,但是注意一个很重要的一点是,第一步做完后,并没有任何因为预处理而占用的缓存,如下代码:

import numpy as np
import tensorflow as tf
import tensorflow.keras as K
import matplotlib.pyplot as plt

# First set up what are we going to deal with the images
img_augment = K.preprocessing.image.ImageDataGenerator(
    rotation_range=10, width_shift_range=0.2, height_shift_range=0.2,
    shear_range=0.15, zoom_range=0.1, channel_shift_range=0.3,
    horizontal_flip=True, vertical_flip=False)
# Second appoint the certain images into the preset procedure using .fit
img_augment.fit(cifar_img_train, augment=True)

Step 2

经过第一步骤告知好所有信息后,接下来就让数据沿着这些信息参数 "流" 出来,经过 .flow 方法流出来的对象是一个需要被遍历的函数,每次出来的量设定为一个 batch,放到循环里面遍历之后出来的结果就直接是增强过后的数据本身。

# What we will get from the called function below is an "iterable object"
Iteration = img_augment.flow(cifar_img_train, 
                             cifar_lab_train, 
                             batch_size=12)
k = 1
for aug_img, aug_lab in Iteration:
    fig, axes = plt.subplots(3, 4)
    fig.subplots_adjust(hspace=0.6, wspace=0.6)
    for n, ax in enumerate(axes.flat):
        ax.imshow(aug_img[n])
        xlabel = get_class_name()[aug_lab[n]]
        ax.set_xlabel(xlabel)
        ax.set_xticks([])
        ax.set_yticks([])
    plt.show()
    print("---------- Separation {} ----------".format(k))
    k += 1

---------- Separation 1 ----------

---------- Separation 2 ----------

....

... This process will be iterated all the time~

....

从上面执行的结果我们可以看到,使用遍历会以每次一个 batch 的速度持续执行,直到 fit 的目标图像所有都被强化一遍之后才算结束。

Step 3

接着是我们熟悉的模型构建方法,这里结合了上面用 Keras 使用 Tensorboard 的代码环节,并注意在 fit model 的时候使用的函数将不再是 .fit 而是 .fit_generator。这么一来 model 才能够接受数据增强所流出来的增强了的数据,而 .flow 后面除了增强的数据外,还接了一个标签参数,注意使用的标签是 one hot 形式,放在 .flow 中的标签会被自动的对应增强的数据被迭代出来。

### Model construction using Sequential method
model = K.models.Sequential()
model.add(K.layers.InputLayer(input_shape=(32, 32, 3)))
model.add(K.layers.Flatten())
model.add(K.layers.Dense(units=128, activation=tf.nn.relu))
model.add(K.layers.Dense(units=128, activation=tf.nn.relu))
model.add(K.layers.Dense(units=10, activation=tf.nn.softmax))

model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# ----------------------------------------------------------------------

### Tensorboard activated by Keras API
tb = K.callbacks.TensorBoard(log_dir='./keras.tb',
                             histogram_freq=0,
                             batch_size=128,
                             write_graph=True,
                             write_grads=True,
                             write_images=True)
#                              embeddings_freq=1,
#                              embeddings_layer_names=None,
#                              embeddings_metadata=None)
# Third feed the input images into the model set above letting it "flow"
model.fit_generator(img_augment.flow(cifar_img_train, 
                                     cc.one_hot(cifar_lab_train), 
                                     batch_size=128),
                    steps_per_epoch=len(cifar_lab_train)/128, epochs=10,
                    callbacks=[tb])
Epoch 1/10
391/390 [==============================] - 31s 80ms/step - loss: 1.8821 - acc: 0.3279
Epoch 2/10
391/390 [==============================] - 30s 77ms/step - loss: 1.8726 - acc: 0.3318
Epoch 3/10
391/390 [==============================] - 32s 83ms/step - loss: 1.8704 - acc: 0.3313
Epoch 4/10
391/390 [==============================] - 31s 79ms/step - loss: 1.8581 - acc: 0.3353
Epoch 5/10
391/390 [==============================] - 32s 81ms/step - loss: 1.8555 - acc: 0.3361
Epoch 6/10
391/390 [==============================] - 31s 80ms/step - loss: 1.8506 - acc: 0.3376
Epoch 7/10
391/390 [==============================] - 32s 82ms/step - loss: 1.8516 - acc: 0.3395
Epoch 8/10
391/390 [==============================] - 32s 81ms/step - loss: 1.8442 - acc: 0.3399
Epoch 9/10
391/390 [==============================] - 31s 80ms/step - loss: 1.8419 - acc: 0.3439
Epoch 10/10
391/390 [==============================] - 31s 79ms/step - loss: 1.8327 - acc: 0.3455

Step 4

最后一步例行公事检测一下模型经过数据增强后的效果,能够发现其一定程度的提升了分类的准确率,同时也增强了模型泛化的能力。

cifar_img_test = cc.format_images(cc.load_binary_data(
    'test_batch', 'data', file_dir=path_cifar) / 255.0)
cifar_lab_test = cc.one_hot(cc.load_binary_data(
    'test_batch', 'labels', file_dir=path_cifar).astype(np.int))

cifar_loss, cifar_acc = model.evaluate(cifar_img_test, cifar_lab_test)
print('The loss value: {}'.format(cifar_loss))
print('The accuracy: {}'.format(cifar_acc))
10000/10000 [==============================] - 1s 61us/step
The loss value: 1.6989541765213012
The accuracy: 0.4079

p.s. 如果准确率没有显著提升,表示数据增强的强度可能过大,或是训练的 epoch 次数不够多表示。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值