import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt
(train_images, train_labels), (test_images,test_labels) = datasets.mnist.load_data()![请添加图片描述](https://img-blog.csdnimg.cn/503266d154bd43bdbc02f68ff57c3e29.png)
#图像为28*28的图片,因此像素取值在0-255
train_images, test_images = train_images/255.0, test_images/255.0
plt.figure(figsize=(20,10))
#遍历前20个图片
for i in range(20):
plt.subplot(2,10,i+1)
plt.imshow(train_images[i])
plt.xlabel(train_labels[i])
plt.xticks([])
plt.yticks([])
plt.show()
train_images = train_images.reshape((60000,28,28,1))#CNN网络模型需要宽、高和深度的三维数据结构
test_images = test_images.reshape((60000,28,28,1))
train_images.shape
首先以线性回归预测模型为例,预测值可以表示为输入特征的加权求和,而神经网络会多次重复该加权求和过程,首先计算代表中间过程的隐单元,在将这些隐单元加权求和。若是这样则无论网络如何复杂,最后的输出都应是相同的加权求和,因此在每个隐单元后添加激活函数,决定对应单元是否传递信号以及发送给下一个神经元的内容。
为了增强网络的表示能力和学习能力,神经网络的激活函数都是非线性的
主要用于提取数据特征,类似滤波矩阵,以二维为例:是将原数据矩阵与设计的卷积核矩阵做卷积运算,按照步长stride进行平移矩阵对应元素做乘积并求和,直到将原矩阵每个部分都覆盖未知。
感受野:
我们让每个神经元只与输入数据的一个局部区域连接。该连接的空间大小叫做神经元的感受野(receptive field),它的尺寸是一个超参数(其实就是滤波器的空间尺寸)。
在深度方向上,这个连接的大小总是和输入量的深度相等。需要强调,对待空间维度(宽和高)与深度维度是不同的:连接在空间(宽高)上是局部的,但是在深度上总是和输入数据的深度一致,
局部感知:
因为两个相距很远的像素之间的关系并不大。因而,每个神经元其实没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。
作用是减少特征数量
以2828像素像素为例,若仅提取一种特征假定卷积核为33,则卷积得到(28-3+1)(28-3+1)=676维卷积特征,容易过拟合,同时对计算机性能也提出要求。为此可以对不同未知的特征进行聚合统计,这种聚合的操作就叫做池化 (pooling),有时也称为平均池化或者最大池化
这也可以被视为一种特殊的卷积,通常采用22的格式,并取步长为2
在整个卷积神经网络中起到“分类器”的作用。如果说卷积层、池化层和激活函数层等操作是将原始数据映射到隐层特征空间的话,全连接层则起到将学到的“分布式特征表示”映射到样本标记空间的作用。
在 CNN 中,全连接常出现在最后几层,用于对前面设计的特征做加权和
全连接层中的每个神经元与其前一层的所有神经元进行全连接.全连接层可以整合卷积层或者池化层中具有类别区分性的局部信息.为了提升 CNN网络性能,全连接层每个神经元的激励函数一般采用ReLU函数。最后一层全连接层的输出值被传递给一个输出,可以采用softmax逻辑回归(softmax regression)进行 分 类,该层也可 称为 softmax层
简单的说就是将特征表示整合成一个值,其优点在于减少特征位置对于分类结果的影响,提高了整个网络的鲁棒性
卷积( Conv2d ) -> 激励函数( ReLU ) -> 池化, 向下采样 ( MaxPooling ) -> 再来一遍 -> 展平多维的卷积成的特征图 -> 接入全连接层 ( Linear ) -> 输出
model = models.Sequential([
layers.Conv2D(32,(3,3),activation='relu',input_shape=(28,28,1)),
#设置第一层的2维卷积层,共32个3*3的卷积核
layers.MaxPool2D((2,2)), #池化层1,2*2
layers.Conv2D(64,(3,3),activation='relu'), #卷积层2,64个 3*3,
layers.MaxPool2D((2,2)), #池化层2
layers.Flatten(),
layers.Dense(64,activation='relu'), #特征进一步提取,64维输出一维空间长度
layers.Dense(10,activation='softmax') #用softmax函数进行分类,输出层
])
#Sequential的精髓是将一些网络层线性堆叠在一起,最后组成tf.keras.Model的方式。因此可以认为Sequential是tf.keras.Model的一种特殊形式。
#Sequential的组成方式是layer-by-layer,优点是实现起来最简明,但网络只能是线性结构,所以适合构建结构比较简单的线性网络。
model.summary()
Model: “sequential”
conv2d (Conv2D) (None, 26, 26, 32) 320
max_pooling2d (MaxPooling2D (None, 13, 13, 32) 0
)
conv2d_1 (Conv2D) (None, 11, 11, 64) 18496
max_pooling2d_1 (MaxPooling (None, 5, 5, 64) 0
2D)
flatten (Flatten) (None, 1600) 0
dense (Dense) (None, 64) 102464
dense_1 (Dense) (None, 10) 650
=================================================================
Total params: 121,930
Trainable params: 121,930
Non-trainable params: 0
# model.compile()方法用于在配置训练方法时,告知训练时用的优化器、损失函数和准确率评测标准
model.compile(
#设置优化器为Adam
optimizer='adam',
#设置损失函数为交叉熵损失函数
# from_logits为True时,会将y_pred转化为概率(用softmax),否则不进行转换,通常情况下用True结果更稳定
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
# 设置性能指标列表,将在模型训练时监控列表中的指标
metrics=['accuracy'])
history = model.fit(
#输入训练集
train_images,
#训练集标签
train_labels,
# 设置10个epoch,每一个epoch都将会把所有的数据输入模型完成一次训练,训练轮次。
epochs=10,
# 设置验证集
validation_data=(test_images, test_labels))
#输出结果为一个长度为10的数组,表示图片为0-9中各个数的概率大小
plt.imshow(test_images[5])
pre = model.predict(test_images)
print(pre[5])
313/313 [==============================] - 1s 4ms/step
[2.7552569e-09 9.9999595e-01 1.0471517e-11 8.2769540e-16 5.5294475e-07
1.1609476e-11 1.7552965e-10 3.5027660e-06 1.1175217e-09 1.7023377e-09]``