如何制作数据集,实现特定应用?

11 Python/DL/ML 专栏收录该内容
241 篇文章 7 订阅

一、理论部分                                                                                                                                     点击此处返回总目录

二、实战部分

 

 

从这里下载图片用来制作数据集  https://github.com/caoxiaoliang/tensorflow-learning/tree/master/code

这一篇文章也写得不错,推荐  https://blog.csdn.net/miaomiaoyuan/article/details/56865361

 

 

解决了第一个问题,我们再来看第二个问题,实现特定应用。

 

一、理论部分

制作数据集可以使用二进制文件tfrecords,来保存对图片和标签的序列化。

用tf.train.Example协议来存储训练数据,训练数据的特征用键值对表示。如 原始图片:图片的值,标签:标签的值。值可以是字符串、实数列表、整数列表。

用SerializeToString()把数据序列化成字符串来存储。

 

        

 

要生成tfrecords文件,首先要创建一个writer。writer=tf.python_io.TFRecordWriter(),在括号中告知要生成的tfRecords在哪里,叫什么名。

用for循环遍历每张图片和标签:

    用tf.train.Example中的teatures封装到example中。在tf.train.Features()中,特征会以字典的形式给出。"[img_raw]"这个位置放入二进制的图片,"labels"这个位置放入这张图片所对应的标签。

    再用writer.write()把example进行序列化。

这样就生成了tfrecords文件。

 

            

 

 

如果想从tfrecords文件解析出图片和标签,需要新建立文件队列名filename,"[tfRecord_path]"告知tfrecords文件放到哪里了,包括路径和文件名。

新建一个reader。

读出的每一个样本保存在serialized_example中。

进行解序列化。

恢复img_raw到img。

把img的形状变为1行784列。也就是包含784个元素的一维数组。

把img的每个元素变为浮点数,并且在0~1之间。

把label的每一个元素也变为浮点数。

这样img和label就满足上一节课模型的输入要求了。

 

              

 

 

二、实战部分

 

首先准备数据,从这里下载图片,解压。

 

在.\mnist_data_jpg下有四个文件(夹):

 

其中:

.\mnist_data_jpg\mnist_train_jpg_60000下,有60000张图片,如下:

 

.\mnist_data_jpg\mnist_test_jpg_10000下,有10000张图片,如下:

 

mnist_train_jpg_60000.txt,共有60000行,内容如下:

 

mnist_test_jpg_10000.txt共有10000行,内容如下:

 

下面我们来看一下代码:

比上一节的代码多了一个mnist_generateds.py文件,里面包含了tfrecord文件的生成和标签图片的批获取。在mnist_backward.py和mnist_test.py中,修改了图片和标签的获取接口。mnist_forward.py和mnist_app.py和上一节的完全相同。

 

            

 

//mnist.generateds.py

#coding:utf-8
import tensorflow as tf 
import numpy as np 
from PIL import Image
import os 

image_train_path = './mnist_data_jpg/mnist_train_jpg_60000/'
label_train_path = './mnist_data_jpg/mnist_train_jpg_60000.txt'
tfRecord_train = './data/mnist_train.tfrecords'
image_test_path = './mnist_data_jpg/mnist_test_jpg_10000/'
label_test_path = './mnist_data_jpg/mnist_test_jpg_10000.txt'
tfRecord_test = './data/mnist_test.tfrecords'
data_path = './data'
resize_height = 28
resize_width = 28

 

def write_tfRecord(tfRecordName, image_path, label_path): #参数分别为:存放tfrecords文件的路径和文件名,图像路径和标签文件
    writer = tf.python_io.TFRecordWriter(tfRecordName) #创建一个writer.
    num_pic = 0                                                                #为了显示进度,创建一个计数器num_pic
    f = open(label_path, 'r')                          #以读的形式打开标签文件。标签文件是一个txt文件。txt文件每行由文件名和标签组成。

                                                                     中间用空格隔开。
    contents = f.readlines()                           #读取整个文件的内容,赋给contents
    f.close()                                                   #关闭文件
    for content in contents:                           #在for循环中,遍历每行内容。
        value = content.split()                         #用空格分割每行的内容。分割后组成列表value。
        print("value[0]:"+value[0])
        print("value[1]:"+value[1])
        image_path_new = image_path + value[0]             #图片文件的路径就变成了image_path接value[0]
        print("图片为:"+image_path_new)
        img = Image.open(image_path_new)                   #打开图片。
        img_raw = img.tobytes()                                      #将img转换成二进制数据。
        labels = [0]*10                                    #把labels的每一个元素赋值为0。
        labels[int(value[1])] = 1                      #把labels所对应的标签为赋值为1.


        #创建一个example,用tf.train.Example()中的features封装到example中。
        example = tf.train.Example(features=tf.train.Features(feature={  
            'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])), #img_raw这个位置放入二进制图片。
            'label': tf.train.Feature(int64_list=tf.train.Int64List(value=labels))  #labels这个位置放入这张图片所对应的标签。
        }))

 

        writer.write(example.SerializeToString())  #用writer.write()把example进行序列化。
        num_pic += 1                               #每保存一张图片,计数器加1
        print("the number of picture:", num_pic)   #打印出进度提示。
    writer.close()                                 #当for循环把所有的图片和标签都完成序列化后,关闭writer.
    print("Write tfrecord sussessful")

 

def generate_tfRecord():
    isExists = os.path.exists(data_path)   #判断保存路径是否存在
    if not isExists:
        os.makedirs(data_path)                #如果不存在,则新建路径。
        print("The directory was create successfully")
    else:
        print ("directory already exists")

    #使用自定义函数,把训练集中的图片和标签生成名叫tfRecord_train的tfrecords文件。
    write_tfRecord(tfRecord_train, image_train_path, label_train_path)   

    #同样把测试集中的图片和标签生成名叫tfRecord_test的函数
    write_tfRecord(tfRecord_test, image_test_path, label_test_path)

 

def read_tfRecord(tfRecord_path):    #read_tfRecord()接收到待读取的tfrecords文件。

     #新建文件名队列。告知文件名队列包括哪些文件。我们的数据集比较小,只有一个tfrecords文件。 
    filename_queue = tf.train.string_input_producer([tfRecord_path])
    reader = tf.TFRecordReader() # 新建一个reader

     #把读出的每一个样本保存到serialized_example中,进行解序列化。
    _, serialized_example = reader.read(filename_queue)  
    features = tf.parse_single_example(serialized_example, features={
                                                            'img_raw':tf.FixedLenFeature([],tf.string),
                                                            'label':tf.FixedLenFeature([10],tf.int64)}) #标签和图片的键名,应该和制作tfrecords的键名相同。标签的10表示是十分类,手写数字时10分类,所以写10.
    img = tf.decode_raw(features['img_raw'],tf.uint8)    #decode_raw()函数将img_raw字符串转换成8位无符号整型。
    img.set_shape([784])                                 #把形状变为1行784列。
    img = tf.cast(img,tf.float32)*(1./255)               #再变成浮点数,0~1之间。
    label = tf.cast(features['label'], tf.float32)       #把标签列表也变成浮点数形式。
    return img, label                                    #返回图片和标签

 

 

#这个函数实现了批获取训练集或者测试集中的图片和标签。如果读取训练集,参数写True;如果读取测试集,参数写False。num表示一次读取多少组

def get_tfRecord(num, isTrain=True):  
    if isTrain:
        tfRecord_path = tfRecord_train
    else:
        tfRecord_path= tfRecord_test
    img, label = read_tfRecord(tfRecord_path)  #读取过程用read_tfRecord()实现。

    #tf.train.shuffle_batch会从总样本中顺序取出capacity组数据,打乱顺序,每次输出batch_size组。如果capacity少于       

    #min_after_dequene,会从总样本中取数据填满capacity。整个过程使用了两个线程。
    img_batch, label_batch = tf.train.shuffle_batch([img, label],
                                                    batch_size=num,
                                                    num_threads=2,
                                                    capacity=1000,
                                                    min_after_dequeue=700)
    return img_batch, label_batch                #这个时候返回的图片和标签就是随机抽取出的batch_size组数据了。

 

def main():
    generate_tfRecord()

 

if __name__ == '__main__':
    main()
 

运行结果:

在./data文件夹下生成了以下两个文件:

 

 

 

在反向传播和测试程序中,修改了图片和标签的批获取接口。

在实际应用中,我们可以使用多线程来提高图片和标签的批获取效率,方法就是把批获取的操作放在线程协调器开启和关闭之间。上面两行表示开启线程协调器,下面两行表示关闭线程协调器。

 

          

 

//mnist_forward.py(跟上一节的完全相同)

import tensorflow as tf

#首先定义了神经网络结构的相关参数
INPUT_NODE = 784                  #神经网络的输入节点是784个。因为输入的是图片像素值,每张图片是28*28=784个像素点。
OUTPUT_NODE = 10                  #输出10个数,每个数表示对应的索引号出现的概率。实现了10分类。
LAYER1_NODE = 500                 #隐藏层节点的个数

 

def get_weight(shape,regularizer):
    w = tf.Variable(tf.truncated_normal(shape,stddev = 0.1))     #随机生成参数w
    if regularizer !=None:
        tf.add_to_collection('losses',tf.contrib.layers.l2_regularizer(regularizer)(w)) #如果使用正则化,则将每一个w的正则化损失加入到总损失集合losses
    return w    

 

def get_bias(shape):
    b = tf.Variable(tf.zeros(shape))
    return b


#搭建网络,描述从输入到输出的数据流
def forward(x,regularizer):
    w1 = get_weight([INPUT_NODE,LAYER1_NODE],regularizer)
    b1 = get_bias([LAYER1_NODE])
    y1 = tf.nn.relu(tf.matmul(x,w1)+b1)

    w2 = get_weight([LAYER1_NODE,OUTPUT_NODE],regularizer)
    b2 = get_bias([OUTPUT_NODE])
    y = tf.matmul(y1,w2)+b2                                 #这个结果是直接输出的,因为要对输出使用softmax函数,使它符合概率分布,所以输出y,不过relu函数。
    return y

//mnist_backward.py。修改的地方用noi标出来了。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data   #导入模块
import mnist_forward
import os
import mnist_generateds                #no1.

 

BATCH_SIZE = 200
LEARNING_RATE_BASE = 0.1
LEARNING_RATE_DECAY = 0.99
REGULARIZER = 0.0001
STEPS = 50000
MOVING_AVERAGE_DECAY = 0.99
MODEL_SAVE_PATH = "./model/"
MODEL_NAME = "mnist_model"
train_num_examples=60000      #no2.之前可以通过mnist.train.num_examples得到总样本数,现在只能自己给出了。

 

def backward():                          #13
    x=tf.placeholder(tf.float32,shape=(None,mnist_forward.INPUT_NODE))
    y_ = tf.placeholder(tf.float32,shape=(None,mnist_forward.OUTPUT_NODE))
    
    #首先进行前向传播
    y = mnist_forward.forward(x,REGULARIZER)
    global_step = tf.Variable(0,trainable = False)
    
    
    ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels= tf.argmax(y_,1))
    cem = tf.reduce_mean(ce)
    loss = cem+tf.add_n(tf.get_collection('losses'))
    
    #指数学习衰减率
    learning_rate = tf.train.exponential_decay(
            LEARNING_RATE_BASE,
            global_step,
            train_num_examples/BATCH_SIZE,   #no3。之前可以通过mnist.train.num_examples得到总样本数,现在只能自己给出了。
            LEARNING_RATE_DECAY,
            staircase=True)
    
    
    train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
    
    ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
    ema_op = ema.apply(tf.trainable_variables())
    with tf.control_dependencies([train_step,ema_op]):
        train_op = tf.no_op(name='train')
        
        
        
    saver = tf.train.Saver()
    img_batch,label_batch = mnist_generateds.get_tfRecord(BATCH_SIZE,isTrain=True)  #no5.一次从训练集中获取BATCH_SIZE组
    
    with tf.Session() as sess:
        init_op = tf.global_variables_initializer()
        sess.run(init_op)
        
        ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
        if ckpt and ckpt.model_checkpoint_path:
            saver.restore(sess, ckpt.model_checkpoint_path)

        coord = tf.train.Coordinator()                    #no7.线程协调器。
        threads = tf.train.start_queue_runners(sess=sess , coord=coord)  #no8

        for i in range(STEPS):
            #xs,ys = mnist.train.next_batch(BATCH_SIZE)    #no4 以前通过mnist.train.next_batch()可以直接读出图片和标签喂给网络,现在需要自己读。
            xs, ys = sess.run([img_batch,label_batch])    #no6 涉及到计算,所以在run中执行。
            _,loss_value,step = sess.run([train_op,loss,global_step],feed_dict={x:xs,y_:ys})
            if i%1000 ==0:
                print("After %d training step(s),loss on training batchis %g" %(step,loss_value))
                saver.save(sess,os.path.join(MODEL_SAVE_PATH,MODEL_NAME),global_step = global_step)

        coord.request_stop()  #no9
        coord.join(threads)   #no10

 

def main():
    #mnist = input_data.read_data_sets("./data/",one_hot = True)   #11
    backward()   #12

 

if __name__ =='__main__':
    main()

//mnist_test.py。修改的地方用noi标出了。

# -*- coding: utf-8 -*-

import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import mnist_backward
import mnist_generateds    #no1
TEST_INTERVAL_SECS = 5
TEST_NUM = 10000           #no2.手动给出测试样本数。


def test():                 #12
    with tf.Graph().as_default() as g:
        x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
        y_ = tf.placeholder(tf.float32, [None,mnist_forward.OUTPUT_NODE])
        y = mnist_forward.forward(x, None)
        
        ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
        ema_restore = ema.variables_to_restore()
        saver = tf.train.Saver(ema_restore)
        
        
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

        img_batch,label_batch = mnist_generateds.get_tfRecord(TEST_NUM, isTrain = False) #no3.读取所有测试集10000张图片。

        while True:
            with tf.Session() as sess:
                ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
                if ckpt and ckpt.model_checkpoint_path:
                    saver.restore(sess, ckpt.model_checkpoint_path)
                    global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
                    
                    coord = tf.train.Coordinator() #4
                    threads = tf.train.start_queue_runners(sess=sess,coord=coord)#5
                    
                    xs,ys=sess.run([img_batch,label_batch]) #8
                    accuracy_score = sess.run(accuracy, feed_dict={x: xs, y_: ys}) #9
                    print("After %s training steps, test accuracy = %g" %(global_step, accuracy_score))
                    
                    coord.request_stop()  #6
                    coord.join(threads)   #7
                    
                else:
                    print("No checkpoint file found")
                    return
            time.sleep(TEST_INTERVAL_SECS)
            
def main():
    #mnist = input_data.read_data_sets("./data/", one_hot = True)  #10
    test()   #11
    
if __name__ =='__main__':
    main()

首先执行mnist_backward.py,然后同步执行mnist_test.py查看准确率的变化:

 

 

带训练完之后,或者准确率比较高的时候,执行mnist_app.py(与上一节的完全相同)。

#coding:utf-8

import numpy as np
import tensorflow as tf
from PIL import Image
import mnist_backward
import mnist_forward

def restore_model(testPicArr):
    with tf.Graph().as_default() as tg:       #重现计算图
        x=tf.placeholder(tf.float32,[None,mnist_forward.INPUT_NODE])   #仅需要给输入x占位
        y=mnist_forward.forward(x,None)                               #计算求得输出y
        preValue = tf.argmax(y,1)                                     #y的最大值对应的索引列表号,就是预测结果
        
        #实例化带有滑动平均值的saver
        variable_averages = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
        variables_to_restore = variable_averages.variables_to_restore()
        saver = tf.train.Saver(variables_to_restore)

        with tf.Session() as sess:
            ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
            if ckpt and ckpt.model_checkpoint_path:
                saver.restore(sess, ckpt.model_checkpoint_path)     #恢复ckpt的信息到当前会话
                
                preValue = sess.run(preValue,feed_dict={x:testPicArr})    #把图片喂入网络,执行预测操作
                return preValue
            else:
                print("No checkpoint found")
                return -1

def pre_pic(picName):
    img = Image.open(picName)   #首先打开图片
    reIm = img.resize((28,28),Image.ANTIALIAS) #将图片改为28*28像素,Image.ANTIALIAS表示用消除锯齿的方法resize
    im_arr = np.array(reIm.convert('L')) #为了符合模型对颜色的要求,把reIm用convert('L')变成灰度图。用np.array()把reIm转化成矩阵的形式。赋给im_arr
   
    #给图像进行二值化处理,让图片只有纯白色点和纯黑色点。不要有灰色点。这样可以滤掉手写图片中的噪声,留下图片主要特征。
    threshold = 50      #阈值。可以自己调节阈值,让图片尽量包含手写数字的完整信息,也可以尝试其他方法来滤掉噪声。
    for i in range(28):
        for j in range(28):
            im_arr[i][j] = 255-im_arr[i][j]    #由于模型要求的是黑底白字,而我们的图片是白底黑字,所以要给图片反色。
            if(im_arr[i][j] < threshold):
                im_arr[i][j]=0              #小于阈值的点认为是纯黑色0.
            else:
                im_arr[i][j]=255            #大于阈值的点认为是纯白色255.
    nm_arr = im_arr.reshape([1,784])        #im_arr整理形状为1行784列。
    nm_arr = nm_arr.astype(np.float32)      #由于模型要求像素点是0~1之间的浮点数,先让nm_arr变成浮点型。
    img_ready = np.multiply(nm_arr,1.0/255.0) #再让现有的rgb图从0到255之间的数,变为0~1之间的浮点数。
    
    return img_ready


def application():
    testNumtmp = input("input the number of test picture:")  #读数字
    testNum = int(testNumtmp)
    for i in range(testNum):
        testPic = input("the path of test picture:")
        testPicArr = pre_pic(testPic)     #预处理。由于要使用已有的模型作应用,所以图片必须符合输入要求.
        preValue = restore_model(testPicArr)
        print("The prediction number is:",preValue)


def main():
    application()
    
if __name__ == '__main__':
    main()

结果如下:

        

 

7没有识别出来,其他的识别出来了~~

 

 

 

 

 

 

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值