Keras实现——使用预训练的卷积神经网络(VGG16)提取图像特征


参考文献:

https://blog.csdn.net/weixin_42560055/article/details/110097730

https://blog.csdn.net/kan2281123066/article/details/83474456

用VGG-16预训练好的模型提取特征,通过相关学者预训练好的模型使用的都是公开的标准数据集,所以我们直接用预训练的模型提取我们自己图像的特征,可以用于对图像进行描述。

1、首先就要下载模型结构

https://github.com/2281123066/vgg-tensorflow

预训练好的模型是VGG16.npy,这个文件需要单独下载,上面那个连接上有下载连接,不过一般打不开,我把网盘地址分享 出来,希望可以帮助需要的人。
文件test_vgg16.py可以用于提取特征。其中vgg16.npy是需要单独下载的文件。
2、使用预训练的模型提取特征
github地址:https://github.com/leiup/tensorflow-vgg/blob/master/test_vgg16.py
打开test_vgg16.py,做如下修改:

import numpy as np
import tensorflow as tf
import vgg16
import utils

img1 = utils.load_image(“./test_data/tiger.jpeg”)
img2 = utils.load_image(“./test_data/puzzle.jpeg”)

batch1 = img1.reshape((1, 224, 224, 3))
batch2 = img2.reshape((1, 224, 224, 3))

batch = np.concatenate((batch1, batch2), 0)
with tf.device(’/cpu:0’):

with tf.Session() as sess:
    images = tf.placeholder("float", [2, 224, 224, 3])
    feed_dict = {images: batch}
    
    vgg = vgg16.Vgg16()
    with tf.name_scope("content_vgg"):
        vgg.build(images)

    prob = sess.run(vgg.fc7, feed_dict=feed_dict)   #需要提取哪一层特征,就在这里做修改,比如fc6,只需要把vgg.fc7修改为vgg.fc6
    print(prob)

提取哪一层的特征,需要把名字修改一下即可,而名字可以查vgg16.py,里面定义了每一层的名字。
所有操作已经完毕

https://github.com/speechdnn/deep-learning-models

VGG16内置于Keras,可以通过keras.applications模块中导入。
--------------------------------------将VGG16 卷积实例化:-------------------------------------------------------

from keras.applications import VGG16

conv_base = VGG16(weights = 'imagenet',#指定模型初始化的权重检查点
                   include_top = False,
                   input_shape = (48,48,3))   

weights:指定模型初始化的权重检查点、

include_top: 指定模型最后是否包含密集连接分类器。默认情况下,这个密集连接分类器对应于ImageNet的100个类别。如果打算使用自己的密集连接分类器,可以不适用它,置为False。

input_shape: 是输入到网络中的图像张量的形状。这个参数完全是可选的,如果不传入这个参数,那么网络能够处理任意形状的输入。

--------------------------------------查看VGG详细架构:----------------------------------------

conv_base.summary()

Keras实现——使用预训练的卷积神经网络(VGG16)提取图像特征_第1张图片
Keras实现——使用预训练的卷积神经网络(VGG16)提取图像特征_第2张图片
同理,可以查看VGG19网络的结构:
Keras实现——使用预训练的卷积神经网络(VGG16)提取图像特征_第3张图片
Keras实现——使用预训练的卷积神经网络(VGG16)提取图像特征_第4张图片
提取各层特征:

# cnn训练fer2013

import matplotlib as mpl
import matplotlib.pyplot as plt
# %matplotlib inline
import numpy as np
import pandas as pd
import os
import sys
import time
import tensorflow as tf
#from tensorflow import keras
import keras   # keras版本不一致 配置环境有时会出错
import scipy.misc as sm
import scipy
from PIL import Image
from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay


# 按照顺序定义class_names
# 数据集可改成fer2013/fer2013+
# fer2013+多了一类contempt
class_names=['anger','contempt','disgust','fear','happy','neutral','sad','surprised']   #fer共7个类   fer2013共8个类
train_folder=r'E:\_Datasets\fer2013_plus\train'     #数据集的存放路径
val_folder=r'E:\_Datasets\fer2013_plus\val'
test_folder=r'E:\_Datasets\fer2013_plus\test'

# 增强数据集
height=48
width=48
channels=1
batch_size=64
num_classes=8           # fer共7个类   ferplus共8个类

