专栏首页贾志刚-OpenCV学堂干货 | Tensorflow设计简单分类网络实现猫狗图像分类训练与测试

干货 | Tensorflow设计简单分类网络实现猫狗图像分类训练与测试

模型结构与代码实现

第一层:32个feature map 5x5卷积、步长为2、最大值池化 局部相应归一化处理(LRN) 第二层:64个feature map 3x3卷积、步长为1、没有池化 第三层:128个feature map 3x3卷积、步长为1、最大值池化 局部相应归一化处理(LRN) 扁平层操作12x12x128个神经元 输出层操作2个神经元输出、sigmoid激活函数 卷积层采用relu作为激活函数。

模型解释

卷积层深度不断加深,用以补偿分辨率下降带来的信息损失、 LRN提升神经元竞争能力,增强最终模型的泛化能力。

通过上述简单的卷积神经网络,对25000张的猫狗图像进行训练,对卷积层1、3后面使用局部响应归一化处理(LRN), 最终输出二分类图像。从测试集选择测试图像进行分类预测,计算准确率。

网络模型代码实现

def inference(input_tensor):
    # -----------------------第一层----------------------------

    with tf.variable_scope('layer1-conv1'):
        # 初始化权重conv1_weights为可保存变量,大小为5x5,3个通道(RGB),数量为32个
        conv1_weights = tf.get_variable("weight", [5, 5, 3, 32],
                                        initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv1_biases = tf.get_variable("bias", [32], initializer=tf.constant_initializer(0.0))
        conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
        relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
        print(relu1)

    with tf.name_scope("layer2-pool1"):
        # 池化计算,调用tensorflow的max_pool函数,strides=[1,2,2,1],表示池化边界,2个对一个生成,padding="VALID"表示不操作。
        pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="VALID")
        norm1 = tf.nn.lrn(pool1, depth_radius=5, bias=2.0, alpha=1e-3, beta=0.75, name='norm1')

    # -----------------------第二层----------------------------
    with tf.variable_scope("layer3-conv2"):
        # 同上,不过参数的有变化,根据卷积计算和通道数量的变化,64个feature maps
        conv2_weights = tf.get_variable("weight", [3, 3, 32, 64],
                                        initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv2_biases = tf.get_variable("bias", [64], initializer=tf.constant_initializer(0.0))
        conv2 = tf.nn.conv2d(norm1, conv2_weights, strides=[1, 2, 2, 1], padding='SAME')
        relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
        print(relu2)
        # Local Response Normalization (parameters from paper)

    # 128个 feature maps
    with tf.variable_scope("layer4-conv3"):
        conv3_weights = tf.get_variable("weight", [3, 3, 64, 128],
                                        initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv3_biases = tf.get_variable("bias", [128], initializer=tf.constant_initializer(0.0))
        conv3 = tf.nn.conv2d(relu2, conv3_weights, strides=[1, 1, 1, 1], padding='SAME')
        relu3 = tf.nn.relu(tf.nn.bias_add(conv3, conv3_biases))
        print(relu3)

    with tf.name_scope("layer5-pool2"):
        pool2 = tf.nn.max_pool(relu3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
        print(pool2)
        norm2 = tf.nn.lrn(pool2, depth_radius=5, bias=2.0, alpha=1e-3, beta=0.75, name='norm2')

    # -----------------------全连接层----------------------------

    with tf.variable_scope("fc1"):
        fc1 = tf.layers.flatten(norm2)
        fc2 = tf.layers.dense(fc1, 2, activation=tf.nn.sigmoid)
    return fc2

数据加载与训练

对下载的训练数据集根据名称排序,分为两个目录

  • 文件夹0,所有猫的图像
  • 文件夹1,所有狗的图像

使用one-hot编码标签 [0, 1] 表示猫 [1, 0] 表示狗

加载所有图像数据与标签的代码如下:

def get_filelist():
    images = []
    labels = []
    for root, dirs, files in os.walk('D:/images/train_data/train_img/0'):
        for file in files:
            file = 'D:/images/train_data/train_img/0/' + file
            images.append(file)
            labels.append([0, 1])
    for root, dirs, files in os.walk('D:/images/train_data/train_img/1'):
        for file in files:
            file = 'D:/images/train_data/train_img/1/' + file
            images.append(file)
            labels.append([1, 0])

    return np.asarray(images), np.asarray(labels, np.int32)


def get_data(file_list, index, batch_size, label_list):
    images = []
    labels = []

    for i in range(index * batch_size, (1 + index) * batch_size):
        i = i % (len(file_list))
        img = io.imread(file_list[i])
        img = transform.resize(img, (100, 100))
        images.append(img)
        labels.append(label_list[i])
    return np.asarray(images, np.float32), np.asarray(labels, np.int32)

每个batch=64张图像进行训练,输入图像大小resize为100x100x3, RGB三通道彩色图像 训练时候输入图像与标签定义代码如下:

# 两个占位符
x = tf.placeholder(tf.float32, shape=[None, 100, 100, 3], name='x')
y_ = tf.placeholder(tf.float32, shape=[None, 2], name='y_')

计算损失采用交叉熵损失,使用Adam优化器进行优化,代码实现如下:

logits = inference(x)
cross_loss = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_)
loss = tf.reduce_mean(cross_loss)

tf.add_to_collection('losses', loss)
# 设置整体学习率为α为0.001
train_vars = tf.trainable_variables()

train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss, var_list=train_vars)

在1050ti GPU上运行10000次迭代,会保存最后的检查点文件、训练与保存检查点代码如下:

# 设置为gpu
tf.device('/gpu:0')
print("training start")

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    train_acc = 0
    test_acc = 0
    train_loss = 0
    for epoch in range(n_epoch):
        start_time = time.time()
        feed_img, feed_label = get_data(x_train, epoch, batch_size, y_train)
        _, err, ac = sess.run([train_op, loss, acc], feed_dict={x: feed_img, y_: feed_label})

        if epoch % 100 == 0:
            print("epoch %d, loss: %.2f, ac : %.2f"%(epoch, err, ac))
    saver.save(sess, "./dog_and_cat.model", global_step=10000)

使用模型进行预测

定义预测结果代码如下:

prediction = tf.cast(tf.argmax(logits, 1), tf.float32)

对保存好的检查点进行恢复,加载随机测试图像数据,调用模型进行测试,代码如下:

with tf.Session() as sess:
    saver.restore(sess, tf.train.latest_checkpoint('.'))
    cat_path = "D:/images/train_data/test_img/0/"
    dog_path = "D:/images/train_data/test_img/1/"
    dogs = os.listdir(dog_path)
    cats = os.listdir(cat_path)
    count = 0
    for f in dogs:
        if os.path.isfile(os.path.  join(dog_path, f)):
            image = io.imread(os.path.join(dog_path, f))
            copy = np.copy(image)
            image = transform.resize(image, (100, 100))
            image = np.float32(image)
            image_tensor = np.expand_dims(image, 0)
            digit = sess.run(prediction, feed_dict={x: image_tensor})
            print("predict digit : %d., actual digit : %s"%(digit[0], 0))
            if digit[0] == 0:
                count = count + 1
                cv.putText(copy, "dog", (20, 50), cv.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, (0, 0, 255), 2, 8)
                cv.imshow("Image Classification", copy)
                cv.waitKey(0)
    for f in cats:
        if os.path.isfile(os.path.join(cat_path, f)):
            image = io.imread(os.path.join(cat_path, f))
            copy = np.copy(image)
            image = transform.resize(image, (100, 100))
            image = np.float32(image)
            image_tensor = np.expand_dims(image, 0)
            digit = sess.run(prediction, feed_dict={x: image_tensor})
            print("predict digit : %d., actual digit : %s"%(digit[0], 1))
            if digit[0] == 1:
                count = count + 1
                cv.putText(copy, "cat", (20, 50), cv.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, (0, 0, 255), 2, 8)
                cv.imshow("Image Classification", copy)
                cv.waitKey(0)
    print("correct precent: %f"%(count/(len(cats)+len(dogs))))

测试运行截图如下:

本文分享自微信公众号 - OpenCV学堂(CVSCHOOL)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-11-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • tensorflow中实现神经网络训练手写数字数据集mnist

    基于tensorflow实现一个简单的三层神经网络,并使用它训练mnist数据集,神经网络三层分别为:

    OpenCV学堂
  • TensorFlow中的feed与fetch

    TensorFlow中的feed与fetch 一:占位符(placeholder)与feed 当我们构建一个模型的时候,有时候我们需要在运行时候输入一些初始数...

    OpenCV学堂
  • 教程 | 基于LSTM实现手写数字识别

    基于tensorflow,如何实现一个简单的循环神经网络,完成手写数字识别,附完整演示代码。

    OpenCV学堂
  • 基于tensorflow实现简单卷积神经网络Lenet5

    徐飞机
  • tensorflow中的数据类型dtype

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。

    于小勇
  • tensorflow学习笔记(三十五):control flow

    tf.cond(pred, fn1, fn2, name=None) 等价于: res = fn1() if pred else fn2() 注意:pred不能...

    ke1th
  • 机器学习的大局:用神经网络和TensorFlow分类文本

    开发人员常说,如果你想开始机器学习,你应该先学习算法是如何工作的。但是我的经验表明并不是这样子。

    人工智能资讯小编
  • 强化学习笔记-Python/OpenAI/TensorFlow/ROS-程序指令

    版权声明:本文为zhangrelay原创文章,有错请轻拍,转载请注明,谢谢... https://...

    zhangrelay
  • tensorflow.models.rnn.rnn_cell.linear在tensorflow1.0版本之后找不到(附tensorflow1.0 API新变化)

    由于版本更新关系,从原来的tensorflow低版本到升级到tensorflow1.0以上时,发现有很多API函数变化是很正常的事情,大多碰到的如: 如其中tf...

    sparkexpert
  • 深度学习入门实战(三):图片分类中的逻辑回归

    上一讲我们介绍了一下线性回归如何通过TensorFlow训练,这一讲我们介绍下逻辑回归模型,一句话说概括,逻辑回归就是多分类问题。

    serena

扫码关注云+社区

领取腾讯云代金券