CV】keras_resnet 在cifar10数据集上分类

2024-02-02 11:38

本文主要是介绍CV】keras_resnet 在cifar10数据集上分类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

码农有道 2020-06-01 14:29:17  510  收藏
展开
文章目录
1.导入库
2.数据准备
2.1 加载训练集
2.2 加载测试集
2.3 对类别做One-Hot编码
2.4 对图片像素的0-255值做归一化,并减去均值
3.搭建神经网络
3.1 定义函数resnet_layer,返回值是经过resnet_layer计算的结果
3.2 定义函数resnet_v1,返回值是模型对象
3.3 定义函数resnet_v2,返回值是模型对象
3.4 实例化模型对象
3.5 多GPU并行训练
3.6 打印模型架构信息
4. 模型训练
4.1 规划学习率(训练到后期时学习率需减小)
4.2 模型训练时的参数设置
4.3 使用图像增强的结果做模型训练
5.模型评估
5.1 加载训练好的模型
5.2 计算训练集的准确率
5.3 计算测试集的准确率
6. 模型测试结果可视化
6.1 随机选100张图可视化
6.2 随机选取100张图片的同时,要求10个类别,每个类别取10张
7.Keras中权重文件的读写
7.1 使用load_model方法加载模型文件
7.2 使用save_weights方法保存权重文件
7.3 使用load_weights方法加载权重文件
1.导入库
1.keras(resnet):https://github.com/keras-team/keras/blob/master/examples/cifar10_resnet.py
2.用到的cifar10数据集和模型权重链接:https://pan.baidu.com/s/1L4oZAPg_9B_YipPeihmBwQ 提取码:8jcw
5个data_batch文件,每个1万数据

# 加入下面2行,可以使py代码文件中的修改即时生效
%load_ext autoreload
%autoreload 2
# 下行如果python2使用print,也得加上括号
from __future__ import print_function
import keras
# 导入keras库的这4种层:全连接层Dense,2维卷积层Conv2D,批量归一化层BatchNormalization,激活层Activation
from keras.layers import Dense, Conv2D, BatchNormalization, Activation
# 导入keras库的这3种层:平均2维池化层AveratePooling2D, 输入层Input,激活层Activation
from keras.layers import AveragePooling2D, Input, Flatten
# 导入keras库的优化器:Adam优化器
from keras.optimizers import Adam
# 导入keras库的回传函数:模型检查点ModelCheckpoint, LearningRateScheduler
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
# 导入keras库的回传函数:学习率递减ReduceLROnPlateau
from keras.callbacks import ReduceLROnPlateau
# 导入keras库的图片处理函数:图片数据生成器
from keras.preprocessing.image import ImageDataGenerator
# 导入keras库的正则化函数:L2正则化
from keras.regularizers import l2
# 导入keras库的后端:backend中文叫做后端,取别名为K
from keras import backend as K
# 导入keras库的模型函数:Model
from keras.models import Model
# 导入keras库的数据集类:cifar10
from keras.datasets import cifar10
# 导入必需的常用库
import numpy as np
import os
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2.数据准备
2.1 加载训练集
官方代码没有指定路径:


from keras.datasets.cifar import load_batch #load_batch用于加载指定路径
## 加载数据集cifar10里面的训练集
def load_train_dataset(dirPath='../resources/cifar-10-batches-py/'):
    train_sample_quantity = 50000
    image_width = 32
    image_height = 32
    channel_quantity = 3
    train_X = np.zeros((train_sample_quantity, channel_quantity, image_width, image_height),
                       dtype='uint8')
    train_y = np.zeros((train_sample_quantity, ),
                       dtype='uint8')  #下面循环写入相同大小零矩阵
    for i in range(1, 6):
        fileName = 'data_batch_%d' %i  #看文件名格式
        filePath = os.path.join(dirPath, fileName)
        startIndex = (i - 1) * 10000
        endIndex = i * 10000             #用到了load_batch,训练集定义5万,循环5次,0-1万行,1万-2万行....
        train_X[startIndex:endIndex, :, :, :], train_y[startIndex:endIndex] = load_batch(filePath)
                                      
    print('train_X矩阵转置前:', train_X.shape)
    # 从官网上下载的数据集的4个维度为样本个数n、通道数c、宽度w、高度h
    # Keras基于Tensorflow,数据的维度顺序要求:样本个数n、宽度w、高度h、通道数c,所以使用np.transpose完成矩阵转置
    train_X = train_X.transpose(0, 2, 3, 1)
    print('train_X矩阵转置后:', train_X.shape)
    return train_X, train_y

