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实现多种分类网络的方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。