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

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真心简单方便.

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值