卷积神经网络之优化参数(剪子包袱锤)

目录

一.优化参数的三个方法

1.手动修改

2.for循环调参

3.Keras Tunner自动调参工具

介绍

1.安装

 2.准备训练数据和加载的库

3.创建HyperParameters对象以及模型生成函数

4.创建Hyperband对象

4.开始优化

5.获取最佳模型

6.结果显示

二.注释

1.为什么二次调参无效,不起作用?(避坑)

2.dropout的意义

3.WARNING:tensorflow:Callbacks method `on_train_batch_end` is slow compared to the batch time原因

4.WARNING:tensorflow:From F:/deeplearning/dp4.py:133: Model.fit_generator (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.

5.tensorflow显存占比高但是GPU利用率低的问题


下面内容是对CV4中的程序进行优化,在CV4中我们卷积层的数量、过滤器的数量、全连接层神经元的个数、学习率都需要去优化一下。在CV3中我们已经介绍过keras Tunner自动调参工具,当时这次的例子是剪子包袱锤,在这里再重复介绍下,在下文中将使用这种工具进行调参优化。注意与cv2,cv3不同的是这里我们使用了GPU加速训练,tensorflow的版本和cuda,cudnn的版本都更换了。这里要注意的就是使用gpu加速的话,再使用keras tunner调参工具可能会报错,这个时候我们的tensorflow-gpu,cudnn的版本要求是比较新的,可以参考我下面的依赖。注意使用GPU加速必须显卡能支持。

这里提供比较快的pypi源


1.使用国内源(pip比较快):
超快豆瓣源:
pip --default-timeout=100 install 库名称 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 
举例:
pip --default-timeout=100 install tensorflow-gpu==2.1.0  -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 
清华源:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
举例:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow-gpu==2.2.0
中科大源:
举例:pip install -i https://pypi.mirrors.ustc.edu.cn/simple/ tensorflow-gpu==2.3.0

用法:例:pip install -i https://pypi.doubanio.com/simple/ 包名
源汇总:
阿里云 http://mirrors.aliyun.com/pypi/simple/

中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 

豆瓣(douban) http://pypi.douban.com/simple/ 

清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/


解决超时的一些其他办法:

2,设置超时时间:pip --default-timeout=100 install  Pillow,

3,不使用缓存:pip  --no-cache-dir install Pillow

在下面中我们将解决这个问题

一.优化参数的三个方法

有以下三个方法

1.手动修改

我们可以有最原始的办法,就是手动修改参数,然后观察训练的效果(损失和精确度),从而判断参数的设置是否合理,但是这样很麻烦。

2.for循环调参

还有一个办法就是,那就是编程写for循环来调参,但是也有点麻烦。

3.Keras Tunner自动调参工具

在这里我们可以借助这款自动调参工具来实现我们参数的优化,优点是不容易出错,效果也比较好。

介绍

keras Tunner是一个可以自动搜索模型训练参数的库,它的基本思路是在需要调整参数的地方插入一个特殊的对象(可指定参数范围),然后调用类似训练那样的search方法。

1.安装

依赖(重要)

  • python 3.7
  • TensorFlow gpu-2.3.0(pip就好)
  • cuda 10.1(官网下载)
  • cudnn 8.0.5(下载地址:cudnn8.0.5对应CUDA10.1-深度学习文档类资源-CSDN下载)
  • keras 2.3.1(pip就好)

安装命令:

pip install -U keras-tuner

 2.准备训练数据和加载的库

#石头剪刀布(优化版)

#用GPU跑的话记得需要设置为仅在需要时申请显存。
import tensorflow as tf
config = tf.compat.v1.ConfigProto(gpu_options=tf.compat.v1.GPUOptions(allow_growth=True))
sess = tf.compat.v1.Session(config=config)

import tensorflow as tf
from keras_preprocessing.image import ImageDataGenerator

#归一化数据以及数据增强
TRAINING_DIR = "F:/deeplearning/rps/rps"
training_datagen = ImageDataGenerator(
    rescale=1. / 255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest')


#训练集数据不用做数据增强,只归一化数据即可
VALIDATION_DIR = "F:/deeplearning/rps/rps-test-set"
validation_datagen = ImageDataGenerator(rescale=1. / 255)

#分类数据集(指向训练集数据)
train_generator = training_datagen.flow_from_directory(
    TRAINING_DIR,
    target_size=(150, 150),
    class_mode='categorical'
  )

# 分类数据集(指向测试集数据)
validation_generator = validation_datagen.flow_from_directory(
    VALIDATION_DIR,
    target_size=(150, 150),
    class_mode='categorical'
)
from kerastuner.tuners import Hyperband
from kerastuner.engine.hyperparameters import HyperParameters
from tensorflow.keras.optimizers import RMSprop

3.创建HyperParameters对象以及模型生成函数

先创建HyperParameters对象。进而我们定义一个模型,然后在模型中插入Choice以及int等调参用的对象。该函数返回一个编译好的模型。

hp = HyperParameters()#声明一个变量,类型为HyperParameters,等会通过hp来调

def build_model(hp):
    #模型构建
    model = tf.keras.models.Sequential()
    model.add(tf.keras.layers.Conv2D(hp.Choice('num_filters_top_layer',#这个名字是和其数值对应的
                                               values=[16,64],#取值范围
                                               default=16),
                                                (3, 3), activation='relu', input_shape=(150, 150, 3)))
    model.add(tf.keras.layers.MaxPooling2D(2, 2))
    for i in range(hp.Int('num_conv_layers',1,3)):
        model.add(tf.keras.layers.Conv2D(hp.Choice(f'num_filters_layer{i}',
                                                   values=[16,64],#取值范围
                                                   default=16),
                                                    (3, 3), activation='relu'))
        model.add(tf.keras.layers.MaxPooling2D(2, 2))

    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dropout(0.5))#Dropout是深度学习中的一种防止过拟合手段,具体看注释2

    model.add(tf.keras.layers.Dense(hp.Int('hidden_units',128,512,step=32),#给出范围和搜索步长
                                    activation='relu'))
    model.add(tf.keras.layers.Dense(3, activation='softmax'))
    # 模型编译
    model.compile(loss='categorical_crossentropy', optimizer=RMSprop(lr=0.001), metrics=['accuracy'])
    return model

4.创建Hyperband对象

进而我们再创建Hyperband对象,这是keras tuner支持的四种方法的其中一种。

tuner = Hyperband(#生成一个tuner对象,输入Hyperband
        build_model,#函数的名字,告诉他用哪个函数生成这个模型
        objective='val_accuracy',#以测试集的训练效果为准
        max_epochs=15,#猜最多几次可以达到会聚
        directory='rpsPData',#参数数据目录
        hyperparameters=hp,#告诉他用这个变量调
        project_name='rps1',#调优参数工程名字
)

4.开始优化

搜索过程:通过调用模型构建函数,使用hp跟踪的超参空间(搜索空间)中的参数配置,多次构建模型。优化器逐渐探索超参空间,记录每种配置的评估结果。

#接下来搜一下参数,search和fit用法差不多
tuner.search(train_generator,epochs=15,validation_generator=validation_generator)

5.获取最佳模型

搜索到最优参数之后,可通过下面的程序,用tunner对象提取最优参数构建神经元网络模型。并调用summary方法观察优化后的网络结构。

#优化完参数之后可以通过这个看到结果
best_hps=tuner.get_best_hyperparameters(1)[0]

model=tuner.hypermodel.build(best_hps)#用调优之后的参数构建模型

#查看模型网络结构
model.summary()
tuner.results_summary()#可打印结果综述

6.结果显示

Search: Running Trial #27

Hyperparameter    |Value             |Best Value So Far 
num_filters_top...|64                |16                
num_conv_layers   |2                 |3                 
num_filters_layer0|16                |64                
hidden_units      |416               |160               
num_filters_layer1|16                |16                
num_filters_layer2|16                |64                
tuner/epochs      |15                |15                
tuner/initial_e...|0                 |5                 
tuner/bracket     |0                 |2                 
tuner/round       |0                 |2                 

Epoch 1/15
79/79 [==============================] - 19s 239ms/step - loss: 1.2429 - accuracy: 0.3667 - val_loss: 1.0400 - val_accuracy: 0.6022
Epoch 2/15
79/79 [==============================] - 19s 239ms/step - loss: 0.9449 - accuracy: 0.5532 - val_loss: 0.6880 - val_accuracy: 0.5968
Epoch 3/15
79/79 [==============================] - 19s 238ms/step - loss: 0.7442 - accuracy: 0.6774 - val_loss: 0.3666 - val_accuracy: 0.9247
Epoch 4/15
79/79 [==============================] - 19s 243ms/step - loss: 0.6191 - accuracy: 0.7500 - val_loss: 0.3868 - val_accuracy: 0.9247
Epoch 5/15
79/79 [==============================] - 18s 231ms/step - loss: 0.5086 - accuracy: 0.7956 - val_loss: 0.1944 - val_accuracy: 0.9570
Epoch 6/15
79/79 [==============================] - 18s 223ms/step - loss: 0.4437 - accuracy: 0.8210 - val_loss: 0.2616 - val_accuracy: 0.8817
Epoch 7/15
79/79 [==============================] - 17s 220ms/step - loss: 0.3864 - accuracy: 0.8520 - val_loss: 0.2162 - val_accuracy: 0.9194
Epoch 8/15
79/79 [==============================] - 18s 232ms/step - loss: 0.3319 - accuracy: 0.8778 - val_loss: 0.1309 - val_accuracy: 0.9624
Epoch 9/15
79/79 [==============================] - 17s 215ms/step - loss: 0.2984 - accuracy: 0.8960 - val_loss: 0.1338 - val_accuracy: 0.9624
Epoch 10/15
79/79 [==============================] - 19s 237ms/step - loss: 0.2665 - accuracy: 0.8984 - val_loss: 0.0902 - val_accuracy: 0.9758
Epoch 11/15
79/79 [==============================] - 18s 232ms/step - loss: 0.2220 - accuracy: 0.9163 - val_loss: 0.2438 - val_accuracy: 0.8898
Epoch 12/15
79/79 [==============================] - 18s 234ms/step - loss: 0.2247 - accuracy: 0.9187 - val_loss: 0.0518 - val_accuracy: 1.0000
Epoch 13/15
79/79 [==============================] - 18s 228ms/step - loss: 0.1829 - accuracy: 0.9357 - val_loss: 0.1361 - val_accuracy: 0.9301
Epoch 14/15
79/79 [==============================] - 18s 228ms/step - loss: 0.2124 - accuracy: 0.9290 - val_loss: 0.1054 - val_accuracy: 0.9651
Epoch 15/15
79/79 [==============================] - 18s 226ms/step - loss: 0.1914 - accuracy: 0.9345 - val_loss: 0.0912 - val_accuracy: 0.9758

Trial 27 Complete [00h 04m 39s]
val_accuracy: 1.0

Best val_accuracy So Far: 1.0
Total elapsed time: 00h 52m 44s
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 148, 148, 16)      448       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 74, 74, 16)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 72, 72, 64)        9280      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 36, 36, 64)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 34, 34, 16)        9232      
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 17, 17, 16)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 15, 15, 64)        9280      
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 7, 7, 64)          0         
_________________________________________________________________
flatten (Flatten)            (None, 3136)              0         
_________________________________________________________________
dropout (Dropout)            (None, 3136)              0         
_________________________________________________________________
dense (Dense)                (None, 160)               501920    
_________________________________________________________________
dense_1 (Dense)              (None, 3)                 483       
=================================================================
Total params: 530,643
Trainable params: 530,643
Non-trainable params: 0