dirPath = '../resources/cifar-10-batches-py/'
train_imageData, train_y = load_train_dataset() 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27


2.2 加载测试集
# 加载数据集cifar10里面的测试集
def load_test_dataset(dirPath='../resources/cifar-10-batches-py/'):
    fileName = 'test_batch'
    filePath = os.path.join(dirPath, fileName)
    test_X, test_y = load_batch(filePath)
    print('test_X矩阵转置前:', test_X.shape)
    test_X = test_X.transpose(0, 2, 3, 1)
    print('test_X矩阵转置后:', test_X.shape)
    return test_X, test_y

dirPath = '../resources/cifar-10-batches-py/'
test_imageData, test_y = load_test_dataset()
1
2
3
4
5
6
7
8
9
10
11
12


2.3 对类别做One-Hot编码
# 对类别ID做One-Hot编码
from keras.utils import to_categorical

class_quantity = 10
train_Y = to_categorical(train_y, class_quantity)
test_Y = to_categorical(test_y, class_quantity)
1
2
3
4
5
6
2.4 对图片像素的0-255值做归一化,并减去均值
train_X = train_imageData.astype('float32') / 255
test_X = test_imageData.astype('float32') / 255
pixel_mean = np.mean(train_X, axis=0)
print('pixel_mean.shape:', pixel_mean.shape)
train_X = train_X - pixel_mean
test_X = test_X - pixel_mean
1
2
3
4
5
6


3.搭建神经网络
3.1 定义函数resnet_layer,返回值是经过resnet_layer计算的结果
def resnet_layer(inputs,   #定义了一层resnet_layer
                 num_filters=16,
                 kernel_size=3,
                 strides=1,
                 activation='relu',
                 batch_normalization=True,
                 conv_first=True):
    
    conv = Conv2D(num_filters,
                  kernel_size=kernel_size,
                  strides=strides,
                  padding='same',
                  kernel_initializer='he_normal',
                  kernel_regularizer=l2(1e-4))

    x = inputs
    if conv_first: #为resnet V1
        x = conv(x) #conv为一函数,相当于下图weight
        if batch_normalization:
            x = BatchNormalization()(x)
        if activation is not None:
            x = Activation(activation)(x)
    else:  #为resnet V2
        if batch_normalization:
            x = BatchNormalization()(x) #BatchNormalization()实例化一个函数对象
        if activation is not None:
            x = Activation(activation)(x)
        x = conv(x)
    return x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29


3.2 定义函数resnet_v1,返回值是模型对象
def resnet_v1(input_shape, depth, num_classes=10):
    if (depth - 2) % 6 != 0:
        raise ValueError('depth should be 6n+2 (eg 20, 32, 44 in [a])')
    # Start model definition.
    num_filters = 16
    num_res_blocks = int((depth - 2) / 6)

    inputs = Input(shape=input_shape)
    x = resnet_layer(inputs=inputs)
    # Instantiate the stack of residual units
    for stack in range(3):
        for res_block in range(num_res_blocks):
            strides = 1
            if stack > 0 and res_block == 0:  # first layer but not first stack
                strides = 2  # downsample
            y = resnet_layer(inputs=x,
                             num_filters=num_filters,
                             strides=strides)
            y = resnet_layer(inputs=y,
                             num_filters=num_filters,
                             activation=None)
            if stack > 0 and res_block == 0:  # first layer but not first stack
                # linear projection residual shortcut connection to match
                # changed dims
                x = resnet_layer(inputs=x,
                                 num_filters=num_filters,
                                 kernel_size=1,
                                 strides=strides,
                                 activation=None,
                                 batch_normalization=False)
            x = keras.layers.add([x, y])
            x = Activation('relu')(x)
        num_filters *= 2
    # Add classifier on top.
    # v1 does not use BN after last shortcut connection-ReLU
    x = AveragePooling2D(pool_size=8)(x)
    y = Flatten()(x)
    outputs = Dense(num_classes,
                    activation='softmax',
                    kernel_initializer='he_normal')(y)

    # Instantiate model.
    model = Model(inputs=inputs, outputs=outputs)
    return model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
3.3 定义函数resnet_v2,返回值是模型对象
def resnet_v2(input_shape, depth, num_classes=10):
    if (depth - 2) % 9 != 0:#深度必须是9n+2,比如20层,56层,110层
        raise ValueError('depth should be 9n+2 (eg 56 or 110 in [b])')
    # Start model definition.
    num_filters_in = 16 # 卷积核数量
    num_res_blocks = int((depth - 2) / 9)
    inputs = Input(shape=input_shape)
    
    x = resnet_layer(inputs=inputs,  # resnet lay 0如下表,第一次调用了一层resnet_layer
                     num_filters=num_filters_in,
                     conv_first=True)
                     
    # Instantiate the stack of residual units 实例化剩余单元的堆栈
    for stage in range(3):
        for res_block in range(num_res_blocks):
            activation = 'relu'
            batch_normalization = True
            strides = 1
            if stage == 0: 
            #如果stage和res_block == 0,不进行activation,batch_normalization,
                num_filters_out = num_filters_in * 4
                if res_block == 0:  # first layer and first stage
                    activation = None
                    batch_normalization = False
            else:
                num_filters_out = num_filters_in * 2
                if res_block == 0:  # first layer but not first stage
                    strides = 2    # downsample
            # bottleneck residual unit
            y = resnet_layer(inputs=x,
                             num_filters=num_filters_in,
                             kernel_size=1,
                             strides=strides,
                             activation=activation,
                             batch_normalization=batch_normalization,
                             conv_first=False)
            y = resnet_layer(inputs=y,
                             num_filters=num_filters_in,
                             conv_first=False)
            y = resnet_layer(inputs=y,
                             num_filters=num_filters_out,
                             kernel_size=1,
                             conv_first=False)
            if res_block == 0:
                # linear projection residual shortcut connection to match
                # changed dims
                x = resnet_layer(inputs=x,
                                 num_filters=num_filters_out,
                                 kernel_size=1,
                                 strides=strides,
                                 activation=None,
                                 batch_normalization=False)
            x = keras.layers.add([x, y]) #实现shotcut

        num_filters_in = num_filters_out
    #如上三个resnet_layer调用一个shotcut
    
    # Add classifier on top.
    # v2 has BN-ReLU before Pooling
    x = BatchNormalization()(x)  #如下三行代码对应下表对应后面几行
    x = Activation('relu')(x)
    x = AveragePooling2D(pool_size=8)(x)
    y = Flatten()(x)
    outputs = Dense(num_classes,
                    activation='softmax',
                    kernel_initializer='he_normal')(y)

    # Instantiate model.
    model = Model(inputs=inputs, outputs=outputs)
    return model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
3.4 实例化模型对象
# Model version
# Orig paper: version = 1 (ResNet v1), Improved ResNet: version = 2 (ResNet v2)
version = 2
# Computed depth from supplied model parameter n
n = 2
if version == 1:
    depth = n * 6 + 2
elif version == 2:
    depth = n * 9 + 2
    
# 根据ResNet版本,获取对应的模型对象
if version == 2:
    model = resnet_v2(input_shape=input_shape, depth=depth)
else:
    model = resnet_v1(input_shape=input_shape, depth=depth)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
3.5 多GPU并行训练
https://github.com/matterport/Mask_RCNN/blob/master/mrcnn/parallel_model.py
打开parallel_model.py文件,在原来文件加入红点一行:


from parallel_model import ParallelModel

gpu_count = 2
model = ParallelModel(model, gpu_count)
model.compile(loss='categorical_crossentropy',
              optimizer=Adam(lr=0.001),
              metrics=['accuracy'])
