keras_keras 拼接 - CSDN
keras 订阅
Keras是一个由Python编写的开源人工神经网络库,可以作为Tensorflow、Microsoft-CNTK和Theano的高阶应用程序接口,进行深度学习模型的设计、调试、评估、应用和可视化 [1]  。Keras在代码结构上由面向对象方法编写,完全模块化并具有可扩展性,其运行机制和说明文档有将用户体验和使用难度纳入考虑,并试图简化复杂算法的实现难度 [1]  。Keras支持现代人工智能领域的主流算法,包括前馈结构和递归结构的神经网络,也可以通过封装参与构建统计学习模型 [2]  。在硬件和开发环境方面,Keras支持多操作系统下的多GPU并行计算,可以根据后台设置转化为Tensorflow、Microsoft-CNTK等系统下的组件 [3]  。Keras的主要开发者是谷歌工程师François Chollet,此外其GitHub项目页面包含6名主要维护者和超过800名直接贡献者 [4]  。Keras在其正式版本公开后,除部分预编译模型外,按MIT许可证开放源代码 [1]  。 展开全文
Keras是一个由Python编写的开源人工神经网络库,可以作为Tensorflow、Microsoft-CNTK和Theano的高阶应用程序接口,进行深度学习模型的设计、调试、评估、应用和可视化 [1]  。Keras在代码结构上由面向对象方法编写,完全模块化并具有可扩展性,其运行机制和说明文档有将用户体验和使用难度纳入考虑,并试图简化复杂算法的实现难度 [1]  。Keras支持现代人工智能领域的主流算法,包括前馈结构和递归结构的神经网络,也可以通过封装参与构建统计学习模型 [2]  。在硬件和开发环境方面,Keras支持多操作系统下的多GPU并行计算,可以根据后台设置转化为Tensorflow、Microsoft-CNTK等系统下的组件 [3]  。Keras的主要开发者是谷歌工程师François Chollet,此外其GitHub项目页面包含6名主要维护者和超过800名直接贡献者 [4]  。Keras在其正式版本公开后,除部分预编译模型外,按MIT许可证开放源代码 [1]  。
信息
开发者
François Chollet 等 [4]
类    型
神经网络库,应用程序接口
平    台
Linux,macOS,Windows
许可协议
MIT License(不包含预编译模型)
初始版本
0.1.0/2015年6月13日 [5]
外文名
Keras
编程语言
Python
稳定版本
2.3.0/2019年09月17日 [5]
Keras历史与命名
Keras的前身是François Chollet为ONEIROS(Open-ended Neuro-Electronic Intelligent Robot Operating System)项目所的编写的代码,在2015年分离成为开源的人工神经网络工具。Keras的最初版本以Theano为后台,设计理念参考了Torch但完全由Python编写 [5]  。2015年11月的Keras测试版本0.3.0,Tensorflow被加入了后台选项。2016年4月,Keras在PIPy上发布了第一个稳定版本1.0.0 [5]  。2017年5月,Keras版本2.0.0发布 [5]  。同年6月,Keras版本2.0.5测试性地将Microsoft-CNTK加入后台选项 [5]  。自2017年起,Keras得到了Tensorflow团队的支持,其大部分组件被整合至Tensorflow的Python API中。在2018年Tensorflow 2.0.0公开后,Keras被正式确立为Tensorflow高阶API,即tf.keras [6]  。此外自2017年7月开始,Keras也得到了CNTK 2.0的后台支持 [7]  。在2019年9月17日Keras稳定版本2.3.0的更新文档中,Keras团队宣布了计划调整:在该版本之后,Keras将集中于Tensoflow后台的有关内容,多后台Keras的开发优先度被降低,且更新将仅包含补丁(bug fix),不会有新的功能性内容移植/加入 [5]  。Keras的命名来自古希腊语“κέρας (牛角)”或 “κραίνω(实现)”,意为将梦境化为现实的“牛角之门” [1]  。由荷马史诗《奥德赛》第19卷佩涅罗佩与奥德修斯的对话,无法挽留的梦幻拥有两座门,一座门由牛角制成,一座门由象牙制成,象牙之门内光彩夺目,却仅是无法实现的梦境;唯有走进牛角之门,才能由梦境看见真实 [8]  。
收起全文
  • 通过大量实战,掌握Tensorflow和Keras经常用到的各种建模方式,参数优化方法,自定义参数和模型的手段,以及对训练结果评估与分析的技巧。 2 从机器学习基础算法开始,然后进入到图像分类领域,使用MNIST...
  • keras 入门上

    千次阅读 多人点赞 2018-04-26 17:55:17
    1. 什么是 KerasKeras 是基于 Theano 或 TensorFlow 的一个深度学习...安装 Keras使用 Keras 前还需要安装 Numpy、Scipy 等 Python 包,建议直接安装 Python 科学计算环境 Anaconda,一步到位。然后直接通过 pip...

    1. 什么是 Keras

    Keras 是基于 Theano 或 TensorFlow 的一个深度学习框架,它的设计参考了 Torch,用 Python 语言编写,是一个高度模块化的神经网络库,支持 GPU 和 CPU。

    安装 Keras

    使用 Keras 前还需要安装 Numpy、Scipy 等 Python 包,建议直接安装 Python 科学计算环境 Anaconda,一步到位。然后直接通过 pip install keras 安装 Keras 就可以了,非常的方便。

    在 Theano 和 TensorFlow 间切换

    Keras 的底层库使用 Theano 或 TensorFlow,这两个库也称为 Keras 的后端。无论是 Theano 还是 TensorFlow,都是一个“符号式”的库,这也使得 Keras 的编程与传统的 Python 代码有所差别。笼统的说,符号主义的计算首先定义各种变量,然后建立一个“计算图”,计算图规定了各个变量之间的计算关系。建立好的计算图需要编译以确定其内部细节,但是此时的计算图只是一个“空壳子”,里面没有任何实际的数据,只有当你把需要运算的输入放进去后,才能在整个模型中形成数据流,从而形成输出值。Keras 的模型搭建形式就是这种方法,搭建好的 Keras 模型只是一个空壳子,只有实际生成可调用的函数后(K.function),输入数据,才会形成真正的数据流。

    使用计算图的语言,如 Theano,以难以调试而闻名,当 Keras 的 Debug 进入 Theano 这个层次时,往往也令人头痛。但大多数的深度学习框架使用的都是符号计算这一套方法,因为符号计算能够提供关键的计算优化、自动求导等功能。

    Keras 会根据环境自动设置后端为 Theano 或 TensorFlow,我们也可以通过修改 Keras 配置文件来设置。Keras 配置文件位于用户目录下的 .keras 目录中,名称为 keras.json

    {
        "epsilon": 1e-07,
        "backend": "tensorflow",
        "floatx": "float32",
        "image_data_format": "channels_last"
    }
    

    其中 backend 字段设定 Keras 的后端,这里选择的是 tensorflow,也可以设定为 theano

    data_format

    在如何表示一组彩色图片的问题上,Theano 和 TensorFlow 发生了分歧:Theano 会把 100 张 RGB 三通道的 16×32 彩色图表示为 (100,3,16,32),第 0 维是样本维,代表样本的数目,第 1 维是通道维,代表颜色通道数,后面两个就是高和宽了,这种数据组织方法,称为 channels_first,即通道维靠前;而 TensorFlow 的表达形式是 (100,16,32,3),即把通道维放在了最后,因而称为 channels_last

    Keras 默认的数据组织形式也在配置文件 keras.json 中规定,由 image_data_format 一项设定,也可在代码中通过 K.image_data_format() 函数返回,请在网络的训练和测试中保持维度顺序一致。对 2D 数据来说,channels_last 设定维度顺序为 (rows,cols,channels) 而 channels_first 设定维度顺序为 (channels, rows, cols)。对 3D 数据而言,channels_last 设定为 (conv_dim1, conv_dim2, conv_dim3, channels),而 channels_first 则是 (channels, conv_dim1, conv_dim2, conv_dim3)

    2. 一些基本概念

    下面介绍几个使用 Keras 过程中经常会遇到的词汇:

    张量

    张量(tensor)可以看作是向量、矩阵的自然推广,用来表示广泛的数据类型。0 阶张量即标量,也就是一个数;1 阶张量就是一个向量;2 阶张量就是一个矩阵;3 阶张量可以称为一个立方体,具有 3 个颜色通道的彩色图片就是一个这样的立方体;把立方体摞起来就是 4 阶张量了,不同去想像 4 阶张量是什么样子,它就是个数学上的概念。

    张量的阶数有时候也称为维度,或者轴,轴这个词翻译自英文 axis。譬如一个矩阵 [[1,2],[3,4]],是一个 2 阶张量,有两个维度或轴,沿着第 0 个轴(为了与 python 的计数方式一致,维度和轴从 0 算起)你看到的是 [1,2],[3,4] 两个向量,沿着第 1 个轴你看到的是 [1,3],[2,4] 两个向量。要理解“沿着某个轴”是什么意思,不妨试着运行一下下面的代码:

    import numpy as np
    a = np.array([[1,2],[3,4]])
    sum0 = np.sum(a, axis=0)
    sum1 = np.sum(a, axis=1)
    print sum0
    print sum1
    

    函数式模型

    在 Keras 0.x 中有两种模型,一种是 Sequential 模型,又称为序贯模型,也就是单输入单输出,一条路通到底,层与层之间只有相邻关系,没有跨层连接。这种模型编译速度快,操作上也比较简单。第二种模型称为 Graph,即图模型,这个模型支持多输入多输出,层与层之间想怎么连怎么连,但是编译速度慢。可以看到,Sequential 其实是 Graph 的一个特殊情况。

    在 Keras 1 和 Keras 2 中,图模型被移除,从而增加了“functional model API”这个东西,更加强调了 Sequential 模型是特殊的一种。一般的模型就称为 Model。

    由于 functional model API 在使用时利用的是“函数式编程”的风格,这里将其称为函数式模型。总而言之,只要这个东西接收一个或一些张量作为输入,然后输出的也是一个或一些张量,但不管它是什么,统统都叫做“模型”。

    batch

    深度学习的优化算法,说白了就是梯度下降。每次的参数更新有两种方式。

    第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这种方法每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习,这称为批梯度下降(Batch gradient descent)

    另一种,每看一个数据就算一下损失函数,然后求梯度更新参数,这个称为随机梯度下降(stochastic gradient descent)。这个方法速度比较快,但是收敛性能不太好,可能在最优点附近晃来晃去,达不到最优点。两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。

    为了克服两种方法的缺点,现在一般采用的是一种折中手段,小批的梯度下降(mini-batch gradient decent),这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,所以计算量也不是很大。基本上现在的梯度下降都是基于 mini-batch 的,所以 Keras 的模块中经常会出现 batch_size,就是指这个。

    Keras 中用的优化器 SGD 是 stochastic gradient descent 的缩写,但不代表是一个样本就更新一回,而是基于 mini-batch 的。

    epochs

    简单说,epochs 指的就是训练过程中数据将被“轮询”多少次,就这样。

    3. 快速上手 Keras

    Keras 的核心数据结构是“模型”,模型是一种组织网络层的方式。Keras 中主要的模型是 Sequential 模型,Sequential 是一系列网络层按顺序构成的栈。你也可以查看函数式模型来学习建立更复杂的模型。

    Sequential 模型如下:

    from keras.models import Sequential
    model = Sequential()
    

    将一些网络层通过 .add() 堆叠起来,就构成了一个模型:

    from keras.layers import Dense, Activation
    
    model.add(Dense(units=64, input_dim=100))
    model.add(Activation("relu"))
    model.add(Dense(units=10))
    model.add(Activation("softmax"))
    

    完成模型的搭建后,我们需要使用 .compile() 方法来编译模型:

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

    编译模型时必须指明损失函数和优化器,如果你需要的话,也可以自己定制损失函数。Keras 的一个核心理念就是简明易用同时,保证用户对 Keras 的绝对控制力度,用户可以根据自己的需要定制自己的模型、网络层,甚至修改源代码。例如,我们使用自定义的 SGD 优化器:

    from keras.optimizers import SGD
    model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9, nesterov=True))
    

    完成模型编译后,我们在训练数据上按 batch 进行一定次数的迭代来训练网络:

    model.fit(x_train, y_train, epochs=5, batch_size=32)
    

    当然,我们也可以手动将一个个 batch 的数据送入网络中训练,这时候需要使用:

    model.train_on_batch(x_batch, y_batch)
    

    随后,我们可以使用一行代码对我们的模型进行评估,看看模型的指标是否满足我们的要求:

    loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128)
    

    或者,我们可以使用我们的模型,对新的数据进行预测:

    classes = model.predict(x_test, batch_size=128)
    

    搭建一个问答系统、图像分类模型,或神经图灵机、word2vec 词嵌入器就是这么快。支撑深度学习的基本想法本就是简单的,现在让我们把它的实现也变的简单起来!

    为了更深入的了解 Keras,接下来我们介绍一下 Sequntial 模型和函数式模型的使用方法。

    4. Sequntial 模型

    构建序贯(Sequential)模型

    序贯模型是多个网络层的线性堆叠,也就是“一条路走到黑”。可以通过向 Sequential 模型传递一个 layer 的 list 来构造该模型:

    from keras.models import Sequential
    from keras.layers import Dense, Activation
    
    model = Sequential([
    Dense(32, units=784),
    Activation('relu'),
    Dense(10),
    Activation('softmax'),
    ])
    

    也可以通过 .add() 方法一个个的将 layer 加入模型中:

    model = Sequential()
    model.add(Dense(32, input_shape=(784,)))
    model.add(Activation('relu'))
    

    指定输入数据的 shape

    模型需要知道输入数据的 shape,因此,Sequential 模型的第一层需要接受一个关于输入数据 shape 的参数,后面的各个层则可以自动的推导出中间数据的 shape,因此不需要为每个层都指定这个参数。有几种方法来为第一层指定输入数据的 shape:

    • 传递一个 input_shape 的关键字参数给第一层,input_shape 是一个 tuple 类型的数据,其中也可以填入 None,如果填入 None 则表示此位置可能是任何正整数。数据的 batch 大小不应包含在其中。
    • 有些 2D 层,如 Dense,支持通过指定其输入维度 input_dim 来隐含的指定输入数据 shape。一些 3D 的时域层支持通过参数 input_dim 和 input_length 来指定输入shape。
    • 如果你需要为输入指定一个固定大小的 batch_size(常用于 stateful RNN 网络),可以传递 batch_size 参数到一个层中,例如你想指定输入张量的 batch 大小是 32,数据 shape 是 (6,8),则你需要传递 batch_size=32 和 input_shape=(6,8)
    model = Sequential()
    model.add(Dense(32, input_dim=784))
    
    model = Sequential()
    model.add(Dense(32, input_shape=784))
    

    编译

    在训练模型之前,我们需要通过 compile 来对学习过程进行配置。compile 接收三个参数:

    • 优化器 optimizer:该参数可指定为已预定义的优化器名,如 rmspropadagrad,或一个 Optimizer 类的对象。
    • 损失函数 loss:该参数为模型试图最小化的目标函数,它可为预定义的损失函数名,如categorical_crossentropymse,也可以为一个损失函数。
    • 指标列表 metrics:对分类问题,我们一般将该列表设置为 metrics=['accuracy']。指标可以是一个预定义指标的名字,也可以是一个用户定制的函数。指标函数应该返回单个张量,或一个完成 metric_name - > metric_value 映射的字典。
    # 对于一个多分类问题
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    
    # 对于一个二分类问题
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    
    # 对于一个均方误差回归问题
    model.compile(optimizer='rmsprop',
                  loss='mse')
    
    # 用户自定义指标列表
    import keras.backend as K
    
    def mean_pred(y_true, y_pred):
        return K.mean(y_pred)
    
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy', mean_pred])
    

    训练

    Keras以Numpy数组作为输入数据和标签的数据类型。训练模型一般使用 fit 函数。下面是一些例子:

    # 对于一个单输入模型的二分类问题
    model = Sequential()
    model.add(Dense(32, activation='relu', input_dim=100))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    
    # 创建虚假数据
    import numpy as np
    data = np.random.random((1000, 100))
    labels = np.random.randint(2, size=(1000, 1))
    
    # 训练模型, 以每批次32样本迭代数据
    model.fit(data, labels, epochs=10, batch_size=32)
    
    # 对于一个单输入模型的10分类问题
    model = Sequential()
    model.add(Dense(32, activation='relu', input_dim=100))
    model.add(Dense(10, activation='softmax'))
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    
    # 创建虚假数据
    import numpy as np
    data = np.random.random((1000, 100))
    labels = np.random.randint(10, size=(1000, 1))
    
    # 将标签转换为one-hot表示
    one_hot_labels = keras.utils.to_categorical(labels, num_classes=10)
    
    # 训练模型, 以每批次32样本迭代数据
    model.fit(data, one_hot_labels, epochs=10, batch_size=32)
    

    5. Sequntial 模型示例

    基于多层感知器的 softmax 多分类:

    from keras.models import Sequential
    from keras.layers import Dense, Dropout, Activation
    from keras.optimizers import SGD
    
    # 创建虚假数据
    import numpy as np
    x_train = np.random.random((1000, 20))
    y_train = keras.utils.to_categorical(np.random.randint(10, size=(1000, 1)), num_classes=10)
    x_test = np.random.random((100, 20))
    y_test = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)
    
    model = Sequential()
    # Dense(64) 是一个含有64个隐单元的全连接层
    # 在第一层,你必须指定预期的输入数据shape:
    # 这里是一个20维的向量.
    model.add(Dense(64, activation='relu', input_dim=20))
    model.add(Dropout(0.5))
    model.add(Dense(64, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(10, activation='softmax'))
    
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy',
                  optimizer=sgd,
                  metrics=['accuracy'])
    
    model.fit(x_train, y_train,
              epochs=20,
              batch_size=128)
    score = model.evaluate(x_test, y_test, batch_size=128)
    

    MLP的二分类:

    import numpy as np
    from keras.models import Sequential
    from keras.layers import Dense, Dropout
    
    # 创建虚假数据
    x_train = np.random.random((1000, 20))
    y_train = np.random.randint(2, size=(1000, 1))
    x_test = np.random.random((100, 20))
    y_test = np.random.randint(2, size=(100, 1))
    
    model = Sequential()
    model.add(Dense(64, input_dim=20, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(64, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    model.fit(x_train, y_train,
              epochs=20,
              batch_size=128)
    score = model.evaluate(x_test, y_test, batch_size=128)
    

    类似VGG的卷积神经网络:

    import numpy as np
    import keras
    from keras.models import Sequential
    from keras.layers import Dense, Dropout, Flatten
    from keras.layers import Conv2D, MaxPooling2D
    from keras.optimizers import SGD
    
    # 创建虚假数据
    x_train = np.random.random((100, 100, 100, 3))
    y_train = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)
    x_test = np.random.random((20, 100, 100, 3))
    y_test = keras.utils.to_categorical(np.random.randint(10, size=(20, 1)), num_classes=10)
    
    model = Sequential()
    # 输入: 100x100的3通道图像 -> 张量 (100, 100, 3).
    # 在每块3x3的区域应用32个卷积过滤器.
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(10, activation='softmax'))
    
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=sgd)
    
    model.fit(x_train, y_train, batch_size=32, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=32)
    

    使用LSTM的序列分类

    from keras.models import Sequential
    from keras.layers import Dense, Dropout
    from keras.layers import Embedding
    from keras.layers import LSTM
    
    model = Sequential()
    model.add(Embedding(max_features, output_dim=256))
    model.add(LSTM(128))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    
    model.fit(x_train, y_train, batch_size=16, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=16)
    

    使用1D卷积的序列分类

    from keras.models import Sequential
    from keras.layers import Dense, Dropout
    from keras.layers import Embedding
    from keras.layers import Conv1D, GlobalAveragePooling1D, MaxPooling1D
    
    model = Sequential()
    model.add(Conv1D(64, 3, activation='relu', input_shape=(seq_length, 100)))
    model.add(Conv1D(64, 3, activation='relu'))
    model.add(MaxPooling1D(3))
    model.add(Conv1D(128, 3, activation='relu'))
    model.add(Conv1D(128, 3, activation='relu'))
    model.add(GlobalAveragePooling1D())
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    
    model.fit(x_train, y_train, batch_size=16, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=16)
    

    用于序列分类的栈式LSTM

    在该模型中,我们将三个 LSTM 堆叠在一起,是该模型能够学习更高层次的时域特征表示。开始的两层 LSTM 返回其全部输出序列,而第三层 LSTM 只返回其输出序列的最后一步结果,从而其时域维度降低(即将输入序列转换为单个向量):

    1

    from keras.models import Sequential
    from keras.layers import LSTM, Dense
    import numpy as np
    
    data_dim = 16
    timesteps = 8
    num_classes = 10
    
    # 预期输入数据shape: (batch_size, timesteps, data_dim)
    model = Sequential()
    model.add(LSTM(32, return_sequences=True,
                   input_shape=(timesteps, data_dim)))  # 返回一个32维向量的序列
    model.add(LSTM(32, return_sequences=True))  # 返回一个32维向量的序列
    model.add(LSTM(32))  # 返回一个独立的32维的向量
    model.add(Dense(10, activation='softmax'))
    
    model.compile(loss='categorical_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    
    # 创建虚假的训练数据
    x_train = np.random.random((1000, timesteps, data_dim))
    y_train = np.random.random((1000, num_classes))
    
    # 创建虚假的验证数据
    x_val = np.random.random((100, timesteps, data_dim))
    y_val = np.random.random((100, num_classes))
    
    model.fit(x_train, y_train,
              batch_size=64, epochs=5,
              validation_data=(x_val, y_val))
    

    采用stateful LSTM的相同模型

    stateful LSTM 的特点是,在处理过一个 batch 的训练数据后,其内部状态(记忆)会被作为下一个 batch 的训练数据的初始状态。状态 LSTM 使得我们可以在合理的计算复杂度内处理较长序列:

    from keras.models import Sequential
    from keras.layers import LSTM, Dense
    import numpy as np
    
    data_dim = 16
    timesteps = 8
    num_classes = 10
    batch_size = 32
    
    # 预期输入批shape: (batch_size, timesteps, data_dim)
    # 注意我们需要提供完整的 batch_input_shape 因为网络是有状态的.
    # 第k批中的样本i跟踪第k-1批中的样本i.
    model = Sequential()
    model.add(LSTM(32, return_sequences=True, stateful=True,
                   batch_input_shape=(batch_size, timesteps, data_dim)))
    model.add(LSTM(32, return_sequences=True, stateful=True))
    model.add(LSTM(32, stateful=True))
    model.add(Dense(10, activation='softmax'))
    
    model.compile(loss='categorical_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    
    # 创建虚假的训练数据
    x_train = np.random.random((batch_size * 10, timesteps, data_dim))
    y_train = np.random.random((batch_size * 10, num_classes))
    
    # 创建虚假的验证数据
    x_val = np.random.random((batch_size * 3, timesteps, data_dim))
    y_val = np.random.random((batch_size * 3, num_classes))
    
    model.fit(x_train, y_train,
              batch_size=batch_size, epochs=5, shuffle=False,
              validation_data=(x_val, y_val))
    

    6. Functional 模型

    在 Keras 2 里我们将 Functional 译为“函数式”,对函数式编程有所了解的同学应能够快速 get 到该类模型想要表达的含义。函数式模型称作 Functional,但它的类名是 Model,因此我们有时候也用 Model 来代表函数式模型。

    Keras 函数式模型接口是用户定义多输出模型、非循环有向模型或具有共享层的模型等复杂模型的途径。一句话,只要你的模型不是类似 VGG 一样一条路走到黑的模型,或者你的模型需要多于一个的输出,那么你总应该选择函数式模型。函数式模型是最广泛的一类模型,序贯模型(Sequential)只是它的一种特殊情况。

    让我们从简单一点的模型开始:

    第一个模型:全连接网络

    Sequential 模型当然是实现全连接网络的最好方式,但我们从简单的全连接网络开始,有助于我们学习这部分的内容。在开始前,有几个概念需要澄清:

    • 层对象接受张量为参数,返回一个张量。
    • 输入是张量,输出也是张量的一个框架就是一个模型,通过 Model 定义。
    • 这样的模型可以被像 Keras 的 Sequential 一样被训练。
    from keras.layers import Input, Dense
    from keras.models import Model
    
    # 这会返回一个张量
    inputs = Input(shape=(784,))
    
    # 层对象接受张量为参数,返回一个张量
    x = Dense(64, activation='relu')(inputs)
    x = Dense(64, activation='relu')(x)
    predictions = Dense(10, activation='softmax')(x)
    
    # 这会创建一个模型,包含输入层和三个Dense层
    model = Model(inputs=inputs, outputs=predictions)
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    model.fit(data, labels)  # 开始训练
    

    所有的模型都是可调用的,就像层一样

    利用函数式模型的接口,我们可以很容易的重用已经训练好的模型:你可以把模型当作一个层一样,通过提供一个 tensor 来调用它。注意当你调用一个模型时,你不仅仅重用了它的结构,也重用了它的权重。

    x = Input(shape=(784,))
    # 这会返回我们之前定义的 10-way softmax.
    y = model(x)
    

    这种方式可以允许你快速的创建能处理序列信号的模型,你可以很快将一个图像分类的模型变为一个对视频分类的模型,只需要一行代码:

    from keras.layers import TimeDistributed
    
    # 20个时间步序列的输入张量,每个包含一个784维的向量
    input_sequences = Input(shape=(20, 784))
    
    # 这会应用我们之前定义的模型到输入序列的每一个时间步
    # 之前模型的输出是一个 10-way softmax,
    # 所以下面这个层的输出会是一个含有20个10维向量的序列
    processed_sequences = TimeDistributed(model)(input_sequences)
    

    多输入和多输出模型

    使用函数式模型的一个典型场景是搭建多输入、多输出的模型。

    考虑这样一个模型。我们希望预测 Twitter 上一条新闻会被转发和点赞多少次。模型的主要输入是新闻本身,也就是一个词语的序列。但我们还可以拥有额外的输入,如新闻发布的日期等。这个模型的损失函数将由两部分组成,辅助的损失函数评估仅仅基于新闻本身做出预测的情况,主损失函数评估基于新闻和额外信息的预测的情况,即使来自主损失函数的梯度发生弥散,来自辅助损失函数的信息也能够训练 Embeddding 和 LSTM 层。在模型中早点使用主要的损失函数是对于深度网络的一个良好的正则方法。总而言之,该模型框图如下:

    2

    让我们用函数式模型来实现这个框图。

    主要的输入接收新闻本身,即一个整数的序列(每个整数编码了一个词)。这些整数位于 1 到 10,000 之间(即我们的字典有 10,000 个词)。这个序列有 100 个单词。

    from keras.layers import Input, Embedding, LSTM, Dense
    from keras.models import Model
    
    # 标题输入: 接收一个100个整数的序列,每个整数处于1到10000之间.
    # 注意我们可以通过"name"参数命名任何层.
    main_input = Input(shape=(100,), dtype='int32', name='main_input')
    
    # 这个embedding层会编码输入序列到一个512维的向量序列
    x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)
    
    # 一个LSTM会转化向量序列到一个单独的保存整个序列信息的向量
    lstm_out = LSTM(32)(x)
    

    然后,我们插入一个额外的损失,使得即使在主损失很高的情况下,LSTM 和 Embedding 层也可以平滑的训练。

    auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)
    

    再然后,我们将 LSTM 与额外的输入数据串联起来组成输入,送入模型中:

    auxiliary_input = Input(shape=(5,), name='aux_input')
    x = keras.layers.concatenate([lstm_out, auxiliary_input])
    
    # 我们堆叠一个深度的全连接网络
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    
    # 最后我们加上一个主要的logistic回归层
    main_output = Dense(1, activation='sigmoid', name='main_output')(x)
    

    最后,我们定义整个 2 输入,2 输出的模型:

    model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])
    

    模型定义完毕,下一步编译模型。我们给额外的损失赋 0.2 的权重。我们可以通过关键字参数 loss_weights 或 loss 来为不同的输出设置不同的损失函数或权值。这两个参数均可为 Python 的列表或字典。这里我们给 loss 传递单个损失函数,这个损失函数会被应用于所有输出上。

    model.compile(optimizer='rmsprop', loss='binary_crossentropy',
                  loss_weights=[1., 0.2])
    

    编译完成后,我们通过传递训练数据和目标值训练该模型:

    model.fit([headline_data, additional_data], [labels, labels],
              epochs=50, batch_size=32)
    

    因为我们输入和输出是被命名过的(在定义时传递了“name”参数),我们也可以用下面的方式编译和训练模型:

    model.compile(optimizer='rmsprop',
                  loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
                  loss_weights={'main_output': 1., 'aux_output': 0.2})
    
    model.fit({'main_input': headline_data, 'aux_input': additional_data},
              {'main_output': labels, 'aux_output': labels},
              epochs=50, batch_size=32)
    

    共享层

    另一个使用函数式模型的场合是使用共享层的时候。

    考虑微博数据,我们希望建立模型来判别两条微博是否是来自同一个用户,这个需求同样可以用来判断一个用户的两条微博的相似性。

    一种实现方式是,我们建立一个模型,它分别将两条微博的数据映射到两个特征向量上,然后将特征向量串联并加一个 logistic 回归层,输出它们来自同一个用户的概率。这种模型的训练数据是一对对的微博。

    因为这个问题是对称的,所以处理第一条微博的模型当然也能重用于处理第二条微博。所以这里我们使用一个共享的 LSTM 层来进行映射。

    首先,我们将微博的数据转为 (140,256) 的矩阵,即每条微博有 140 个字符,每个单词的特征由一个 256 维的词向量表示,向量的每个元素为 1 表示某个字符出现,为 0 表示不出现,这是一个 one-hot 编码。

    之所以是 (140,256) 是因为一条微博最多有 140 个字符,而扩展的 ASCII 码表编码了常见的 256 个字符。

    注:原文中此处为 Tweet,所以对外国人而言这是合理的。如果考虑中文字符,那一个单词的词向量就不止 256 了。

    import keras
    from keras.layers import Input, LSTM, Dense
    from keras.models import Model
    
    tweet_a = Input(shape=(140, 256))
    tweet_b = Input(shape=(140, 256))
    

    若要对不同的输入共享同一层,就初始化该层一次,然后多次调用它:

    # 该层会输入一个矩阵然后返回一个大小为64的向量
    shared_lstm = LSTM(64)
    
    # 当我们重用相同层的实例很多次,并且层的权值也是重用的
    # (这实际上完全是相同的层)
    encoded_a = shared_lstm(tweet_a)
    encoded_b = shared_lstm(tweet_b)
    
    # 我们可以连接这两个向量:
    merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1)
    
    # 然后在最上面添加一个logistic回归层
    predictions = Dense(1, activation='sigmoid')(merged_vector)
    
    # 我们定义了一个可训练的模型,将tweet的输入连接起来,输出预测
    model = Model(inputs=[tweet_a, tweet_b], outputs=predictions)
    
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    model.fit([data_a, data_b], labels, epochs=10)
    

    层“节点”的概念

    无论何时,当你在某个输入上调用层时,你就创建了一个新的张量(即该层的输出),同时你也在为这个层增加一个“计算节点”。这个节点将输入张量映射为输出张量。当你多次调用该层时,这个层就有了多个节点,其下标分别为 0,1,2…

    在上一版本的 Keras 中,你可以通过 layer.get_output() 方法来获得层的输出张量,或者通过 layer.output_shape 获得其输出张量的 shape。这个版本的 Keras 你仍然可以这么做(除了 layer.get_output() 被 output 替换)。但如果一个层与多个输入相连,会出现什么情况呢?

    如果层只与一个输入相连,那没有任何困惑的地方。.output 将会返回该层唯一的输出:

    a = Input(shape=(140, 256))
    
    lstm = LSTM(32)
    encoded_a = lstm(a)
    
    assert lstm.output == encoded_a
    

    但当层与多个输入相连时,会出现问题:

    a = Input(shape=(140, 256))
    b = Input(shape=(140, 256))
    
    lstm = LSTM(32)
    encoded_a = lstm(a)
    encoded_b = lstm(b)
    
    lstm.output
    

    上面这段代码会报错:

    >> AssertionError: Layer lstm_1 has multiple inbound nodes,
    hence the notion of "layer output" is ill-defined.
    Use `get_output_at(node_index)` instead.
    

    通过下面这种调用方式即可解决:

    assert lstm.get_output_at(0) == encoded_a
    assert lstm.get_output_at(1) == encoded_b
    

    对于 input_shape 和 output_shape 也是一样,如果一个层只有一个节点,或所有的节点都有相同的输入或输出 shape,那么 input_shape 和 output_shape 都是没有歧义的,并也只返回一个值。但是,例如你把一个相同的 Conv2D 应用于一个大小为 (3,32,32) 的数据,然后又将其应用于一个 (3,64,64) 的数据,那么此时该层就具有了多个输入和输出的 shape,你就需要显式的指定节点的下标,来表明你想取的是哪个了。

    a = Input(shape=(3, 32, 32))
    b = Input(shape=(3, 64, 64))
    
    conv = Conv2D(16, (3, 3), padding='same')
    conved_a = conv(a)
    assert conv.input_shape == (None, 3, 32, 32)
    
    conved_b = conv(b)
    assert conv.get_input_shape_at(0) == (None, 3, 32, 32)
    assert conv.get_input_shape_at(1) == (None, 3, 64, 64)s
    

    7. Functional 模型示例

    inception模型

    inception的详细结构参见Google的这篇论文:Going Deeper with Convolutions

    from keras.layers import Conv2D, MaxPooling2D, Input
    
    input_img = Input(shape=(3, 256, 256))
    
    tower_1 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
    tower_1 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_1)
    
    tower_2 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
    tower_2 = Conv2D(64, (5, 5), padding='same', activation='relu')(tower_2)
    
    tower_3 = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(input_img)
    tower_3 = Conv2D(64, (1, 1), padding='same', activation='relu')(tower_3)
    
    output = keras.layers.concatenate([tower_1, tower_2, tower_3], axis=1)
    

    卷积层的残差连接

    残差网络(Residual Network)的详细信息请参考这篇文章:Deep Residual Learning for Image Recognition

    from keras.layers import Conv2D, Input
    
    # 输入张量是一个3通道的256x256图像
    x = Input(shape=(3, 256, 256))
    # 3x3卷积,3输出通道 (与输入通道一样)
    y = Conv2D(3, (3, 3), padding='same')(x)
    # 返回 x + y.
    z = keras.layers.add([x, y])
    

    共享视觉模型

    该模型在两个输入上重用了图像处理的模型,用来判别两个 MNIST 数字是否是相同的数字

    from keras.layers import Conv2D, MaxPooling2D, Input, Dense, Flatten
    from keras.models import Model
    
    # 首先定义视觉模型
    digit_input = Input(shape=(1, 27, 27))
    x = Conv2D(64, (3, 3))(digit_input)
    x = Conv2D(64, (3, 3))(x)
    x = MaxPooling2D((2, 2))(x)
    out = Flatten()(x)
    
    vision_model = Model(digit_input, out)
    
    # 然后定义tell-digits-apart模型
    digit_a = Input(shape=(1, 27, 27))
    digit_b = Input(shape=(1, 27, 27))
    
    # 共享视觉模型
    out_a = vision_model(digit_a)
    out_b = vision_model(digit_b)
    
    concatenated = keras.layers.concatenate([out_a, out_b])
    out = Dense(1, activation='sigmoid')(concatenated)
    
    classification_model = Model([digit_a, digit_b], out)
    

    视觉问答模型

    在针对一幅图片使用自然语言进行提问时,该模型能够提供关于该图片的一个单词的答案。

    这个模型将自然语言的问题和图片分别映射为特征向量,将二者合并后训练一个 logistic 回归层,从一系列可能的回答中挑选一个。

    from keras.layers import Conv2D, MaxPooling2D, Flatten
    from keras.layers import Input, LSTM, Embedding, Dense
    from keras.models import Model, Sequential
    
    # 首先我们使用Sequential模型定义一个视觉模型
    # 该模型会将一个图像编码成一个向量
    vision_model = Sequential()
    vision_model.add(Conv2D(64, (3, 3), activation='relu', padding='same', input_shape=(3, 224, 224)))
    vision_model.add(Conv2D(64, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(128, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Flatten())
    
    # 现在我们获得视觉模型的输出张量
    image_input = Input(shape=(3, 224, 224))
    encoded_image = vision_model(image_input)
    
    # 接下来,我们定义一个语言模型把问题编码成一个向量
    # 每个问题最多包含100个词,并且每个词用从1到9999的整数表示
    question_input = Input(shape=(100,), dtype='int32')
    embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
    encoded_question = LSTM(256)(embedded_question)
    
    # 我们连接问题向量和图像向量
    merged = keras.layers.concatenate([encoded_question, encoded_image])
    
    # 然后我们在1000个可能的回答词语上训练一个logistic回归
    output = Dense(1000, activation='softmax')(merged)
    
    # 这是我们最终的模型:
    vqa_model = Model(inputs=[image_input, question_input], outputs=output)
    
    # 下一阶段在真实的数据上训练这个模型
    

    视频问答模型

    在做完图片问答模型后,我们可以快速将其转为视频问答的模型。在适当的训练下,你可以为模型提供一个短视频(如 100 帧)然后向模型提问一个关于该视频的问题,如“what sport is the boy playing?”->“football”

    from keras.layers import TimeDistributed
    
    video_input = Input(shape=(100, 3, 224, 224))
    # 通过之前已经训练好的 vision_model (权重重用)为视频编码
    encoded_frame_sequence = TimeDistributed(vision_model)(video_input)  # 输出是一个向量的序列
    encoded_video = LSTM(256)(encoded_frame_sequence)  # 输出是一个向量
    
    # 这是一个模型层面的对问题的编码器表示,使用与之前相同的权值
    question_encoder = Model(inputs=question_input, outputs=encoded_question)
    
    # 使用编码器对问题进行编码
    video_question_input = Input(shape=(100,), dtype='int32')
    encoded_video_question = question_encoder(video_question_input)
    
    # 这是我们的视频问题回答模型
    merged = keras.layers.concatenate([encoded_video, encoded_video_question])
    output = Dense(1000, activation='softmax')(merged)
    video_qa_model = Model(inputs=[video_input, video_question_input], outputs=output)
    

    8. 常见问题

    保存 Keras 模型

    一般我们不推荐使用 pickle 或 cPickle 来保存 Keras 模型。Keras 自己就提供了 model.save(filepath) 函数将模型和权重保存在一个 HDF5 文件中,该文件将包含:

    • 模型的结构,以便重构该模型
    • 模型的权重
    • 训练配置(损失函数,优化器等)
    • 优化器的状态,以便于从上次训练中断的地方开始

    使用 keras.models.load_model(filepath) 来重新实例化你的模型,如果文件中存储了训练配置的话,该函数还会同时完成模型的编译。

    from keras.models import load_model
    
    model.save('my_model.h5')  # 创建一个HDF5文件'my_model.h5'
    del model  # 删除已经存在的model
    
    # 返回一个编译好的模型,与之前的完全相同
    model = load_model('my_model.h5')
    

    注意,在使用前需要确保你已安装了 HDF5 和其 Python 库 h5py

    如果你只是希望保存模型的结构,而不包含其权重或配置信息,可以使用:

    # 保存为JSON
    json_string = model.to_json()
    
    # 保存为YAML
    yaml_string = model.to_yaml()
    

    这项操作将把模型序列化为 json 或 yaml 文件,这些文件对人而言也是友好的,如果需要的话你甚至可以手动打开这些文件并进行编辑。当然,你也可以从保存好的 json 文件或 yaml 文件中载入模型:

    # 通过JSON重建模型:
    from keras.models import model_from_json
    model = model_from_json(json_string)
    
    # 通过YAML重建模型
    model = model_from_yaml(yaml_string)
    

    如果需要保存模型的权重,可通过下面的代码利用 HDF5 进行保存。

    model.save_weights('my_model_weights.h5')
    

    如果你需要在代码中初始化一个完全相同的模型,请使用:

    model.load_weights('my_model_weights.h5')
    

    如果你需要加载权重到不同的网络结构(有些层一样)中,例如 fine-tune 或 transfer-learning,你可以通过层名字来加载模型:

    model.load_weights('my_model_weights.h5', by_name=True)
    
    """
    假如原模型为:
        model = Sequential()
        model.add(Dense(2, input_dim=3, name="dense_1"))
        model.add(Dense(3, name="dense_2"))
        ...
        model.save_weights(fname)
    """
    # 新模型
    model = Sequential()
    model.add(Dense(2, input_dim=3, name="dense_1"))  # will be loaded
    model.add(Dense(10, name="new_dense"))  # will not be loaded
    
    # 从第一个模型加载权值; 只会影响第一层 dense_1.
    model.load_weights(fname, by_name=True)
    

    获取中间层的输出

    一种简单的方法是创建一个新的 Model,使得它的输出是你想要的那个输出:

    from keras.models import Model
    
    model = ...  # 创建原模型
    
    layer_name = 'my_layer'
    intermediate_layer_model = Model(input=model.input,
                                     output=model.get_layer(layer_name).output)
    intermediate_output = intermediate_layer_model.predict(data)
    

    此外,我们也可以建立一个 Keras 的函数来达到这一目的:

    from keras import backend as K
    
    # Sequential模型
    get_3rd_layer_output = K.function([model.layers[0].input],
                                      [model.layers[3].output])
    layer_output = get_3rd_layer_output([X])[0]
    

    在每个epoch后记录训练/测试的loss和正确率

    model.fit在运行结束后返回一个History对象,其中含有的history属性包含了训练过程中损失函数的值以及其他度量指标。

    hist = model.fit(X, y, validation_split=0.2)
    print(hist.history)
    展开全文
  • 深度学习框架-Keras基础入门系列

    千人学习 2018-10-22 21:38:11
    Keras是一种高度模块化,使用简单上手快,合适深度学习初学者使用的深度学习框架。Keras由纯Python编写而成并以Tensorflow、Theano以及CNTK为后端。Keras为支持实验而生,能够把你的idea迅速转换为结果。 对于深度...
  • 深度学习:Keras入门(一)之基础篇

    万次阅读 多人点赞 2017-07-07 16:33:21
    1.关于Keras  1)简介  Keras是由纯python编写的基于theano/tensorflow的深度学习框架。  Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有

    http://www.cnblogs.com/lc1217/p/7132364.html

    1.关于Keras

            1)简介          

             Keras是由纯python编写的基于theano/tensorflow的深度学习框架。

             Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需求,可以优先选择Keras:

                    a)简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)

                    b)支持CNN和RNN,或二者的结合

                    c)无缝CPU和GPU切换

             2)设计原则

                   a)用户友好:Keras是为人类而不是天顶星人设计的API。用户的使用体验始终是我们考虑的首要和中心内容。Keras遵循减少认知困难的最佳实践:Keras提供一致而简洁的API, 能够极大减少一般应用下用户的工作量,同时,Keras提供清晰和具有实践意义的bug反馈。

                   b)模块性:模型可理解为一个层的序列或数据的运算图,完全可配置的模块可以用最少的代价自由组合在一起。具体而言,网络层、损失函数、优化器、初始化策略、激活函数、正则化方法都是独立的模块,你可以使用它们来构建自己的模型。

                  c)易扩展性:添加新模块超级容易,只需要仿照现有的模块编写新的类或函数即可。创建新模块的便利性使得Keras更适合于先进的研究工作。

                  d)与Python协作:Keras没有单独的模型配置文件类型(作为对比,caffe有),模型由python代码描述,使其更紧凑和更易debug,并提供了扩展的便利性。

     

    2.Keras的模块结构

       

     

    3.使用Keras搭建一个神经网络

     

    4.主要概念

       1)符号计算

            Keras的底层库使用Theano或TensorFlow,这两个库也称为Keras的后端。无论是Theano还是TensorFlow,都是一个“符号式”的库。符号计算首先定义各种变量,然后建立一个“计算图”,计算图规定了各个变量之间的计算关系。

           符号计算也叫数据流图,其过程如下(gif图不好打开,所以用了静态图,数据是按图中黑色带箭头的线流动的):

            

         2)张量

              张量(tensor),可以看作是向量、矩阵的自然推广,用来表示广泛的数据类型。张量的阶数也叫维度。

              0阶张量,即标量,是一个数。

              1阶张量,即向量,一组有序排列的数

              2阶张量,即矩阵,一组向量有序的排列起来

              3阶张量,即立方体,一组矩阵上下排列起来

              4阶张量......
              依次类推

              重点:关于维度的理解

              假如有一个10长度的列表,那么我们横向看有10个数字,也可以叫做10维度,纵向看只能看到1个数字,那么就叫1维度。注意这个区别有助于理解Keras或者神经网络中计算时出现的维度问题。

        3)数据格式(data_format)

            目前主要有两种方式来表示张量:
            a) th模式或channels_first模式,Theano和caffe使用此模式。
            b)tf模式或channels_last模式,TensorFlow使用此模式。

     
            下面举例说明两种模式的区别:
             对于100张RGB3通道的16×32(高为16宽为32)彩色图,
             th表示方式:(100,3,16,32)
             tf表示方式:(100,16,32,3)
             唯一的区别就是表示通道个数3的位置不一样。

         4)模型

              Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。
              a)序贯模型(Sequential):单输入单输出,一条路通到底,层与层之间只有相邻关系,没有跨层连接。这种模型编译速度快,操作也比较简单
              b)函数式模型(Model):多输入多输出,层与层之间任意连接。这种模型编译速度慢。

     

    5.第一个示例

              这里也采用介绍神经网络时常用的一个例子:手写数字的识别。

              在写代码之前,基于这个例子介绍一些概念,方便大家理解。

              PS:可能是版本差异的问题,官网中的参数和示例中的参数是不一样的,官网中给出的参数少,并且有些参数支持,有些不支持。所以此例子去掉了不支持的参数,并且只介绍本例中用到的参数。

              1)Dense(500,input_shape=(784,))

                   a)Dense层属于网络层-->常用层中的一个层

                   b) 500表示输出的维度,完整的输出表示:(*,500):即输出任意个500维的数据流。但是在参数中只写维度就可以了,比较具体输出多少个是有输入确定的。换个说法,Dense的输出其实是个N×500的矩阵。

                  c)input_shape(784,) 表示输入维度是784(28×28,后面具体介绍为什么),完整的输入表示:(*,784):即输入N个784维度的数据

             2)Activation('tanh')

                  a)Activation:激活层

                  b)'tanh' :激活函数

             3)Dropout(0.5)

                  在训练过程中每次更新参数时随机断开一定百分比(rate)的输入神经元,防止过拟合。

             4)数据集

                 数据集包括60000张28×28的训练集和10000张28×28的测试集及其对应的目标数字。如果完全按照上述数据格式表述,以tensorflow作为后端应该是(60000,28,28,3),因为示例中采用了mnist.load_data()获取数据集,所以已经判断使用了tensorflow作为后端,因此数据集就变成了(60000,28,28),那么input_shape(784,)应该是input_shape(28,28,)才对,但是在这个示例中这么写是不对的,需要转换成(60000,784),才可以。为什么需要转换呢?

               

                  如上图,训练集(60000,28,28)作为输入,就相当于一个立方体,而输入层从当前角度看就是一个平面,立方体的数据流怎么进入平面的输入层进行计算呢?所以需要进行黄色箭头所示的变换,然后才进入输入层进行后续计算。至于从28*28变换成784之后输入层如何处理,就不需要我们关心了。(喜欢钻研的同学可以去研究下源代码)。

             并且,Keras中输入多为(nb_samples, input_dim)的形式:即(样本数量,输入维度)。

            5)示例代码

    复制代码
    from keras.models import Sequential  
    from keras.layers.core import Dense, Dropout, Activation  
    from keras.optimizers import SGD  
    from keras.datasets import mnist  
    import numpy 
    '''
        第一步:选择模型
    '''
    model = Sequential()
    '''
       第二步:构建网络层
    '''
    model.add(Dense(500,input_shape=(784,))) # 输入层,28*28=784  
    model.add(Activation('tanh')) # 激活函数是tanh  
    model.add(Dropout(0.5)) # 采用50%的dropout
    
    model.add(Dense(500)) # 隐藏层节点500个  
    model.add(Activation('tanh'))  
    model.add(Dropout(0.5))
    
    model.add(Dense(10)) # 输出结果是10个类别,所以维度是10  
    model.add(Activation('softmax')) # 最后一层用softmax作为激活函数
    
    '''
       第三步:编译
    '''
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) # 优化函数,设定学习率(lr)等参数  
    model.compile(loss='categorical_crossentropy', optimizer=sgd, class_mode='categorical') # 使用交叉熵作为loss函数
    
    '''
       第四步:训练
       .fit的一些参数
       batch_size:对总的样本数进行分组,每组包含的样本数量
       epochs :训练次数
       shuffle:是否把数据随机打乱之后再进行训练
       validation_split:拿出百分之多少用来做交叉验证
       verbose:屏显模式 0:不输出  1:输出进度  2:输出每次的训练结果
    '''
    (X_train, y_train), (X_test, y_test) = mnist.load_data() # 使用Keras自带的mnist工具读取数据(第一次需要联网)
    # 由于mist的输入数据维度是(num, 28, 28),这里需要把后面的维度直接拼起来变成784维  
    X_train = X_train.reshape(X_train.shape[0], X_train.shape[1] * X_train.shape[2]) 
    X_test = X_test.reshape(X_test.shape[0], X_test.shape[1] * X_test.shape[2])  
    Y_train = (numpy.arange(10) == y_train[:, None]).astype(int) 
    Y_test = (numpy.arange(10) == y_test[:, None]).astype(int)
    
    model.fit(X_train,Y_train,batch_size=200,epochs=50,shuffle=True,verbose=0,validation_split=0.3)
    model.evaluate(X_test, Y_test, batch_size=200, verbose=0)
    
    '''
        第五步:输出
    '''
    print("test set")
    scores = model.evaluate(X_test,Y_test,batch_size=200,verbose=0)
    print("")
    print("The test loss is %f" % scores)
    result = model.predict(X_test,batch_size=200,verbose=0)
    
    result_max = numpy.argmax(result, axis = 1)
    test_max = numpy.argmax(Y_test, axis = 1)
    
    result_bool = numpy.equal(result_max, test_max)
    true_num = numpy.sum(result_bool)
    print("")
    print("The accuracy of the model is %f" % (true_num/len(result_bool)))
    复制代码

     

    展开全文
  • 人工智能框架实战精讲:Keras项目

    千人学习 2020-06-24 14:27:13
    Keras项目实战课程从实战的角度出发,基于真实数据集与实际业务需求,从零开始讲解如何进行数据处理,模型训练与调优,最后进行测试与结果展示分析。全程实战操作,以最接地气的方式详解每一步流程与解决方案。课程...
  • Keras学习笔记(一)

    万次阅读 多人点赞 2017-05-23 11:45:41
    1.Dense 全连接层(对上一层的神经元进行全部连接,实现特征的非线性组合) keras.layers.core.Dense(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', ...

    1.Dense

    全连接层(对上一层的神经元进行全部连接,实现特征的非线性组合

    keras.layers.core.Dense(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)

    Dense就是常用的全连接层,所实现的运算是output = activation(dot(input, kernel)+bias)。其中activation是逐元素计算的激活函数,kernel````是本层的权值矩阵,bias为偏置向量,只有当use_bias=True```才会添加。

    如果本层的输入数据的维度大于2,则会先被压为与kernel相匹配的大小。

    • units:大于0的整数,代表该层的输出维度。

    • activation:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)

    • use_bias: 布尔值,是否使用偏置项

    # as first layer in a sequential model:

    model = Sequential()

    model.add(Dense(32, input_shape=(16,)))  #input_shape=(16,)等价于input_dim=16

    # now the model will take as input arrays of shape (*, 16) ,输入维度=16

    # and output arrays of shape (*, 32) ,输出维度=32

    # after the first layer, you don't need to specify

    # the size of the input anymore:

    model.add(Dense(32)) #这一层的input_shape=(32,)

    全连接层(Fully Connected layer)就是使用了softmax激励函数作为输出层的多层感知机(Multi-Layer Perceptron),其他很多分类器如支持向量机也使用了softmax。“全连接”表示上一层的每一个神经元,都和下一层的每一个神经元是相互连接的。

    卷积层和池化层呢个的输出代表了输入图像的高级特征,全连接层的目的就是用这些特征进行分类,类别基于训练集。比如图14所示的图像分类任务,有四种可能的类别。(注意,图14没有显示出所有的神经元节点)

    v2-45a9987d6c4838c4c8a24c1b3a4ce7d8_b.png

    图14:全连接层——每个节点都与相邻层的所有节点相连

    除了分类以外,加入全连接层也是学习特征之间非线性组合的有效办法。卷积层和池化层提取出来的特征很好,但是如果考虑这些特征之间的组合,就更好了。

    全连接层的输出概率之和为1,这是由激励函数Softmax保证的。Softmax函数把任意实值的向量转变成元素取之0-1且和为1的向量。

    2.Reshape
         用来将输入shape转换为特定的shape

    # as first layer in a Sequential model

    model = Sequential()

    model.add(Reshape((3, 4), input_shape=(12,)))

    # now: model.output_shape == (None, 3, 4) ,None任意正整数

    # note: `None` is the batch dimension ,批次大小,就是每次样本数量

    # as intermediate layer in a Sequential model ,中间层

    model.add(Reshape((6, 2)))

    # now: model.output_shape == (None, 6, 2)

    # also supports shape inference using `-1` as dimension ,推断inference ,自动判断大小

    model.add(Reshape((-1, 2, 2)))

    # now: model.output_shape == (None, 3, 2, 2),3*2*2=12

     

    3.BatchNormalization

    该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1

    由于在训练神经网络的过程中,每一层的 params是不断更新的,由于params的更新会导致下一层输入的分布情况发生改变,所以这就要求我们进行权重初始化,减小学习率。这个现象就叫做internal covariate shift。虽然可以通过whitening来加速收敛,但是需要的计算资源会很大。而Batch Normalizationn的思想则是对于每一组batch,在网络的每一层中,分feature对输入进行normalization,对各个feature分别normalization,即对网络中每一层的单个神经元输入,计算均值和方差后,再进行normalization。对于CNN来说normalize “Wx+b”而非 “x”,也可以忽略掉b,即normalize “Wx”,而计算均值和方差的时候,是在feature map的基础上(原来是每一个feature)

    详细参考:http://blog.csdn.net/meanme/article/details/48679785

    4.Activation

    激活层对一个层的输出施加激活函数

    5.Dropout

    为输入数据施加Dropout。Dropout将在训练过程中每次更新参数时随机断开一定百分比(rate)的输入神经元,Dropout层用于防止过拟合。

    6.UpSampling2D

    上采样,扩大矩阵,可以用于复原图像等。

    1240

    keras.layers.convolutional.UpSampling2D(size=(2, 2), data_format=None)

    将数据的行和列分别重复size[0]和size[1]次

    7.Conv2D

    keras.layers.convolutional.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)

    二维卷积层,即对图像的空域卷积。该层对二维输入进行滑动窗卷积,当使用该层作为第一层时,应提供input_shape参数。例如input_shape = (128,128,3)代表128*128的彩色RGB图像(data_format='channels_last').

    参数
    • filters:卷积核的数目(即输出的维度)

    • kernel_size:单个整数或由两个整数构成的list/tuple,卷积核的宽度和长度。如为单个整数,则表示在各个空间维度的相同长度。

    • strides:单个整数或由两个整数构成的list/tuple,为卷积的步长。如为单个整数,则表示在各个空间维度的相同步长。任何不为1的strides均与任何不为1的dilation_rata均不兼容

    • padding:补0策略,为“valid”, “same” 。“valid”代表只进行有效的卷积,即对边界数据不处理。“same”代表保留边界处的卷积结果,通常会导致输出shape与输入shape相同,因为卷积核移动时在边缘会出现大小不够的情况

    • activation:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)

    • dilation_rate:单个整数或由两个个整数构成的list/tuple,指定dilated convolution中的膨胀比例。任何不为1的dilation_rata均与任何不为1的strides均不兼容。

    • data_format:字符串,“channels_first”或“channels_last”之一,代表图像的通道维的位置。该参数是Keras 1.x中的image_dim_ordering,“channels_last”对应原本的“tf”,“channels_first”对应原本的“th”。以128x128的RGB图像为例,“channels_first”应将数据组织为(3,128,128),而“channels_last”应将数据组织为(128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channels_last”。

    • use_bias:布尔值,是否使用偏置项

    • kernel_initializer:权值初始化方法,为预定义初始化方法名的字符串,或用于初始化权重的初始化器。参考initializers

    • bias_initializer:权值初始化方法,为预定义初始化方法名的字符串,或用于初始化权重的初始化器。参考initializers

    • kernel_regularizer:施加在权重上的正则项,为Regularizer对象

    • bias_regularizer:施加在偏置向量上的正则项,为Regularizer对象

    • activity_regularizer:施加在输出上的正则项,为Regularizer对象

    • kernel_constraints:施加在权重上的约束项,为Constraints对象

    • bias_constraints:施加在偏置上的约束项,为Constraints对象

    卷积的根本目的是从输入图片中提取特征。

    在下右图中,假如每个神经元只和10×10个像素值相连,那么权值数据为1000000×100个参数,减少为原来的千分之一。而那10×10个像素值对应的10×10个参数,其实就相当于卷积操作。

    511-600x224.jpg

    如下图所示,展示了一个33的卷积核在55的图像上做卷积的过程。每个卷积都是一种特征提取方式,就像一个筛子,将图像中符合条件(激活值越大越符合条件)的部分筛选出来。

    参考:http://www.36dsj.com/archives/24006

    6.gif

    model.add(Conv2D(64, 5, strides=2, input_shape=(28,28,1),padding='same', activation=LeakyReLU(alpha=0.2)))

    5为卷积核大小,共有64个卷积核(卷积核矩阵的具体值是随机生成的吗?,参考:https://zhuanlan.zhihu.com/p/25754846),strides=2,每次移动步长为2,28/2=14,用大小为5的卷积核移动14次得到的就是一个14*14的矩阵,采用64个不同的卷积核(为了抽取不同的特征)可以得到14*14*16的特征。

    model.add(Conv2D(128, 5, strides=2, input_shape=(28,28,1),padding='same', activation=LeakyReLU(alpha=0.2)))

    model.add(Conv2D(256, 5, strides=2, padding='same', activation=LeakyReLU(alpha=0.2)))

    model.add(Conv2D(512, 5, strides=1, padding='same', activation=LeakyReLU(alpha=0.2)))

    因为strides=1所以得到的大小还是4*4,共有512的特征

    90

    8.Conv2DTranspose

    keras.layers.convolutional.Conv2DTranspose(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)

    该层是转置的卷积操作(反卷积)。需要反卷积的情况通常发生在用户想要对一个普通卷积的结果做反方向的变换。例如,将具有该卷积层输出shape的tensor转换为具有该卷积层输入shape的tensor。同时保留与卷积层兼容的连接模式。

    当使用该层作为第一层时,应提供input_shape参数。例如input_shape = (3,128,128)代表128*128的彩色RGB图像

    参数
    • filters:卷积核的数目(即输出的维度)

    • kernel_size:单个整数或由两个个整数构成的list/tuple,卷积核的宽度和长度。如为单个整数,则表示在各个空间维度的相同长度。

    • strides:单个整数或由两个整数构成的list/tuple,为卷积的步长。如为单个整数,则表示在各个空间维度的相同步长。任何不为1的strides均与任何不为1的dilation_rata均不兼容

    • padding:补0策略,为“valid”, “same” 。“valid”代表只进行有效的卷积,即对边界数据不处理。“same”代表保留边界处的卷积结果,通常会导致输出shape与输入shape相同。

    • activation:激活函数,为预定义的激活函数名(参考激活函数),或逐元素(element-wise)的Theano函数。如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)

    • dilation_rate:单个整数或由两个个整数构成的list/tuple,指定dilated convolution中的膨胀比例。任何不为1的dilation_rata均与任何不为1的strides均不兼容。

    • data_format:字符串,“channels_first”或“channels_last”之一,代表图像的通道维的位置。该参数是Keras 1.x中的image_dim_ordering,“channels_last”对应原本的“tf”,“channels_first”对应原本的“th”。以128x128的RGB图像为例,“channels_first”应将数据组织为(3,128,128),而“channels_last”应将数据组织为(128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channels_last”。

    • use_bias:布尔值,是否使用偏置项

    图中,我们使用了卷积的倒数,即转置卷积(transposed convolution),从 100 维的噪声(满足 -1 至 1 之间的均匀分布)中生成了假图像。如在 DCGAN 模型中提到的那样,去掉微步进卷积,这里我们采用了模型前三层之间的上采样来合成更逼真的手写图像。在层与层之间,我们采用了批量归一化的方法来平稳化训练过程。以 ReLU 函数为每一层结构之后的激活函数。最后一层 Sigmoid 函数输出最后的假图像。第一层设置了 0.3-0.5 之间的 dropout 值来防止过拟合。具体代码如下。

    不到 200 行代码,教你如何用 Keras 搭建生成对抗网络(GAN)

    self.G = Sequential()
    dropout = 0.4
    depth = 64+64+64+64
    dim = 7
    # In: 100
    # Out: dim x dim x depth
    self.G.add(Dense(dim*dim*depth, input_dim=100))
    self.G.add(BatchNormalization(momentum=0.9))
    self.G.add(Activation('relu'))
    self.G.add(Reshape((dim, dim, depth)))
    self.G.add(Dropout(dropout))
    # In: dim x dim x depth
    # Out: 2*dim x 2*dim x depth/2
    self.G.add(UpSampling2D()) #扩大一倍14
    self.G.add(Conv2DTranspose(int(depth/2), 5, padding='same'))
    self.G.add(BatchNormalization(momentum=0.9))
    self.G.add(Activation('relu'))
    self.G.add(UpSampling2D()) #扩大一倍28
    self.G.add(Conv2DTranspose(int(depth/4), 5, padding='same'))
    self.G.add(BatchNormalization(momentum=0.9))
    self.G.add(Activation('relu'))
    self.G.add(Conv2DTranspose(int(depth/8), 5, padding='same'))  #这层没有上采样
    self.G.add(BatchNormalization(momentum=0.9))
    self.G.add(Activation('relu'))
    # Out: 28 x 28 x 1 grayscale image [0.0,1.0] per pix
    self.G.add(Conv2DTranspose(1, 5, padding='same')) #卷积核数为1,还原为1张图片
    self.G.add(Activation('sigmoid'))
    self.G.summary()
    return self.G

    9.Flatten

    Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。

    model = Sequential()

    model.add(Convolution2D(64, 3, 3, border_mode='same', input_shape=(3, 32, 32)))

    # now: model.output_shape == (None, 64, 32, 32)

    model.add(Flatten())

    # now: model.output_shape == (None, 65536)=64*32*32,压平了

    10.LeakyReLU

    keras.layers.advanced_activations.LeakyReLU(alpha=0.3)

    LeakyRelU是修正线性单元(Rectified Linear Unit,ReLU)的特殊版本,当不激活时,LeakyReLU仍然会有非零输出值,从而获得一个小梯度,避免ReLU可能出现的神经元“死亡”现象。即,f(x)=alpha * x for x < 0, f(x) = x for x>=0

    参数
    • alpha:大于0的浮点数,代表激活函数图像中第三象限线段的斜率

    11.ReLU

    参考:https://zhuanlan.zhihu.com/p/25754846

    图3所示,每个卷积操作之后,都有一个叫ReLU的附加操作。ReLU的全称是纠正线性单元(Rectified Linear Unit),是一种非线性操作,其输出如下:

    v2-c8afbf19afabcfccb1d0f27ac5f7eed0_b.png

    图8:ReLU

    ReLU是以像素为单位生效的,其将所有负值像素替换为0。ReLU的目的是向卷积网络中引入非线性,因为真实世界里大多数需要学习的问题都是非线性的(单纯的卷积操作时线性的——矩阵相乘、相加,所以才需要额外的计算引入非线性)。

    图9可以帮助我们清晰地理解,ReLU应用在图6得到的特征映射上,输出的新特征映射也叫“纠正”特征映射。(黑色被抹成了灰色)

    v2-9feb833b3e855d9d282fce472429311b_b.png图9:ReLU

    其他非线性方程比如tanhsigmoid也可以替代ReLU,但多数情况下ReLU的表现更好。

    12.MaxPooling2D

    空间池化(也叫亚采样或下采样)降低了每个特征映射的维度,但是保留了最重要的信息。空间池化可以有很多种形式:最大(Max),平均(Average),求和(Sum)等等。

    以最大池化为例,我们定义了空间上的邻域(2x2的窗)并且从纠正特征映射中取出窗里最大的元素。除了取最大值以额外,我们也可以取平均值(平均池化)或者把窗里所有元素加起来。实际上,最大池化已经显示了最好的成效。

    图10显示了对纠正特征映射的最大池化操作(在卷积+ReLU之后),使用的是2x2的窗。

    v2-97065f08e3bb34c4e42e223636cc5b0e_b.png

    图10:最大池化

    池化的功能室逐步减少输入表征的空间尺寸。特别地,池化

    • 使输入表征(特征维度)更小而易操作
    • 减少网络中的参数与计算数量,从而遏制过拟合
    • 增强网络对输入图像中的小变形、扭曲、平移的鲁棒性(输入里的微小扭曲不会改变池化输出——因为我们在局部邻域已经取了最大值/平均值)。
    • 帮助我们获得不因尺寸而改变的等效图片表征。这非常有用,因为这样我们就可以探测到图片里的物体,不论那个物体在哪。

    13 反向传播训练

    联合起来——反向传播训练

    综上,卷积+池化是特征提取器,全连接层是分类器。

    注意图15,因为输入图片是条船,所以目标概率对船是1,其他类别是0.

    • 输入图像 = 船
    • 目标向量 = [0, 0, 1 ,0]
    v2-73cc788cfc81dfe5411c82cd53b007be_b.png

    图15:训练卷积神经网络

    卷积网络的训练过程可以概括如下:

    Step 1: 用随机数初始化所有的滤波器和参数/权重
    • Step 2: 网络将训练图片作为输入,执行前向步骤(卷积,ReLU,池化以及全连接层的前向传播)并计算每个类别的对应输出概率。

      • 假设船图的输出概率是[0.2, 0.4, 0.1, 0.3]
      • 因为第一个训练样本的权重都是随机的,所以这个输出概率也跟随机的差不多
    • Step 3: 计算输出层的总误差(4类别之和)

      • 总误差=∑12(目标概率−输出概率)2总误差=∑12(目标概率−输出概率)2
    • Step 4: 反向传播算法计算误差相对于所有权重的梯度,并用梯度下降法更新所有的滤波器/权重和参数的值,以使输出误差最小化。

      • 权重的调整程度与其对总误差的贡献成正比。
      • 当同一图像再次被输入,这次的输出概率可能是[0.1, 0.1, 0.7, 0.1],与目标[0, 0, 1, 0]更接近了。
      • 这说明我们的神经网络已经学习着分类特定图片了,学习的方式是调整权重/滤波器以降低输出误差。
      • 如滤波器个数、滤波器尺寸、网络架构这些参数,是在Step 1之前就已经固定的,且不会在训练过程中改变——只有滤波矩阵和神经元突触权重会更新。

    以上步骤训练了卷积网络——本质上就是优化所有的权重和参数,使其能够正确地分类训练集里的图片。

    当一个新的(前所未见的)的图片输入至卷积网络,网络会执行前向传播步骤并输出每个类别的概率(对于新图像,输出概率用的也是训练过的权重值)。如果我们的训练集足够大,网络就有望正确分类新图片,获得良好的泛化(generalization)能力。

    展开全文
  • 一、这个IMDB数据集包含了50000条电影评论,其中25000条用于训练,另外25000条用于测试...from keras.datasets import imdb (train_data,train_labels),(test_data,test_labels) = imdb.load_data(num_words=8000) ...

    一、这个IMDB数据集包含了50000条电影评论,其中25000条用于训练,另外25000条用于测试。其label只包含0或1,其中0表示负面评价,1表示正面评价

    from keras.datasets import imdb
    (train_data,train_labels),(test_data,test_labels) = imdb.load_data(num_words=8000) #前8000个单词(每局评论至多包含8000个单词)

    二、数据集的相关信息

    print('shape of train data is ',train_data.shape)
    print('shape of train labels is ',train_labels.shape)
    print('an example of train data is ',train_data[5])
    shape of train data is  (25000,)
    shape of train labels is  (25000,)
    an example of train data is  [1, 778, 128, 74, 12, 630, 163, 15, 4, 1766, 7982, 1051, 2, 32, 85, 156, 45, 40, 148, 139, 121, 664, 665, 10, 10, 1361, 173, 4, 749, 2, 16, 3804, 8, 4, 226, 65, 12, 43, 127, 24, 2, 10, 10]
    

    三、处理数据集

    import numpy as np
    # 神经网络的输入必须是tensor而不是list,所以需要将数据集处理为25000*8000
    def vectorize_sequences(sequences,dimension=8000):
        # 生成25000*8000的二维Numpy数组
        results = np.zeros((len(sequences),dimension))
        # one-hot编码
        for i,sequence in enumerate(sequences):
            results[i,sequence] = 1.
        return results
    x_train = vectorize_sequences(train_data)
    x_test = vectorize_sequences(test_data)
    y_train = np.asarray(train_labels).astype('float32')
    y_test = np.asarray(test_labels).astype('float32')

    四、设计网络结构

    • 对于一个输入为向量的二分类问题,使用relu做为激活函数的全连接网络可以很好的解决这个问题
    • 输出层使用sigmoid的目的是使网络输出的是介于0到1的一个概率值
    • 对于二分类问题,通常使用binary_crossentropy
    from keras import models
    from keras import layers
    def build_model():
        model = models.Sequential()
        model.add(layers.Dense(16,activation='relu',input_shape=(8000,)))
        model.add(layers.Dense(16,activation='relu'))
        model.add(layers.Dense(1,activation='sigmoid'))
        model.compile(optimizer='rmsprop',# 还可以通过optimizer = optimizers.RMSprop(lr=0.001)来为优化器指定参数
                      loss='binary_crossentropy', # 等价于loss = losses.binary_crossentropy
                      metrics=['accuracy']) # 等价于metrics = [metircs.binary_accuracy]
        return model
    model = build_model()

    五、划分验证集用于选择超参数epochs

    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, # 在全数据集上迭代20次
                        batch_size=512, # 每个batch的大小为512
                        validation_data=(x_val,y_val))
    Train on 15000 samples, validate on 10000 samples
    Epoch 1/20
    15000/15000 [==============================] - 2s 100us/step - loss: 0.5112 - acc: 0.7813 - val_loss: 0.3790 - val_acc: 0.8654
    Epoch 2/20
    15000/15000 [==============================] - 1s 79us/step - loss: 0.3057 - acc: 0.9003 - val_loss: 0.3029 - val_acc: 0.8884
    Epoch 3/20
    15000/15000 [==============================] - 1s 77us/step - loss: 0.2272 - acc: 0.9245 - val_loss: 0.3130 - val_acc: 0.8718
    Epoch 4/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.1874 - acc: 0.9365 - val_loss: 0.2842 - val_acc: 0.8859
    Epoch 5/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.1571 - acc: 0.9467 - val_loss: 0.2845 - val_acc: 0.8868
    Epoch 6/20
    15000/15000 [==============================] - 1s 77us/step - loss: 0.1316 - acc: 0.9587 - val_loss: 0.3343 - val_acc: 0.8692
    Epoch 7/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.1159 - acc: 0.9625 - val_loss: 0.3089 - val_acc: 0.8851
    Epoch 8/20
    15000/15000 [==============================] - 1s 79us/step - loss: 0.0993 - acc: 0.9685 - val_loss: 0.3608 - val_acc: 0.8703
    Epoch 9/20
    15000/15000 [==============================] - 1s 80us/step - loss: 0.0850 - acc: 0.9750 - val_loss: 0.3473 - val_acc: 0.8788
    Epoch 10/20
    15000/15000 [==============================] - 1s 80us/step - loss: 0.0745 - acc: 0.9781 - val_loss: 0.3719 - val_acc: 0.8757
    Epoch 11/20
    15000/15000 [==============================] - 1s 81us/step - loss: 0.0658 - acc: 0.9811 - val_loss: 0.4018 - val_acc: 0.8736
    Epoch 12/20
    15000/15000 [==============================] - 1s 79us/step - loss: 0.0566 - acc: 0.9837 - val_loss: 0.4373 - val_acc: 0.8679
    Epoch 13/20
    15000/15000 [==============================] - 1s 77us/step - loss: 0.0483 - acc: 0.9861 - val_loss: 0.4484 - val_acc: 0.8703
    Epoch 14/20
    15000/15000 [==============================] - 1s 79us/step - loss: 0.0406 - acc: 0.9897 - val_loss: 0.4728 - val_acc: 0.8677
    Epoch 15/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.0355 - acc: 0.9913 - val_loss: 0.4968 - val_acc: 0.8693
    Epoch 16/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.0301 - acc: 0.9934 - val_loss: 0.5280 - val_acc: 0.8676
    Epoch 17/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.0277 - acc: 0.9933 - val_loss: 0.5561 - val_acc: 0.8654
    Epoch 18/20
    15000/15000 [==============================] - 1s 79us/step - loss: 0.0222 - acc: 0.9949 - val_loss: 0.5822 - val_acc: 0.8654
    Epoch 19/20
    15000/15000 [==============================] - 1s 79us/step - loss: 0.0175 - acc: 0.9971 - val_loss: 0.6369 - val_acc: 0.8581
    Epoch 20/20
    15000/15000 [==============================] - 1s 78us/step - loss: 0.0152 - acc: 0.9977 - val_loss: 0.6359 - val_acc: 0.8636
    

    history对象保存了在模型训练过程的相关信息

    history_dict = history.history
    history_dict.keys()
    dict_keys(['val_loss', 'val_acc', 'loss', 'acc'])
    

    七、绘制loss和accuracy

    x轴为epochs,y轴为loss

    import matplotlib.pyplot as plt
    %matplotlib inline
    loss_values = history_dict['loss']
    val_loss_values = history_dict['val_loss']
    epochs = range(1,len(loss_values)+1)
    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()

    这里写图片描述

    x轴为epochs,y轴为accuracy

    plt.clf()
    acc_values = history_dict['acc']
    val_acc_values = history_dict['val_acc']
    
    plt.plot(epochs,acc_values,'bo',label='Training acc')
    plt.plot(epochs,val_acc_values,'b',label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.xlabel('Epochs')
    plt.ylabel('Acc')
    plt.legend()

    这里写图片描述

    八、选择合适的超参数,然后在所有训练集上重新训练模型

    model.fit(x_train,
             y_train,
             epochs=4, # 由loss图发现在epochs=4的位置上validation loss最低
             batch_size=512)
    Epoch 1/4
    25000/25000 [==============================] - 1s 55us/step - loss: 0.2172 - acc: 0.9436
    Epoch 2/4
    25000/25000 [==============================] - 1s 56us/step - loss: 0.1509 - acc: 0.9552
    Epoch 3/4
    25000/25000 [==============================] - 1s 54us/step - loss: 0.1221 - acc: 0.9632
    Epoch 4/4
    25000/25000 [==============================] - 1s 54us/step - loss: 0.1012 - acc: 0.9678
    <keras.callbacks.History at 0x7f68945847b8>
    

    评估模型在测试集上的loss和accuracy

    results = model.evaluate(x_test,y_test)
    results
    [0.49199876737356185, 0.8586]
    
    展开全文
  • tf.keraskeras有什么区别?

    千次阅读 2019-03-28 18:34:15
    利益相关:Google Brain员工,参与TensorFlow和Keras的编写) 要回答这个问题,首先需要简单谈一下keras的历史。keras是François Chollet于2014-2015年开始编写的开源高层深度学习API。所谓“高层”,是相对于...
  • Keras介绍   Keras是一个开源的高层神经网络API,由纯Python编写而成,其后端可以基于Tensorflow、Theano、MXNet以及CNTK。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果。Keras适用的Python版本是:...
  • keras 搭建神经网络

    千次阅读 2018-10-29 15:00:58
    1 简单的回归 #coding=utf-8 import numpy as np ...from keras.models import Sequential from keras.layers import Dense import matplotlib.pyplot as plt # create some data X = np.linspace(-...
  • keras系列(一):参数设置

    万次阅读 多人点赞 2018-09-28 10:54:53
    常用的 权重/偏置 初始化 常数初始化 为了在伪代码中形象化,让我们考虑一个具有64个输入和32个输出的神经网络的任意一层。 ...W = np.zeros((64, 32)) ...虽然常量初始化很容易理解和理解,但使用这种方法的问题是...
  • 深度学习(十)keras学习笔记

    万次阅读 2016-03-26 12:25:04
    keras与torch7的使用非常相似,是最近才火起来的深度学习开源库,底层是用了theano。keras可以说是python版的torch7,对于快速构建CNN模型非常方便。同时也包含了一些最新文献的算法,比如Batch Noramlize,文档教程...
  • Keras入门

    千次阅读 多人点赞 2018-08-28 11:01:11
    注解:关于Keras本人是小白,此次也是因为学习其他东西,需要了解Keras的相关知识,所以稍微整理一下........ http://www.cnblogs.com/lc1217/p/7132364.html 为何要用Keras 如今在深度学习大火的时候,第三方...
  • Keras

    千次阅读 2018-08-11 14:45:57
    Keras是由纯python编写的基于theano/tensorflow的深度学习框架。Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需求,可以优先选择Keras: a)简易和快速的原型设计(keras...
  • Keras安装与测试

    万次阅读 2018-08-19 12:22:55
    Keras是高度封装的包,适合初学者学习深度学习网络框架,比如我这个小白,一切都在尝试中,每天都在安装各种库各种API!!! Keras 安装: 环境 anconda(含pip,python3.6) 本人是在cmd中使用pip安装的keras,...
  • 不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前路坑太多。 到发文为止,已经有theano/tensorflow/CNTK支持keras,虽然说tensorflow造势...
  • 全卷积神经网络图像分割(U-net)-keras实现

    万次阅读 多人点赞 2018-11-04 19:10:13
    最近在研究全卷积神经网络在图像分割方面的应用,因为自己是做医学图像处理方面的工作,所以就把一个基于FCN(全卷积神经网络)的神经网络用 keras 实现了,并且用了一个医学图像的数据集进行了图像分割。...
  • TextCNN文本分类(keras实现)

    万次阅读 多人点赞 2019-08-27 20:56:32
    二、Keras文本预处理 1、读取数据集 2、将文字转换成数字特征 3、将每条文本转换为数字列表 4、将每条文本设置为相同长度 5、将每个词编码转换为词向量 6、Keras文本预处理代码实现 三、基于keras的TextCNN...
  • Keras大法(3)——使用Keras的一般流程(一)基本流程(二)流程示例(1)导入Keras库(2)定义模型(3)编译模型(4)训练模型(5)评估模型(6)保存模型(三)总 结 (一)基本流程 使用Keras的基本流程可以...
  • 不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前路坑太多。 到发文为止,已经有theano/tensorflow/CNTK支持keras,虽然说tensorflow造势很...
1 2 3 4 5 ... 20
收藏数 59,865
精华内容 23,946
关键字:

keras