keras实现多种分类网络的方式


Posted in Python onJune 11, 2020

Keras应该是最简单的一种深度学习框架了,入门非常的简单.

简单记录一下keras实现多种分类网络:如AlexNet、Vgg、ResNet

采用kaggle猫狗大战的数据作为数据集.

由于AlexNet采用的是LRN标准化,Keras没有内置函数实现,这里用batchNormalization代替

收件建立一个model.py的文件,里面存放着alexnet,vgg两种模型,直接导入就可以了

#coding=utf-8
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, ZeroPadding2D, BatchNormalization
from keras.layers import *
from keras.layers.advanced_activations import LeakyReLU,PReLU
from keras.models import Model
 
def keras_batchnormalization_relu(layer):
 BN = BatchNormalization()(layer)
 ac = PReLU()(BN)
 return ac
 
def AlexNet(resize=227, classes=2):
 model = Sequential()
 # 第一段
 model.add(Conv2D(filters=96, kernel_size=(11, 11),
      strides=(4, 4), padding='valid',
      input_shape=(resize, resize, 3),
      activation='relu'))
 model.add(BatchNormalization())
 model.add(MaxPooling2D(pool_size=(3, 3),
       strides=(2, 2),
       padding='valid'))
 # 第二段
 model.add(Conv2D(filters=256, kernel_size=(5, 5),
      strides=(1, 1), padding='same',
      activation='relu'))
 model.add(BatchNormalization())
 model.add(MaxPooling2D(pool_size=(3, 3),
       strides=(2, 2),
       padding='valid'))
 # 第三段
 model.add(Conv2D(filters=384, kernel_size=(3, 3),
      strides=(1, 1), padding='same',
      activation='relu'))
 model.add(Conv2D(filters=384, kernel_size=(3, 3),
      strides=(1, 1), padding='same',
      activation='relu'))
 model.add(Conv2D(filters=256, kernel_size=(3, 3),
      strides=(1, 1), padding='same',
      activation='relu'))
 model.add(MaxPooling2D(pool_size=(3, 3),
       strides=(2, 2), padding='valid'))
 # 第四段
 model.add(Flatten())
 model.add(Dense(4096, activation='relu'))
 model.add(Dropout(0.5))
 
 model.add(Dense(4096, activation='relu'))
 model.add(Dropout(0.5))
 
 model.add(Dense(1000, activation='relu'))
 model.add(Dropout(0.5))
 
 # Output Layer
 model.add(Dense(classes,activation='softmax'))
 # model.add(Activation('softmax'))
 
 return model
 
def AlexNet2(inputs, classes=2, prob=0.5):
 '''
 自己写的函数,尝试keras另外一种写法
 :param inputs: 输入
 :param classes: 类别的个数
 :param prob: dropout的概率
 :return: 模型
 '''
 # Conv2D(32, (3, 3), dilation_rate=(2, 2), padding='same')(inputs)
 print "input shape:", inputs.shape
 
 conv1 = Conv2D(filters=96, kernel_size=(11, 11), strides=(4, 4), padding='valid')(inputs)
 conv1 = keras_batchnormalization_relu(conv1)
 print "conv1 shape:", conv1.shape
 pool1 = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(conv1)
 print "pool1 shape:", pool1.shape
 
 conv2 = Conv2D(filters=256, kernel_size=(5, 5), padding='same')(pool1)
 conv2 = keras_batchnormalization_relu(conv2)
 print "conv2 shape:", conv2.shape
 pool2 = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(conv2)
 print "pool2 shape:", pool2.shape
 
 conv3 = Conv2D(filters=384, kernel_size=(3, 3), padding='same')(pool2)
 conv3 = PReLU()(conv3)
 print "conv3 shape:", conv3.shape
 
 conv4 = Conv2D(filters=384, kernel_size=(3, 3), padding='same')(conv3)
 conv4 = PReLU()(conv4)
 print "conv4 shape:", conv4
 
 conv5 = Conv2D(filters=256, kernel_size=(3, 3), padding='same')(conv4)
 conv5 = PReLU()(conv5)
 print "conv5 shape:", conv5
 
 pool3 = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(conv5)
 print "pool3 shape:", pool3.shape
 
 dense1 = Flatten()(pool3)
 dense1 = Dense(4096, activation='relu')(dense1)
 print "dense2 shape:", dense1
 dense1 = Dropout(prob)(dense1)
 # print "dense1 shape:", dense1
 
 dense2 = Dense(4096, activation='relu')(dense1)
 print "dense2 shape:", dense2
 dense2 = Dropout(prob)(dense2)
 # print "dense2 shape:", dense2
 
 predict= Dense(classes, activation='softmax')(dense2)
 
 model = Model(inputs=inputs, outputs=predict)
 return model
 