1
2
3
4
5
6
7
3.6 打印模型架构信息
# Model name, depth and version
model_type = 'ResNet%dv%d' % (depth, version)
print(model_type)
model.summary()
1
2
3
4

如下所示三个resnet_layer为一个shotcut,但如上图是两个layer再加,作者用的三个效果更好

用于数据集cifar10的图像分类网络ResNet20v2架构

    处理层_0: 输入层,调用keras.layers中的Input类,通过传递参数shape实例化对象
    数据层_0:矩阵形状:              N x 32 x 32 x 3

resnet_layer_0 #对应2.3节第一个x = resnet_layer  #第一个3表示上层通道数或卷积核fliter数                 
        处理层_1:conv2d_1      卷积核形状:        3 x 3 x 3 x 16 / 1 
 #输入3大小3*3输出16,步长1,因为输出是16,所以加16个b 
 #所以3*3*3*16=432(卷积核占的参数量)再加16为第一层conv2d_1参数个数448                        
    数据层_1:矩阵形状:              N x 32 x 32 x 16  #None表示batch size       
        处理层_2:batch_normalization_1
    数据层_2: 矩阵形状:              N x 32 x 32 x 16
        处理层_3:activation_1
    数据层_3:矩阵形状:              N x 32 x 32 x 16 


resnet_layer_1        
        处理层_4:conv2d_2      卷积核形状:        16 x 1 x 1 x 16 / 1        
    数据层_4:矩阵形状:              N x 32 x 32 x 16


resnet_layer_2    
        处理层_5:batch_normalization_2
    数据层_5:矩阵形状:              N x 32 x 32 x 16
        处理层_6:activation_2
    数据层_6: 矩阵形状:              N x 32 x 32 x 16
        处理层_7:conv2d_3      卷积核形状:         16 x 3 x 3 x 16 / 1
    数据层_7:矩阵形状:              N x 32 x 32 x 16
    
    
resnet_layer_3    
        处理层_8: batch_normalization_3
    数据层_8:矩阵形状:               N x 32 x 32 x 16
        处理层_9:activation_3    
    数据层_9:矩阵形状:               N x 32 x 32 x 16
        处理层_10:conv2d_4     卷积核形状:       16 x 1 x 1 x 64 / 1
    数据层_10:矩阵形状:              N x 32 x 32 x 64


shortcut_1 #不默认对上层处理,取指定层处理,相加,route_1是自己定义的
        处理层_11:route_1   取数据层_3 #数据层_3和下行数据层_11是同一层
    数据层_11:矩阵形状:            N x 32 x 32 x 16   
        处理层_12:conv2d_5     卷积核形状:       16 x 1 x 1 x 64 / 1
        #(32-1+0)/1 +1=32,公式里第一个32表示上层长32,第二个32是得出这层长
        #N x 32 x 32 x 16经过16 x 1 x 1 x 64 / 1处理得出N x 32 x 32 x 64即下行
    数据层_12:矩阵形状:            N x 32 x 32 x 64 
        处理层_13:add_1     把数据层_10、数据层_12相加
    数据层_13:矩阵形状:            N x 32 x 32 x 64    
    
///   
    
resnet_layer_4
        处理层_14:batch_normalization_4
    数据层_14:矩阵形状:             N x 32 x 32 x 64
        处理层_15:activation_4
    数据层_15:矩阵形状:             N x 32 x 32 x 64
        处理层_16:conv2d_6    卷积核形状:        64 x 1 x 1 x 16 / 1  
    数据层_16:矩阵形状:             N x 32 x 32 x 16
    
    
resnet_layer_5    
        处理层_17:batch_normalization_5
    数据层_17:矩阵形状:             N x 32 x 32 x 16
        处理层_18:activation_5
    数据层_18:矩阵形状:             N x 32 x 32 x 16
        处理层_19:conv2d_7    卷积核形状:        16 x 3 x 3 x 16 / 1  
    数据层_19:矩阵形状:             N x 32 x 32 x 16
    
    
