使用slim模型做自己的数据分类详细过程

使用GitHub上的模型

       1. 在https://github.com/tensorflow/models下载model-master压缩包

  1. 本案例要使用slim文件夹中的train_image_classifier.py(可以将slim文件夹单独copy出来)

使用slim模型做自己的数据分类详细过程

使用slim模型做自己的数据分类详细过程

  1. 下载并制作自己的数据集放到创建的H:\Self-Study\PyCharm\test\slim\images目录中,这里做了五种分类,每类中有800个数据,共4000,其中按8:2分为train和test

使用slim模型做自己的数据分类详细过程

  1. 将自己的数据集制作成tfrecord文件。编写generate_tfrecord.py脚本文件,代码如下(高亮部分分别为:指定数据集路径、生成标签文件名、生成tfrecord文件当时犯错的地方):

import tensorflow as tf

import os

import random

import math

import sys

 

# 验证集数量

_NUM_TEST = 800

# 随机种子

_RANDOM_SEED = 0

# 数据块

_NUM_SHARDS = 5

# 数据集路径

DATASET_DIR = "H:/Self-Study/PyCharm/test/slim/images/"

# 标签文件名字

LABELS_FILENAME = "H:/Self-Study/PyCharm/test/slim/images/labels.txt"

 

# 定义tfrecord文件的路径+名字

def _get_dataset_filename(dataset_dir, split_name, shard_id):

output_filename = 'image_%s_%05d-of-%05d.tfrecord' % (split_name, shard_id, _NUM_SHARDS)

return os.path.join(dataset_dir, output_filename) # 获取dataser_dir当前目录,并与output_filename组合成新目录

 

# 判断tfrecord文件是否存在

def _dataset_exists(dataset_dir):

for split_name in ['train', 'test']:

for shard_id in range(_NUM_SHARDS):

# 定义tfrecord文件的路径+名字

output_filename = _get_dataset_filename(dataset_dir, split_name, shard_id)

if not tf.gfile.Exists(output_filename): # 判断目录或文件是否存在

return False

return True

 

# 获取所有文件及分类

def _get_filenames_and_classes(dataset_dir):

directories = [] # 这是一个数据目录列表

class_names = [] # 这是一个分类名称列表

for filename in os.listdir(dataset_dir): # 用于返回指定的文件夹包含的文件或文件夹的名字的列表。这个列表以字母顺序。

path = os.path.join(dataset_dir, filename)

if os.path.isdir(path): # 判断path是不是一个目录,不是则为False

directories.append(path)

class_names.append(filename)

photo_filenames = [] # 文件目录列表

for directory in directories:

for filename in os.listdir(directory): # 每一类文件夹下的文件

path = os.path.join(directory, filename) # 每个文件的路径+名称

photo_filenames.append(path) # 添加到文件目录列表中

 

return photo_filenames, class_names

 

def int64_feature(values):

if not isinstance(values, (tuple, list)):

values = [values]

return tf.train.Feature(int64_list=tf.train.Int64List(value=values))

 

def bytes_feature(values):

return tf.train.Feature(bytes_list=tf.train.BytesList(value=[values]))

 

def image_to_tfexample(image_data, image_format, class_id):

return tf.train.Example(features=tf.train.Features(feature={

'image/encoded': bytes_feature(image_data),

'image/format': bytes_feature(image_format),

'image/class/label': int64_feature(class_id)

}))

 

def write_label_file(labels_to_class_names, dataset_dir, filename=LABELS_FILENAME):

labels_filename = os.path.join(dataset_dir, filename)

with tf.gfile.Open(labels_filename, 'wb') as f:

for label in labels_to_class_names:

class_name = labels_to_class_names[label]

f.write('%d:%s\n' % (label, class_name))

 

def _convert_dataset(split_name, filenames, class_names_to_ids, dataset_dir):

assert split_name in ['train', 'test']

