狗狗分类

进行了验证码识别的操作成功得训练读取了文件进行预测以后

下面编写一个狗狗分类程序

图片属性均为227*227

将阿拉斯加犬、博美犬、贵宾犬、哈巴犬(狗?)、哈士奇各150张图片组成训练集(感觉训练集可能有点少了,可以之后增加),分别对应种类1、2、3、4、5,编号分别是0-150,151-300,301-450,451-600,601,750

编写了关于标签值狗狗种类对应的csv文件

其中用到了编写文件名的bat文件http://www.360doc.com/content/16/0723/10/5572937_577742312.shtml

不知道数据量足不足 可以先尝试一下:

#author MJY
import tensorflow as tf
import glob
import pandas as pd   #涉及文件读取(csv)
import numpy as np
import os


tf.app.flags.DEFINE_integer("is_train", 2, "指定是否是训练模型,还是拿数据去预测")
FLAGS = tf.app.flags.FLAGS


#读取图片数据
def read_pic():

    #1.构建文件名队列
    #获取文件名列表,用global命令
    file_names = glob.glob("./GenPics/*.jpg")
    file_names_test = glob.glob("./test/*.jpg")
    #print("file_name:\n", file_names)
    #即可构建文件名队列
    file_queue = tf.train.string_input_producer(file_names)
    file_queue_test = tf.train.string_input_producer(file_names_test)



    #2.读取与解码
    #构造读图片的阅读器
    reader = tf.WholeFileReader()

    #读取阶段
    filename, image = reader.read(file_queue)
    filename_test, image_test = reader.read(file_queue_test)


    #解码阶段
    decoded = tf.image.decode_jpeg(image)
    decoded_test = tf.image.decode_jpeg(image_test)



    #更新形状,将图片形状确定下来以方便批处理
    decoded.set_shape([227,227,3])   #高 宽 通道数
    #print("decoded:\n",decoded)
    decoded_test.set_shape([227,227,3])



    #修改图片的类型  因为此时是unit8,但输入卷积层的数据必须是float32或者float64
    image_cast = tf.cast(decoded, tf.float32)
    image_cast_test = tf.cast(decoded_test, tf.float32)


    #3.批处理
    filename_batch, image_batch = tf.train.batch([filename, image_cast],batch_size=100, num_threads=2, capacity=100)
    filename_batch_test, image_batch_test = tf.train.batch([filename_test, image_cast_test],batch_size=3, num_threads=1, capacity=3)



    return filename_batch, image_batch,filename_batch_test, image_batch_test





#接下来解析csv文件,建立文件名和标签值的对应表格
#可以先在jupyter notebook上面实验   实验成功  运用float()
def parse_csv():
    # 读取文件
    csv_data = pd.read_csv("./Genpics/labels.csv", names=["file_num", "type"], index_col="file_num")

    #创建空列表  遍历
    labels = []
    for label in csv_data["type"]:
        float(label)
        label = label - 1
        labels.append(label)

    csv_data["labels"] = labels


    return csv_data
#至此  文件名和标签对应的列表生成完毕


#生成用于测试的  文件名和标签名的对应表格
def parse_csv_test():
    # 读取文件
    csv_data_test = pd.read_csv("./test/labels.csv", names=["file_num", "type"], index_col="file_num")

    #创建空列表  遍历
    labels_test = []
    for label_test in csv_data_test["type"]:
        float(label_test)
        label_test = label_test - 1
        labels_test.append(label_test)

    csv_data_test["labels_test"] = labels_test


    return csv_data_test
#至此  用于测试的文件名和标签对应的列表生成完毕



#将文件名与csv_data一一对应通过文件名查表
def filename2label(filename, csv_data):

    labels = []

    for file_name in filename:
        #filter方法判断是否是数字
        file_num = "".join(list(filter(str.isdigit, str(file_name))))
        #查表
        target = csv_data.loc[int(file_num), "labels"]
        labels.append(target)

    #print("labels:\n", labels)

    return  np.array(labels)




#用于测试的————将文件名与csv_data_test一一对应通过文件名查表
def filename2label_test(filename_test, csv_data_test):

    labels_test = []

    for file_name in filename_test:
        #filter方法判断是否是数字
        file_num = "".join(list(filter(str.isdigit, str(file_name))))
        #查表
        target_test = csv_data_test.loc[int(file_num), "labels_test"]
        labels_test.append(target_test)

    #print("labels:\n", labels)

    return  np.array(labels_test)







#定义权重生成器
def create_weights(shape):
    return tf.Variable(initial_value=tf.random_normal(shape=shape,stddev=0.001))


