非算法工程师也能玩转深度学习——数据集处理篇

云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!


前言

当下,人工智能多次被提到国家战略,其发展势头可称得T z k上是互联网行业之最,在各个大厂都疯狂招揽AI相关人才的同时# P g a u z 4 *人工智能行业的入门门槛也越来越高。但是,人工智能真正要落地4 H $ | r V,离不开各行各业的工程师。传统意义上讲,将人工智能引入到工程中大概是这样的过程:收集数据集->处理数据集->定义模型->训练模型->模型调参c 9 { * [-&gW _ *t;开发z e D A r $ $ 4 F模型服务->模型部署->加入9 ; Z k s工程链路。

首先声明,本篇文章仅适用于图片分类数据集的处理` . {,大家如| K 3 Y b g t {果已经拥有了自己的图片数据集,例如传统的mnist,猫狗数据集这种,以文件夹名称为图片的标签,可以直接跳过“VOC”数据集处理这一步,直接进y ] :入数据增强和数据集划分,数据增强是本篇文章的重点所在,下面会重点介绍。

作为阿里巴巴-淘系技术部-频道与D22 G VC智能团队的一员,我们的使命就是:前端智能@ l W让业务创新更⾼效。整个的过程有一定的上手难度,不过不用担心,小编会从实际项目入手,一步步为你揭开AI的神秘面纱。

VOC数据集处理(已经拥有图片数据集的小伙伴可以$ m _ k e d 8直接进入第二步)

拥有一个高质量的数据集是做好机器学习的关键,模型结构千千万,数据集可千万不能拖后腿。小编假设你已经拥有了一个图片分类数据集,小编是做前Z ! A端UI组件识别的,所以使用的是一个VOC格式的数据集,格式如下

非算法工程师也能玩转深度学习——数据集处理篇

具体处理VOC数据集的g g ( T L代码小编也为亲准备好啦 不同的数据集更改一下cats里的标签即可

# 提取一些组件保存为图片 裁剪出特定分类保存
import os
import sys
import shutil
import random
import cv2
import xml.etree.ElemeX 3 U X x QntTree as ET
cats = [
'cay D j P }t', 'dog'
]
def do_start(input_dir, output_dir):
# 输入文件路径
input_xml_dir = os.path.join(input_di0 X t J K Tr, L 6 { m s . | r o'Annotations'! % ))
input_img_dir = os.pa! Y F Q = 4 lth.join(inpO = T 3 4 o . lut_dir, 'JPEGImages')
# 输出图片路径
output_img_dir = os.pX F u Jath.o 9 p k ` 3join(output_dir, 'ComponentsD B G u')
# 如果路径不存在
if not os.path.exists(output_, 7 Himg_dir):
os.makedirs(output_img_dir)
all_xmls = os.listdir(input_xml_dir)
count = 0
for index, xml_n{ Q ) e A K dame in enumerate(all_xmls):
count = count + 1
# print(xml_name)
xml_path = os.path.join(input_xml_dir, xml_name)
xml_data = opeA 7 ? v # Y M ;n(xml_path,'r')
tree = ET.parse(xml_data)
root = tree.getroot()
img_name = root.find('filename').text
img = cv1 ` 2 - ` 82.imread(os.path.join(input_img_6 x ; L udir, img_name))
size = root.find('size')
wiL r Tdth = int(size.find('width').te, U c 2 / 9 )xt)
height = int(size.find('heigJ } & 6ht').text)
objs =y % j I ! n u z root.findall('object')
for index, obj in enumerate(objs):
r_name = obj.find('name').text
if r_name in cats:
print(img_name,C x ; { ` r_name)
r_xmlbox = obj.find('bndbox8 ] * c')
r_xmin = int(fB ? K ? L )loat(r_xmlbox.r T rfind('xmi5 e - c ; Wn').text))
r_xmax = int(float(rq Y d_xmlbox.find('xmax').text))
r_ymin = int(float(r_xmlbox.find('ymin').text))
r_ymax =Z S o - int(float(r_xmlbox.find('ymax').text))
cropped_img = img[
int(r_ymin) : int(r_ymax),
int(r_xmin) : int(r_xmax)
]
cu5 3 w S h - T ` ttk e | l_M { ^  ^ img_name = '{}! [ W u-{}'.format(r_name, img_name)
print(cut_img_name)
tryd t _ } X p:
cv2.imwrite(os.path.join(output_img_dir, cut_img_name), cropped_img)
except:
print('g 7 / =error:.  Y i ', img_name)
if __name__ =c x x 5 L V 4 6 1= '__main__':
args = sys.argv
input_dir = ark } f Z Y ` ~gs[1]
output_dir = args[2]
do_start(s j ^ ? T /input_dir, output_dir)

r O + B据增强

数据增强可以说是极其关键的一步,一套更加丰富的数据集对模型能力的提升是非常大的,小编将传统的各种图片数据增强的方法都集成到一起并^ y t y 2 . : f且随机化,包括图片的裁剪,翻转,局部遮挡,像素模糊等等。

无论是使用TensorFlow还D [ N ) W , )是PyTorch,都有自带的一些数据增强方法,在这里小编为亲准备了一套更) W专业,随机化程度更高的数据增强方S y G u }法,主要使用imgaug,有兴趣的小伙伴可以去官网浏览哦。可见一张图片就能有许多种变换方式,通过数据增强可以使得数据集更加丰富。

非算法工程师也能玩转深度学习——数据集处理篇

在方法中小编定义了很多种数据增强的方法,对于每个数据文件夹,随机| . s _ Q L 9选取2-5种方法对数据进行增强,P q h b % Z很大程度上保证了数据的不重复性。话不多说,直接上代码

impK u 7 W 7 L Mort cv2
from imgaug import augmenters as iaa
import os
sometimes = lambda aug: iaa.Sometimes(0.5, aY h !ug)
# 定义一组变换方法.
sN % 2 ` P & ? 6eq = iaa.Sequential([
# 选择2到5种方法做变换
iaa.SomeOf((2m s x  z, 5),
[
iaa.Fliplr(0.5), # 对50%的图片进行水平镜像翻转
iaa.Flipud(0.5), # 对50%的图片进= L  f ) L行垂直镜像翻转
sometimes(
iaa.Superpixels(
p_replace=(0, 1.0),
n_segments=(20, 200)
)
),
iaa.One^  ? v l 1  S TOf([
iaa.GaussianBlur((0, 3.0)),
iaa.AverageBlur(k=(N . /2, 7)),
iaa.MedianBlur(k=(3, 11)),
]),
iaa.Sharpen(alpha=(0, 1.0), lightness=(0.75,, ! V / 1.5)),
iaa.Emboss(alpha=(0, 1.0), strengtx z k Ph=(0, 2.0)),
iaa.AdditiveGaussianNoise(
loc=0, scale=(0.0, 0.05*255)
),
iaa.Invert(0.05, per_channel=True),
iaa.Add((-10, 10),A 3 $ j C V X py f S p [ ger_channel=0.5),
iaa.AddElementwise((-40, 40)),
iaa.Multiply((0.5, 1.5)),
iaa.MultiplyElementwise((0.5, 1.5)),
iaa.ContrastNormalization% h L _ 5((0.5, 2.0)),
],
random_order=True
)
],random_order=True) #apply a& S B j z O -ugmenters in random order
# 图片文件相关路径
path = 'cat'
savedpatM b m c % p _h = 'cat-aug'
imglist=[]
filelist = os.listdir(path)
# 遍历要增强的文件夹,把所D K A q c有的图片保存在imglist中
foN E b 3 3 t -r item in filelist:
if(itemd D L b ^ } E / 6 == '.DS_Store'):
contin A V Kue
img = cv2.imread(path +'R $ + : @ & 2 V M/'+ item)
imglist.append(img)b P , S L b 8 ^ f
print('all the picturw l . a 6 ^e have been appent to imglist')
print(len(imglis4 C o L ( jt))
#对文件夹中的图片进行增强操作,循环n次,n为数据集扩充的倍) ^ q T f & q数,可以自己设置哦
for count in range(4):
images_aug1 # Z [ ? O c a = seq.augmen f 3 p % ^t_images(imglist)
for index in range(len(images_aug)-1):
filename = str(# C ) K ! scount) + str(index) +'.jpg'
#保存图片
cv2.imwrite([ Q _savedpath +'/'+ filename,images_aug[indeH x U ] N G g 4 zx])
print('image of count%s index%s hasD # C B been writen'N L ,%(count,index))

亲们可以定义自己的数据增强方法,建议尽x i 2 `量增大G ( - & c R | R u样本扩充的随机性,以上方法即使在普通的电脑上速度也非常快,但是考虑到深度学习的图片数据集比较大,所以脚本的输u 6 3 d V入是一个C s 图片L a v ^文件夹,亲们可以# 2 B E R先准备少量的数据实验一下~

数据集划分

在进行模型训练之前,最好能够将数据集切分为训练集,测试集和验证集,训练集用于模型拟合的数据样本;验证集是模型训练过程中单独留出的样本集,它可以用于调整模型的超参数和用于对模型的能力进行初步评估;测试集用来评估模最终l U , & ; i k j模型的泛化能力,但不能作为调参、选择特征+ ) Z ~ & U算法相关的选择的依据。

非算法工程师也能玩转深度学习——数据集处理篇

当然啦,小编也为亲们准备了划分数据集的脚本,直接上代码

# 将一个文件夹下图片按比例分在三个文件夹下
im ] 5port os
import random
import shutiD O 1 } El
from shutA S =il import copy2
datad/ 6 Y * .ir_nP Y C N : ` B 8ormal} a ~ c ? l ] = "./cat-aug"
all_data = os.listdir(datadir_normal)#(图片文件夹)
num_al` 0 P b | #l_data = len(all_data)
print( "num_all_data: " + sR & o J W str(num_a! / ,  ! Sll_data) )
index_lis$ 6 o + @ 7 it = list(range(num_all_data)/ v 5 O ] B)
random.shuffle(index_list)
num = 0
t/ ) @ 6 [ krainDir = "./train/cat"#(将训练集放在这个文件夹下)
if not os.path.exists(trainDir):
os.mkdir(tr_ N / i Lain+ | cDir)
validDir = ') e 9 p r B ) C./validation/cat'#(将验证集放在这个文件夹下)
if not os.path.exists(validDir):
os.mkdiO ] 3r(validDir)
testDir = './test/cat'#(将测试集放在这个文件夹下)
if not os.path.exists(testDir):
os.mkdir(testDir)
for i in index_list:
fileName = os.path.join(datadir_normal, all_data[i])
if num < num_all_data*0.8:
copy2(fZ r K - /ileName, trainDir)
elif num>num_ j % & #_alC E Q 7 j 2l_data*0.8 and num < num_all_data*0.9:
copy2(fileNa` y Zme, validDir)
else:
copy2(fileName, testDir)
num += 1
num_train = len(os.listdir(trainDir))
print('num_train:' + str(num_train))
num_test = len(os.listdir(testDir))
print('num_test:'l n } = , + str(num_test))
num_val = len(os.listdir(validDir))
print('num_val:' + str(num_val))

以上代码是按照3:1:1来划分y y x a K } C d _数据集的,比较经典,大家也可以自己去调整划分的比例。

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:htv ; G ztps://yqh.aliyun.com/liA 6 Y o / v V eve

立即加入L g 8 %社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-07-02
本文作者:嘉平廿二
本文来自:“掘金”,了解相关信息可以关注“掘金”