def vgg13(resize=224, classes=2, prob=0.5):
 model = Sequential()
 model.add(Conv2D(64, (3, 3), strides=(1, 1), input_shape=(resize, resize, 3), padding='same', activation='relu',
      kernel_initializer='uniform'))
 model.add(Conv2D(64, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(128, (3, 2), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Flatten())
 model.add(Dense(4096, activation='relu'))
 model.add(Dropout(prob))
 model.add(Dense(4096, activation='relu'))
 model.add(Dropout(prob))
 model.add(Dense(classes, activation='softmax'))
 return model
 
def vgg16(resize=224, classes=2, prob=0.5):
 model = Sequential()
 model.add(Conv2D(64, (3, 3), strides=(1, 1), input_shape=(resize, resize, 3), padding='same', activation='relu',
      kernel_initializer='uniform'))
 model.add(Conv2D(64, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(128, (3, 2), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform'))
 model.add(MaxPooling2D(pool_size=(2, 2)))
 model.add(Flatten())
 model.add(Dense(4096, activation='relu'))
 model.add(Dropout(prob))
 model.add(Dense(4096, activation='relu'))
 model.add(Dropout(prob))
 model.add(Dense(classes, activation='softmax'))
 return model

然后建立一个train.py文件,用于读取数据和训练数据的.

#coding=utf-8
import keras
import cv2
import os
import numpy as np
import model
import modelResNet
import tensorflow as tf
from keras.layers import Input, Dense
from keras.preprocessing.image import ImageDataGenerator
 
resize = 224
batch_size = 128
path = "/home/hjxu/PycharmProjects/01_cats_vs_dogs/data"
 
trainDirectory = '/home/hjxu/PycharmProjects/01_cats_vs_dogs/data/train/'
def load_data():
 imgs = os.listdir(path + "/train/")
 num = len(imgs)
 train_data = np.empty((5000, resize, resize, 3), dtype="int32")
 train_label = np.empty((5000, ), dtype="int32")
 test_data = np.empty((5000, resize, resize, 3), dtype="int32")
 test_label = np.empty((5000, ), dtype="int32")
 for i in range(5000):
  if i % 2:
   train_data[i] = cv2.resize(cv2.imread(path + '/train/' + 'dog.' + str(i) + '.jpg'), (resize, resize))
   train_label[i] = 1
  else:
   train_data[i] = cv2.resize(cv2.imread(path + '/train/' + 'cat.' + str(i) + '.jpg'), (resize, resize))
   train_label[i] = 0
 for i in range(5000, 10000):
  if i % 2:
   test_data[i-5000] = cv2.resize(cv2.imread(path + '/train/' + 'dog.' + str(i) + '.jpg'), (resize, resize))
   test_label[i-5000] = 1
  else:
   test_data[i-5000] = cv2.resize(cv2.imread(path + '/train/' + 'cat.' + str(i) + '.jpg'), (resize, resize))
   test_label[i-5000] = 0
 return train_data, train_label, test_data, test_label
 
def main():
 
 train_data, train_label, test_data, test_label = load_data()
 train_data, test_data = train_data.astype('float32'), test_data.astype('float32')
 train_data, test_data = train_data/255, test_data/255
 
 train_label = keras.utils.to_categorical(train_label, 2)
 '''
  #one_hot转码,如果使用 categorical_crossentropy,就需要用到to_categorical函数完成转码
 '''
 test_label = keras.utils.to_categorical(test_label, 2)
 
 inputs = Input(shape=(224, 224, 3))
 
 modelAlex = model.AlexNet2(inputs, classes=2)
 '''
 导入模型
 '''
 modelAlex.compile(loss='categorical_crossentropy',
     optimizer='sgd',
     metrics=['accuracy'])
 '''
 def compile(self, optimizer, loss, metrics=None, loss_weights=None,
     sample_weight_mode=None, **kwargs):
  optimizer:优化器,为预定义优化器名或优化器对象,参考优化器
  loss: 损失函数,为预定义损失函数名或者一个目标函数
  metrics:列表,包含评估模型在训练和测试时的性能指标,典型用法是 metrics=['accuracy']
  sample_weight_mode:如果需要按时间步为样本赋值,需要将改制设置为"temoral"
  如果想用自定义的性能评估函数:如下
   def mean_pred(y_true, y_pred):
   return k.mean(y_pred)
  model.compile(loss = 'binary_crossentropy', metrics=['accuracy', mean_pred],...)
  损失函数同理,再看 keras内置支持的损失函数有
   mean_squared_error
  mean_absolute_error
  mean_absolute_percentage_error
  mean_squared_logarithmic_error
  squared_hinge
  hinge
  categorical_hinge
  logcosh
  categorical_crossentropy
  sparse_categorical_crossentropy
  binary_crossentropy
  kullback_leibler_divergence
  poisson
  cosine_proximity
 '''
 modelAlex.summary()
 '''
 # 打印模型信息
 '''
 modelAlex.fit(train_data, train_label,
    batch_size=batch_size,
    epochs=50,
    validation_split=0.2,
    shuffle=True)
 '''
 def fit(self, x=None,   # x:输入数据
   y=None,     # y:标签 Numpy array
   batch_size=32,   # batch_size:训练时,一个batch的样本会被计算一次梯度下降
   epochs=1,    # epochs: 训练的轮数,每个epoch会把训练集循环一遍
   verbose=1,    # 日志显示:0表示不在标准输入输出流输出,1表示输出进度条,2表示每个epoch输出
   callbacks=None,   # 回调函数
   validation_split=0.,  # 0-1的浮点数,用来指定训练集一定比例作为验证集,验证集不参与训练
   validation_data=None, # (x,y)的tuple,是指定的验证集
   shuffle=True,   # 如果是"batch",则是用来处理HDF5数据的特殊情况,将在batch内部将数据打乱
   class_weight=None,  # 字典,将不同的类别映射为不同的权值,用来在训练过程中调整损失函数的
   sample_weight=None,  # 权值的numpy array,用于训练的时候调整损失函数
   initial_epoch=0,   # 该参数用于从指定的epoch开始训练,继续之前的训练
   **kwargs):
 返回:返回一个History的对象,其中History.history损失函数和其他指标的数值随epoch变化的情况
 '''
 scores = modelAlex.evaluate(train_data, train_label, verbose=1)
 print(scores)
 
 scores = modelAlex.evaluate(test_data, test_label, verbose=1)
 print(scores)
 modelAlex.save('my_model_weights2.h5')
 
def main2():
 train_datagen = ImageDataGenerator(rescale=1. / 255,
          shear_range=0.2,
          zoom_range=0.2,
          horizontal_flip=True)
 test_datagen = ImageDataGenerator(rescale=1. / 255)
 train_generator = train_datagen.flow_from_directory(trainDirectory,
              target_size=(224, 224),
              batch_size=32,
              class_mode='binary')
 
 validation_generator = test_datagen.flow_from_directory(trainDirectory,
               target_size=(224, 224),
               batch_size=32,
               class_mode='binary')
 
 inputs = Input(shape=(224, 224, 3))
 # modelAlex = model.AlexNet2(inputs, classes=2)
 modelAlex = model.vgg13(resize=224, classes=2, prob=0.5)
 # modelAlex = modelResNet.ResNet50(shape=224, classes=2)
 modelAlex.compile(loss='sparse_categorical_crossentropy',
      optimizer='sgd',
      metrics=['accuracy'])
 modelAlex.summary()
 
 modelAlex.fit_generator(train_generator,
      steps_per_epoch=1000,
      epochs=60,
      validation_data=validation_generator,
      validation_steps=200)
 
 modelAlex.save('model32.hdf5')
 #
if __name__ == "__main__":
 '''
 如果数据是按照猫狗大战的数据,都在同一个文件夹下,使用main()函数
 如果数据按照猫和狗分成两类,则使用main2()函数
 '''
 main2()

得到模型后该怎么测试一张图像呢?

建立一个testOneImg.py脚本,代码如下

#coding=utf-8
from keras.preprocessing.image import load_img#load_image作用是载入图片
from keras.preprocessing.image import img_to_array
from keras.applications.vgg16 import preprocess_input
from keras.applications.vgg16 import decode_predictions
import numpy as np
import cv2
import model
from keras.models import Sequential
 
pats = '/home/hjxu/tf_study/catVsDogsWithKeras/my_model_weights.h5'
modelAlex = model.AlexNet(resize=224, classes=2)
# AlexModel = model.AlexNet(weightPath='/home/hjxu/tf_study/catVsDogsWithKeras/my_model_weights.h5')
 
modelAlex.load_weights(pats)
#
img = cv2.imread('/home/hjxu/tf_study/catVsDogsWithKeras/111.jpg')
img = cv2.resize(img, (224, 224))
x = img_to_array(img/255) # 三维(224,224,3)
 
x = np.expand_dims(x, axis=0) # 四维(1,224,224,3)#因为keras要求的维度是这样的,所以要增加一个维度
# x = preprocess_input(x) # 预处理
print(x.shape)
y_pred = modelAlex.predict(x) # 预测概率 t1 = time.time() print("测试图:", decode_predictions(y_pred)) # 输出五个最高概率(类名, 语义概念, 预测概率)
print y_pred

不得不说,Keras真心简单方便。

补充知识:keras中的函数式API——残差连接+权重共享的理解

1、残差连接

# coding: utf-8
"""残差连接 residual connection:
  是一种常见的类图网络结构,解决了所有大规模深度学习的两个共性问题:
   1、梯度消失
   2、表示瓶颈
  (甚至,向任何>10层的神经网络添加残差连接,都可能会有帮助)

  残差连接:让前面某层的输出作为后面某层的输入,从而在序列网络中有效地创造一条捷径。
       """
from keras import layers

x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)

y = layers.add([y, x]) # 将原始x与输出特征相加

# ---------------------如果特征图尺寸不同,采用线性残差连接-------------------
x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.MaxPooling2D(2, strides=2)(y)

residual = layers.Conv2D(128, 1, strides=2, padding='same')(x) # 使用1*1的卷积,将原始张量线性下采样为y具有相同的形状

y = layers.add([y, residual]) # 将原始x与输出特征相加

2、权重共享

即多次调用同一个实例

# coding: utf-8
"""函数式子API:权重共享
  能够重复的使用同一个实例,这样相当于重复使用一个层的权重,不需要重新编写"""
from keras import layers
from keras import Input
from keras.models import Model


lstm = layers.LSTM(32) # 实例化一个LSTM层,后面被调用很多次

# ------------------------左边分支--------------------------------
left_input = Input(shape=(None, 128))
left_output = lstm(left_input) # 调用lstm实例

# ------------------------右分支---------------------------------
right_input = Input(shape=(None, 128))
right_output = lstm(right_input) # 调用lstm实例

# ------------------------将层进行连接合并------------------------
merged = layers.concatenate([left_output, right_output], axis=-1)

# -----------------------在上面构建一个分类器---------------------
predictions = layers.Dense(1, activation='sigmoid')(merged)

# -------------------------构建模型,并拟合训练-----------------------------------
model = Model([left_input, right_input], predictions)
model.fit([left_data, right_data], targets)

以上这篇keras实现多种分类网络的方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的高级函数map/reduce使用实例
Apr 13 Python
python开启多个子进程并行运行的方法
Apr 18 Python
Python实现高效求解素数代码实例
Jun 30 Python
Python中集合的内建函数和内建方法学习教程
Aug 19 Python
Python3.6正式版新特性预览
Dec 15 Python
Python2与python3中 for 循环语句基础与实例分析
Nov 20 Python
Python提取支付宝和微信支付二维码的示例代码
Feb 15 Python
Python爬取视频(其实是一篇福利)过程解析
Aug 01 Python
Python数组并集交集补集代码实例
Feb 18 Python
Python3标准库glob文件名模式匹配的问题
Mar 13 Python
利用Python实现自动扫雷小脚本
Dec 17 Python
给numpy.array增加维度的超简单方法
Jun 02 Python
python的help函数如何使用
Jun 11 #Python
新手学python应该下哪个版本
Jun 11 #Python
python开发前景如何
Jun 11 #Python
python编写softmax函数、交叉熵函数实例
Jun 11 #Python
python能开发游戏吗
Jun 11 #Python
使用sklearn对多分类的每个类别进行指标评价操作
Jun 11 #Python
python属于解释语言吗
Jun 11 #Python
You might like
十天学会php(3)
2006/10/09 PHP
基于mysql的论坛(2)
2006/10/09 PHP
php设计模式 Decorator(装饰模式)
2011/06/26 PHP
Codeigniter校验ip地址的方法
2015/03/21 PHP
PHP操作Postgresql封装类与应用完整实例
2018/04/24 PHP
基于laravel-admin 后台 列表标签背景的使用方法
2019/10/03 PHP
flash 得到自身url参数的代码
2009/11/15 Javascript
关于 文本框默认值 的操作js代码
2012/01/12 Javascript
JS HTML5 音乐天气播放器(Ajax获取天气信息)
2013/05/26 Javascript
Chrome下ifame父窗口调用子窗口的问题示例探讨
2014/03/17 Javascript
jQuery UI插件自定义confirm确认框的方法
2015/03/20 Javascript
基于Echarts 3.19 制作常用的图形(非静态)
2016/05/19 Javascript
js实现鼠标拖动功能
2017/03/20 Javascript
使用node打造自己的命令行工具方法教程
2018/03/26 Javascript
JS实现动态生成html table表格的方法分析
2018/07/11 Javascript
layui获取多选框中的值方法
2018/08/15 Javascript
使用electron制作满屏心特效的示例代码
2018/11/27 Javascript
微信小程序实现打卡日历功能
2020/09/21 Javascript
javascript防抖函数debounce详解
2019/06/11 Javascript
微信小程序的授权实现过程解析
2019/08/02 Javascript
vue 使用localstorage实现面包屑的操作
2020/11/16 Javascript
[01:16:37]【全国守擂赛】第三周决赛 Dark Knight vs. 一个弱队
2020/05/04 DOTA
Python从单元素字典中获取key和value的实例
2018/12/31 Python
python实现七段数码管和倒计时效果
2019/11/23 Python
如何编写python的daemon程序
2021/01/07 Python
html5中去掉input type date默认样式的方法
2018/09/06 HTML / CSS
英国知名奢侈品包包品牌:Milli Millu
2016/12/22 全球购物
财务会计应届生求职信
2013/11/24 职场文书
机械设计职业生涯规划书
2013/12/27 职场文书
农民工创业典型事迹
2014/01/25 职场文书
超市国庆节促销方案
2014/02/20 职场文书
化工专业自荐书
2014/06/16 职场文书
肖申克的救赎观后感
2015/06/02 职场文书
Python turtle实现贪吃蛇游戏
2021/06/18 Python
铁头也玩根德 YachtBoy YB-230......
2022/04/05 无线电
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL