• 深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)


    1.cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)

    参数说明:image表示输入图片,image_size表示变化后的图片大小,0, 0表示dx和dy, cv2.INTER_LINEAR表示插值的方式为线性插值

    2.image.get_shape[1:4].num_elements() 获得最后三个维度的大小之和

    参数说明:image表示输入的图片

    3. saver.save(sess, path, global_step=i) 进行sess的加载

    参数说明:sess表示输入,path表示保存路径, global_step表示路径的结尾

    4.saver = tf.train.import_meta_graph('./dog-cats-model/dog-cat.ckpt-3700.meta')  # 加载训练好的模型的meta值

    参数说明:./dog-cats-model/dog-cat.ckpt-3700.meta表示meta 的路径

    5.saver.restore(sess, ckpt_path) # 加载训练好的参数模型

    参数说明:sess表示执行函数,ckpt_path表示ckpt的路径

    6.graph = tf.get_defualt_graph 获得训练好的参数图

    7.graph.get_tensor_by_name('x:0') 获得模型的占位参数,以便进行模型的预测

    参数说明:’x:0‘ 表示模型在训练过程中,tf.placeholder(name=’x') 输入数据设置的名字

    代码中的学习点:1. 使用cv2.resize对图片的维度进行压缩

                                 2.使用np.zeros(num_classes)构造标签,lable[index] = 1 构造标签

                                 3.使用image.get_shape[1:4].num_elements获得最后三个维度的大小

                                  4. saver.save(sess, path, global_step=i) 进行模型参数的存储

                                  5.save.restore(sess, path)  进行模型的加载

    猫狗识别的代码:主要分为3个部分,

                                 第一部分:数据的准备

                                 第二部分:构造卷积神经网络,进行模型的训练

                                 第三部分:使用saver.restore加载训练好的参数,进行模型的预测。

    第一部分:数据的准备,构建read_train_data函数

    第一步:输入的参数是文件的地址,图片的大小(进行图像的矩阵变换),标签,验证集的比例

    第二步:对构造一个类dataset, 用于存储训练集和验证集

    第三步:对标签进行循环,对输入的文件与标签值进行拼接,获得图片文件的地址,使用glob.glob获得每张图片的地址。

    第四步:循环图片地址,读入图片

                  第一步:使用cv2.imread() 读入图片

                  第二步: 使用cv2.resize(img, (img_size, img_size), 0, 0, cv2.Inter) 进行图片的维度变换

                  第三步: 使用.astype('float32') 对图片进行数据类型的转换

                  第四步: 使用np.multiply(img, 1.0/255.0) 进行图片数值归一化操作, 并将图片加到列表中

                  第五步:使用np.zeros(num_classes) 构造标签的零矩阵

                  第六步:使用index = classes.index(filed) 获得标签值对应的索引,label[index] = 1 将索引位置赋值为1 

                  第七步: 将标签加到列表中

                  第八步:使用os.path.basename(file) 获得图片的名字,添加到列表中,获得标签的名字,添加到列表中

    第五步:对图片和标签使用np.array转换为数组类型,并返回图片,标签,名字,类别名

    第六步:使用sklearn.utils 中的shuffle,对图片,标签,名字和类别名进行清洗

    第七步:使用val_size,验证集的比例对训练集和验证集进行分割

    第八步:创建类别DataSet,实例化dataset.train和dataset.val,创建.next_batch函数,

    第九步:next_batch函数说明:使用一个变量self._epoch_index 对start和end进行递增循环,如果end > self._num_image, 将start置为0, self._epoch_index置为batch_size。

     代码:dataset.py 

    import numpy as np
    import tensorflow as tf
    import os
    import glob
    import cv2
    from sklearn.utils import shuffle
    
    
    
    def load_image(file_path, image_size, classes):
    
        num_classes = len(classes)
        images = []
        labels = []
        names = []
        cls = []
        # 第三步:循环标签,将路径和标签名进行拼接,获得图片文件路径,使用glob.glob获得图片路径
        for filed in classes:
            index = classes.index(filed)
            path = os.path.join(file_path, filed, '*g')
            files = glob.glob(path)
            # 第四步:循环图片路径,进行图片的读取
            for file in files:
                # cv2.imread图片的读取
                image = cv2.imread(file)
                # cv2.resize进行图片维度的重构
                image = cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)
                # .astype进行图片的数据类型的变换
                image = image.astype('float32')
                # 使用np.multipy进行图片的归一化操作
                image = np.multiply(image, 1.0/255.0)
                # 将图片添加到列表中
                images.append(image)
                # 标签零值初始化
                label = np.zeros(num_classes)
                # 对于类别位置与标签位置对应,即设置为1
                label[index] = 1
                # 将标签进行添加
                labels.append(label)
                # 获得图片的名字,使用os.path.basename
                name = os.path.basename(file)
                # 将名字进行添加
                names.append(name)
                # 将类别名进行添加
                cls.append(filed)
        # 第五步: 将图片和标签名都转换为array格式, 并返回图片,标签,名字和类别
        images = np.array(images)
        labels = np.array(labels)
    
    
        return images, labels, names, cls
    
    
    
    class DataSet(object):
    
    
        def __init__(self, images, labels, names, cls):
    
            self._num_image = images.shape[0]
            self._images = images
            self._labels = labels
            self._names = names
            self._cls = cls
            self._epoch_index = 0
        # 私有属性,返回实际的函数值
        @property
        def images(self):
            return self._images
        @property
        def labels(self):
            return self._labels
        @property
        def names(self):
            return self._names
        @property
        def cls(self):
            return self._cls
        @property
        def num_image(self):
            return self._num_image
        # next_batch函数,使用self._epoch_index用来创建初始索引和结束索引,返回batch图像,标签,名字和类别
        def next_batch(self, batch_size):
            start = self._epoch_index
            self._epoch_index += batch_size
            if self._epoch_index > self._num_image:
                start = 0
                self._epoch_index = batch_size
                assert batch_size < self._num_image
            end = self._epoch_index
            return self._images[start:end], self._labels[start:end], self._names[start:end], self._cls[start:end]
    
    
    # 第一步:输入文件名,图片大小,标签,验证集的比例
    def read_train_data(file_path, image_size, classes, val_size):
        # 第二步:构造类,实例化dataset用于存储训练集和验证集
         class DataSets(object):
             pass
         dataset = DataSets()
         # 第三步:载入图片,标签, 名字,类别名
         images, labels, names, cls = load_image(file_path, image_size, classes)
         # 第六步:对图片,标签,名字和类别名进行清洗
         images, labels, names, cls = shuffle(images, labels, names, cls)
         # 第七步:使用val_size 对训练集和验证集图片进行分开
         val_num = int(images.shape[0] * val_size)
    
         val_images = images[0:val_num]
         val_labels = labels[0:val_num]
         val_names = names[0:val_num]
         val_cls = cls[0:val_num]
    
         train_images = images[val_num:]
         train_labels = labels[val_num:]
         train_names = names[val_num:]
         train_cls = cls[val_num:]
         # 第八步:创建类别DataSet,实例化train和val数据集,并创建next_batch 
         dataset.train = DataSet(train_images, train_labels, train_names, train_cls)
         dataset.val = DataSet(val_images, val_labels, val_names, val_cls)
    
         return dataset

     第二步:模型的训练

    第一步:参数设置,一二三层卷积的大小和个数,以及全连接层的隐藏层的个数

    第二步:使用tf.placeholder设置初始的输入参数x和y_pred,并命名为x和y_pred, 使用np.argmax获得预测的索引值

    第三步:构建生成卷积过程中参数的函数, tf.Variable(tf.truncate_normal(shape, stddev=0.05))

    第四步:构建进行卷积的函数,使用tf.nn.conv2(x, w, stride=[1, 2, 2, 1], padding='SAME'),再加上偏置项b, 使用激活层tf.nn.relu构建, 使用tf.nn.max_pool构建池化层

    第五步:构建进行维度变换的函数,用于进行第一次全连接层的卷积到全连接的维度变换,使用image.get_shape()[1:4].num_elements获得后3个维度的个数之和,即乘积

    第六步:构造进行全连接的函数,使用tf.matmul构造全连接函数,这里的话,需要使用tf.nn.dropout进行dropout防止过拟合

    第七步:开始进行卷积过程

                  第一步:第一层卷积

                  第二步:第二层卷积

                  第三步:第三次卷积

                  第四步:第一次全连接,使用conv.get_shape[1:4].num_elements获得维度,构造参数

                   第五步:第二次全连接

    第八步:y_pred = tf.nn.softmax构造y_pred, 使用tf.argmax(y_pred, 1)输出索引值

    第九步:使用tf.nn.softmax_logits构造损失值loss, logits=score, labels= y_true

    第十步:使用tf.train.Adaoptimer().minimize自适应梯度下降降低损失值

    第十一步:使用tf.equal(y_pred_cls, y_true_cls) ,tf.reduce_mean构造准确率

    第十二步:构建train函数, 开始进行训练,首先使用data.train.next_batch获得batch训练样本,使用sess.run训练trainopt降低损失值,进行参数的训练

    第十三步:每一个epoch值,获得train 的batch,获得val_batch,对训练集和验证集的准确率进行展示

    代码:train.py

    import numpy as np
    import tensorflow as tf
    import matplotlib.pyplot as plt
    import dataset
    
    
    from numpy.random import  seed
    
    seed(0)
    
    from tensorflow import  set_random_seed
    
    set_random_seed(20)
    
    
    image_size = 60
    val_size = 0.2
    file_path = 'training_data'
    classes = ['cats', 'dogs']
    num_channel = 3
    num_classes = len(classes)
    
    # 第一部分数据的载入
    data = dataset.read_train_data(file_path, image_size, classes, val_size)
    
    image_num = data.train.images.shape[0]
    # 第二部分:数据的实际训练
    
    
    # 第一步参数设置,卷积层的维度和filter的个数
    # 第一层卷积大小
    filter1_size = 3
    filter1_num = 32
    # 第二层卷积大小
    filter2_size = 3
    filter2_num = 32
    # 第三层卷积大小
    filter3_size = 3
    filter3_num = 64
    # 隐含层大小
    fc1_num = 1024
    # 第二步:使用tf.placeholder设置初始输入参数
    # 输入参数大小, [图片的数目,图片的宽度, 图片的长度, 图片的通道数]
    x = tf.placeholder(tf.float32, [None, image_size, image_size, num_channel], name='x')
    # 输入图片标签值,大小为[N, num_classes] 这里为N*2
    y_true = tf.placeholder(tf.float32, [None, num_classes], name='y_true')
    #真实类别对应的索引值,即1所在的位置
    y_true_cls = tf.argmax(y_true, 1)
    
    # 第三步:生成卷积过程中所需要的函数
    def create_weight(shape):
        # 生成正态分布的初始值
        return tf.Variable(tf.truncated_normal(shape, stddev=0.05))
    
    def create_bias(size):
        # 生成常数分布的初始值
        return tf.Variable(tf.constant(0.05, shape=[size]))
    # 第四步:构造进行卷积的函数
    def create_convolution_layers(input, input_channel, filter_size, filter_num):
        # 生成卷积使用的W,[3, 3, 3, 32]第一层卷积核大小
        W = create_weight([filter_size, filter_size, input_channel, filter_num])
        # 生成偏置项b [32]
        b = create_bias(filter_num)
        # 进行卷积操作
        conv_layer = tf.nn.conv2d(input, W, strides=[1, 1, 1, 1], padding='SAME') + b
        # 进行激活操作
        conv_layer = tf.nn.relu(conv_layer)
        # 使用tf.nn.max_pool进行池化操作
        max_pool = tf.nn.max_pool(conv_layer, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
        # 返回池化的结果
        return max_pool
    # 第五步:构造图像变换的函数
    def create_flatten_conv(input):
        # 获得图片的后3个维度的大小
        input_shape = input.get_shape()[1:4].num_elements()
        # 对图像进行维度的变化,即[-1, input_shape] 以便用于后续的全连接操作
        out = tf.reshape(input, shape=[-1, input_shape])
    
        return out
    # 第六步:构造进行全连接变化的函数
    def create_fc_layer(input, num_input, fc1_num, relu_true = True):
        # 构造全连接的函数,即后三个维度的大小和第一个全连接的大小
        W = create_weight([num_input, fc1_num])
        # 构造偏置项b
        b = create_bias(fc1_num)
        # 构造线性变化,即x * w + b
        layer = tf.matmul(input, W) + b
        # 对全连接层进行dropout变化
        layer = tf.nn.dropout(layer, keep_prob=0.7)
        # 如果需要进行激活层
        if relu_true:
            # 就进行激活变化
            layer = tf.nn.relu(layer)
        # 返回结果
        return layer
    # 第七步:进行正式的卷积过程
    # 第一层卷积,输入为x, 通道数,卷积核的大小,卷积的个数
    conv_h1 = create_convolution_layers(x, num_channel, filter1_size, filter1_num)
    # 第二层卷积
    conv_h2 = create_convolution_layers(conv_h1, filter1_num, filter2_size, filter2_num)
    # 第三层卷积
    conv_h3 = create_convolution_layers(conv_h2, filter2_num, filter3_size, filter3_num)
    # 获得第三层卷积后的后3个维度的大小
    flatten_shape = conv_h3.get_shape()[1:4].num_elements()
    # 对图像进行维度变化
    flatten_conv = create_flatten_conv(conv_h3)
    # 进行全连接操作,输入的是变换后的图像,全连接的第一个维度和第二个维度
    fc_h1 = create_fc_layer(flatten_conv, flatten_shape, fc1_num)
    # 进行第二次全连接,输出预测的得分值
    out = create_fc_layer(fc_h1, fc1_num, num_classes, relu_true=False)
    # 第八步:使用tf.nn.softmax获得输入得分的概率值
    y_pred = tf.nn.softmax(out, name='y_pred')
    # 使用tf.agrmax获得对应的最大索引的大小
    y_pred_cls = tf.argmax(y_pred, 1)
    # 第九步:使用tf.reduce_mean获得softmax的损失值
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=out))
    # 第十步:使用自适应梯度下降,进行损失值的下降
    train_op = tf.train.AdamOptimizer(0.0001).minimize(cost)
    # 第十一步:使用tf.equal表示类别是否相同
    correct_pred = tf.equal(y_true_cls, y_pred_cls)
    accur = tf.reduce_mean(tf.cast(correct_pred, 'float'))
    
    # 构造session函数
    session = tf.Session()
    # 构造存储函数
    saver = tf.train.Saver()
    # 进行初始化操作
    session.run(tf.global_variables_initializer())
    
    batch_size = 32
    
    def show_progress(data, lost, epoch, i):
        
        tr_image_batch, tr_label_batch = data.train.next_batch(batch_size)[0:2]
        val_image_batch, val_label_batch = data.val.next_batch(batch_size)[0:2]
        # 输出训练样本的准确率
        tr_accur = session.run(accur, feed_dict={x:tr_image_batch, y_true:tr_label_batch})
        # 输出验证样本的准确率
        val_accur = session.run(accur, feed_dict={x:val_image_batch, y_true:val_label_batch})
        # 打印epoch值,训练集和验证集准确率,训练的损失值,迭代的次数
        content = ('train_epoch {0} tr_accur {1:>6.1%} val_accur {2:6.1%} train_loss {3:.3f} iteration_num {4}')
        print(content.format(epoch, tr_accur, val_accur, lost, i))
    def train(num_iteration):
        start_epoch = 0
        for i in range(num_iteration):
            # 第十二步:构造函数进行参数的实际代入,使用data.train.next_batch获得模型的训练样本和验证集样本,进行模型训练
            batch_image, batch_labels, batch_nams, batch_cls = data.train.next_batch(batch_size)
            session.run(train_op, feed_dict={x:batch_image, y_true:batch_labels})
            #第十三步:每一个epoch进行模型的准确率的输出
            if i % int(data.train.num_image / batch_size) == 0:
                # 计算模型的损失值
                loss = session.run(cost, feed_dict={x:batch_image, y_true:batch_labels})
                # 展示模型的训练集和验证集的准确率
                show_progress(data, loss, start_epoch, i)
                start_epoch += 1
                # 第十四步:使用saver.save(session, './dog-cats-model/dog-cat.ckpt', global_step)进行模型的参数保存
                saver.save(session, './dog-cats-model/dog-cat.ckpt', global_step=i)
    
    
    train(8000)

    第三部分:进行模型的预测

    第一步:图片的输入,对于输入的图片需要进行与训练样本输入时相同的处理

                  第一步:使用cv2.imread()进行样本的读取

                  第二步:使用cv2.resize进行图片的维度变换

                  第三步:.astype对样本的类型进行变换

                  第四步:使用np.multipy对样本进行归一化操作

                  第五步:将图片的维度进行变换,因为是一张图片,维度变化为[1, 60, 60, 3]

               

    第二步:将训练好的模型进行加载

                  第一步:构建sess = tf.Session() 
                  第二步:使用saver = tf.train.import_meta_graph 加载模型的meta 

                  第三步:使用saver.restore() 加载模型的ckpt-3750

                  第四步:graph = tf.get_default_graph()获得参数结构图

                  第五步:使用graph.get_tensor_by_name('y_pred:0') 获得预测y_pred

                   第五步:使用graph.get_tensor_by_name('x:0') 获得输入x

                   第六步:使用graph.get_tensor_by_name('y_pred:0') 获得输入标签y_true 

                   第七步:使用np.zeros((1, 2))构造输入值得标签

                   第八步:使用sess.run(y_pred, feed_dict={x:x_batch, y_pred:y_test_img}) 进行结果的预测

                   第九步:使用tf.argmax获得标签的索引,使用标签名获得最终的预测结果

     代码:predict.py 

    import tensorflow as tf
    import numpy as np
    import cv2
    
    # 第一步图片的载入
    image_size = 60
    # 图片的文件名
    path = 'cat.4.jpg'
    # 读取图片
    image = cv2.imread(path)
    # 改变图片的大小
    image = cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR)
    # 图片类型的转换
    image = image.astype('float32')
    # 进行图像的归一化
    image = np.multiply(image, 1.0/255.0)
    # 对图像进行维度的变化
    x_batch = image.reshape(1, image_size, image_size, 3)
    
    # 加载模型,对图片进行预测
    # 初始化sess
    sess = tf.Session()
    # 载入saver,获得模型的结果saver
    saver = tf.train.import_meta_graph('./dog-cats-model/dog-cat.ckpt-3700.meta')
    # 使用saver加载sess
    saver.restore(sess, './dog-cats-model/dog-cat.ckpt-3700')
    # 获得模型的结构图
    graph = tf.get_default_graph()
    # 使用结构图获得模型参数y_pred
    y_pred = graph.get_tensor_by_name('y_pred:0')
    # 获得模型参数x
    x = graph.get_tensor_by_name('x:0')
    # 获得模型参数y_true
    y_true = graph.get_tensor_by_name('y_true:0')
    # 构造真实的标签值,初始化
    y_test_images = np.zeros((1, 2))
    # 输入的样本参数
    feed_dict_testing = {x:x_batch, y_pred:y_test_images}
    # 获得模型的预测结果,使用sess.run 
    result = sess.run(y_pred, feed_dict=feed_dict_testing)
    # 根据预测得分,获得最大值的标签索引做为标签索引,获得最终的预测结果
    res_label = ['cat', 'dog']
    print(res_label[result.argmax()])

              

  • 相关阅读:
    跨域的异步请求二
    cloneNode在兼容问题
    实现here document的一些副产品
    跨域的异步请求三
    getBasePath 函数第二版
    跨域的异步请求一
    IE6的base标签导致页面结构大混乱
    元素的自定义属性
    IE6与IE7封杀器与浏览器杀手
    ImageMagick 打水印支持透明度设置
  • 原文地址:https://www.cnblogs.com/my-love-is-python/p/10541030.html
Copyright © 2020-2023  润新知