基于Keras的CNN/Densenet实现分类

1. 定义网络的基本参数

定义输入网络的是什么:

input = Input(shape=(240, 640, 3))

反向传播时梯度下降算法

SGD一定会收敛,但是速度慢
Adam速度快但是可能不收敛
[link](https://blog.csdn.net/wydbyxr/article/details/84822806)
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)

学习率

lrate = LearningRateScheduler(step_decay)

其中step_decay函数是自动学习率算法

def step_decay(epoch):
    init_lrate = 0.001
    drop = 0.5
    epochs_drop = 10
    lrate = init_lrate * pow(drop, np.floor(1 + epoch) / epochs_drop)
    print('learning rate: ', lrate)
    return lrate

设置batch size

batch_size = 32 //一次丢给网络的数目

读入训练集和验证集

train_lines = []
val_lines = []
with open('data.txt') as file:
    lines = file.readlines()
    for line in lines:
        line = line.strip()
        line = line.split(' ')
        train_lines.append([line[0], line[1]])

with open('val.txt') as file:
    lines = file.readlines()
    for line in lines:
        line = line.strip()
        line = line.split(' ')
        val_lines.append([line[0], line[1]])

/*txt中是这样的:数字是第几类
moredata/1/001.png 1
moredata/1/002.png 1
moredata/1/003.png 2
moredata/1/004.png 3
moredata/1/005.png 4
moredata/1/006.png 1
moredata/1/007.png 1
moredata/1/008.png 1
moredata/1/009.png 1
……
*/

2. 定义网络结构

CNN

def cnn(input):
 	**三层卷积层**
    conv1 = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(input)
    # conv1a = BatchNormalization()(conv1a) // BN层,防止飘移,过拟合
    conv1 = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(conv1)
    pool1 = MaxPooling2D((2, 2))(conv1)

    conv2 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(pool1)
    # conv1a = BatchNormalization()(conv1a)
    conv2 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(conv2)
    pool2 = MaxPooling2D((2, 2))(conv2)

    conv3 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(pool2)
    # conv1a = BatchNormalization()(conv1a)
    conv3 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(conv3)
    pool3 = MaxPooling2D((2, 2))(conv3)

    flatten = Flatten()(pool3) //拉成一列
    dense1 = Dense(1024, activation='relu')(flatten) //全连接层
    dense2 = Dense(3, activation='softmax')(dense1)
    model = Model(inputs=input, outputs=dense2)
    return model

Densenet