# 计算每个数据块的数据量

num_per_shard = int(len(filenames) / _NUM_SHARDS)

with tf.Graph().as_default():

with tf.Session() as sess:

for shard_id in range(_NUM_SHARDS):

output_filename = _get_dataset_filename(dataset_dir, split_name,shard_id)

with tf.python_io.TFRecordWriter(output_filename) as tfrecord_writer:

start_ndx = shard_id * num_per_shard

end_ndx = min((shard_id + 1) * num_per_shard, len(filenames))

for i in range(start_ndx, end_ndx):

try:

sys.stdout.write('\r>> Converting image %d/%d shard %d' % (i + 1, len(filenames), shard_id))

sys.stdout.flush()

image_data = tf.gfile.FastGFile(filenames[i], 'rb').read()

class_name = os.path.basename(os.path.dirname(filenames[i]))

class_id = class_names_to_ids[class_name]

example = image_to_tfexample(image_data, b'jpg', class_id)

tfrecord_writer.write(example.SerializeToString())

except IOError as e:

print("Could not read: ", filenames[i])

print("Error: ", e)

print("Skip it\n")

 

sys.stdout.write('\n')

sys.stdout.flush()

 

if __name__ == '__main__':

# 判断tfrecord文件是否存在

if _dataset_exists(DATASET_DIR):

print("tfrecord文件已存在")

else:

photo_filenames, class_names = _get_filenames_and_classes(DATASET_DIR)

# 把分类转为字典格式,类似于{"houses": 2, "flowers": 0, ... , "guitars": 1}

class_names_to_ids = dict(zip(class_names, range(len(class_names))))

 

# 将数据切分为训练集和测试集

random.seed(_RANDOM_SEED)

random.shuffle(photo_filenames) # 打乱数据

training_filenames = photo_filenames[_NUM_TEST:]

testing_filenames = photo_filenames[:_NUM_TEST]

 

# 数据转换

_convert_dataset('train', training_filenames, class_names_to_ids, DATASET_DIR)

_convert_dataset('test', testing_filenames, class_names_to_ids, DATASET_DIR)

 

labels_to_class_names = dict(zip(range(len(class_names)),class_names))

write_label_file(labels_to_class_names, DATASET_DIR)

        运行之后会产生:

使用slim模型做自己的数据分类详细过程

  1. 到H:\Self-Study\PyCharm\test\slim\datasets\中修改文件

使用slim模型做自己的数据分类详细过程

        在dataset_factory.py中做两处内容增加:

        myimages.py文件是在flowers.py文件的基础上修改而创建的,主要做两处修改如下:(分别是你生成的tfrecord的文件格式,以及自己设置的数据集train和test的大小)

使用slim模型做自己的数据分类详细过程

  1. 在H:\Self-Study\PyCharm\test\slim文件夹中创建train.batwindows批处理文件

使用slim模型做自己的数据分类详细过程

        文件内容如下:

D:/Users/HZK/Anaconda3/envs/tensorflow-gpu/python H:/Self-Study/PyCharm/test/slim/train_image_classifier.py ^

--train_dir=H:/Self-Study/PyCharm/test/slim/model ^

--dataset_name=myimages ^

--dataset_split_name=train ^

--dataset_dir=H:/Self-Study/PyCharm/test/slim/images ^

--batch_size=10 ^

--max_number_of_steps=10000 ^

--model_name=inception_v3 ^

pause

 

第一行表示运行训练文件,路径为全路径

第二行表示模型存放位置

第三行为创建的myimages文件名

第四行为使用的训练集

第五行为数据集所在的位置

第六行为批次大小,默认为32,看个人GPU,我用10

第七行为训练次数,默认无限次

第八行为使用模型名称

 

  1. 运行train.bat,运行过程显示如下

使用slim模型做自己的数据分类详细过程

会在model文件夹中产生如下文件:

使用slim模型做自己的数据分类详细过程