tensorflow下 自制rfrecords数据集采用one-hot编码做图像分类**

tensorflow下 自制TFRecords数据集采用one-hot编码做图像分类

TFRecords数据集读取与存储借鉴于 http://blog.csdn.net/wiinter_fdd/article/details/72835939
运行平台: Windows
Python版本: Python3.x
IDE: Spyder

前言

笔者近几日在研究如何用自制的数据集来进行深度学习的训练,开始尝试把图片以np的形式存储成txt格式,并手动采用one-hot标签,但是数据集标签标注复杂,不适用于数据分类多的数据集,并且数据存储与读取缓慢。由于以上原因,这时我们就采用了TFRecords数据集存储与读取,但是TFRecords数据集的标签为数字(如:1,2,3,8等),这时候我们在获取TFRecords数据集的标签进行one-hot编码,这样就可以进行深度学习的训练了。

数据集的展示

在这里插入图片描述
笔者的数据集基于实验室的荧光小球与微片,一共有8类,在TFRecords数据集下标签为0—7.

TFRecords数据集存储与读取

####TFRecords数据集存储
cwd = "E://玻片小球//"
classes = {'clips', 'balls'} #预先自己定义的类别
cwd = os.getcwd()#自动获取当前目录路径
cwd = "E:/玻片小球/"#手动输入路径
classes = {'clips_red', 'clips_yellows','clips_Microscopic','balls_green','balls_red','balls_yellow','balls_Microscopic', 'clips_green'} #类别设定
#定义writer用于写入数据,tf.python_io.TFRecordWriter 写入到TFRecords文件中
writer = tf.python_io.TFRecordWriter("train1.tfrecords")#定义生成的文件名为“train1.tfrecords”
for index, name in enumerate(classes):
    class_path = cwd + name + "/"
    for img_name in os.listdir(class_path):
        img_path = class_path + img_name #每一个图片的地址
        img = Image.open(img_path)
        img = img.resize((height, weight))  #将数据集中的所有图片保存成100×100大小
        img_raw = img.tobytes()              #将图片转化为原生bytes,#tf.train.Example 协议内存块包含了Features字段,通过feature将图片的二进制数据和label进行统一封装
        example = tf.train.Example(features=tf.train.Features(feature={
            "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[index])),
            'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
        }))   #example对象对label和image进行封装
        writer.write(example.SerializeToString())  #序列化为字符串,example协议内存块转化为字符串
writer.close()
#######数据的读取
def read_and_decode(filename):#读入tfrecords文件
    filename_queue=tf.train.string_input_producer([filename])
    reader=tf.TFRecordReader()
    _,serialized_example=reader.read(filename_queue)#生成一个queue队列
    #将image数据和label数据读取出来放入features
    features=tf.parse_single_example(serialized_example,features={
        'label':tf.FixedLenFeature([],tf.int64),
        'img_raw':tf.FixedLenFeature([],tf.string)})
    img=tf.decode_raw(features['img_raw'],tf.uint8)
    img=tf.reshape(img,[height, weight,3])#将图像reshape成128*128
    img=tf.cast(img,tf.float32)*(1./255)-0.5#将image归一化
    label=tf.cast(features['label'],tf.int32)#将label转化成int32
    return(img,label)

这里笔者有话要说,大家可能在数据读取的时候遇到如下的问题:
tensorflow.python.framework.errors.InvalidArgumentError: Input to reshape is a tensor with xxx values, but the requested shape requires a multiple of xxx values
大家可以检查一下自己的数据集是否有问题,如:数据集里有黑白图片,有gif格式图片,都会出现如下问题,笔者因为这个原因卡了一晚上。

CNN网络的搭建以及one-hot编码

CNN网络的搭建主要借鉴了这篇博客https://blog.csdn.net/qq_38375282/article/details/81542795
但是由于这篇博客只有猫狗两种分类,没有one-hot编码,所以标签只有0和1,笔者认为有一定问题,欢迎大家来指正。

batch_size=432
 
#定义初始化权重和偏置函数
def weight_variable(shape):
    return(tf.Variable(tf.random_normal(shape,stddev=0.01)))
def bias_variable(shape):
    return(tf.Variable(tf.constant(0.1,shape=shape)))
