赞
踩
修改说明:为了能使迁移学习所训练出的模型能适应后续的知识蒸馏,因此对迁移的代码做了细节上的修订。后续红色标明字样,皆为修改后的内容
采用模型分离的方式构造迁移学习,可以降低反向传播时卷积运算的工作量。
首先选定迁移的目标并提取其卷积基 可按照不同的需求提取迁移特征。keras除此外还有 DenseNet121、MobileNet、Xception等网络可以用于迁移
注意:1、要按照个人需求和电脑配置调整 shape,batch_size, 和models数组内的模型名称
2、要从tensorflow.kreas中引入application库,这样子才能支持更多的模型库(如EfficientNet系列)
3、新增os环境设置,避免价值tensorflow时输出太多不必要的信息
- import os
- os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # or any {'0', '1', '2'}
- from keras.preprocessing.image import ImageDataGenerator
- from keras.utils import np_utils
- #from tensorflow.python.keras.utils import np_utils #上面语句报错可以改成这个
- from tensorflow.keras import applications,Model
- import numpy as np
- import os,gc
- batch_size=32#ResNet50,VGG16,InceptionV3 EfficientNetB7 NASNetLarge
- shape=(226, 226)
- # DenseNet169 DenseNet201 #DenseNet121 ResNet152V2 ,"InceptionV3","MobileNetV3Small","ResNet50V2","VGG19"
- models=["EfficientNetB0"]#
- for modelname in models:
- mstr="applications.%s(include_top=False,input_shape=(114,114,3), weights='imagenet')"%modelname
- base = eval(mstr)
- print(modelname)
- print(modelname)
- model= Model(input=base.input, output=base.layers[-1].output)
数据集的划分可以查看python工具方法 4 依据随机种子将图片文件划分为训练集、测试集、验证集_a486259的博客-CSDN博客,代码复制后即可运行
文件夹:flower 通过该代码可得到:flower-训练,flower-验证,flower-测试三个文件夹
所提取的特征保存在features文件夹中,命名方式为:
modelname_data_训练、modelname_data_验证、modelname_data_测试
modelname_labels_训练、modelname_labels_验证、modelname_labels_测试
- #代码复制过来不想调整缩进,所以使用了if True来控制
- if True:
- datagen = ImageDataGenerator()#(rescale=1.0 / 255)
- root_path='./features/'
- if not os.path.exists(root_path):
- os.makedirs(root_path)
- dirList=['训练','验证','测试']
- data_path='flower//'
- for path in dirList:
- generator = datagen.flow_from_directory(data_path+'-'+path,
- target_size=shape,
- batch_size=batch_size,
- class_mode='categorical',
- shuffle=False)
- print(generator.class_indices)#输出数据的labels
- labels= np_utils.to_categorical(generator.classes)
- np.save(open(root_path+'label.npy', 'wb'), generator.class_indices)
- features= model.predict_generator(generator, len(generator.classes)/generator.batch_size)
- print('result.shape: ',features.shape)
- #import sys;sys.exit()
- print(len(generator.classes))
- print(path,'集-卷积池化数据固化成功!')
- np.save(open('%s%s_data_%s.npy'%(root_path,modelname,path), 'wb'), features)
- np.save(open('%s%s_labels_%s.npy'%(root_path,modelname,path), 'wb'), labels)
- np.save(open('%s%s_fileName_%s.npy'%(root_path,modelname,path), 'wb'), generator.filenames)
- gc.collect()
- import numpy as np
- root_path='./features/VGG16_'
- train_data = np.load(root_path+'data_训练.npy')
- train_data=train_data.reshape(train_data.shape[0],-1)
- train_label = np.load(root_path+'labels_训练.npy')
- shuffle=True
- if shuffle:
- import random
- randnum = random.randint(0,100)
- random.seed(randnum)
- random.shuffle(train_data)
- random.seed(randnum)
- random.shuffle(train_label)
-
- validation_data = np.load(root_path+'data_验证.npy')
- validation_data=validation_data.reshape(validation_data.shape[0],-1)
- validation_label =np.load(root_path+'labels_验证.npy')
-
- test_data = np.load(root_path+'data_测试.npy')
- test_data=test_data.reshape(test_data.shape[0],-1)
- test_label =np.load(root_path+'labels_测试.npy')
-
- #数据的扁平化
- inputShape=np.array(train_data.shape[1:]).prod()
- train_data=train_data.reshape(-1,inputShape)
- test_data=test_data.reshape(-1,inputShape)
- validation_data=validation_data.reshape(-1,inputShape)
在这里修改了两行代码,移除了最后一个Dense中的激活函数,并为每一个dense设置了name,通过这种操作,可以已另一种方式实现模型拼接。需要进行更高级的知识蒸馏(实现kl loss,softmax升温)的朋友,请不要使用后续的模型拼接代码。
output = Dense(class_types,name='dense_out')(x)
output = Activation(tf.nn.softmax,name='Activation_out')(output)
- import tensorflow as tf
- from keras.models import Model
- from keras.layers import Dense,Input,Dropout,Activation
-
- inputs = Input(shape=(inputShape,))
- x = Dense(100, activation='relu',name='dense1')(inputs)
- x = Dense(50, activation='relu',name='dense2')(x)
- x = Dropout(0.2)(x)
- output = Dense(class_types,name='dense_out')(x)
- output = Activation(tf.nn.softmax,name='Activation_out')(output)
- model = Model(inputs=inputs, outputs=output)
- model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['acc'])
-
- from keras.callbacks import History,ModelCheckpoint,EarlyStopping
- #最佳模型保存
- ModelCheckpoint=ModelCheckpoint('best_model.h5', monitor='acc', verbose=0, save_best_only=True, save_weights_only=False, mode='auto', period=1)
- #提前终止
- EarlyStopping=EarlyStopping(monitor='val_loss', patience=2, verbose=2, mode='auto')
- #历史数据记录
- loss_history = History()
- #模型训练
- model.fit(train_data,train_label,epochs=100,batch_size=32,
- callbacks=[ModelCheckpoint,EarlyStopping,loss_history]
- validation_data=(validation_data, validation_label),
- verbose=2)
- #模型评估
- loss,acc=model.evaluate(test_data, test_label )
- print('loss:',loss,'acc:',acc)
- #历史数据绘图
- import pandas as pd
- d=pd.DataFrame(data=loss_history.history)
- d.to_csv('history.csv')
01.feature_save.py 复制代码保存为01.feature_save.py,然后执行,完成迁移特征的提取与保存
- import os
- os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # or any {'0', '1', '2'}
- from tensorflow.keras.preprocessing.image import ImageDataGenerator
- from tensorflow.python.keras.utils.np_utils import to_categorical
- from tensorflow.keras import applications,Model
- import numpy as np
- import os,gc
- batch_size=32#ResNet50,VGG16,InceptionV3 EfficientNetB7 NASNetLarge
- shape=(56, 56)
- # DenseNet169 DenseNet201 #DenseNet121 ResNet152V2 ,"InceptionV3","MobileNetV3Small","ResNet50V2","VGG19"
- models=["EfficientNetB0"]#
- for modelname in models:
- mstr="applications.%s(include_top=False,input_shape=(114,114,3), weights='imagenet')"%modelname
- base = eval(mstr)
- print(modelname)
- print(modelname)
- model= Model(inputs=base.input, outputs=base.layers[-1].output)
- datagen = ImageDataGenerator()#(rescale=1.0 / 255)
- root_path='./features/'
- if not os.path.exists(root_path):
- os.makedirs(root_path)
- dirList=['训练','验证','测试']
- data_path = r"./flower"
- for path in dirList:
- generator = datagen.flow_from_directory(data_path+'-'+path,
- target_size=shape,
- batch_size=batch_size,
- class_mode='categorical',
- shuffle=False)
- print(generator.class_indices)#输出数据的labels
- labels= to_categorical(generator.classes)
- np.save(open(root_path+'label.npy', 'wb'), generator.class_indices)
- features= model.predict_generator(generator, len(generator.classes)/generator.batch_size)
- print('result.shape: ',features.shape)
- #import sys;sys.exit()
- print(len(generator.classes))
- print(path,'集-卷积池化数据固化成功!')
- np.save(open('%s%s_data_%s.npy'%(root_path,modelname,path), 'wb'), features)
- np.save(open('%s%s_labels_%s.npy'%(root_path,modelname,path), 'wb'), labels)
- np.save(open('%s%s_fileName_%s.npy'%(root_path,modelname,path), 'wb'), generator.filenames)
- gc.collect()
02.new_cls.py 复制代码保存为02.new_cls.py,然后执行,完成分类器训练
- #------------------------------特征数据读取---------------------------------------
- import numpy as np
- class_types=2
- root_path='./features/VGG16_'
- train_data = np.load(root_path+'data_训练.npy')
- train_label = np.load(root_path+'labels_训练.npy')
- shuffle=True
- if shuffle:
- import random
- randnum = random.randint(0,100)
- random.seed(randnum)
- random.shuffle(train_data)
- random.seed(randnum)
- random.shuffle(train_label)
-
- validation_data = np.load(root_path+'data_验证.npy')
- validation_label =np.load(root_path+'labels_验证.npy')
-
- test_data = np.load(root_path+'data_测试.npy')
- test_label =np.load(root_path+'labels_测试.npy')
- #-----------------------------------重新训练全连接分类器--------------------------
-
- from keras.models import Model
- from keras.layers import Dense,Input,Dropout,GlobalAveragePooling2D
-
- inputs = Input(shape=test_data[0].shape)
- x = GlobalAveragePooling2D()(inputs)#GlobalAveragePooling2D 为了减少对数据的形变操作,和降低模型参数量
- x = Dense(100, activation='relu')(x)
- x = Dense(50, activation='relu')(x)
- x = Dropout(0.2)(x)
- output = Dense(class_types, activation='softmax')(x)
- model = Model(inputs=inputs, outputs=output)
- model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['acc'])
-
- from keras.callbacks import History,ModelCheckpoint,EarlyStopping
- #最佳模型保存
- ModelCheckpoint=ModelCheckpoint('gap_best_model.h5', monitor='acc', verbose=0, save_best_only=True, save_weights_only=False, mode='auto', period=1)
- #提前终止
- EarlyStopping=EarlyStopping(monitor='val_loss', patience=15, verbose=2, mode='auto')
- #历史数据记录
- loss_history = History()
- #模型训练
- model.fit(train_data,train_label,epochs=100,batch_size=32,
- callbacks=[ModelCheckpoint,EarlyStopping,loss_history],
- validation_data=(validation_data, validation_label),
- verbose=2)
- #模型评估
- loss,acc=model.evaluate(test_data, test_label)
- print('test loss:',loss,'acc:',acc)
- loss,acc=model.evaluate(train_data, train_label)
- print('train loss:',loss,'acc:',acc)
- loss,acc=model.evaluate(validation_data, validation_label)
- print('valid loss:',loss,'acc:',acc)
- #历史数据绘图
- import pandas as pd
- d=pd.DataFrame(data=loss_history.history)
- d.to_csv(root_path+'history.csv')
复制代码既可用 深度学习 11 keras迁移学习模型拼接_a486259的博客-CSDN博客
迁移后的模型体量太大,复制该代码既可
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。