前言
当下,人工智能多次被提到国家战略,其发展势头可称得上是互联网行业之最,在各个大厂都疯狂招揽AI相关人才的同时,人工智能行业的入门门槛也越来越高。但是,人工智能真正要落地,离不开各行各业的工程师。传统意义上讲,将人工智能引入到工程中大概是这样的过程:收集数据集->处理数据集->定义模型->训练模型->模型调参->开发模型服务->模型部署->加入工程链路。
首先声明,本篇文章仅适用于图片分类数据集的处理,大家如果已经拥有了自己的图片数据集,例如传统的mnist,猫狗数据集这种,以文件夹名称为图片的标签,可以直接跳过“VOC”数据集处理这一步,直接进入数据增强和数据集划分,数据增强是本篇文章的重点所在,下面会重点介绍。
作为阿里巴巴-淘系技术部-频道与D2C智能团队的一员,我们的使命就是:前端智能让业务创新更⾼效。整个的过程有一定的上手难度,不过不用担心,小编会从实际项目入手,一步步为你揭开AI的神秘面纱。
VOC数据集处理(已经拥有图片数据集的小伙伴可以直接进入第二步)
拥有一个高质量的数据集是做好机器学习的关键,模型结构千千万,数据集可千万不能拖后腿。小编假设你已经拥有了一个图片分类数据集,小编是做前端UI组件识别的,所以使用的是一个VOC格式的数据集,格式如下
具体处理VOC数据集的代码小编也为亲准备好啦 不同的数据集更改一下cats里的标签即可
# 提取一些组件保存为图片 裁剪出特定分类保存
import os
import sys
import shutil
import random
import cv2
import xml.etree.ElementTree as ET
cats = [
'cat', 'dog'
]
def do_start(input_dir, output_dir):
# 输入文件路径
input_xml_dir = os.path.join(input_dir, 'Annotations')
input_img_dir = os.path.join(input_dir, 'JPEGImages')
# 输出图片路径
output_img_dir = os.path.join(output_dir, 'Components')
# 如果路径不存在
if not os.path.exists(output_img_dir):
os.makedirs(output_img_dir)
all_xmls = os.listdir(input_xml_dir)
count = 0
for index, xml_name in enumerate(all_xmls):
count = count + 1
# print(xml_name)
xml_path = os.path.join(input_xml_dir, xml_name)
xml_data = open(xml_path,'r')
tree = ET.parse(xml_data)
root = tree.getroot()
img_name = root.find('filename').text
img = cv2.imread(os.path.join(input_img_dir, img_name))
size = root.find('size')
width = int(size.find('width').text)
height = int(size.find('height').text)
objs = root.findall('object')
for index, obj in enumerate(objs):
r_name = obj.find('name').text
if r_name in cats:
print(img_name, r_name)
r_xmlbox = obj.find('bndbox')
r_xmin = int(float(r_xmlbox.find('xmin').text))
r_xmax = int(float(r_xmlbox.find('xmax').text))
r_ymin = int(float(r_xmlbox.find('ymin').text))
r_ymax = int(float(r_xmlbox.find('ymax').text))
cropped_img = img[
int(r_ymin) : int(r_ymax),
int(r_xmin) : int(r_xmax)
]
cut_img_name = '{}-{}'.format(r_name, img_name)
print(cut_img_name)
try:
cv2.imwrite(os.path.join(output_img_dir, cut_img_name), cropped_img)
except:
print('error: ', img_name)
if __name__ == '__main__':
args = sys.argv
input_dir = args[1]
output_dir = args[2]
do_start(input_dir, output_dir)
数据增强
数据增强可以说是极其关键的一步,一套更加丰富的数据集对模型能力的提升是非常大的,小编将传统的各种图片数据增强的方法都集成到一起并且随机化,包括图片的裁剪,翻转,局部遮挡,像素模糊等等。
无论是使用TensorFlow还是PyTorch,都有自带的一些数据增强方法,在这里小编为亲准备了一套更专业,随机化程度更高的数据增强方法,主要使用imgaug,有兴趣的小伙伴可以去官网浏览哦 imgaug官网 可见一张图片就能有许多种变换方式,通过数据增强可以使得数据集更加丰富。
在方法中小编定义了很多种数据增强的方法,对于每个数据文件夹,随机选取2-5种方法对数据进行增强,很大程度上保证了数据的不重复性。话不多说,直接上代码
import cv2
from imgaug import augmenters as iaa
import os
sometimes = lambda aug: iaa.Sometimes(0.5, aug)
# 定义一组变换方法.
seq = iaa.Sequential([
# 选择2到5种方法做变换
iaa.SomeOf((2, 5),
[
iaa.Fliplr(0.5), # 对50%的图片进行水平镜像翻转
iaa.Flipud(0.5), # 对50%的图片进行垂直镜像翻转
sometimes(
iaa.Superpixels(
p_replace=(0, 1.0),
n_segments=(20, 200)
)
),
iaa.OneOf([
iaa.GaussianBlur((0, 3.0)),
iaa.AverageBlur(k=(2, 7)),
iaa.MedianBlur(k=(3, 11)),
]),
iaa.Sharpen(alpha=(0, 1.0), lightness=(0.75, 1.5)),
iaa.Emboss(alpha=(0, 1.0), strength=(0, 2.0)),
iaa.AdditiveGaussianNoise(
loc=0, scale=(0.0, 0.05*255)
),
iaa.Invert(0.05, per_channel=True),
iaa.Add((-10, 10), per_channel=0.5),
iaa.AddElementwise((-40, 40)),
iaa.Multiply((0.5, 1.5)),
iaa.MultiplyElementwise((0.5, 1.5)),
iaa.ContrastNormalization((0.5, 2.0)),
],
random_order=True
)
],random_order=True) #apply augmenters in random order
# 图片文件相关路径
path = 'cat'
savedpath = 'cat-aug'
imglist=[]
filelist = os.listdir(path)
# 遍历要增强的文件夹,把所有的图片保存在imglist中
for item in filelist:
if(item == '.DS_Store'):
continue
img = cv2.imread(path +'/'+ item)
imglist.append(img)
print('all the picture have been appent to imglist')
print(len(imglist))
#对文件夹中的图片进行增强操作,循环n次,n为数据集扩充的倍数,可以自己设置哦
for count in range(4):
images_aug = seq.augment_images(imglist)
for index in range(len(images_aug)-1):
filename = str(count) + str(index) +'.jpg'
#保存图片
cv2.imwrite(savedpath +'/'+ filename,images_aug[index])
print('image of count%s index%s has been writen'%(count,index))
亲们可以定义自己的数据增强方法,建议尽量增大样本扩充的随机性,以上方法即使在普通的电脑上速度也非常快,但是考虑到深度学习的图片数据集比较大,所以脚本的输入是一个图片文件夹,亲们可以先准备少量的数据实验一下~
数据集划分
在进行模型训练之前,最好能够将数据集切分为训练集,测试集和验证集,训练集用于模型拟合的数据样本;验证集是模型训练过程中单独留出的样本集,它可以用于调整模型的超参数和用于对模型的能力进行初步评估;测试集用来评估模最终模型的泛化能力,但不能作为调参、选择特征等算法相关的选择的依据。
数据集 | 作用 | 比喻 |
---|---|---|
训练集 | 用于模型的训练 | 学生的课本 |
验证集 | 用于调超参数,监控模型是否发生过拟合(以决定是否停止训练) | 课后作业 |
测试集 | 为了评估最终模型泛化能力(仅最后一次使用) | 期末考试 |
当然啦,小编也为亲们准备了划分数据集的脚本,直接上代码 |
# 将一个文件夹下图片按比例分在三个文件夹下
import os
import random
import shutil
from shutil import copy2
datadir_normal = "./cat-aug"
all_data = os.listdir(datadir_normal)#(图片文件夹)
num_all_data = len(all_data)
print( "num_all_data: " + str(num_all_data) )
index_list = list(range(num_all_data))
random.shuffle(index_list)
num = 0
trainDir = "./train/cat"#(将训练集放在这个文件夹下)
if not os.path.exists(trainDir):
os.mkdir(trainDir)
validDir = './validation/cat'#(将验证集放在这个文件夹下)
if not os.path.exists(validDir):
os.mkdir(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(fileName, trainDir)
elif num>num_all_data*0.8 and num < num_all_data*0.9:
copy2(fileName, 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:' + str(num_test))
num_val = len(os.listdir(validDir))
print('num_val:' + str(num_val))
以上代码是按照3:1:1来划分数据集的,比较经典,大家也可以自己去调整划分的比例。
写在最后
以上三步就是处理数据集的整个流程,也是做深度学习的第一步,之后小编会出一系列的文章,和大家一起了解最新的AI技术。希望大家点个关注,点个赞呀~