卷积神经网络之优化参数(剪子包袱锤)_第1张图片

发现了没有我们的结果其实还不理想,在这里最有可能的原因是训练迭代的次数还不够多,所以需要增加训练迭代次数。

卷积神经网络之优化参数(剪子包袱锤)_第2张图片

这个是训练迭代20次的结果,这个结果中train accuracy趋于不变,test accuracy不断下降,train accuracy大于test accuracy,这里的结果相比较上面的结果更好一些。但是也不算很好。 所以我们继续增加迭代次数。

卷积神经网络之优化参数(剪子包袱锤)_第3张图片

训练迭代30次的结果

卷积神经网络之优化参数(剪子包袱锤)_第4张图片

这个是训练迭代50次的结果。

卷积神经网络之优化参数(剪子包袱锤)_第5张图片

这个是训练迭代80次的结果。

从中我们可以看出迭代50次的结果是最好的。证明在这里增加训练迭代的次数是能够提高模型的拟合效果,但并不是越多越好,太多了反而会造成过拟合现象.......

二.注释

1.为什么二次调参无效,不起作用?(避坑)

是因为第一次调参之后把调参之后的结果存储在directory里面了,二次调参需要把那个文件夹删了才会重新优化。

2.dropout的意义

dropout

作用:避免过拟合

