CNN实现离散数据的分类(以图像分类为例)

用CNN实现离散数据的分类(以图像分类为例)

卷积计算

  1. 卷积计算可认为是一种有效提取图像特征的方法
  2. 一般会用一个正方形的卷积核,按指定步长,在输入特征图上滑动。遍历输入特征图中的每一个像素点,每一个步长,卷积核会与输入特征图出现重合区域,重合区域对应元素相乘、求和再加上偏置项得到输入特征的一个像素点
  3. 输入特征图的深度,决定了当前层卷积核的深度
  4. 当前卷积核的个数,决定了当前层输出特征图的深度

感受野

  1. 感受野:卷积神经网络各输出特征图中的每个像素点,在原始输入图片上映射区域等的大小

全零填充(padding)

  1. 卷积计算保持输入特征图的尺寸不变
  2. TF描述全零填充,用参数padding='SAME'padding='VALID'表示

TF描述卷积计算层

tf.keras.layers.Conv2D(
    filters=卷积核个数,
    kernel_size=卷积核尺寸,#正方形写核长整数,或(核高h,核宽w)
    strides=滑动步长,#横纵向相同写步长整数,或(纵向步长h,横向步长w),默认1
    padding="same" or "valid",#使用全零填充是"same",不使用是"valid"(默认)
    activation="relu" or "sigmoid" or "tanh" or "softmax"等,#如有BN此处不写
    input_shape=(高,宽,通道数) #输入特征图维度,可省略
)

举个例子

model=tf.keras.models.Sequential([
    Conv2D(6,5,padding='valid',activation='sigmoid'),
    MaxPool2D(2,2),
    Conv2D(6,(5,5),padding='valid',activation='sigmoid'),
    MaxPool2D(2,2),
    Conv2D(filters=6,kernel_size=(5,5),padding='valid',activation='sigmoid'),
    MaxPool2D(pool_size=(2,2),strides=2),
    Flatten(),
    Dense(10,activation='softmax')
])

批标准化(batch normalization,BN)

  1. 标准化:使数据符合0均值,1为标准差的分布
  2. 批标准化:对一小批数据(batch),做标准化处理,使数据回归标准正态分布,常用在卷积操作和激活操作之间,
  3. 批标准化后,第个卷积核的输出特征图中第个像素点满足公式如下
  • 上述公式中,:批标准化前,第k个卷积核,输出特征图中第i个像素点

  • :批标准化前,第k个卷积核,batch张输出特征图中所有像素点平均值

  • :批处理化前,第k个卷积核,batch张输出特征图中所有像素点标准差

但是这种简单的特征数据标准化使特征数据完全满足标准正态分布,集中在激活函数中心的线性区域,使激活函数丧失了非线性特性,因此在BN操作中为每个卷积核引入了两个可训练参数,缩放因子和偏移因子

反向传播时,缩放因子和偏移因子会与其他待训练参数一同被训练优化,使标准正态分布后的特征数据通过缩放因子和偏移因子优化了特征数据分布的宽窄和偏移量,保证了网络的非线性表达力

BN层位于卷积层之后,激活层之前

TF描述批标准化tf.keras.layers.BatchNormalization()

model=tf.keras.models.Squential([
    Conv2D(filters=6,kernel_size=(5,5),padding='same'),#卷积层
    BatchNormalization(),#BN层
    Activation('relu'),#激活层
    MaxPool2D(pool_size=(2,2),strides=2,padding='same'),#池化层
    Dropout(0.2), #Dropout层
])

池化(Pooling)

  1. 池化操作用于减少卷积神经网络中特征数据量,池化的主要方法有最大池化和均值池化,最大池化可以提取图片纹理,均值池化可以保留背景特征
  2. TF描述池化
tf,keras.layers.MaxPool2D(
    pool_size=池化核尺寸, #正方形写核长整数,或(核高h,核宽w)
    strides=池化步长, #步长整数,或(纵向步长h,横向步长w),默认为pool_size
    padding='valid' or 'same'#使用全零填充是"same",不使用是"valid"(默认)
)
-------------------------------------------------------------------------
tf.keras.layers.AveragePooling2D(
    pool_size=池化核尺寸,#正方形写核长整数,或(核高h,核宽w)
    strides=池化步长,#步长整数,或(纵向步长h,横向步长w),默认为pool_size
    padding='valid' or 'same' #使用全零填充是"same",不使用是"valid"(默认)
)
--------------------------------------------------------------------------
model=tf.keras.models.Sequential([
    Conv2D(filters=6,kernel_size=(5,5),padding='same'),#卷积层
    BatchNormalization(),#BN层
    Activation('relu'), #激活层
    MaxPool2D(pool_size=(2,2),strides=2,padding='same'),#池化层
    Dropout(0.2),#dropout层
])

