首页 > 基于Keras的CNN/Densenet实现分类

基于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.001drop = 0.5epochs_drop = 10lrate = 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 或 lossverbose=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/97500808callbacks=[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 cv2def 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 modeldef 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 modeldef 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 = 3while 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, labelsdef step_decay(epoch):init_lrate = 0.001drop = 0.5epochs_drop = 10lrate = init_lrate * pow(drop, np.floor(1 + epoch) / epochs_drop)print('learning rate: ', lrate)return lrateinput = 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 = Truemodel_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')

更多相关:

  • size_t和int       size_t是一些C/C++标准在stddef.h中定义的。这个类型足以用来表示对象的大小。size_t的真实类型与操作系统有关。 在32位架构中被普遍定义为: typedef   unsigned int size_t; 而在64位架构中被定义为: typedef  unsigned lo...

  • 我在 https://blog.csdn.net/wowricky/article/details/83218126 介绍了一种内存池,它的实现类似于linux 中打开slub_debug (1. make menuconfig: Kenel hacking -> Memory Debugging, 2. comand line中传入...

  • 项目开发中需要从引擎 获取一定范围的数据大小,用作打点上报,测试过程中竟然发现写入了一部分数据之后通过GetApproximateSizes 获取写入的key的范围时取出来的数据大小竟然为0。。。难道发现了一个bug?(欣喜) 因为写入的数据是小于一个sst的data-block(默认是4K),会不会因为GetApproximate...

  •   在使用tensorflow分类MNIST数据集中,最容易遇到的问题是下载MNIST样本的问题。   一般是通过使用tensorflow内置的函数进行下载和加载,   from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read...

  • 学习计划 MyPlan11 主题:Python描述统计、简单统计图形 时间:8.5-8.11周内完成 参考资料:新书《谁说菜鸟不会数据分析python篇》 各位星友们,在这个星球里每个人都要逼迫自己学习未知的领域或知识点,每天进步一点点,积累的时间久了 ,菜鸟也能起飞。 完成情况: 在pandas中,使用describe函数进行描述统...

  • 利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信。 首先,先了解下SocketServer模块中可供使用的类: BaseServer:包含服务器的核心功能与混合(mix-in)类挂钩;这个类只用于派生,所以不会生成这个类的实例;可以考虑使用TCPServer和UDPServer。 TCPServer/UDPS...

  • 题目:序列化二叉树 请实现两个函数,分别用来序列化和反序列化二叉树。 示例:  你可以将以下二叉树:     1    /   2   3      /     4   5 序列化为 "[1,2,3,null,null,4,5]" 解题: /*** Definition for a binary tree no...

  • sd.js  import $global from "./global"; import $g from "./sg"; import $ from "jquery"; import {Message, Loading} from "element-ui";//引入饿了么相关组件 import {Base64} from "js-...

  •     原生sd.js----------------------------------------------------------------  const API_ROOT_URL = "http://www.api.com";const $d= {_postList_url: API_ROOT_URL + "/api...