Dropout与L1和L2正则化区别:L1和L2正则化通过在损失函数上增加参数的惩罚项,通过对参数大小的约束,起到类似降维的作用(若高阶项参数接近0,相当于降阶)。进而简化模型,提高模型泛化力,避免过拟合。

L1和L2是正则化修改代价函数,而Dropout则是修改神经网络本身(dropout直接让一些神经元随机停止工作,其实就是比如挑选几个神经元组成小团队高效地工作)。

工作原理:dropout就是"抛弃",抛弃的是网络中隐藏层的节点(输入层和输出层是由数据类型和问题类型决定的,当然不能抛弃了),怎么抛弃呢?dropout有一个参数p,p的取值是每个节点有p概率被抛弃。抛弃这个节点有什么影响呢,影响在于一旦某个节点被选定为抛弃的节点,那么对于神经网络的forward过程这个节点的输出就被置为0,对于backward过程,这个节点的权重和偏置不参与更新,这就是说,在某次迭代中,网络中有部分节点不参与这一次的训练,整个网络结构等同于下图右侧(左侧是dropout前的)。

卷积神经网络之优化参数(剪子包袱锤)_第6张图片

3.WARNING:tensorflow:Callbacks method `on_train_batch_end` is slow compared to the batch time原因

出现的原因是一开始verbose=1,在一个epoch中训练一个batch就会打印进度条和结果,但是打印到控制台所需时间比训练模型时间更长,所以有了警告。将verbose=0,使得一点训练过程信息也不打印,verbose=2,每一个epoch打印一次。

