python深度学习--提升模型性能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunChao3555/article/details/88821005
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pylab
from pandas import DataFrame, Series
from keras import models, layers, optimizers, losses, metrics
from keras.utils.np_utils import to_categorical

plt.rcParams['font.sans-serif'] = ['SimHei']  #指定默认字体
plt.rcParams['axes.unicode_minus'] = False  #解决保存图像是负号'-'显示为方块的问题

#让模型性能发挥到极致

#高级架构模式:标准化和深度可分离卷积

'''
最常见的数据标准化形式就是你已经在本书中 多次见到的那种形式:将数据减去其平均值使其中心为 0,然后将数据除以其标准差使其标准 差为 1。实际上,这种做法假设数据服从正态分布(也叫高斯分布),并确保让该分布的中心为 0, 同时缩放到方差为 1
normalized_data = (data - np.mean(data, axis=...)) / np.std(data, axis=...)

但这样,并不能保证网络的输出的数据也是满足的,因此Ioffe 和 Szegedy 在 2015 年提出的一种层的类型(在Keras 中是 BatchNormalization),
即使在训练过程中均值和方差随时间发生变化,它也可以适应性地将数据标准化。
批标准化的工作原理是,训练过程中在内部保存已读取每批数据均值和方差的指数移动平均值。
批标准化的主要效果是,它有助于梯度传播(这一点和残差连接很像),因此允许更深的网络。对于有些特别深的网络,只有包含多个 BatchNormalization 层时才能进行训练
'''
#BatchNormalization 广泛用于 Keras 内置的许多高级卷积神经网络 架构,比如 ResNet50、Inception V3 和 Xception。

#BatchNormalization 层通常在卷积层或密集连接层之后使用。

 # 批再标准化
# 对普通批标准化的最新改进是批再标准化(batch renormalization),由 Ioffe 于 2017 年提出。与批标准化相比,它具有明显的优势,且代价没有明显增加。在此之后,Klambauer 等人又提出了自标准化神经网络(self-normalizing neural network),它使用特殊的激活函数(selu)和特殊的初始化器(lecun_normal),能够让数据通过任何 Dense 层之后保持数据标准化。这种方案虽然非常有趣,但目前仅限于密集连接网络,其有效性尚未得到大规模重复

def example_of_BatchNormalization(conv_model,dense_model):
    '''
    对于 Dense 层、Conv1D 层、RNN 层和将 data_format 设为 "channels_last"(通道在后)的 Conv2D 层,这个默认值都是正确的。但有少数人使用将 data_format 设为 "channels_first"(通道在前)的 Conv2D 层,这时 特征轴是编号为 1 的轴,因此 BatchNormalization 的 axis 参数应该相应地设为 1。

    :return:
    '''
    conv_model.add(layers.Conv2D(32,3,activation='relu'))
    conv_model.add(layers.BatchNormalization(axis=...))#axis指定对哪个轴标准化,默认-1,即输入张量的最后一个轴

    dense_model.add(layers.Dense(32, activation='relu'))
    dense_model.add(layers.BatchNormalization())
    return

深度可分离卷积:可以让模型更加轻量(即更少的可训练权重参数)、速度更快(即更少的浮点数运算),还可以让任务性能提高几个百分点
这个层对输入的每个通道分别执行空间卷积,然后通过逐点卷积(1×1 卷积)将输出通 道混合,如图 7-16 所示。这相当于将空间特征学习和通道特征学习分开,如果你假设输入中的 空间位置高度相关,但不同的通道之间相对独立,那么这么做是很有意义的。它需要的参数要 少很多,计算量也更小,因此可以得到更小、更快的模型。因为它是一种执行卷积更高效的方法, 所以往往能够使用更少的数据学到更好的表示,从而得到性能更好的模型



#如果只用有限的数据从头开始训练小型模型,这些优点就变得尤为重要。例如,下面这个示例是在小型数据集上构建一个轻量的深度可分离卷积神经网络,用于图像分类任务(softmax多分类)。

 
height=64
width=64
channels=3
num_classes=10