舍弃(Dropout)

  1. 为了缓解神经网络过拟合,在神经网络训练过程中,常把隐藏层的部分神经元按照一定比例从神经网络中临时舍弃,在使用神经网络时,再把所有神经元恢复到神经网络中
  2. TF描述舍弃`tf.keras.layers.Dropout(舍弃的概率)
model=tf.keras.models.Sequential([
    Conv2D(filters=6,kernel_size=(5,5),padding='same'),#卷积层
    BatchNormalization(),#BN层
    Activation('relu'), #激活层
    MaxPool2D(pool_size=(2,2),strides=2,padding='same'),#池化层
    Dropout(0.2),#dropout层,0.2表示随机舍弃掉20%的神经元
])

卷积神经网络

  1. 卷积神经网络就是借助卷积核对输入特征进行特征提取,再把提取到的特征送入全连接网络进行识别预测,提取特征包括卷积、批标准化、激活、池化四步,卷积就是特征提取器,就是CBAPD,C代表卷积计算Conv2D,B代表批标准化BN,A代表激活层Avtivation,P代表池化Pooling,D代表舍弃Dropout

cifar10数据集

  1. 提供5万张像素点的十分类彩色图片和标签,用于训练
  2. 提供1万张像素点的十分类彩色图片和标签,用于测试
import tensorflow as tf
from matplotlib import pyplot as plt
import numpy as np

np.set_printoptions(threshold=np.inf)

cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# 可视化训练集输入特征的第一个元素
plt.imshow(x_train[0])  # 绘制图片
plt.show()

# 打印出训练集输入特征的第一个元素
#print("x_train[0]:\n", x_train[0])
# 打印出训练集标签的第一个元素
#print("y_train[0]:\n", y_train[0])

# 打印出整个训练集输入特征形状
print("x_train.shape:\n", x_train.shape)
# 打印出整个训练集标签的形状
print("y_train.shape:\n", y_train.shape)
# 打印出整个测试集输入特征的形状
print("x_test.shape:\n", x_test.shape)
# 打印出整个测试集标签的形状
print("y_test.shape:\n", y_test.shape)
output_1_0.png
x_train.shape:
 (50000, 32, 32, 3)
y_train.shape:
 (50000, 1)
x_test.shape:
 (10000, 32, 32, 3)
y_test.shape:
 (10000, 1)

卷积神经网络搭建示例

卷积过程

  • C(核:,步长:1,填充:same)
  • B(yes)
  • A(relu)
  • P(max,核:,步长:2,填充:same)
  • D(0.2)

Flatten

Dense(神经元:128,激活:relu,Dropout:0.2)

Dense(神经元:10,激活:softmax)

实现LeNet、ALexNet、VGGNet、InceptionNet、ResNet五个经典卷积网络

import tensorflow as tf
import os
import numpy as np
from matplotlib import pyplot as plt
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense
from tensorflow.keras import Model

np.set_printoptions(threshold=np.inf)

cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


class Baseline(Model):
    def __init__(self):
        super(Baseline, self).__init__()
        self.c1 = Conv2D(filters=6, kernel_size=(5, 5), padding='same')  # 卷积层
        self.b1 = BatchNormalization()  # BN层
        self.a1 = Activation('relu')  # 激活层
        self.p1 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')  # 池化层
        self.d1 = Dropout(0.2)  # dropout层

        self.flatten = Flatten()
        self.f1 = Dense(128, activation='relu')
        self.d2 = Dropout(0.2)
        self.f2 = Dense(10, activation='softmax')

    def call(self, x):
        x = self.c1(x)
        x = self.b1(x)
        x = self.a1(x)
        x = self.p1(x)
        x = self.d1(x)

        x = self.flatten(x)
        x = self.f1(x)
        x = self.d2(x)
        y = self.f2(x)
        return y


model = Baseline()

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

checkpoint_save_path = "./checkpoint/Baseline.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
    print('-------------load the model-----------------')
    model.load_weights(checkpoint_save_path)

cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
                                                 save_weights_only=True,
                                                 save_best_only=True)

history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
                    callbacks=[cp_callback])
model.summary()

# print(model.trainable_variables)
file = open('./weights.txt', 'w')
for v in model.trainable_variables:
    file.write(str(v.name) + '\n')
    file.write(str(v.shape) + '\n')
    file.write(str(v.numpy()) + '\n')
file.close()

###############################################    show   ###############################################

# 显示训练集和验证集的acc和loss曲线
acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
-------------load the model-----------------
Epoch 1/5
1563/1563 [==============================] - 15s 9ms/step - loss: 1.2475 - sparse_categorical_accuracy: 0.5558 - val_loss: 1.4672 - val_sparse_categorical_accuracy: 0.5108
Epoch 2/5
1563/1563 [==============================] - 15s 10ms/step - loss: 1.2192 - sparse_categorical_accuracy: 0.5673 - val_loss: 1.1591 - val_sparse_categorical_accuracy: 0.5880
Epoch 3/5
1563/1563 [==============================] - 15s 10ms/step - loss: 1.1987 - sparse_categorical_accuracy: 0.5734 - val_loss: 1.1963 - val_sparse_categorical_accuracy: 0.5760
Epoch 4/5
1563/1563 [==============================] - 15s 10ms/step - loss: 1.1813 - sparse_categorical_accuracy: 0.5805 - val_loss: 1.1741 - val_sparse_categorical_accuracy: 0.5820
Epoch 5/5
1563/1563 [==============================] - 15s 10ms/step - loss: 1.1692 - sparse_categorical_accuracy: 0.5839 - val_loss: 1.1454 - val_sparse_categorical_accuracy: 0.5940
Model: "baseline_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            multiple                  456       
_________________________________________________________________
batch_normalization_1 (Batch multiple                  24        
_________________________________________________________________
activation_1 (Activation)    multiple                  0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 multiple                  0         
_________________________________________________________________
dropout_2 (Dropout)          multiple                  0         
_________________________________________________________________
flatten_1 (Flatten)          multiple                  0         
_________________________________________________________________
dense_2 (Dense)              multiple                  196736    
_________________________________________________________________
dropout_3 (Dropout)          multiple                  0         
_________________________________________________________________
dense_3 (Dense)              multiple                  1290      
=================================================================
Total params: 198,506
Trainable params: 198,494
Non-trainable params: 12
_________________________________________________________________
output_3_1.png

你可能感兴趣的:(CNN实现离散数据的分类(以图像分类为例))