4.WARNING:tensorflow:From F:/deeplearning/dp4.py:133: Model.fit_generator (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.

原因:
新版本的tensorflow已经把这个方法废弃了,我们可以直接使用fit来代替fit_generator了,fit也有fit_generator的功能了。(当然fit_generator也可以用)

5.tensorflow显存占比高但是GPU利用率低的问题

这个问题其实挺重要,如果我们在做大型试验的话,train一次跑几天就比较.......

卷积神经网络之优化参数(剪子包袱锤)_第7张图片

这个跟自己写的代码有关系,在读取磁盘中数据的时候,是依靠CPU在读取数据(此时磁盘读写会非常高),同时,tensorflow在运行模型训练的时候,会从内存中读取数据,GPU训练会比较快,而CPU一直在从磁盘中读数据到内存中,而跟不上GPU从内存中读取数据并训练数据的速度(就是你处理的速度反而比读写速度快很多),此时可以用两种发放来处理,一个是将磁盘中的数据转成TFRecords类型数据,让tensorflow直接读取数据,而不是让CPU读取数据后再给tensorflow读取,另一个方法就是增加线程数(num_threads),在tf.train.shuffle_batch和tf.train.batch中,有一个num_threads参数,默认为1,可以稍微调高一点。 

你可能感兴趣的:(CV,gpu,tensorflow,神经网络,python,卷积神经网络)