#构建卷积神经网络,得到y_predict
def create_model(x):
    #x的形状为[None,227,227,3]
    # 1)第一个卷积大层
    with tf.variable_scope("conv1"):
        # 卷积层

        # 定义filter和偏置
        conv1_weights = create_weights(shape=[5, 5, 3, 32])
        conv1_bias = create_weights(shape=[32])
        conv1_x = tf.nn.conv2d(input=x, filter=conv1_weights, strides=[1, 1, 1, 1], padding="SAME") + conv1_bias

        # 激活层
        relu1_x = tf.nn.relu(conv1_x)

        # 池化层....5
        pool1_x = tf.nn.max_pool(value=relu1_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 2)第二个卷积大层
    with tf.variable_scope("conv2"):
        # x的形状为[None,114,114,32],卷积向下取整,池化向上取整
        # 卷积层
        # 定义filter和偏置
        conv2_weights = create_weights(shape=[5, 5, 32, 64])
        conv2_bias = create_weights(shape=[64])
        conv2_x = tf.nn.conv2d(input=pool1_x, filter=conv2_weights, strides=[1, 1, 1, 1], padding="SAME") + conv2_bias

        # 激活层
        relu2_x = tf.nn.relu(conv2_x)

        # 池化层
        pool2_x = tf.nn.max_pool(value=relu2_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 3)全连接层
    # x的形状为[None,57,57,64]
    with tf.variable_scope("full_connection"):
        # 首先做形状修改
        # [None, 57, 57, 64] - ------>[None, 57 * 57 * 64]
        # [None, 57 * 57 * 64] * [] = [None, 5]   所以权重为[57 * 57 * 64, 5]
        x_fc = tf.reshape(pool2_x, shape=[-1,57 * 57 * 64])  # 注意reshape没有None的用法  需要用-1
        weights_fc = create_weights(shape=[57 * 57 * 64, 5])
        bias_fc = create_weights(shape=[5])
        y_predict = tf.matmul(x_fc, weights_fc) + bias_fc


    return y_predict














if __name__ == "__main__":


    filename, image, filename_test, image_test = read_pic()
    csv_data = parse_csv()
    csv_data_test = parse_csv_test()

    #1.准备数据
    x = tf.placeholder(tf.float32, shape=[None,227,227,3])
    y_true = tf.placeholder(tf.float32, shape=[None,5])  #因为计算损失的时候需要一维



    #2.构建模型
    y_predict = create_model(x)


    #3.构造损失函数
    loss_list = tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)
    loss = tf.reduce_mean(loss_list)


    #4.优化损失
    optimizer = tf.train.AdamOptimizer(learning_rate=0.0001).minimize(loss)




    #5.准确率计算
    with tf.variable_scope("accuracy"):
        #训练集准确率计算
        #1)比较预测值和真实值最大值所在位置,tf.argmax表示按行返回最大值的索引
        equal_list=tf.equal(tf.arg_max(y_true,1),tf.arg_max(y_predict,1))
        #2)将布尔值转换为浮点数,求平均,即为准确率
        accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))

    #初始化变量
    init = tf.global_variables_initializer()




    #(2)收集要显示的变量
    #先收集损失和准确率
    tf.summary.scalar("losses", loss)
    tf.summary.scalar("accuracy",accuracy)

    #(3)合并所有变量op
    merged = tf.summary.merge_all()
    #创建模型保存与加载
    saver = tf.train.Saver()



    #开启会话
    with tf.Session() as sess:


        sess.run(init)

        #开启线程
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)


        # (1)创建一个events文件实例
        file_writer = tf.summary.FileWriter("./tmp/summary2/", graph=sess.graph)

        # 加载模型
        if os.path.exists("./tmp/modelckpt2/checkpoint"):
            saver.restore(sess, "./tmp/modelckpt2/cnn_model")  # 注意modelckpt2这个文件夹要自己建立
            # 也就是说 模型保存和加载的时候 也就是saver.save或saver.restore的路径需要自己建立 否则会蓝屏
            # 但是创建envents实例化的路径可以不用自己建立

        if FLAGS.is_train == 1:

            for i in range(1000):
                filename_value, image_value = sess.run([filename, image])
                # print("filename_value:\n", filename_value)
                #print("image_value:\n", image_value)
                labels = filename2label(filename_value, csv_data)
                #print("labels:\n", labels)

                # 将标签值转换为one-hot
                labels_value = tf.reshape(tf.one_hot(labels, depth=5), [-1, 5]).eval()
                #print("labels_value:\n", labels_value)
                y_predict_value = sess.run(y_predict, feed_dict={x: image_value, y_true: labels_value})
                #print("y_predict:\n", y_predict_value)

                _, error, accuracy_value = sess.run([optimizer, loss, accuracy],
                                                    feed_dict={x: image_value, y_true: labels_value})

                print("第%d次训练后损失为%f,准确率为%f" % (i + 1, error, accuracy_value))

                # 运行合变量op,写入事件文件当中
                summary = sess.run(merged, feed_dict={x: image_value, y_true: labels_value})
                file_writer.add_summary(summary, i)
                if i % 100 == 0:
                    saver.save(sess, "./tmp/modelckpt2/cnn_model")


        else:
            # 如果不是训练,则是用测试集对模型进行测试
            for i in range(1):
                filename_value_test, image_value_test = sess.run([filename_test, image_test])
                labels_test = filename2label_test(filename_value_test, csv_data_test)
                labels_value_test = tf.reshape(tf.one_hot(labels_test, depth=5), [-1, 5]).eval()
                accuracy_value = sess.run(accuracy, feed_dict={x: image_value_test, y_true: labels_value_test})


                #print("labels_value_test:\n", labels_value_test)

                print("真实值为\n", labels_test)

                y_predict_final_print = tf.reshape(y_predict, shape=[-1, 1, 5])


                y_predict_final = tf.argmax(tf.reshape(y_predict, shape=[-1, 1, 5]), axis=2)

                print("预测值为\n",
                      sess.run(y_predict_final, feed_dict={x: image_value_test, y_true: labels_value_test}))


            print("准确率为:\n", accuracy_value)

                #print("y_predict_final_print:\n", sess.run(y_predict_final_print, feed_dict={x: image_value_test, y_true: labels_value_test}))


        #回收线程
        coord.request_stop()
        coord.join(threads)

样本太少效果不是特别好 先把样本做大 用到了图片增强程序使得每一种狗都含有6980张训练图片
其实没必要名称改为1 2 3 4 5 。。。只需要与csv文件对应好就可以

你可能感兴趣的:(python学习)