迁移学习案例 基于VGG16的迁移学习

由于深度学习网络的训练复杂,耗时,并且对硬件要求较高,因此对于目标相似的任务,并且自己的数据集数目较小的时候,比如分类任务,不同的分类任务之间的对象具有较为相似的特征,我们就可以使用已经预训练的模型来应用到自己的项目任务中,当然对于已经预训练的模型,需要经过微调才能应用到自己的分类任务中来。
微调主要包括训练参数的变动,全连接层神经元个数,当我们自己的数据集很少时,我们可以仅仅改变最后一层全连接层的神经元的个数即可,当我们的数据量大的时候,我们可以选择训练模型的后几层参数。
这里我们采用VGG16来实现简单的迁移学习案例
VGG16的网络结构如下:
在这里插入图片描述
这里我们仅仅通过重新训练最后一层全连接层的参数将预训练好的VGG16模型应用到猫狗大战的数据集上。
VGG16预备训练模型:https://pan.baidu.com/s/1FfNiUAigFBRknftXCXcThw
提取码:cfs1

kaggle猫狗数据集:
链接:https://pan.baidu.com/s/1ohg-q2WWcYSNG7SC-C74cQ
提取码:a4xj

首先我们需要定义网络的结构,定义一个vgg类

class vgg16:
    def __init__(self, imgs):
        #加入全局列表,把所需参数加载进类里
        self.parameters=[]
        #初始化
        self.imgs=imgs
        self.convlayers()
        self.fc_layers()
        #输出类别的概率
        self.probs=tf.nn.softmax(self.fc8)
    def saver(self):
        return tf.train.Saver()
        #定义卷积层
    def conv(self,name,input_data,out_channel,trainable=False):
        #获取通道数
        in_channel=input_data.get_shape()[-1]
        with tf.variable_scope(name):
            #初始化
            kernel=tf.get_variable('weights',[3,3,in_channel,out_channel],dtype=tf.float32,trainable=False)
            biases=tf.get_variable('baises',[out_channel],dtype=tf.float32,trainable=False)
            conv_res=tf.nn.conv2d(input_data,kernel,[1,1,1,1],padding='SAME')
            res=tf.nn.bias_add(conv_res,biases)
            out=tf.nn.relu(res,name=name)
        self.parameters+=[kernel,biases]
        return out
    #定义全连接层
    def fc(self,name,input_data,out_channel,trainable=True):
        #获取维度
        shape=input_data.get_shape().as_list()
        if len(shape)==4:
            size=shape[-1]*shape[-2]*shape[-3]
        else :size=shape[1]
        #数据展开
        input_data_flat=tf.reshape(input_data,[-1,size])
        with tf.variable_scope(name):
            #初始化
            weights=tf.get_variable('weights',shape=[size,out_channel],dtype=tf.float32,trainable=trainable)
            biases=tf.get_variable('baises',shape=[out_channel],dtype=tf.float32,trainable=trainable)
            res=tf.matmul(input_data_flat,weights)
            out=tf.nn.relu(tf.nn.bias_add(res,biases))
        self.parameters+=[weights,biases]
        return out
    #定义池化
    def maxpool(self,name,input_data):
        out=tf.nn.max_pool(input_data,[1,2,2,1],[1,2,2,1],padding='SAME',name=name)
        return out
    #卷积堆叠
    def convlayers(self):
        #cov1
        self.conv1_1=self.conv('conv1_1',self.imgs,64,trainable=False)
        self.conv1_2=self.conv('conv1_2',self.conv1_1,64,trainable=False)
        self.pool1=self.maxpool('poolre1',self.conv1_2)
        #cov2
        self.conv2_1=self.conv('conv2_1',self.pool1,128,trainable=False)
        self.conv2_2=self.conv('conv2_2',self.conv2_1,128,trainable=False)
        self.pool2=self.maxpool('pool1',self.conv2_2)
        #cov3
        self.conv3_1=self.conv('conv3_1',self.pool2,256,trainable=False)
        self.conv3_2=self.conv('conv3_2',self.conv3_1,256,trainable=False)
        self.conv3_3=self.conv('conv3_3',self.conv3_2,256,trainable=False)
        self.pool3=self.maxpool('pool3',self.conv3_3)
        #cov4
        self.conv4_1=self.conv('conv4_1',self.pool3,512,trainable=False)
        self.conv4_2=self.conv('conv4_2',self.conv4_1,512,trainable=False)
        self.conv4_3=self.conv('conv4_3',self.conv4_2,512,trainable=False)
        self.pool4=self.maxpool('pool4',self.conv4_3)
        #cov5
        self.conv5_1=self.conv('conv5_1',self.pool4,512,trainable=False)
        self.conv5_2=self.conv('conv5_2',self.conv5_1,512,trainable=False)
        self.conv5_3=self.conv('conv5_3',self.conv5_2,512,trainable=False)
        self.pool5=self.maxpool('pool5',self.conv5_3)
    #全连接层
    def fc_layers(self):
        self.fc6=self.fc('fc1',self.pool5,4096,trainable=False)
        self.fc7=self.fc('fc2',self.fc6,4096,trainable=False)
        #要进行微调,trainable为true
        self.fc8=self.fc('fc3',self.fc7,2,trainable=True)
    #载入权重
    def load_weights(self,weight_file,sess):
        weights=np.load(weight_file)
        keys=sorted(weights.keys())
        for i,k in enumerate(keys):
            if i not in[30,31]:
                sess.run(self.parameters[i].assign(weights[k]))
        print("weights loading......")

