tensorflow 猫狗识别(卷积神经网络CNN)

数据集来自51-CTO唐宇迪老师的“tensorflow入门视频教程”

内有500张猫和500张狗的图片(大小不一),我将它们全部放到一个文件夹里,前500张为猫,后500张为狗。

关于模型的保存和读取,这个博客讲的非常好:一份快速完整的Tensorflow模型保存和恢复教程(译)

代码:

import tensorflow as tf
import numpy as np
import cv2
import random
import os

def get_batch(batch_size=32,image_size=64,class_size=2):
    x=[]
    y=[]
    all_image=os.listdir('./training_data')#返回指定的文件夹包含的文件或文件夹的名字的列表
    for i in range(batch_size):
        random_file=random.randint(0,999)
        image=cv2.imread('./training_data/'+all_image[random_file])#我把猫狗图片放在一个文件夹里了,前500张是猫,后500张是狗
        image=cv2.resize(image,(image_size,image_size),0,0,cv2.INTER_LINEAR)
        image=image.astype(np.float32)#image原来是float64
        image=image/255.0
        lable=np.zeros(class_size)
        if(random_file<500):
            lable[0]=1.0
        else:
            lable[1]=1.0
        x.append(image)
        y.append(lable)
    x=np.array(x)
    y=np.array(y)
    return x,y

def creat_conv_layer(input,filter_size1, filter_size2, filter_size3, filter_num):
    w=tf.Variable(tf.truncated_normal(shape=[filter_size1, filter_size2, filter_size3, filter_num],stddev=0.05))
    b=tf.Variable(tf.constant(0.05,shape=[filter_num]))
    conv=tf.nn.conv2d(input=input,filter=w,strides=[1,1,1,1],padding='SAME')+b
    conv=tf.nn.relu(conv)
    conv=tf.nn.max_pool(conv,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
    #conv=tf.nn.dropout(conv,keep_prob)
    return conv

def full_connect_layer(input, w_fc_shape1, w_fc_shape2, w_fc_shape3, unit_num, class_size, keep_prob=0.5):
    w_fc = tf.Variable(tf.truncated_normal(shape=[w_fc_shape1*w_fc_shape2*w_fc_shape3, unit_num], stddev=0.05))
    b_fc = tf.Variable(tf.constant(0.05, shape=[unit_num]))
    input_flat = tf.reshape(input,[-1,w_fc_shape1*w_fc_shape2*w_fc_shape3])
    fc=tf.matmul(input_flat,w_fc)+b_fc
    fc=tf.nn.dropout(fc,keep_prob)
    fc=tf.nn.relu(fc)
    w=tf.Variable(tf.truncated_normal(shape=[unit_num, class_size], stddev=0.05))
    b=tf.Variable(tf.constant(0.05, shape=[class_size]))
    y_predic=tf.matmul(fc,w)+b
    return y_predic

def train():
    X = tf.placeholder(tf.float32, [None, 64, 64, 3], name='X')#命名好的变量(用于test读取)需放到函数里,放到外边test时会报错
    Y = tf.placeholder(tf.float32, [None, 2], name='Y')        #我的理解是在test时已经读取了,而全局上又有一个相同的变量,会导致
    keep_prob = tf.placeholder(tf.float32, name='keep_prob')  #变量重定义
    conv1=creat_conv_layer(X,3,3,3,32)
    conv2=creat_conv_layer(conv1,3,3,32,32)
    conv3=creat_conv_layer(conv2,3,3,32,64)
    y_predic=full_connect_layer(conv3,8,8,64,1024,2,keep_prob)
    y_sofmax = tf.nn.softmax(y_predic)#对结果softmax得到该图像是猫的概率以及是狗的概率
    y_ped_cls = tf.argmax(y_sofmax, 1,name='prediction')#取概率最大的作为预测结果
    #是猫结果是0,是狗结果是1

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y_predic,labels=Y))
    opt=tf.train.AdamOptimizer(learning_rate=0.0001).minimize(loss)
    #之前学习率设为0.01,然后精确度就一直停在50%左右,每个batch总是全预测猫或全是狗,推测是学习率太大,而分类就两个,导致模型在更新的时候容易从一个极端跳到另一个极端,故减小了学习率,精确度就上升了。

    correct_prediction=tf.equal(y_ped_cls,tf.argmax(Y,1))#这两步为一个batch的预测值与实际值进行比较,得到精确度。
    accuracy=tf.reduce_mean(tf.cast(correct_prediction,'float'))

    saver=tf.train.Saver(max_to_keep=1)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        #saver.restore(sess, tf.train.latest_checkpoint('./self_study_model/'))#由于在训练的时候就已经创建了网络模型,再训练只要恢复参数即可
        #将sess.run注释,saver.restore打开可以实现模型再训练
        batch_size=32
        for step in range(6000):#迭代6000次
            x_batch,y_batch=get_batch(batch_size,image_size=64,class_size=2)
            _,train_loss,acc,prediction,lable=sess.run([opt,loss,accuracy,y_ped_cls,tf.argmax(Y,1)],feed_dict={X:x_batch,Y:y_batch,keep_prob:0.5})
            print('step=',step,' prediction',prediction,' Y=',lable)
            if (step+1)%10==0:
                print('        acc=',acc,
                      '  loss=',train_loss)
                if acc>=1.0:
                    break
        saver.save(sess, './self_study_model/my_model.ckpt')
        print('模型更新了')

def get_test_data(index=0,image_size=64):
    x=[]
    all_image = os.listdir('./testing_data/dogs')
    random_file = index
    image = cv2.imread('./testing_data/dogs/' + all_image[random_file])
    image = cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)
    image = image.astype(np.float32)  # image原来是float64
    image = image / 255.0
    x.append(image)
    x=np.array(x)
    return x
def test():
    sess=tf.Session()
    saver=tf.train.import_meta_graph('./self_study_model/my_model.ckpt.meta')#读取网络模型
    saver.restore(sess,'./self_study_model/my_model.ckpt')#读取模型里的各种参数
    graph=tf.get_default_graph()
    X=graph.get_tensor_by_name("X:0")#之前对变量命名在这可以用其名字调出
    Y=graph.get_tensor_by_name("Y:0")#占位符一定要全部命名,因为测试时feed_dict需要用到所有的占位符
    keep_prob=graph.get_tensor_by_name("keep_prob:0")
    prediction=graph.get_tensor_by_name("prediction:0")
    image=get_test_data(index=100)
    image_prdic=np.zeros((1,2))
    feed_dict={X:image,Y:image_prdic,keep_prob:0.5}
    result=sess.run(prediction,feed_dict=feed_dict)
    classes = ['cat', 'dog']
    print(classes[result[0]])

#训练模型
train()
# #step= 1409   acc= 1.0   loss= 0.18543181
#读取模型进行测试
#test()

这份代码可以实现模型的训练,保存,读取(可用于再训练以及测试)。

测试方面,每次可以测试一张图片,判断猫狗,具体精度没测(模型训练时可以在1400步左右精度达到100%),但实际效果还可以。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值