resnet_layer_6
        处理层_20:batch_normalization_6
    数据层_20:矩阵形状:           N x 32 x 32 x 16
        处理层_21:activation_6
    数据层_21:矩阵形状:            N x 32 x 32 x 16
        处理层_22:conv2d_8    卷积核形状:       16 x 1 x 1 x 64 / 1
    数据层_22:矩阵形状:           N x 32 x 32 x 64


shortcut_2
        处理层_23:add_2     把数据层_22、数据层_13相加
    数据层_23:矩阵形状:            N x 32 x 32 x 64
    
//
  
resnet_layer_7    
        处理层_24:batch_normalization_7 
    数据层_24:矩阵形状:            N x 32 x 32 x 64
        处理层_25:activation_7
    数据层_25:矩阵形状:            N x 32 x 32 x 64
        处理层_26:conv2d_9     卷积核形状:      64 x 1 x 1 x 64 / 2
    数据层_26:矩阵形状:           N x 16 x 16 x 64 #通道扩展指最后位64变大,
                                                   #下采样指由32*32变为16*16

resnet_layer_8
        处理层_25:batch_normalization_8
    数据层_25:矩阵形状:            N x 16 x 16 x 64
        处理层_26:activation_8
    数据层_26:矩阵形状:            N x 16 x 16 x 64
        处理层_27:conv2d_10    卷积核形状:      64 x 3 x 3 x 64 / 1
    数据层_27:矩阵形状:            N x 16 x 16 x 64
    
resnet_layer_9
        处理层_28:batch_normalization_9
    数据层_28:矩阵形状:           N x 16 x 16 x 64
        处理层_29:activation_9
    数据层_29:矩阵形状             N x 16 x 16 x 64
        处理层_30:conv2d_11    卷积核形状:      64 x 1 x 1 x 128 / 1
    数据层_30:矩阵形状             N x 16 x 16 x 128

shortcut_3
        处理层_31:route_2        取数据层_23
    数据层_31:矩阵形状:            N x 32 x 32 x 64
        处理层_32:conv2d_12    卷积核形状:      64 x 1 x 1 x 128 / 2
    数据层_32:矩阵形状:           N x 16 x 16 x 128
        处理层_33:add_3        把数据层_32、数据层_30相加
    数据层_33:矩阵形状:           N x 16 x 16 x 128    

resnet_layer_10    
        处理层_34:batch_normalization_10
    数据层_34:矩阵形状:            N x 16 x 16 x 128
        处理层_35:activation_10
    数据层_35:矩阵形状:            N x 16 x 16 x 128
        处理层_36:conv2d_13    卷积核形状:      128 x 1 x 1 x 64 / 1
    数据层_36:矩阵形状:            N x 16 x 16 x 64

resnet_layer_11
        处理层_37:batch_normalization_11
    数据层_37:矩阵形状:            N x 16 x 16 x 64
        处理层_38:activation_11
    数据层_38:矩阵形状:            N x 16 x 16 x 64
        处理层_39:conv2d_14    卷积核形状:       64 x 3 x 3 x 64 / 1
    数据层_39:矩阵形状:            N x 16 x 16 x 64
    
resnet_layer_12    
        处理层_40:batch_normalization_12
    数据层_40:矩阵形状:            N x 16 x 16 x 64
        处理层_41:activation_12
    数据层_41:矩阵形状:            N x 16 x 16 x 64
        处理层_42:conv2d_15    卷积核形状:       64 x 1 x 1 x 128 / 1
    数据层_42:矩阵形状:            N x 16 x 16 x 128
    
shortcut_4
        处理层_43:add_4        把数据层_42、数据层_33相加
    数据层_43:矩阵形状:           N x 16 x 16 x 128

/

resnet_layer_13    
        处理层_44:batch_normalization_13
    数据层_44:矩阵形状:            N x 16 x 16 x 128
        处理层_45:activation_13
    数据层_45:矩阵形状:            N x 16 x 16 x 128
        处理层_46:conv2d_16    卷积核形状:       128 x 1 x 1 x 128 / 2
    数据层_46:矩阵形状:            N x 8 x 8 x 128    