定义提取训练数据集图片的地址和标签,并使用独热编码形式

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

import numpy as np
import os 
from time import time
import utils


 #数据输入
def get_file(file_dir):
        images=[]
        labels=[]
        for fs in os.listdir(file_dir):
            images.append(os.path.join(file_dir,fs))
            if fs.split('.')[0]=='cat':
                labels.append(1)
            else:
                labels.append(0)
        temp=np.array([images,labels])
        temp=temp.transpose()
        np.random.shuffle(temp)
        image_list=list(temp[:,0])
        label_list=list(temp[:,1])
        label_list=[int(float(i)) for i in label_list]
        return image_list,label_list
    

def get_batch(image_list,label_list,img_width,img_height,batch_size,capacity):
        image=tf.cast(image_list,tf.string)
        label=tf.cast(label_list,tf.int32)
        input_queue=tf.train.slice_input_producer([image,label])
        label=input_queue[1]
        image_contents=tf.read_file(input_queue[0])
        image=tf.image.decode_jpeg(image_contents,channels=3)
        image= tf.image.resize_images(image, [224, 224], method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
        image_batch,label_batch=tf.train.batch([image,label],batch_size=batch_size,num_threads=64,capacity=capacity)
        label_batch=tf.reshape(label_batch,[batch_size])
        return image_batch,label_batch
    #转换独热编码
def onehot(labels):
        n_sample=len(labels)
        n_class=max(labels)+1
        onehot_labels=np.zeros((n_sample,n_class))
        onehot_labels[np.arange(n_sample),labels]=1
        return onehot_labels

下面我们进行模型的训练

batch_size=10
capacity=256#存储容量
#VGG预训练是减掉的均值
means=[123.68,116.779,103.939]
img_width=224
img_height=224
start_time=time()
xs,ys =get_file(r'D:/study/MOOC/deeplearning/dataset_kaggledogvscat/dataset_kaggledogvscat/train')
image_batch,label_batch=get_batch(xs,ys,img_width,img_height,batch_size,capacity)
print(len(xs),len(ys))
x=tf.placeholder(tf.float32,[None,224,224,3])
y=tf.placeholder(tf.int32,[None,2])
vgg=vgg16(x)
fc8_finetuining=vgg.probs
loss_function=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=fc8_finetuining,labels=y))
optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(loss_function)
sess=tf.Session()
sess.run(tf.global_variables_initializer())
vgg.load_weights(r'D:\study\MOOC\deeplearning\dataset_kaggledogvscat\dataset_kaggledogvscat/vgg16_weights.npz',sess)
saver=tf.train.Saver()
coord= tf.train.Coordinator()
threads=tf.train.start_queue_runners(coord=coord,sess=sess)
epoch_start_time=time()
for i in range (100):
    print('开始训练......')
    images,labels=sess.run([image_batch,label_batch])
    labels=onehot(labels)
    sess.run(optimizer,feed_dict={x:images,y:labels})
    loss=sess.run(loss_function,feed_dict={x:images,y:labels})
    print("loss:%f"%loss)
    epoch_end_time=time()
    print('time:',(epoch_end_time-epoch_start_time))
    epoch_start_time=epoch_end_time
    if(i+1)%20==0:
        saver.save(sess,os.path.join('./model/','epoch{:06d}.ckpt'.format(i+1)))
    print("____epoch%d finish"%(i+1))
saver.save(sess,'./model/')

coord.request_stop()
coord.join(threads)

输出训练的结果,训练的次数,loss
在这里插入图片描述
下面我们来进行验证

tf.reset_default_graph()
means=[123.68,116.779,103.939]
x=tf.placeholder(tf.float32,[None,224,224,3])
with tf.Session() as sess:
    vgg=vgg16(x)
    fc8_finetuining=vgg.probs
    saver=tf.train.Saver()
    print('restoring...')
    saver.restore(sess,'./model/')
    filepath=r'D:\study\MOOC\deeplearning\dataset_kaggledogvscat\dataset_kaggledogvscat\test1\test1\11160.jpg'
    image_raw_data = tf.gfile.FastGFile(filepath,'rb').read()
    img_data = tf.image.decode_jpeg(image_raw_data)
    # plt.imshow(img_data.eval())
    # plt.show()
    image = tf.image.resize_images(img_data, [224, 224], method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
    img = image.eval()
    print(img.shape)
    image = tf.expand_dims(image,0)
    print(image.shape)
    #for c in range(3):
     #  image[:,:,c] -= means[c]
    prob=sess.run(fc8_finetuining,feed_dict={x:[img]})
    max_index=np.argmax(prob)
    if max_index==1:
        print('The result: cat %.6f'%prob[:,0])
        
    else:
        print('The result: dog %.6f'%prob[:,1])

输出某类分类结果的概率
在这里插入图片描述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是菜鸡,我不敢睡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值