#定义输入数据和dropout占位符
X=tf.placeholder(tf.float32,[batch_size,height, weight,3])
y_=tf.placeholder(tf.float32,[batch_size,8])
keep_pro=tf.placeholder(tf.float32)
 
#搭建网络
def model(X,keep_pro):
    w1=weight_variable([5,5,3,32])
    b1=bias_variable([32])
    conv1=tf.nn.relu(tf.nn.conv2d(X,w1,strides=[1,1,1,1],padding='SAME')+b1)
    pool1=tf.nn.max_pool(conv1,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME')
    
    w2=weight_variable([5,5,32,64])
    b2=bias_variable([64])
    conv2=tf.nn.relu(tf.nn.conv2d(pool1,w2,strides=[1,1,1,1],padding='SAME')+b2)
    pool2=tf.nn.max_pool(conv2,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME') 
    tensor=tf.reshape(pool2,[batch_size,-1])
    dim=tensor.get_shape()[1].value
    w3=weight_variable([dim,1024])
    b3=bias_variable([1024])
    fc1=tf.nn.relu(tf.matmul(tensor,w3)+b3)
    h_fc1=tf.nn.dropout(fc1,keep_pro)
    w4=weight_variable([1024,8])
    b4=bias_variable([8])
    y_conv=tf.nn.softmax(tf.matmul(h_fc1,w4)+b4)
    return(y_conv)
 
#定义网络,并设置损失函数和训练器
y_conv=model(X,keep_pro)
cost=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1]))
train_step=tf.train.AdamOptimizer(0.001).minimize(cost)
#计算准确率
correct_prediction=tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
a1=tf.argmax(y_,1)
#读取tfrecords数据
image,label=read_and_decode("train1.tfrecords")
#定义会话,并开始训练
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    #定义多线程
    coord=tf.train.Coordinator()
    threads=tf.train.start_queue_runners(coord=coord)
    #定义训练图像和标签
    example=np.zeros((batch_size,height, weight,3))
    l=np.zeros((batch_size,1))
    try:
        #将数据存入example和l,并将转化成one_hot形式
        for epoch in range(batch_size):
            example[epoch],l[epoch]=sess.run([image,label])
        print(l)       
        enc=OneHotEncoder()
        l=enc.fit_transform(l)
        l=l.toarray()
        print(l)
        for i in range(100):
           #开始训练
            sess.run(train_step,feed_dict={X:example,y_:l,keep_pro:0.5})
            if i%10==0:
                print('train step','%04d ' %(i+1),'Accuracy=',sess.run(accuracy,feed_dict={X:example,y_:l,keep_pro:0.5}))
    except tf.errors.OutOfRangeError:
        print('done!')
    finally:
        coord.request_stop()
    coord.join(threads)

完整代码

import os 
import tensorflow as tf
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import OneHotEncoder


height=100
weight=100
####################################################################################################数据集存储
cwd = "E://玻片小球//"
classes = {'clips', 'balls'} #预先自己定义的类别
cwd = os.getcwd()#自动获取当前目录路径
cwd = "E:/玻片小球/"#手动输入路径
classes = {'clips_red', 'clips_yellows','clips_Microscopic','balls_green','balls_red','balls_yellow','balls_Microscopic', 'clips_green'} #类别设定
#定义writer用于写入数据,tf.python_io.TFRecordWriter 写入到TFRecords文件中
writer = tf.python_io.TFRecordWriter("train1.tfrecords")#定义生成的文件名为“train1.tfrecords”
for index, name in enumerate(classes):
    class_path = cwd + name + "/"
    for img_name in os.listdir(class_path):
        img_path = class_path + img_name #每一个图片的地址
        img = Image.open(img_path)
        img = img.resize((height, weight))  #将图片保存成100×100大小
        img_raw = img.tobytes()              #将图片转化为原生bytes,#tf.train.Example 协议内存块包含了Features字段,通过feature将图片的二进制数据和label进行统一封装
        example = tf.train.Example(features=tf.train.Features(feature={
            "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[index])),
            'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
        }))   #example对象对label和image进行封装
        writer.write(example.SerializeToString())  #序列化为字符串,example协议内存块转化为字符串