def dense(input):
    conv1a = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(input)
    # conv1a = BatchNormalization()(conv1a)
    conv1b = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(conv1a)
    # conv1b = BatchNormalization()(conv1b)
    merge1 = concatenate([conv1a, conv1b], axis=-1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(merge1)

    conv2a = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(pool1)
    # conv2a = BatchNormalization()(conv2a)
    conv2b = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(conv2a)
    # conv2b = BatchNormalization()(conv2b)
    merge2 = concatenate([conv2a, conv2b], axis=-1)
    pool2 = MaxPooling2D(pool_size=(2, 2))(merge2)

    conv3a = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(pool2)
    # conv3a = BatchNormalization()(conv3a)
    conv3b = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(conv3a)
    # conv3b = BatchNormalization()(conv3b)
    merge3 = concatenate([conv3a, conv3b], axis=-1)
    pool3 = MaxPooling2D(pool_size=(2, 2))(merge3)

    conv4a = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(pool3)
    # conv4a = BatchNormalization()(conv4a)
    conv4b = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(conv4a)
    # conv4b = BatchNormalization()(conv4b)
    merge4 = concatenate([conv4a, conv4b], axis=-1)
    pool4 = MaxPooling2D(pool_size=(2, 2))(merge4)

    flatten = Flatten()(pool4)
    dense1 = Dense(128, activation='sigmoid')(flatten)
    dense2 = Dropout(0.25)(dense1)
    output = Dense(3, activation='softmax')(dense2)

    model = Model(inputs=input, outputs=output)
    return model

3. 开始训练吧

输入的参数也定义好了,网络结构也搭建好了,就可以训练了

调用网络

model = cnn(input)

记录网络的参数信息,保留模型的最佳参数,保存到h5文件

ck_name = 'training/cnn' + '.h5'
checkpoint = ModelCheckpoint(ck_name,
                             monitor='val_acc', //val_acc 或 val_loss 或 acc 或 loss
                             verbose=1, //0或1。为1表示输出epoch模型保存信息,默认为0表示不输出该信息
                             save_best_only=True,//是否保存最佳模型
                             mode='auto') //min max auto
history = model.fit_generator(generator=data_generator(train_lines, batch_size),
                              steps_per_epoch=len(train_lines) // batch_size,
                              epochs=100,
                              verbose=2, //日志显示https://blog.csdn.net/Hodors/article/details/97500808
                              callbacks=[lrate, checkpoint],
                              validation_data=data_generator(val_lines, batch_size),
                              validation_steps=len(val_lines) // batch_size)

记录网络结构保存成json文件

model_json = model.to_json()
with open(os.path.join('training/cnn.json'), 'w') as json_file:
    json_file.write(model_json)

运行网络

model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
// categorical_crossentropy 交叉熵损失函数
// 梯度优化器是SGD
history = model.fit_generator(generator=data_generator(train_lines, batch_size),
                              steps_per_epoch=len(train_lines) // batch_size,
                              epochs=100,
                              verbose=2,
                              callbacks=[lrate, checkpoint],
                              validation_data=data_generator(val_lines, batch_size),
                              validation_steps=len(val_lines) // batch_size)

fit_generator是Python 生成器(或 Sequence 实例)逐批生成的数据,按批次训练模型
其中data_generator是自写的,主要是对输入图像或数据的处理

将图像分为2类,txt中标的是1, 2,3,4, 5。我们想让前3个是一类,后两个是一类,用的独热编码。每张图转换为灰度图,然后三张图叠在一起作为一张图,这有点类似于LSTM的思想,使其有时间序列
def data_generator(data_list, batch_size=32):
    get_one_hot = {'1': [1, 0, 0], '2': [1, 0, 0], '3': [1, 0, 0],
                   '4': [0, 1, 0], '5': [0, 0, 1]}
    while True:
        for i in range(0, len(data_list) - 3, batch_size):
            labels = []
            images = []
            data_list_batch = data_list[i:i + batch_size + 3]
            # print(data_list_batch)

            for j in range(len(data_list_batch) - 3):
                # print(data_list_batch[j][0])
                images_3 = []
                image1 = cv2.imread(data_list_batch[j][0])
                image1 = image1[110:590, :, :]
                image1 = cv2.resize(image1, (240, 640))
                image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
                image1 = (image1 - image1.min()) / (image1.max() - image1.min())

                image2 = cv2.imread(data_list_batch[j + 1][0])
                image2 = image2[110:590, :, :]
                image2 = cv2.resize(image2, (240, 640))
                image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)
                image2 = (image2 - image2.min()) / (image2.max() - image2.min())

                image3 = cv2.imread(data_list_batch[j + 2][0])
                image3 = image3[110:590, :, :]
                image3 = cv2.resize(image3, (240, 640))
                image3 = cv2.cvtColor(image3, cv2.COLOR_BGR2GRAY)
                image3 = (image3 - image3.min()) / (image3.max() - image3.min())

                images_3.append(image1)
                images_3.append(image2)
                images_3.append(image3)

                images_3 = np.asarray(images_3).reshape((image1.shape[0], image1.shape[1], 3))

                images.append(images_3)

                label = get_one_hot[data_list_batch[j + 2][1]]
                labels.append(label)

            images = np.asarray(images).reshape([len(data_list_batch) - 3, 240, 640, 3])
            labels = np.asarray(labels).reshape([len(data_list_batch) - 3, 3])
            yield images, labels

结束训练

4. 训练结果可视化

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)

//画图
plt.figure()
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'r', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.savefig('training/accuary_cnn' + '.png')

plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.savefig('training/loss_cnn' + '.png')

Code

from keras import backend as K
from keras.models import Model, Sequential
from keras.layers import Activation
from keras.layers import AveragePooling2D
from keras.layers import BatchNormalization
from keras.layers import Concatenate
from keras.layers import Conv2D, Dense, Dropout
from keras.layers import Dense, Add
from keras.layers import concatenate, LSTM
from keras.layers import GlobalAveragePooling2D
from keras.layers import GlobalMaxPooling2D
from keras.layers import Input, Flatten
from keras.layers import MaxPooling2D
import os
import matplotlib.pyplot as plt
from keras import regularizers, optimizers
import numpy as np
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
import cv2


def cnn(input):
    conv1 = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(input)
    # conv1a = BatchNormalization()(conv1a)
    conv1 = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(conv1)
    pool1 = MaxPooling2D((2, 2))(conv1)

    conv2 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(pool1)
    # conv1a = BatchNormalization()(conv1a)
    conv2 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(conv2)
    pool2 = MaxPooling2D((2, 2))(conv2)

    conv3 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(pool2)
    # conv1a = BatchNormalization()(conv1a)
    conv3 = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(conv3)
    pool3 = MaxPooling2D((2, 2))(conv3)

    flatten = Flatten()(pool3)
    dense1 = Dense(1024, activation='relu')(flatten)
    dense2 = Dense(3, activation='softmax')(dense1)
    model = Model(inputs=input, outputs=dense2)
    return model


def dense(input):
    # input = Input(shape=(128, 128, 3))
    conv1a = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(input)
    # conv1a = BatchNormalization()(conv1a)
    conv1b = Conv2D(16, kernel_size=(3, 3), padding='same', activation='relu')(conv1a)
    # conv1b = BatchNormalization()(conv1b)
    merge1 = concatenate([conv1a, conv1b], axis=-1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(merge1)

    conv2a = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(pool1)
    # conv2a = BatchNormalization()(conv2a)
    conv2b = Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu')(conv2a)
    # conv2b = BatchNormalization()(conv2b)
    merge2 = concatenate([conv2a, conv2b], axis=-1)
    pool2 = MaxPooling2D(pool_size=(2, 2))(merge2)

    conv3a = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(pool2)
    # conv3a = BatchNormalization()(conv3a)
    conv3b = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(conv3a)
    # conv3b = BatchNormalization()(conv3b)
    merge3 = concatenate([conv3a, conv3b], axis=-1)
    pool3 = MaxPooling2D(pool_size=(2, 2))(merge3)

    conv4a = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(pool3)
    # conv4a = BatchNormalization()(conv4a)
    conv4b = Conv2D(64, kernel_size=(3, 3), padding='same', activation='relu')(conv4a)
    # conv4b = BatchNormalization()(conv4b)
    merge4 = concatenate([conv4a, conv4b], axis=-1)
    pool4 = MaxPooling2D(pool_size=(2, 2))(merge4)

    flatten = Flatten()(pool4)
    dense1 = Dense(128, activation='sigmoid')(flatten)
    dense2 = Dropout(0.25)(dense1)
    output = Dense(3, activation='softmax')(dense2)

    model = Model(inputs=input, outputs=output)
    return model


def data_generator(data_list, batch_size=32):
    get_one_hot = {'1': [1, 0, 0], '2': [1, 0, 0], '3': [1, 0, 0],
                   '4': [0, 1, 0], '5': [0, 0, 1]}
    mini_img = 3
    while True:
        for i in range(0, len(data_list) - mini_img, batch_size):
            labels = []
            images = []
            data_list_batch = data_list[i:i + batch_size + mini_img]

            for j in range(len(data_list_batch) - mini_img):
                # print(data_list_batch[j][0])
                images_3 = []
                image1 = cv2.imread(data_list_batch[j][0])
                image1 = image1[110:590, :, :]
                image1 = cv2.resize(image1, (240, 640))
                image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
                image1 = (image1 - image1.min()) / (image1.max() - image1.min())

                image2 = cv2.imread(data_list_batch[j + 1][0])
                image2 = image2[110:590, :, :]
                image2 = cv2.resize(image2, (240, 640))
                image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)
                image2 = (image2 - image2.min()) / (image2.max() - image2.min())

                image3 = cv2.imread(data_list_batch[j + 2][0])
                image3 = image3[110:590, :, :]
                image3 = cv2.resize(image3, (240, 640))
                image3 = cv2.cvtColor(image3, cv2.COLOR_BGR2GRAY)
                image3 = (image3 - image3.min()) / (image3.max() - image3.min())

                images_3.append(image1)
                images_3.append(image2)
                images_3.append(image3)

                images_3 = np.asarray(images_3).reshape((image1.shape[0], image1.shape[1], 3))

                images.append(images_3)

                label = get_one_hot[data_list_batch[j + 2][1]]
                labels.append(label)

            images = np.asarray(images).reshape([len(data_list_batch) - mini_img, 240, 640, 3])
            labels = np.asarray(labels).reshape([len(data_list_batch) - mini_img, mini_img])
            yield images, labels


def step_decay(epoch):
    init_lrate = 0.001
    drop = 0.5
    epochs_drop = 10
    lrate = init_lrate * pow(drop, np.floor(1 + epoch) / epochs_drop)
    print('learning rate: ', lrate)
    return lrate


input = Input(shape=(240, 640, 3))
ck_name = 'training/cnn' + '.h5'
checkpoint = ModelCheckpoint(ck_name,
                             monitor='val_acc',
                             verbose=1,
                             save_best_only=True,
                             mode='auto')

sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
lrate = LearningRateScheduler(step_decay)
batch_size = 32
train_lines = []
val_lines = []
with open('data.txt') as file:
    lines = file.readlines()
    for line in lines:
        line = line.strip()
        line = line.split(' ')
        train_lines.append([line[0], line[1]])

with open('val.txt') as file:
    lines = file.readlines()
    for line in lines:
        line = line.strip()
        line = line.split(' ')
        val_lines.append([line[0], line[1]])
# print(train_lines[0])
# # model = dense(input)
# model = resnet(input)
model = cnn(input)

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

history = model.fit_generator(generator=data_generator(train_lines, batch_size),
                              steps_per_epoch=len(train_lines) // batch_size,
                              epochs=100,
                              verbose=2,
                              callbacks=[lrate, checkpoint],
                              validation_data=data_generator(val_lines, batch_size),
                              validation_steps=len(val_lines) // batch_size)
# for layer in model.layers:
#     layer.trainable = True

model_json = model.to_json()
with open(os.path.join('training/cnn.json'), 'w') as json_file:
    json_file.write(model_json)

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)

plt.figure()
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'r', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.savefig('training/accuary_cnn' + '.png')

plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.savefig('training/loss_cnn' + '.png')

猜你喜欢

转载自blog.csdn.net/qq_41598072/article/details/108730744
今日推荐