tensorflow利用vgg19网络做猫狗识别的迁移学习

这是本人的第一次博客,写的不好请见谅哈。博主大二小菜鸟一个,欢迎指教和私信。楼主学习tensorflow也有一段时间了,最近尝试了一下用vgg19网络做迁移学习。vgg结构如下:

首先下载vgg19网络的mat文件,然后对数据进行预处理,这里博主借用了别人的处理方法,处理好的数据,直接送到了我们预先展开的vgg网络中,注意这里权重是constant,直接把别人训练好的权重拿来初始化,然后最后改一下全连接层。直接贴代码

#迁移学习猫狗识别
import scipy.misc
import scipy.io as scio
import tensorflow as tf
import os
import numpy as np
import sys
def get_files(file_dir):
    cats = []
    label_cats = []
    dogs = []
    label_dogs = []
    for file in os.listdir(file_dir):
        name = file.split(sep='.')
        if 'cat' in name[0]:
            cats.append(file_dir +"\\"+ file)
            label_cats.append(0)
        else:
            if 'dog' in name[0]:
                dogs.append(file_dir +"\\"+ file)
                label_dogs.append(1)
        image_list = np.hstack((cats, dogs))
        label_list = np.hstack((label_cats, label_dogs))
    # print('There are %d cats\nThere are %d dogs' %(len(cats), len(dogs)))
    # 多个种类分别的时候需要把多个种类放在一起,打乱顺序,这里不需要

    # 把标签和图片都放倒一个 temp 中 然后打乱顺序,然后取出来
    temp = np.array([image_list, label_list])
    temp = temp.transpose()
    # 打乱顺序
    np.random.shuffle(temp)

    # 取出第一个元素作为 image 第二个元素作为 label
    image_list = list(temp[:, 0])
    label_list = list(temp[:, 1])
    label_list = [int(i) for i in label_list]
    return image_list, label_list


# 测试 get_files
# imgs , label = get_files('/Users/yangyibo/GitWork/pythonLean/AI/猫狗识别/testImg/')
# for i in imgs:
#  print("img:",i)

# for i in label:
#  print('label:',i)
# 测试 get_files end


# image_W ,image_H 指定图片大小,batch_size 每批读取的个数 ,capacity队列中 最多容纳元素的个数
def get_batch(image, label, image_W, image_H, batch_size, capacity):
    # 转换数据为 ts 能识别的格式
    image = tf.cast(image, tf.string)
    label = tf.cast(label, tf.int32)

    # 将image 和 label 放倒队列里
    input_queue = tf.train.slice_input_producer([image, label])
    label = input_queue[1]
    # 读取图片的全部信息
    image_contents = tf.read_file(input_queue[0])
    # 把图片解码,channels =3 为彩色图片, r,g ,b  黑白图片为 1 ,也可以理解为图片的厚度
    image = tf.image.decode_jpeg(image_contents, channels=3)
    # 将图片以图片中心进行裁剪或者扩充为 指定的image_W,image_H
    image = tf.image.resize_image_with_crop_or_pad(image, image_W, image_H)
    # 对数据进行标准化,标准化,就是减去它的均值,除以他的方差
    image = tf.image.per_image_standardization(image)
    # 生成批次  num_threads 有多少个线程根据电脑配置设置  capacity 队列中 最多容纳图片的个数  tf.train.shuffle_batch 打乱顺序,
    image_batch, label_batch = tf.train.batch([image, label], batch_size=batch_size, num_threads=64, capacity=capacity)

    # 重新定义下 label_batch 的形状
    label_batch = tf.reshape(label_batch, [batch_size])
    # 转化图片
    image_batch = tf.cast(image_batch, tf.float32)
    return image_batch, label_batch
def _conv_layer(input,weights,bias):
     conv=tf.nn.conv2d(input,tf.constant(weights),strides=[1,1,1,1],padding="SAME")
     return tf.nn.bias_add(conv,bias)
def _pool_layer(input):
     return tf.nn.max_pool(input,ksize=(1,2,2,1),strides=(1,2,2,1,),padding="SAME")
def net(data_path,input_image):
    layers=('conv1_1','relu1_1','conv1_2','relu1_2','pool1',
            'conv2_1','relu2_1','conv2_2','relu2_2','pool2',
            'conv3_1','relu3_1','conv3_2','relu3_2','conv3_3','relu3_3','conv3_4','relu3_4','pool3',
            'conv4_1','relu4_1','conv4_2','relu4_2','conv4_3','relu4_3','conv4_4','relu4_4','pool4',
            'conv5_1', 'relu5_1','conv5_2','relu5_2','conv5_3','relu5_3','conv5_4','relu5_4'
            )
    data=scio.loadmat(data_path)
    mean=data['normalization'][0][0][0]
    mean_pixel=np.mean(mean,axis=(0,1))
    weights=data['layers'][0]
    net={}
    current=input_image
    for i,name in enumerate(layers):
        kind=name[:4]
        if kind=='conv':
            kernels,bias=weights[i][0][0][0][0]
            kernels=np.transpose(kernels,[1,0,2,3])
            bias=bias.reshape(-1)
            current=_conv_layer(current,kernels,bias)
        elif kind=='relu':
            current=tf.nn.relu(current)
        elif kind=="pool":
            current=_pool_layer(current)
        net[name]=current
    assert len(net)==len(layers)
    return net,mean_pixel,layers
VGG_PATH="D:\\imagenet-vgg-verydeep-19.mat"
train_dir = 'E:\\BaiduNetdiskDownload\\Dogs vs Cats Redux Kernels Edition\\aaa'  # My dir--20170727-csq
# 获取图片和标签集
train, train_label = get_files(train_dir)
# 生成批次
train_batch, train_label_batch =get_batch(train,train_label,224,224,32,256)
# 进入模型
nets,mean_pixel,all_layers=net(VGG_PATH,train_batch)
with tf.variable_scope("dense1"):
    image=tf.reshape(nets["relu5_4"],[32,-1])
    weights=tf.Variable(tf.random_normal(shape=[14*14*512,1024],stddev=0.1))
    bias=tf.Variable(tf.zeros(shape=[1024])+0.1)
    dense1=tf.nn.tanh(tf.matmul(image,weights)+bias)
with tf.variable_scope("out"):
    weights=tf.Variable(tf.random_normal(shape=[1024,2],stddev=0.1))
    bias=tf.Variable(tf.zeros(shape=[2])+0.1)
    out=tf.matmul(dense1,weights)+bias
loss=tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=out,labels=train_label_batch))
op=tf.train.AdamOptimizer(0.0001).minimize(loss)
correct = tf.nn.in_top_k(out,train_label_batch, 1)
correct = tf.cast(correct, tf.float16)
accuracy = tf.reduce_mean(correct)
init=tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    try:
        for step in np.arange(100):
            if coord.should_stop():
                print("结束")
                sys.exit(0)
            _, tra_loss, tra_acc = sess.run([op, loss, accuracy])
            if step % 1 == 0:
                print("step",step,"loss",tra_loss,"acc",tra_acc)
    except tf.errors.OutOfRangeError:
        print('Done training -- epoch limit reached')
    finally:
        coord.request_stop()
    coord.join(threads)
    sess.close()


猜你喜欢

转载自blog.csdn.net/zhusen123456/article/details/80582371