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
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
#卷积神经网络接收形状为(image_height, image_width, image_channels)的输入张量(不包括批量维度)
#下一步是将最后的输出张量[大小为(3, 3, 64)]输入到一个密集连接分类器网络中,即 Dense 层的堆叠,你已经很熟悉了。这些分类器可以处理 1D 向量,而当前的输出是 3D 张量。 首先,我们需要将 3D 输出展平为 1D,然后在上面添加几个 Dense 层。
model.add(layers.Flatten())#,在进入两个 Dense 层之前,形状(3, 3, 64)的输出被展平为形状 (576,) 的 向量
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
print(model.summary())
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32') / 255
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5, batch_size=64)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(test_acc)
卷积运算
全连接层和卷积层的根本区别在于,Dense 层从输入特征空间中学到的是全局模式 (比如对于MNIST数字,全局模式就是涉及所有像素的模式),而卷积层学到的是局部模式(对于图像来说,就是在输入图像的二维[3*3;5*5]小窗口中发现的模式) 性质: 1.平移不变性(translation invariant)。cnn在右下角学到某个模式后,它可以在任何地方识别这个模式,比如左上角。对于全连接网络,如果模式出现在新的位置,它只能重新学习这个模式。cnn在处理图像时,只需更少的训练样本就可以学到具有泛化能力的数据表示 2.模式的空间层次结构(spatial hierarchies of patterns)。第一个卷积层将学习较小的局部模式(比如边缘),第二个卷积层将学习由第一层特征组成的更大的模式,以此类推。cnn可以有效的学习越来越复杂、越来越抽象的视觉概念 图像:包含两个空间轴(高度和宽度)和一个深度轴(也叫通道轴)的3D张量,其卷积也叫特征图。RGB(height,width,3[3个颜色通道]) 卷积运算从输入特征图中提取图块,并对所有这些图块应用相同的变换,生成输出特征图。也是一个3D张量,但深度可以任意取值,因为输出深度是层的参数,深度轴的不同通道代表过滤器[对输入数据的某一方面进行编码] 卷积的工作原理: 在 3D 输入特征图上滑动(slide)这些 3×3 或 5×5 的窗口,在每个可能 的位置停止并提取周围特征的 3D 图块[形状为 (window_height, window_width, input_ depth)]。然后每个 3D 图块与学到的同一个权重矩阵[叫作卷积核( convolution kernel)]做 张量积,转换成形状为 (output_depth,) 的 1D 向量。然后对所有这些向量进行空间重组, 使其转换为形状为 (height, width, output_depth) 的 3D 输出特征图。输出特征图中的 每个空间位置都对应于输入特征 图中的相同位置(比如输出的右下角包含了输入右下角的信息) 输出特征图的宽度和高度可能与输入的宽度和高度不同,原因: 1.边界效应,可通过对输入特征图进行填充来抵消 假设有一个 5×5 的特征图(共 25 个方块)。其中只有 9 个方块可以作为中心放入一个3×3 的窗口,这 9 个方块形成一个 3×3 的网格(见图 5-5)。因此,输出特征图的尺寸是 3×3。 如果你希望输出特征图的空间维度与输入相同,那么可以使用填充(padding)。填充是在 输入特征图的每一边添加适当数目的行和列,使得每个输入方块都能作为卷积窗口的中心。对 于 3×3 的窗口,在左右各添加一列,在上下各添加一行。对于 5×5 的窗口,各添加两行和两 列(见图 5-6) 对于 Conv2D 层,可以通过 padding 参数来设置填充,这个参数有两个取值: "valid" 表 示不使用填充(只使用有效的窗口位置);"same" 表示“填充后输出的宽度和高度与输入相同”。 padding 参数的默认值为"valid"。 2.使用了步幅 两个连续窗口的距离是卷积的一个参数,叫作步幅,默认值为 1。也可 以使用步进卷积(strided convolution),即步幅大于 1 的卷积 步幅为 2 意味着特征图的宽度和高度都被做了 2 倍下采样(除了边界效应引 起的变化)但在实践中很少使用 为了对特征图进行下采样,我们不用步幅,而是通常使用最大池化(max-pooling)运算 最大池化 使用硬编码的 max 张量运算对局部图块进行变换,而不是使用学到的线性变换(卷 积核)。最大池化与卷积的最大不同之处在于,最大池化通常使用 2×2 的窗口和步幅 2,其目 的是将特征图下采样 2 倍。与此相对的是,卷积通常使用 3×3 窗口和步幅 1。 为什么要用这种方式对特征图下采样?为什么不删除最大池化层,一直保留较大的特征图? 一是减少需要处理的特征图的元素个数, 二是通过让连续 卷积层的观察窗口越来越大(即窗口覆盖原始输入的比例越来越大),从而引入空间过滤器的层级结构。 我们需要让最后一个卷积层的特征包含输入的整体信息