resnet_layer_14    
        处理层_47:batch_normalization_14
    数据层_47:矩阵形状:            N x 8 x 8 x 128
        处理层_48:activation_14
    数据层_48:矩阵形状:            N x 8 x 8 x 128
        处理层_49:conv2d_17    卷积核形状:     128 x 3 x 3 x 128 / 1
    数据层_49:矩阵形状:            N x 8 x 8 x 128

resnet_layer_15    
        处理层_50:batch_normalization_15
    数据层_50:矩阵形状:            N x 8 x 8 x 128
        处理层_51:activation_15
    数据层_51:矩阵形状:            N x 8 x 8 x 128
        处理层_52:conv2d_18    卷积核形状:     128 x 1 x 1 x 256 / 1
    数据层_52:矩阵形状:            N x 8 x 8 x 256
         
shortcut_5
        处理层_53:route_3          取数据层_43
    数据层_53:矩阵形状:            N x 16 x 16 x 128    
        处理层_54:conv2d_19    卷积核形状:      128 x 1 x 1 x 256 / 2
    数据层_54:矩阵形状:            N x 8 x 8 x 256
        处理层_55:add_5        把数据层_54、数据层_52相加
    数据层_55:矩阵形状:           N x 8 x 8 x 256    

 
    
resnet_layer_16    
        处理层_56:batch_normalization_16
    数据层_56:矩阵形状:            N x 8 x 8 x 256 
        处理层_57:activation_16
    数据层_57:矩阵形状:            N x 8 x 8 x 256 
        处理层_58:conv2d_20    卷积核形状:     256 x 1 x 1 x 128 / 1
    数据层_58:矩阵形状:            N x 8 x 8 x 128 

resnet_layer_17
        处理层_59:batch_normalization_17
    数据层_59:矩阵形状:            N x 8 x 8 x 128
        处理层_60:activation_17
    数据层_60:矩阵形状:            N x 8 x 8 x 128 
        处理层_61:conv2d_21    卷积核形状:     128 x 3 x 3 x 128 / 1
    数据层_61:矩阵形状:            N x 8 x 8 x 128

resnet_layer_18
        处理层_62:batch_normalization_18
    数据层_62:矩阵形状:            N x 8 x 8 x 128
        处理层_63:activation_18
    数据层_63:矩阵形状:            N x 8 x 8 x 128 
        处理层_64:conv2d_22    卷积核形状:     128 x 1 x 1 x 256 / 1
    数据层_64:矩阵形状:            N x 8 x 8 x 256

shortcut_6  #18层每3次一共做了6次shortcut
        处理层_62:add_6        把数据层_64、数据层_55相加
    数据层_62:矩阵形状:           N x 8 x 8 x 256

/
    
classifier#如果是yoloV3就是yolo层了
        处理层_63:batch_normalization_19
    数据层_63:矩阵形状:           N x 8 x 8 x 256
        处理层_64:activation_19
    数据层_64:矩阵形状:           N x 8 x 8 x 256
        处理层_65:average_pooling2d_1
    数据层_65:矩阵形状:           N x 1 x 1 x 256
        处理层_66:flatten_1
    数据层_66:矩阵形状:           N x 256
        处理层_67:dense_1
    数据层_67:矩阵形状:           N x 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
所以ResNet20_V2:这个20是conv共19层(layer0)+dense1层

4. 模型训练
4.1 规划学习率(训练到后期时学习率需减小)
def lr_schedule(epoch):
    lr = 1e-3
    if epoch > 180:
        lr *= 0.5e-3
    elif epoch > 160:
        lr *= 1e-3
    elif epoch > 120:
        lr *= 1e-2
    elif epoch > 80:
        lr *= 1e-1
    print('Learning rate: ', lr)
    return lr
1
2
3
4
5
6
7
8
9
10
11
12
4.2 模型训练时的参数设置
# Training parameters
batch_size = 64  # orig paper trained all networks with batch_size=128
epochs = 200

# Prepare model model saving directory.
save_dir = os.path.abspath('../resources/saved_models')
model_name = 'cifar10_%s_model.{epoch:03d}.h5' % model_type
if not os.path.isdir(save_dir):
    os.makedirs(save_dir)
filepath = os.path.join(save_dir, model_name)

# Prepare callbacks for model saving and for learning rate adjustment.
checkpoint = ModelCheckpoint(filepath=filepath,
                             monitor='val_acc',
                             verbose=0,
                             save_best_only=True)
lr_scheduler = LearningRateScheduler(lr_schedule)
lr_reducer = ReduceLROnPlateau(factor=np.sqrt(0.1),
                               cooldown=0,
                               patience=5,
                               min_lr=0.5e-6)
callbacks = [checkpoint, lr_reducer, lr_scheduler]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
4.3 使用图像增强的结果做模型训练
data_augmentation = True
if data_augmentation:
    print('Using real-time data augmentation.')
    # This will do preprocessing and realtime data augmentation:
    datagen = ImageDataGenerator(
        # set input mean to 0 over the dataset
        featurewise_center=False,
        # set each sample mean to 0
        samplewise_center=False,
        # divide inputs by std of dataset
        featurewise_std_normalization=False,
        # divide each input by its std
        samplewise_std_normalization=False,
        # apply ZCA whitening
        zca_whitening=False,
        # epsilon for ZCA whitening
        zca_epsilon=1e-06,
        # randomly rotate images in the range (deg 0 to 180)
        rotation_range=0,
        # randomly shift images horizontally
        width_shift_range=0.1,
        # randomly shift images vertically
        height_shift_range=0.1,
        # set range for random shear
        shear_range=0.,
        # set range for random zoom
        zoom_range=0.,
        # set range for random channel shifts
        channel_shift_range=0.,
        # set mode for filling points outside the input boundaries
        fill_mode='nearest',
        # value used for fill_mode = "constant"
        cval=0.,
        # randomly flip images
        horizontal_flip=True,
        # randomly flip images
        vertical_flip=False,
        # set rescaling factor (applied before any other transformation)
        rescale=None,
        # set function that will be applied on each input
        preprocessing_function=None,
        # image data format, either "channels_first" or "channels_last"
        data_format=None,
        # fraction of images reserved for validation (strictly between 0 and 1)
        validation_split=0.0)

   
    datagen.fit(x_train)

    # Fit the model on the batches generated by datagen.flow().
    model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size),
                        validation_data=(x_test, y_test),
                        epochs=epochs,
                        verbose=1, 
                        workers=4,
                        callbacks=callbacks)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

附:python的生成器与keras.preprocessing.image文件的ImageDataGenerator类的关系:
问号可以找在哪个路径:


如下图打开image.py发现是继承image:


找image:


5.模型评估
5.1 加载训练好的模型
from keras.models import load_model
from keras.optimizers import Adam

model_filePath = '../resources/saved_models/cifar10_ResNet56v2_model.162.h5'
model = load_model(model_filePath)
model.compile(loss='categorical_crossentropy',
              optimizer=Adam(lr=0.001),
              metrics=['accuracy'])
1
2
3
4
5
6
7
8
5.2 计算训练集的准确率
scores = model.evaluate(train_X, train_Y, verbose=1, batch_size=1000)
print('Test loss:%.6f' %scores[0])
print('Test accuracy:%.6f' %scores[1])
1
2
3


5.3 计算测试集的准确率
scores = model.evaluate(test_X, test_Y, verbose=1, batch_size=1000)
print('Test loss:%.6f' %scores[0])
print('Test accuracy:%.6f' %scores[1])
1
2
3


6. 模型测试结果可视化
6.1 随机选100张图可视化
import math
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
import random

def draw_image(position, image, title, isTrue):
    plt.subplot(*position)
    plt.imshow(image)
    plt.axis('off')
    if not isTrue:
        plt.title(title, color='red')
    else:
        plt.title(title)
        
def batch_draw_images(model, batch_size, test_imageData, test_X, test_y, id2name_dict):
    index_list = list(range(len(test_imageData)))
    selected_index_list = random.sample(index_list, batch_size)
    true_imageData = test_imageData[selected_index_list]
    true_X = test_X[selected_index_list]
    true_y = np.array(test_y)[selected_index_list]
    predict_Y = model.predict(true_X)
    predict_y = np.argmax(predict_Y, axis=1)
    row_number = math.ceil(batch_size ** 0.5)
    column_number = row_number
    plt.figure(figsize=(row_number+8, column_number+8))
    for i in range(row_number):
        for j in range(column_number):
            index = i * column_number + j
            if index < batch_size:
                position = (row_number, column_number, index+1)
                image = true_imageData[index]
                actual_classId = true_y[index]
                predict_classId = predict_y[index]
                isTrue = actual_classId==predict_classId
                actual_className = id2name_dict[actual_classId]
                predict_className = id2name_dict[predict_classId]
                title = 'actual:%s\npredict:%s' %(actual_className, predict_className)
                draw_image(position, image, title, isTrue)

batch_size = 100 #展示100张图
className_list = ['飞机', '汽车', '鸟', '猫', '鹿', '狗', '青蛙', '马', '船', '卡车']
id2name_dict = {a:b for a, b in enumerate(className_list)}
batch_draw_images(model, batch_size, test_imageData, test_X, test_y, id2name_dict)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


6.2 随机选取100张图片的同时,要求10个类别,每个类别取10张
def get_selectedIndexList(test_y, batch_size):
    assert batch_size % 10 == 0, 'batch_size must be times by 10, or you change function get_selectedIndexList'
    column_number = int(batch_size / 10)
    classId_ndarray = np.unique(test_y)
    selected_index_list = []
    for i, classId in enumerate(classId_ndarray):
        index_ndarray = np.where(test_y==classId)[0]
        selected_index_ndarray = np.random.choice(index_ndarray, column_number)
        selected_index_list.extend(selected_index_ndarray.tolist())
    return selected_index_list    
        
def batch_draw_images_2(model, selected_index_list, test_imageData, test_X, test_y, id2name_dict):
    true_imageData = test_imageData[selected_index_list]
    true_X = test_X[selected_index_list]
    true_y = np.array(test_y)[selected_index_list]
    predict_Y = model.predict(true_X)
    predict_y = np.argmax(predict_Y, axis=1)
    row_number = math.ceil(batch_size ** 0.5)
    column_number = row_number
    plt.figure(figsize=(row_number+8, column_number+8))
    for i in range(row_number):
        for j in range(column_number):
            index = i * column_number + j
            if index < batch_size:
                position = (row_number, column_number, index+1)
                image = true_imageData[index]
                actual_classId = true_y[index]
                predict_classId = predict_y[index]
                isTrue = actual_classId==predict_classId
                actual_className = id2name_dict[actual_classId]
                predict_className = id2name_dict[predict_classId]
                title = 'actual:%s\npredict:%s' %(actual_className, predict_className)
                draw_image(position, image, title, isTrue)

batch_size = 100     
className_list = ['飞机', '汽车', '鸟', '猫', '鹿', '狗', '青蛙', '马', '船', '卡车']
id2name_dict = {a:b for a, b in enumerate(className_list)}
selected_index_list = get_selectedIndexList(test_y, batch_size)
batch_draw_images_2(model, selected_index_list, test_imageData, test_X, test_y, id2name_dict)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
7.Keras中权重文件的读写
7.1 使用load_model方法加载模型文件
from keras.models import load_model
from keras.optimizers import Adam

model_filePath = '../resources/saved_models/cifar10_ResNet56v2_model.162.h5'
model = load_model(model_filePath)
model.compile(loss='categorical_crossentropy',
              optimizer=Adam(lr=0.001),
              metrics=['accuracy'])
1
2
3
4
5
6
7
8
7.2 使用save_weights方法保存权重文件
weights_h5FilePath = '../resources/saved_models/resnet56v2_weights.h5'
model.save_weights(weights_h5FilePath)
1
2
7.3 使用load_weights方法加载权重文件
input_shape = (32, 32, 3)
depth = 56
model = resnet_v2(input_shape, depth)
weights_h5FilePath = '../resources/saved_models/resnet56v2_weights.h5'
model.load_weights(weights_h5FilePath)
model.compile(loss='categorical_crossentropy',
              optimizer=Adam(lr=0.001),
              metrics=['accuracy'])
 

这篇关于CV】keras_resnet 在cifar10数据集上分类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/670584

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X