keras实现多种分类网络的方式
Keras应该是最简单的一种深度学习框架了,入门非常的简单.
简单记录一下keras实现多种分类网络:如AlexNet、Vgg、ResNet
采用kaggle猫狗大战的数据作为数据集.
由于AlexNet采用的是LRN标准化,Keras没有内置函数实现,这里用batchNormalization代替
收件建立一个model.py的文件,里面存放着alexnet,vgg两种模型,直接导入就可以了
#coding=utf-8 fromkeras.modelsimportSequential fromkeras.layersimportDense,Dropout,Activation,Flatten fromkeras.layersimportConv2D,MaxPooling2D,ZeroPadding2D,BatchNormalization fromkeras.layersimport* fromkeras.layers.advanced_activationsimportLeakyReLU,PReLU fromkeras.modelsimportModel defkeras_batchnormalization_relu(layer): BN=BatchNormalization()(layer) ac=PReLU()(BN) returnac defAlexNet(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)) #OutputLayer model.add(Dense(classes,activation='softmax')) #model.add(Activation('softmax')) returnmodel defAlexNet2(inputs,classes=2,prob=0.5): ''' 自己写的函数,尝试keras另外一种写法 :paraminputs:输入 :paramclasses:类别的个数 :paramprob:dropout的概率 :return:模型 ''' #Conv2D(32,(3,3),dilation_rate=(2,2),padding='same')(inputs) print"inputshape:",inputs.shape conv1=Conv2D(filters=96,kernel_size=(11,11),strides=(4,4),padding='valid')(inputs) conv1=keras_batchnormalization_relu(conv1) print"conv1shape:",conv1.shape pool1=MaxPool2D(pool_size=(3,3),strides=(2,2))(conv1) print"pool1shape:",pool1.shape conv2=Conv2D(filters=256,kernel_size=(5,5),padding='same')(pool1) conv2=keras_batchnormalization_relu(conv2) print"conv2shape:",conv2.shape pool2=MaxPool2D(pool_size=(3,3),strides=(2,2))(conv2) print"pool2shape:",pool2.shape conv3=Conv2D(filters=384,kernel_size=(3,3),padding='same')(pool2) conv3=PReLU()(conv3) print"conv3shape:",conv3.shape conv4=Conv2D(filters=384,kernel_size=(3,3),padding='same')(conv3) conv4=PReLU()(conv4) print"conv4shape:",conv4 conv5=Conv2D(filters=256,kernel_size=(3,3),padding='same')(conv4) conv5=PReLU()(conv5) print"conv5shape:",conv5 pool3=MaxPool2D(pool_size=(3,3),strides=(2,2))(conv5) print"pool3shape:",pool3.shape dense1=Flatten()(pool3) dense1=Dense(4096,activation='relu')(dense1) print"dense2shape:",dense1 dense1=Dropout(prob)(dense1) #print"dense1shape:",dense1 dense2=Dense(4096,activation='relu')(dense1) print"dense2shape:",dense2 dense2=Dropout(prob)(dense2) #print"dense2shape:",dense2 predict=Dense(classes,activation='softmax')(dense2) model=Model(inputs=inputs,outputs=predict) returnmodel defvgg13(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')) returnmodel defvgg16(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')) returnmodel
然后建立一个train.py文件,用于读取数据和训练数据的.
#coding=utf-8 importkeras importcv2 importos importnumpyasnp importmodel importmodelResNet importtensorflowastf fromkeras.layersimportInput,Dense fromkeras.preprocessing.imageimportImageDataGenerator resize=224 batch_size=128 path="/home/hjxu/PycharmProjects/01_cats_vs_dogs/data" trainDirectory='/home/hjxu/PycharmProjects/01_cats_vs_dogs/data/train/' defload_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") foriinrange(5000): ifi%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 foriinrange(5000,10000): ifi%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 returntrain_data,train_label,test_data,test_label defmain(): 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']) ''' defcompile(self,optimizer,loss,metrics=None,loss_weights=None, sample_weight_mode=None,**kwargs): optimizer:优化器,为预定义优化器名或优化器对象,参考优化器 loss:损失函数,为预定义损失函数名或者一个目标函数 metrics:列表,包含评估模型在训练和测试时的性能指标,典型用法是metrics=['accuracy'] sample_weight_mode:如果需要按时间步为样本赋值,需要将改制设置为"temoral" 如果想用自定义的性能评估函数:如下 defmean_pred(y_true,y_pred): returnk.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) ''' deffit(self,x=None,#x:输入数据 y=None,#y:标签Numpyarray 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,#权值的numpyarray,用于训练的时候调整损失函数 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') defmain2(): 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 fromkeras.preprocessing.imageimportload_img#load_image作用是载入图片 fromkeras.preprocessing.imageimportimg_to_array fromkeras.applications.vgg16importpreprocess_input fromkeras.applications.vgg16importdecode_predictions importnumpyasnp importcv2 importmodel fromkeras.modelsimportSequential 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))#输出五个最高概率(类名,语义概念,预测概率) printy_pred
不得不说,Keras真心简单方便。
补充知识:keras中的函数式API——残差连接+权重共享的理解
1、残差连接
#coding:utf-8 """残差连接residualconnection: 是一种常见的类图网络结构,解决了所有大规模深度学习的两个共性问题: 1、梯度消失 2、表示瓶颈 (甚至,向任何>10层的神经网络添加残差连接,都可能会有帮助) 残差连接:让前面某层的输出作为后面某层的输入,从而在序列网络中有效地创造一条捷径。 """ fromkerasimportlayers 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:权重共享 能够重复的使用同一个实例,这样相当于重复使用一个层的权重,不需要重新编写""" fromkerasimportlayers fromkerasimportInput fromkeras.modelsimportModel 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实现多种分类网络的方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。