writer.close()
##########################################################################################数据集读取
def read_and_decode(filename):#读入tfrecords文件
    filename_queue=tf.train.string_input_producer([filename])
    reader=tf.TFRecordReader()
    _,serialized_example=reader.read(filename_queue)#生成一个queue队列
    #将image数据和label数据读取出来放入features
    features=tf.parse_single_example(serialized_example,features={
        'label':tf.FixedLenFeature([],tf.int64),
        'img_raw':tf.FixedLenFeature([],tf.string)})
    img=tf.decode_raw(features['img_raw'],tf.uint8)
    img=tf.reshape(img,[height, weight,3])#将图像reshape成100*100*3
    img=tf.cast(img,tf.float32)*(1./255)-0.5#将image归一化
    label=tf.cast(features['label'],tf.int32)#将label转化成int32
    return(img,label)
#############################################网络搭建
batch_size=432
#定义初始化权重和偏置函数
def weight_variable(shape):
    return(tf.Variable(tf.random_normal(shape,stddev=0.01)))
def bias_variable(shape):
    return(tf.Variable(tf.constant(0.1,shape=shape)))
#定义输入数据和dropout占位符
X=tf.placeholder(tf.float32,[batch_size,height, weight,3])
y_=tf.placeholder(tf.float32,[batch_size,8])
keep_pro=tf.placeholder(tf.float32)
 
#搭建网络
def model(X,keep_pro):
    w1=weight_variable([5,5,3,32])
    b1=bias_variable([32])
    conv1=tf.nn.relu(tf.nn.conv2d(X,w1,strides=[1,1,1,1],padding='SAME')+b1)
    pool1=tf.nn.max_pool(conv1,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME')
    
    w2=weight_variable([5,5,32,64])
    b2=bias_variable([64])
    conv2=tf.nn.relu(tf.nn.conv2d(pool1,w2,strides=[1,1,1,1],padding='SAME')+b2)
    pool2=tf.nn.max_pool(conv2,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME') 
    tensor=tf.reshape(pool2,[batch_size,-1])
    dim=tensor.get_shape()[1].value
    w3=weight_variable([dim,1024])
    b3=bias_variable([1024])
    fc1=tf.nn.relu(tf.matmul(tensor,w3)+b3)
    h_fc1=tf.nn.dropout(fc1,keep_pro)
    w4=weight_variable([1024,8])
    b4=bias_variable([8])
    y_conv=tf.nn.softmax(tf.matmul(h_fc1,w4)+b4)
    return(y_conv)
 
#定义网络,并设置损失函数和训练器
y_conv=model(X,keep_pro)
cost=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1]))
train_step=tf.train.AdamOptimizer(0.001).minimize(cost)
#计算准确率
correct_prediction=tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
a1=tf.argmax(y_,1)
#读取tfrecords数据
image,label=read_and_decode("train1.tfrecords")
#定义会话,并开始训练
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    #定义多线程
    coord=tf.train.Coordinator()
    threads=tf.train.start_queue_runners(coord=coord)
    #定义训练图像和标签
    example=np.zeros((batch_size,height, weight,3))
    l=np.zeros((batch_size,1))
    try:
        #将数据存入example和l,并将转化成one_hot形式
        for epoch in range(batch_size):
            example[epoch],l[epoch]=sess.run([image,label])
        print(l)       
        enc=OneHotEncoder()
        l=enc.fit_transform(l)
        l=l.toarray()
        print(l)
        for i in range(100):
            

            #开始训练
            sess.run(train_step,feed_dict={X:example,y_:l,keep_pro:0.5})
            if i%10==0:
                print('train step','%04d ' %(i+1),'Accuracy=',sess.run(accuracy,feed_dict={X:example,y_:l,keep_pro:0.5}))
    except tf.errors.OutOfRangeError:
        print('done!')
    finally:
        coord.request_stop()
    coord.join(threads)

结果展示

在这里插入图片描述
TFRecords数据集生成的部分标签
tensorflow下 自制rfrecords数据集采用one-hot编码做图像分类**_第1张图片
经过one-hot编码后的标签
tensorflow下 自制rfrecords数据集采用one-hot编码做图像分类**_第2张图片
CNN网络训练结果展示

你可能感兴趣的:(tensorflow下 自制rfrecords数据集采用one-hot编码做图像分类**)