Keras库下的resnet源码应用及解读
其实我也不知道这种东西有没有写下来的必要,但是跑代码的时候总摸鱼总归是不好的。虽然很简单,不过我也大概做个学习记录,写给小白看的。源码来自keras文档,大致地讲解如何使用这个代码来训练你自己的模型,以及重点代码讲解分析。
一、Keras安装
前面一篇文章我已经讲了如何从零安装GPU版tensorflow,那么这里安装keras就很简单了,在cmd窗口里输入:
pip install keras
然后检查是否安装好了,继续在cmd窗口里先输入python,进入python编译环境,然后输入:
import keras
如果出现的是:
Using TensorFlow backend
那么你就安装成功了,如果没成功,多半是版本的问题。
二、数据处理
稍微介绍一下,keras其实只是再把tensorflow封装一次,除此以外还可以接Theano以及CNTK后端,你每次import keras后,都会显示这样的:Using TensorFlow backend,这就是你用的tensorflow做后端的意思,后端是可以改的,具体方法你们自己百度。keras训练过程中的打印非常直观和美观,适合小白入门,了解网络结构,不过也由于封装地太好,可能有些功能你很难找到(X)。
然后我们这里解读的是resnet的源码,残差卷积网络具体理论推导可以去看吴恩达老师的课,我在本文中肯能会提到一点,但是不会过多赘述,主要从代码层面来讲解keras的实现方式。
下面先简单介绍一下拿到一份数据该怎么处理,传入网络。下面是keras直接从库调用的数据集。
# Load the CIFAR10 data.
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
#这里是传入你的数据集的
我一般是先把图片转换成HDF5格式储存的,优点是读取快速方便。我在这里以一个比较复杂的图片集:来自kaggle的九种船型的图片集作为示例,教大家怎么处理自己的数据集。
(一)图片处理
拿到图片集,先看命名是否统一,方便我们接下来的操作。如果需要,我们可以进行重命名:
class BatchRename():
'''
批量重命名文件夹中的图片文件
'''
def __init__(self,path):
self.path = path#表示需要命名处理的文件夹
def rename(self):
filelist = os.listdir(self.path) #获取文件路径
total_num = len(filelist) #获取文件长度(个数)
#print(filelist,',',total_num)
i = 1 #表示文件的命名是从1开始的
for item in filelist:
if item.endswith('.png'): #初始的图片的格式为jpg格式的(或者源文件是png格式及其他格式,后面的转换格式就可以调整为自己需要的格式即可)
src = os.path.join(os.path.abspath(self.path), item)
dst = os.path.join(os.path.abspath(self.path), 'img'+str(i) + '.png')#处理后的格式也为jpg格式的,当然这里可以改成png格式
#dst = os.path.join(os.path.abspath(self.path), '0000' + format(str(i), '0>3s') + '.jpg') 这种情况下的命名格式为0000000.jpg形式,可以自主定义想要的格式
try:
os.rename(src, dst)
print ('converting %s to %s ...' % (src, dst))
i = i + 1
except:
continue
print ('total %d to rename & converted %d pngs' % (total_num, i))
我们拿到手的这个数据集,是每个种类数量不一,图形尺寸不一,通道数不一的需要整理的图片集。对于图片的尺寸批量裁剪,我们有两种方法:
① 截取图片的中间窗口:
这种方法适用于图片的关键信息基本在屏幕中央的,下面贴出代码:
def cut_image(images_dir):
count = os.listdir(images_dir)
print(count)
print("count=", len(count))
print("len(count)=", len(count))
for i in range(1, len(count)):
im = Image.open(images_dir + '/img' + str(i) + '.png')
im_size = im.size
x_mid = im_size[0]/2
y_mid = im_size[1]/2
X1 = x_mid - 360#中间窗口大小720x720
X2 = x_mid + 360
Y1 = y_mid - 360
Y2 = y_mid + 360
output_image = im.crop((X1,Y1,X2,Y2))
output_image.save(images_dir+'/deal/img'+str(i)+'.png')
print('finished')
如果你觉得图片大小过于不一致,可以先将小的图片扩大,再截取中间窗口。
if (im_size[0] > im_size[1]):
if(im_size[1]<650):
im = im.resize((int(im_size[0]*1.2),int(im_size[1]*1.2)))
im.save(images_dir+'/deal/picture'+str(i)+'.png')
else:
if(im_size[0]<650):
im = im.resize((int(im_size[0]*1.2),int(im_size[1]*1.2)))
im.save(images_dir + '/deal/picture' + str(i) + '.png')
② 将图片都扩大成正方形图片,例如1280x960的图片都扩大成1280x1280的
def expand_image(images_dir):
count = os.listdir(images_dir)
# print(count)
print("count=", len(count))
for i in range(1, len(count)):
im = Image.open(images_dir + '/img' + str(i) + '.jpg')
im_size = im.size
# print("图片宽度和高度分别是{}".format(im_size))
if (im_size[0] > im_size[1]):#If the length is larger than the width, choose the length as the edge of the picture.
X1 = 0
X2 = im_size[0]
Y1 = 0
Y2 = im_size[0]
else:#If the width is larger than the length, choose the length as the edge of the picture.
X1 = 0
X2 = im_size[1]
Y1 = 0
Y2 = im_size[1]
output_image = im.crop((X1,Y1,X2,Y2))
output_image.save(images_dir+'/deal/img'