train_datagen=keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,       # 重缩放因子
    rotation_range=40,    # 随机旋转的度数范围(整数)
    width_shift_range=0.2,  # 图片宽度的某个比例,数据提升时图片随机水平偏移的幅度
    height_shift_range=0.2,  # 图片高度的某个比例,数据提升时图片随机竖直偏移的幅度
    shear_range=0.2,        # 浮点数,剪切强度(逆时针方向的剪切变换角度)。是用来进行剪切变换的程度
    zoom_range=0.2,        # 随机缩放的幅度
    horizontal_flip=True,   # 进行随机水平翻转
    fill_mode='nearest')    # 当进行变换时超出边界的点将根据本参数给定的方法进行处理
train_generator=train_datagen.flow_from_directory(
    train_folder,                        # flow_from_directory()数据集构建
    target_size=(height,width),
    batch_size=batch_size,
    seed=7,
    shuffle=True,                          # 训练时,随机打乱数据
    class_mode='categorical')

valid_datagen=keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255)
valid_generator=train_datagen.flow_from_directory(
    val_folder,
    target_size=(height,width),
    batch_size=batch_size,
    seed=7,
    shuffle=False,                 # shuffle的值是布尔值,意思是是否随机打乱数据,默认为True
    class_mode='categorical')

test_datagen=keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255)
test_generator=test_datagen.flow_from_directory(
    test_folder,
    target_size=(height,width),
    batch_size=batch_size,
    seed=7,
    shuffle=False,                # 在使用时随机打乱数据,那么将会导致预测标签和真实标签位置对不上,所以在test和valid上设为false
    class_mode='categorical')

train_num=train_generator.samples
valid_num=valid_generator.samples
print(train_num,valid_num)

# 建立模型结构
model = keras.models.Sequential()
model.add(keras.layers.Conv2D(filters=32,kernel_size=3,
                             padding='same',activation='relu',
                             input_shape=(width,height,3)))
# model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(filters=32,kernel_size=3,
                             padding='same',activation='relu'))
# model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPool2D(pool_size=2))

model.add(keras.layers.Conv2D(filters=64,kernel_size=3,
                             padding='same',activation='relu'))
# model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(filters=64,kernel_size=3,
                             padding='same',activation='relu'))
# model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPool2D(pool_size=2))
model.add(keras.layers.Conv2D(filters=128,kernel_size=3,
                             padding='same',activation='relu'))
# model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Conv2D(filters=128,kernel_size=3,
                             padding='same',activation='relu'))
# model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPool2D(pool_size=2))


model.add(keras.layers.Flatten())
# model.add(keras.layers.AlphaDropout(0.5))
model.add(keras.layers.Dense(128,activation='relu'))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Dense(num_classes,activation='softmax'))      # dense_2的输出
# adam=tf.optimizers.Adam(lr=0.01)
# callbacks=[keras.callbacks.EarlyStopping(patience=5,min_delta=1e-3)]
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'],
              )
model.summary()

#  特征提取函数
from keras.preprocessing import image
from keras.models import Model
from keras.applications.vgg19 import preprocess_input
def feature_extraction(filename,save_path):
    model = Model(inputs=base_model.input, outputs=base_model.get_layer('dense_2').output) #想获取哪层的特征,就把引号里的内容改成那个层的名字就行
    img_path = filename
    img = image.load_img(img_path, target_size=(48, 48))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    d1 = model.predict(x)     #// 获取 xxx层特征
    np.savetxt(save_path +'.csv',d1,fmt='%s') #// 保存特征文件


def read_image(rootdir,save_path):
    list = os.listdir(rootdir) #列出文件夹下所有的目录与文件
    # print(list)
    # files = []
    for i in range(0,len(list)):
        path = os.path.join(rootdir,list[i])
        # print(path)
        # subFiles = []
        for file in os.listdir(path):
            # subFiles.append(file)
            savePath = os.path.join(save_path,file[:-4])
            #print(file)
            filename = os.path.join(path,file)
            feature_extraction(filename,savePath)
            print("successfully saved "+ file[:-4] +".csv !")


if __name__ == '__main__':
    # base_model = VGG19(weights='imagenet', include_top=True) # 加载VGG19模型及参数
    from keras.models import load_model
    base_model = load_model('plus_model.h5')                                  # 加载模型及参数(这里应该加载训练好的模型参数,即权重值)
    print("Model has been onload !")
    rootdir = r'E:\_Datasets\fer2013_plus\train'  # 图片路径
    save_path = r"E:\_Datasets\fer2013_plus\CNN_ferplus_dense2_50epochs"   # 提取特征文件保存路径
    read_image(rootdir,save_path)
    print("work has been done !")

参考文献:

https://blog.51cto.com/u_15076233/3907225

你可能感兴趣的:(#,神经网络,神经网络,卷积神经网络)