model=models.Sequential()
model.add(layers.SeparableConv2D(32,3,activation='relu',input_shape=(height,width,channels)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
model.summary()
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
#对于规模更大的模型,深度可分离卷积是 Xception 架构的基础,Xception 是一个高性能的卷积神经网络,内置于 Keras 中

#超参数优化
'''
这些在架构层面的参数叫作超参数(hyperparameter)。构建深度学习模型时,应该堆叠多少层?每层应该包含多少个单元或过滤器?激活应该使用 relu 还是其他函数?在某一层之后是否应该使用 BatchNormalization ?应该使用多大的 dropout 比率?

超参数优化的过程通常如下所示。 
    (1) 选择一组超参数(自动选择)。 
    (2) 构建相应的模型。 
    (3) 将模型在训练数据上拟合,并衡量其在验证数据上的最终性能。 
    (4) 选择要尝试的下一组超参数(自动选择)。 
    (5) 重复上述过程。 
    (6) 最后,衡量模型在测试数据上的性能。
更新超参数则非常具有挑战性。我们来考虑以下两点。
    计算反馈信号(这组超参数在这个任务上是否得到了一个高性能的模型)的计算代价可 能非常高,它需要在数据集上创建一个新模型并从头开始训练。
    超参数空间通常由许多离散的决定组成,因而既不是连续的,也不是可微的。因此,你 通常不能在超参数空间中做梯度下降。相反,你必须依赖不使用梯度的优化方法,而这 些方法的效率比梯度下降要低很多。
    通常情况下,随机搜索(随机选择需要评估的超参数,并重复这一过程)就是最好的 解决方案,虽然这也是最简单的解决方案。但有一种工具确实比随机搜索更好,它就是 Hyperopt。它是一个用于超参数优化的 Python 库,其内部使用 Parzen 估计器的树(TPE)来预测哪组超参数可能会得到好的结果。
    另一个叫作 Hyperas 的库将 Hyperopt 与 Keras 模型集成在一起。一定要试试。
    
在进行大规模超参数自动优化时,有一个重要的问题需要牢记,那就是验证集过拟合。 因为你是使用验证数据计算出一个信号,然后根据这个信号更新超参数,所以你实际上 是在验证数据上训练超参数,很快会对验证数据过拟合。请始终记住这一点
'''

#模型集成:集成是指将一系列不同模型的预测结果汇集到一起,从而得到更好的预测结果
'''
    将分类器集成有一个更聪明的做法,即加权平均,其权重在验证数据上学习得到。通常来说,更好的分类器被赋予更大的权重,而较差的分类器则被赋予较小的权重。
    为了找到一组好 的集成权重,你可以使用随机搜索或简单的优化算法(比如 Nelder-Mead 方法)
    想要保证集成方法有效,关键在于这组分类器的多样性(diversity)
    用机器学习的术语来说,如果所有模型的偏 差都在同一个方向上,那么集成也会保留同样的偏差。如果各个模型的偏差在不同方向上,那 么这些偏差会彼此抵消,集成结果会更加稳定、更加准确。
'''
#因此,集成的模型应该尽可能好,同时尽可能不同。这通常意味着使用非常不同的架构, 甚至使用不同类型的机器学习方法。
#有一种方法在实践中非常有效(但这一方法还没有推广到所有问题领域),就是将基于树的方法(比如随机森林或梯度提升树)和深度神经网络进行集成

#一种在实践中非常成功的基本集成方法是宽且深(wide and deep)的模型类型, 它结合了深度学习与浅层学习。这种模型联合训练一个深度神经网络和一个大型的线性模型。 对多种模型联合训练,是实现模型集成的另一种选择

hyperopt官方介绍:

http://hyperopt.github.io/hyperopt/ 

猜你喜欢

转载自blog.csdn.net/SunChao3555/article/details/88821005