最近在利用DCNN模型训练自己的数据集,利用SS数据集进行测试,做二分类,结果刚开始训练模型的准确率就为1,后面也是这样,主要原因还是数据集打乱的还不够,不能只靠tensorflow的shuffle操作来打乱,最好先打乱顺序后制作好tfrecords文件,再用shuffle函数打乱一次。
主要步骤如下:
(1)找到SS标签文件
(2)制作TFRecords文件
(3)开始训练
制作TFrecords文件代码如下:
import tensorflow as tf
# 7,8 -- 9,10 -- 11,12
from PIL import Image
import csv
import random
number_pic = 50000 # 空与非空的数量,保存相等
with open('/media/sj/Elements/S5_event_train.csv', 'r') as r:
next(r)
reader = csv.reader(r)
images_list_null = []
images_list_full = []
writer = tf.python_io.TFRecordWriter('./train_SS_50.tfrecords')
for row in reader:
if row[8] == 'NA':
images_list_null.append([row[7], 0])
else:
if row[8] != '':
images_list_full.append([row[7], 1])
else:
print("skip null_8")
if row[10] == 'NA':
images_list_null.append([row[9], 0])
else:
if row[10] != '':
images_list_full.append([row[9], 1])
else:
print("skip null_10")
if row[12] == 'NA':
images_list_null.append([row[11], 0])
else:
if row[12] != '':
images_list_full.append([row[11], 1])
else:
print('skip null_12')
print(len(images_list_null), len(images_list_full))
good_null = []
good_full = []
# 将好的写入到列表
for null in images_list_null:
try:
img = Image.open(null[0], "r")
good_null.append(null)
except:
pass
for full in images_list_full:
try:
img = Image.open(full[0], "r")
good_full.append(full)
except:
pass
print(len(good_null), len(good_full))
filename = good_null[:number_pic] + good_full[:number_pic]
random.shuffle(filename)
m = 0
j = 0
if m < 6:
for file in filename:
if m == 1:
img = file[0].transpose(Image.ROTATE_90) # 旋转
img = Image.open(img, "r")
elif m == 2:
img = file[0].transpose(Image.ROTATE_180) # 旋转
img = Image.open(img, "r")
elif m == 3:
img = file[0].transpose(Image.ROTATE_270) # 旋转
img = Image.open(img, "r")
elif m == 4:
img = file[0].transpose(Image.FLIP_TOP_BOTTOM)
img = Image.open(img, "r")
elif m == 5:
img = file[0].transpose(Image.FLIP_LEFT_RIGHT)
img = Image.open(img, "r")
else:
img = Image.open(file[0], "r")
label = file[1]
with open('./SS_50.csv', 'a+') as f:
f_csv = csv.writer(f)
f_csv.writerow([file[0],label])
img_raw = img.tobytes()
example = tf.train.Example(
features=tf.train.Features(feature={
'path': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
}))
writer.write(example.SerializeToString()) # 序列化为二进制格式
if j == number_pic * 2:
break
j += 1
print(j, m)
m += 1
print("successful")
writer.close()
上面是从SS数据集里面的S5制作一个包含10万张照片的tfrecords文件,其中空照片5万,非空5万。制作平衡数据集。
(1)第一步先遍历csv文件读取相应的图片路径和标签名称,空标记为0,非空标记为1.
for row in reader:
if row[8] == 'NA':
images_list_null.append([row[7], 0])
else:
if row[8] != '':
images_list_full.append([row[7], 1])
else:
print("skip null_8")
if row[10] == 'NA':
images_list_null.append([row[9], 0])
else:
if row[10] != '':
images_list_full.append([row[9], 1])
else:
print("skip null_10")
if row[12] == 'NA':
images_list_null.append([row[11], 0])
else:
if row[12] != '':
images_list_full.append([row[11], 1])
else:
print('skip null_12')
print(len(images_list_null), len(images_list_full))
(2)读取完成后,两个列表下面存在一损坏或者不存在的图片路径,需要检查并且从列表中删除,利用Image.open检查图片是否存在或者损坏,代码如下:
good_null = []
good_full = []
# 将好的写入到列表
for null in images_list_null:
try:
img = Image.open(null[0], "r")
good_null.append(null)
except:
pass
for full in images_list_full:
try:
img = Image.open(full[0], "r")
good_full.append(full)
except:
pass
print(len(good_null), len(good_full))
(3)为了构建平衡数据集,可以通过列表截取的方式各取number_pic万张,最后合并并使用随机函数打乱顺序。
filename = good_null[:number_pic] + good_full[:number_pic]
random.shuffle(filename)
(4)开始制作和写入tfrecords文件,如果数据不够,可以通过旋转,翻转等操作进行操作再写入。这里介绍几种方式。
m = 0
j = 0
if m < 6:
for file in filename:
if m == 1:
img = file[0].transpose(Image.ROTATE_90) # 逆时针旋转90
img = Image.open(img, "r")
elif m == 2:
img = file[0].transpose(Image.ROTATE_180) # 旋转180
img = Image.open(img, "r")
elif m == 3:
img = file[0].transpose(Image.ROTATE_270) # 旋转270
img = Image.open(img, "r")
elif m == 4:
img = file[0].transpose(Image.FLIP_TOP_BOTTOM)#上下翻转
img = Image.open(img, "r")
elif m == 5:
img = file[0].transpose(Image.FLIP_LEFT_RIGHT)#水平翻转
img = Image.open(img, "r")
else:
img = Image.open(file[0], "r")
label = file[1]
with open('./SS_50.csv', 'a+') as f:
f_csv = csv.writer(f)
f_csv.writerow([file[0],label])
img_raw = img.tobytes()
example = tf.train.Example(
features=tf.train.Features(feature={
'path': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
}))
writer.write(example.SerializeToString()) # 序列化为二进制格式
if j == number_pic * 2:
break
j += 1
print(j, m)
m += 1
(5)在进行训练时,每读取一个batch_size,就利用shuffle打乱一次。
(6)开始训练,我的训练结果如下:
关于数据集的制作和打乱的顺序,我也尝试过先写第一类,再写第二类,这样交替的写入数据集,但是也存在相同的问题,可能在前几轮下不会出现这样的问题,但是后面还是会出现,我怀疑是这样的数据分布的太有规律,所以最后迫不得已,先随机打乱再写入。这样的处理目前实验结果来看是最好的。缺点就是需要遍历csv文件,循环比较多,处理的有点慢,欢迎各位多加改进。