赞
踩
VGG是由Simonyan 和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型,其名称来源于作者所在的牛津大学视觉几何组(Visual Geometry Group)的缩写。
该模型参加2014年的 ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。
论文地址:
https://arxiv.org/abs/1409.1556
参考下面两篇文章:
https://www.cnblogs.com/lfri/p/10493408.html
https://baijiahao.baidu.com/s?id=1667221544796169037&wfr=spider&for=pc
(1)结构简单,就是一层一层顺序堆叠
(2)卷积层均采用相同的卷积核参数
(3)池化层均采用相同的池化核参数,2*2 的最大池化
(4)网络很深,达到了16层,在当时已经是最深的网络了
(5)参数多,最后3个全连接层的参数太多
需要的存储容量大,不利于部署。例如存储VGG16权重值文件的大小为500多MB,不利于安装到嵌入式系统中。
(6)特征提取能力强,现在很多网络都以vgg16作为特征提取层
每个类别包含80张图像
# 这个代码有点难懂 import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input import numpy as np import os os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" class TransferModel(object): """VGG迁移学习做5个类别图片识别 """ def __init__(self): # 初始化训练集和测试集的迭代器 self.train_generator = ImageDataGenerator(rescale=1.0 / 255.0, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) self.test_generator = ImageDataGenerator(rescale=1.0 / 255.0) # 数据目录 self.train_dir = r"H:\05学习资料\14,软件开发\黑马人工智能\2课件\阶段4-计算机视觉与图像处理\01_深度学习与CVday04\02-代码\transfer\data\train" self.test_dir = r"H:\05学习资料\14,软件开发\黑马人工智能\2课件\阶段4-计算机视觉与图像处理\01_深度学习与CVday04\02-代码\transfer\data\test" # 定义输入数据的大小和批次大小 self.image_size = (224, 224) self.batch_size = 32 # 初始化VGG基础模型, self.base_model = VGG16(weights='imagenet', include_top=False) self.label_dict = { '0': 'bus', '1': 'dinosaurs', '2': 'elephants', '3': 'flowers', '4': 'horse' } def get_local_data(self): """读取本地的图片数据以及类别标签 :return: """ # 1、datagen.flow_from_directory # 这个函数需要好好看看 # 这里没有用标签,是这个函数自动给赋予了0,1,2,3,4的标签了 train_gen = self.train_generator.flow_from_directory(self.train_dir, target_size=self.image_size, batch_size=self.batch_size, class_mode='binary', shuffle=True) test_gen = self.train_generator.flow_from_directory(self.test_dir, target_size=self.image_size, batch_size=self.batch_size, class_mode='binary', shuffle=True) return train_gen, test_gen def refine_base_model(self): """ 修改VGG的模型,在VGG的5个block,[None, ?, ?, 512]--->全局平均池化-->两个全连接层1024, 5 :return: 新的迁移学习模型 """ # 1、获取VGG模型的输出,不包含原有模型的top结构 x = self.base_model.outputs[0] # 2、在VGG的输出之后定义自己的模型 x = tf.keras.layers.GlobalAveragePooling2D()(x) # 两个全连接层 x = tf.keras.layers.Dense(1024, activation=tf.nn.relu)(x) y_predict = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x) # 3、使用Model封装新的模型返回 transfer_model = tf.keras.models.Model(inputs=self.base_model.inputs, outputs=y_predict) return transfer_model def freeze_vgg_model(self): """ 冻结VGG的前面卷积结构,不参与训练 :return: """ # 循环获取base_model当中的层 for layer in self.base_model.layers: layer.trainable = False return None def compile(self, model): """ 编译模型,指定优化器损失计算方式,准确率衡量 :return: """ model.compile(optimizer=tf.keras.optimizers.Adam(), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy']) return None def fit_generator(self, model, train_gen, test_gen): """进行模型训练,注意使用fit_generator,不是fit :param model: :param train_gen: :param test_gen: :return: """ modelckpt = tf.keras.callbacks.ModelCheckpoint('./ckpt/transfer_{epoch:02d}-{val_accuracy:.2f}.h5', monitor='val_accuracy', save_best_only=True, save_weights_only=False, mode='auto', period=1) model.fit_generator(train_gen, epochs=3, validation_data=test_gen, callbacks=[modelckpt]) return None def predict(self, model): """预测输入图片的类别 :return: """ # 1、加载模型训练好的权重 model.load_weights("./ckpt/transfer_01-0.93.h5") # 2、读取图片处理图片数据,形状,数据归一化 image = tf.io.read_file(r"H:\05学习资料\14,软件开发\黑马人工智能\2课件\阶段4-计算机视觉与图像处理\01_深度学习与CVday04\02-代码\transfer\data\test\dinosaurs\402.jpg") image_decoded = tf.image.decode_jpeg(image) image_resized = tf.image.resize(image_decoded, [224, 224]) / 255.0 # 3维-->4维的形状改变 img = tf.reshape(image_resized, (1, image_resized.shape[0], image_resized.shape[1], image_resized.shape[2])) print("修改之后的形状:", img.shape) # 3、输入数据做预测 y_predict = model.predict(img) index = np.argmax(y_predict, axis=1) print('=====', index) print('-=-=-=', index[0]) print('-=-=-=', type(index[0])) print('-=-=-=', type(str(index[0]))) print(self.label_dict[str(index[0])]) return None if __name__ == '__main__': tm = TransferModel() # 训练模型步骤 # 1、读取数据 train_gen, test_gen = tm.get_local_data() # print(train_gen, test_gen) # 2、定义模型去微调模型和冻结模型 # 3、模型的compile和训练 model = tm.refine_base_model() print(model.summary()) tm.freeze_vgg_model() tm.compile(model) tm.fit_generator(model, train_gen, test_gen) # # 测试数据 transfer_model = tm.refine_base_model() tm.predict(transfer_model)
3个文件
一个训练文件
一个单张图像预测文件
一个批量文件预测实现转移矩阵
import tensorflow as tf import os #定义一个数据读取的函数,读取指定文件夹下的数据,制作样本数据集 def read_image_filename(data_dir): building_dir=data_dir+'building/' #得到建筑的文件夹 cloud_dir=data_dir+'cloud/' farmland_dir = data_dir + 'farmland/' health_dir = data_dir + 'health/' infected_dir = data_dir + 'infected/' water_dir = data_dir + 'water/' #构建特征数据集,值为对应的图片文件名 building_filenames=tf.constant([building_dir+fn for fn in os.listdir(building_dir)]) #猫的文件名 cloud_filenames=tf.constant([cloud_dir+fn for fn in os.listdir(cloud_dir)]) farmland_filenames = tf.constant([farmland_dir + fn for fn in os.listdir(farmland_dir)]) health_filenames = tf.constant([health_dir + fn for fn in os.listdir(health_dir)]) infected_filenames = tf.constant([infected_dir + fn for fn in os.listdir(infected_dir)]) water_filenames = tf.constant([water_dir + fn for fn in os.listdir(water_dir)]) filenames=tf.concat([building_filenames,cloud_filenames,farmland_filenames,health_filenames,infected_filenames,water_filenames],axis=-1) #对矩阵按行结合 #构建标签数据集,build为0,cloud为1 labels=tf.concat([ tf.zeros(building_filenames.shape,dtype=tf.int32), #猫的数量,并赋值相应数量的0 tf.ones(cloud_filenames.shape,dtype=tf.int32), tf.fill(farmland_filenames.shape,2), tf.fill(health_filenames.shape,3), tf.fill(infected_filenames.shape,4), tf.fill(water_filenames.shape,5)], axis=-1) #安行结合 return filenames,labels #解码图片并调整图片大小 def decode_image_and_resize(filename,label): image_string=tf.io.read_file(filename) #读取原始文件 #问题1 image_decoded=tf.image.decode_jpeg(image_string) #解码JPEG图片 #调整图像大小,要和后面模型输入要求一致,并进行标准化 image_resized=tf.image.resize(image_decoded,[224,224])/255.0 return image_resized,label """ train_data_dir='./smalldata/train/' #文件夹 filenames,labels=read_image_filename(train_data_dir) dataset=tf.data.Dataset.from_tensor_slices((filenames,labels)) #构建数据集 ####print(filenames,labels) #######print(dataset) sub_dataset=dataset.take(3) #取出前三项 for x,y in sub_dataset: print('filename:',x.numpy(),'label:',y.numpy()) """ #对数据进行预处理 def prepare_dataset(data_dir,buffer_size=2000,batch_size=16): filenames,labels=read_image_filename(data_dir) print(filenames.shape) print(labels.shape) dataset=tf.data.Dataset.from_tensor_slices((filenames,labels)) dataset=dataset.map( map_func=decode_image_and_resize, #对dataset中的数据统一进行相同处理 num_parallel_calls=tf.data.experimental.AUTOTUNE ) dataset=dataset.shuffle(buffer_size)#打乱 dataset=dataset.batch(batch_size) #划好批次 dataset=dataset.prefetch(tf.data.experimental.AUTOTUNE) return dataset #vgg16模型 def vgg16_model(input_shape=(224,224,3)): vgg16=tf.keras.applications.vgg16.VGG16(include_top=False, weights='imagenet', input_shape=input_shape) for layer in vgg16.layers: layer.trainable=False #设置vgg-16预训练模型不可训练 last=vgg16.output #加入剩下未经训练的全连接层 x=tf.keras.layers.Flatten()(last) x=tf.keras.layers.Dense(128,activation='relu')(x) x=tf.keras.layers.Dropout(0.3)(x) x=tf.keras.layers.Dense(32,activation='relu')(x) x=tf.keras.layers.Dropout(0.3)(x) x=tf.keras.layers.Dense(6,activation='softmax')(x) #建立新的模型 model=tf.keras.models.Model(inputs=vgg16.input,outputs=x) model.summary() return model #建立模型,模型设置 model=vgg16_model() model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) #训练模型 #下面四步读取训练数据 #定义目录 train_data_dir='./dataset/train/' #定义缓存大小,用于打乱 buffer_size=10000 #批次大小,每个批次多少样本数 batch_size=16 #训练用的数据集 dataset_train=prepare_dataset(train_data_dir,buffer_size,batch_size) #定义超参数 training_epochs=4 #进行训练,训练数据,数据训练多少轮 train_history=model.fit(dataset_train,epochs=training_epochs,verbose=1) """ # 从训练集选0.2个用于测试, # model.fit() fit函数参数说明_可乐联盟-CSDN博客 https://blog.csdn.net/LuYi_WeiLin/article/details/88555813 train_history = model.fit(train_dataset,batch_size=batch_size,epochs=training_epochs, validation_data=validation_dataset, validation_freq=1, callbacks=cp_collback, verbose=1) # 4模型训练损失和准确率可视化 # 得到参数 acc = train_history.history['sparse_categorical_accuracy'] val_acc = train_history.history['val_sparse_categorical_accuracy'] loss = train_history.history['loss'] val_loss = train_history.history['val_loss'] # 画图,一行两列 plt.subplot(1,1,1) # 一行两列第一列 plt.plot(acc,label="Training Accuracy") plt.plot(val_acc,label="Validation Accuracy") plt.plot(loss,label="Training Loss") plt.plot(val_loss,label="Validation Loss") plt.title("Accuracy and Loss") plt.legend() # 保存和显示 plt.savefig('./result.jpg') plt.show() """ ######模型存储 #将模型结构和模型权重参数分开存储 #模型结构存储再.yaml文件中 yaml_string=model.to_yaml() with open('./models/cat_dog.yaml','w') as model_file: model_file.write(yaml_string) #模型权重参数存储在.h5文件中 model.save_weights('./models/cat_dog.h5') print("模型保存完毕!")
import tensorflow as tf from tensorflow.keras.preprocessing import image import matplotlib.pyplot as plt import os import numpy as np #载入模型 #恢复模型结构 with open('./models/cat_dog.yaml') as yamlfile: loaded_model_yaml=yamlfile.read() model=tf.keras.models.model_from_yaml(loaded_model_yaml) #导入模型的权重参数 model.load_weights('./models/cat_dog.h5') model.summary() ''' 进行数据测试,显示出准确率的想法 1、读取文件路径 1 2、得到相应的labels 1 3、得到预测结果 1 4、预测结果与labels对比,相同的话t+1, 5、t/totle ''' ###1、2读取文件和labels while True: files=input("filepath") print(files) ###3得到预测结果 #结合原来的两个函数重新定义一个函数,实现数据的预处理和预测 image_size=(224,224) test_images=[] img=image.load_img(files,target_size=image_size) img_array=image.img_to_array(img) test_images.append(img_array) test_data=np.array(test_images) test_data/=255.0 print("The test_data's shape is",end='') #end为空,实现不换行 print(test_data.shape) preds = model.predict(test_data) print(preds.shape) print(preds) max = np.argmax(preds) dict = {0:"building",1:"cloud",2:"farmland",3:"health",4:"infected",5:"water"} print(dict[max]) print("Finish!")
import tensorflow as tf from tensorflow.keras.preprocessing import image import matplotlib.pyplot as plt import os import numpy as np #载入模型 #恢复模型结构 with open('./models/cat_dog.yaml') as yamlfile: loaded_model_yaml=yamlfile.read() model=tf.keras.models.model_from_yaml(loaded_model_yaml) #导入模型的权重参数 model.load_weights('./models/cat_dog.h5') ''' 进行数据测试,显示出准确率的想法 1、读取文件路径 1 2、得到相应的labels 1 3、得到预测结果 1 4、预测结果与labels对比,相同的话t+1, 5、t/totle ''' ###1、2读取文件和labels test_data_dir='./dataset/test/' def read_image_filename(data_dir): building_dir=data_dir+'building/' #得到建筑的文件夹 cloud_dir=data_dir+'cloud/' farmland_dir = data_dir + 'farmland/' health_dir = data_dir + 'health/' infected_dir = data_dir + 'infected/' water_dir = data_dir + 'water/' #构建特征数据集,值为对应的图片文件名 building_filenames=tf.constant([building_dir+fn for fn in os.listdir(building_dir)]) #猫的文件名 cloud_filenames=tf.constant([cloud_dir+fn for fn in os.listdir(cloud_dir)]) farmland_filenames = tf.constant([farmland_dir + fn for fn in os.listdir(farmland_dir)]) health_filenames = tf.constant([health_dir + fn for fn in os.listdir(health_dir)]) infected_filenames = tf.constant([infected_dir + fn for fn in os.listdir(infected_dir)]) water_filenames = tf.constant([water_dir + fn for fn in os.listdir(water_dir)]) filenames=tf.concat([building_filenames,cloud_filenames,farmland_filenames,health_filenames,infected_filenames,water_filenames],axis=-1) #对矩阵按行结合 #构建标签数据集,build为0,cloud为1 labels=tf.concat([ tf.zeros(building_filenames.shape,dtype=tf.int32), #猫的数量,并赋值相应数量的0 tf.ones(cloud_filenames.shape,dtype=tf.int32), tf.fill(farmland_filenames.shape,2), tf.fill(health_filenames.shape,3), tf.fill(infected_filenames.shape,4), tf.fill(water_filenames.shape,5)], axis=-1) #安行结合 return filenames,labels filenames,labels=read_image_filename(test_data_dir) sess=tf.Session() #files:./smalldata/test1/dog.11200.jpg files=sess.run(filenames) print(len(files)) print(files) label=sess.run(labels) print(len(label)) print(label) ###3得到预测结果 #结合原来的两个函数重新定义一个函数,实现数据的预处理和预测 def test_predict(files,image_size=(224,224)): test_images=[] # 读取测试图片并进行预处理 for img_filename in files: img=image.load_img(img_filename,target_size=image_size) img_array=image.img_to_array(img) test_images.append(img_array) test_data=np.array(test_images) test_data/=255.0 print("The test_data's shape is",end='') #end为空,实现不换行 print(test_data.shape) preds = model.predict(test_data) print(preds.shape) print(preds) #4,t+1 k=0 t=0 #用于记录准确值 for i in range(0, len(files)): if np.argmax(preds[i]) == label[i]: t=t+1 print(t) else: print("错误:",files[i]) #5,准确率 accuracy=t/(1.0*len(files)) print("准确率为:",accuracy) return accuracy accuracy=test_predict(files) print("Finish!")
import tensorflow as tf from tensorflow.keras.preprocessing import image import matplotlib.pyplot as plt import os import numpy as np #载入模型 #恢复模型结构 with open('./models/cat_dog.yaml') as yamlfile: loaded_model_yaml=yamlfile.read() model=tf.keras.models.model_from_yaml(loaded_model_yaml) #导入模型的权重参数 model.load_weights('./models/cat_dog.h5') ''' 进行数据测试,显示出准确率的想法 1、读取文件路径 1 2、得到相应的labels 1 3、得到预测结果 1 4、预测结果与labels对比,相同的话t+1, 5、t/totle ''' ###图片路径 test_data_dir='E:/6qiege/zx3' dirs = os.listdir(test_data_dir) print("一共%d张图像"%(len(dirs))) # 用于统计个数 building_num = 0 cloud_num = 0 farmland_num = 0 health_num = 0 infected_num = 0 water_num = 0 number = 0 for jpg in dirs: number +=1 if number%1000 == 0: print("处理到第%d张."%number) image_size = (224, 224) test_images = [] jpgpath='E:/6qiege/zx3/'+jpg img = image.load_img(jpgpath, target_size=image_size) img_array = image.img_to_array(img) test_images.append(img_array) test_data = np.array(test_images) test_data /= 255.0 preds = model.predict(test_data) max = np.argmax(preds) if max==0: building_num +=1 if max==1: cloud_num +=1 if max==2: farmland_num +=1 if max==3: health_num +=1 if max==4: infected_num +=1 if max==5: water_num +=1 print("建筑%d张" % building_num) print("云体%d张" % cloud_num) print("农田%d张" % farmland_num) print("健康林%d张" % health_num) print("受害木%d张" % infected_num) print("水体%d张" % water_num)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。