我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训

目录

赛事题目:挑战智能语音垃圾分类任务

ASR 语音数据集

音频采样

语音数据集制作流程

踩坑 & 建议:

CV 图像数据集

图像搜集

图像数据集制作

踩坑 & 建议

心得体会

建立范式

团队协作

探索试点


赛事题目:挑战智能语音垃圾分类任务

垃圾是世界范围内日益严重的环境问题,实行垃圾分类,关系节约使用资源,也是社会文明水平的一个重要体现。

NVIDIA 正在努力加强技术研究,致力于开发创新计算解决方案,同时鼓励开发者们利用 NVIDIA 各种 AI 开发工具,激发创造力,科技赋能,给垃圾分类注入 “智慧力量”。

本次 Hackathon 活动以 “挑战智能语音垃圾分类任务” 为主题。

赛事涵盖:语音识别、垃圾检测及用户接口的 web 页面实现等。

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第1张图片 图 1-1 - 第七届黑客松比赛应用流程图
我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第2张图片 图 2-1-Audacity 界面截图

ASR 语音数据集

音频采样

录制工具:Audacity

音频要求:①录制声道:立体声

②项目采样率:44100HZ

③音频格式:wav

(图 2-1 红色圆圈标记为①②设定处)

按钮解释 (参见矩形方框):

①红色:开始录制

②蓝色:结束录制

③黄色:播放音频

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第3张图片 图 2-1-Audacity 界面截图

音频内容: 语句公式:请检测出 rubbish

依据比赛任务要求,rubbish 共有三类:瓶子、纸箱、果皮

语音数据集制作流程

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第4张图片 图 2-2-ASR 音频数据集制作流程图

向 jupyter notebook 中导入音频(建议新建一个文件夹,专门用于存储音频)

红色圆圈圈住的按钮就是上传按钮

上传文件后,可以在 jupyter 上建立文件的相对路径(区别于物理机上的绝对路径,便于引用)

如我的就是 yy/

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第5张图片 图 2-3-jupyter 音频文件夹
# 导入librosa音频工具包获取音频时长,用于制作语音数据集
import librosa 
#/yy/all6.wav为待读取音频相对路径
time = librosa.get_duration(filename="/yy/all6.wav")
print(time)

踩坑 & 建议:

1. 音频要求未达标:

音频采样录制声道要求为单声道,误设置为立体声道

ps:单声道只有一条音轨,立体声双音轨

有时候可能设置了单声道,录制的时候也是显示单音轨,但打开后却是双音轨,这时候需要设置默认录制声道。

2. 录制 / 播放没有声音:连接蓝牙后,录制 / 播放没有声音,可能是软件滞后,需要手动更换设备(图 2-1 黄色高亮),方可正常录制播放。

3. 音频纯净度:有时候受限于现实环境,采样音频杂音过多,需要过滤杂音。

操作:顶部导航栏 << 效果<< 降噪

4. 参考标签

格式一定要正确,否则一步错步步错

参见下面

"1.wav""duration": 3.1463038548752835,"text”:"你好大白请让我进入小区”
 文件名              音频时长                          文本内容
#符号一定要用半角符号(即英文符号),中文符号会报错。

5. 标签文本

①可以把所有要录制的内容,先做成预标签文本,即除了音频时长外,其他都填写了。这样直接照着标签文件读,保证标签文本和音频内容一致。

②建议把所有标签文本整理到一个文件里,避免繁琐过程。

③建议文件名带有显而易见的顺序。

6. 噪音是否提高模型的泛化能力?(×)

噪音有负面效果,会导致模型不稳定,对小模型有明显影响。

7. 数据集形式过于单一,脱离实际

刚开始时语句只有

请检测出瓶子 / 果皮 / 纸箱,三句话反复穿插训练,而且语音来源只有一个人,训练效果不明显。

后来讨论复盘后,发现构建情境过于理想化,脱离了实际应用场景。

后来结合实际应用场景,重新组织语言,编辑了标签,重新设计采样方案。

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第6张图片 图2-4 - 采样优化方案
我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第7张图片 图 2-5 - 部分标签内容

8. 训练效果不明显,错误率比较高?

大概是数据集有限的原因。可以考虑扩大数据集规模进一步训练。

图 2-6-80M 语音数据集训练效果示意图
图 2-7-500M 语音数据集训练效果示意图

CV 图像数据集

图像搜集

①网络爬取:自编爬虫脚本 / 利用插件(如 fatkun 图片批量下载)

②现有数据库下载:可以考虑百度飞桨平台(会有广告费吗)

③举办方供应的数据集(因为标注有问题,需要清洗和复标)

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第8张图片 图 3-1 - 百度飞桨页面
我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第9张图片 图 3-2-CSDN 数据集

图片格式:jpg/png 都可以,但是要求统一格式。

小心 gif、jpeg 等格式的图片混杂

数据标注软件:安利 labelimg

labelimg 优势:

①快捷分便:可以打开图片文件夹和设置存储文件夹,从避免繁琐的打开保存图片

②支持广泛:支持 voc、yolo、createML 三种数据集格式

下载和使用教程参见下方链接

Labelme 安装以及使用_期待 686 的博客 - CSDN 博客_labelme​blog.csdn.net/qq_41931453/article/details/125757449?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166929649916800215089994%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166929649916800215089994&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-125757449-null-null.142%5Ev66%5Econtrol,201%5Ev3%5Econtrol_1,213%5Ev2%5Et3_esquery_v3&utm_term=labelme&spm=1018.2226.3001.4187正在上传…重新上传取消icon-default.png?t=M85Bhttps://blog.csdn.net/qq_41931453/article/details/125757449?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166929649916800215089994%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166929649916800215089994&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-125757449-null-null.142%5Ev66%5Econtrol,201%5Ev3%5Econtrol_1,213%5Ev2%5Et3_esquery_v3&utm_term=labelme&spm=1018.2226.3001.4187

图像数据集制作

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第10张图片 图 3-3 - 图像数据集制作流程

voc 数据集转 kitti 数据集脚本源码如下

# 作 者:Leo
# 时 间:2022/11/15 19:12
import xml.etree.ElementTree as ET
import os
from tqdm import tqdm
import cv2
'''
base_xml_dir为xml文件夹路径
kitti_saved_dir为要保存的kitti文件夹的路径,转化前,先把输出文件夹创建好
'''
#只需要修改下面两个文件路径
base_xml_dir = "D:\\PyProject\\tools\\wrong\\xml\\"
xml_list = os.listdir(base_xml_dir)
kitti_saved_dir = "D:\\PyProject\\tools\\wrong\\kitti\\"

clslist = []
def convert_annotation(file_name):
    #print('********')
    #print(base_xml_dir,file_name)
    in_file = open(base_xml_dir + file_name, 'rb')
    tree = ET.parse(in_file)
    root = tree.getroot()

    with open(kitti_saved_dir + file_name[:-4] + '.txt', 'w') as f:
        for obj in root.iter('object'):
            cls = obj.find('name').text
            # if cls not in object_class_list:
            #     object_class_list.append(cls)
            xmlbox = obj.find('bndbox')
            """
                第5~8这4个数:物体的2维边界框
                xmin,ymin,xmax,ymax
            """
            xmin, ymin, xmax, ymax = xmlbox.find('xmin').text, xmlbox.find('ymin').text, \
                                     xmlbox.find('xmax').text, xmlbox.find('ymax').text
            a = int(xmin)
            b = int(ymin)
            c = int(xmax)
            d = int(ymax)
            #print(xmin, ymin, xmax, ymax)
            #print(type(float(xmin)))
            #cv2.rectangle(image, (xmlbox.find('xmin').text, xmlbox.find('ymin').text), (xmlbox.find('xmax').text, xmlbox.find('ymax').text), (0, 0, 255), 2)
            #cv2.rectangle(image, (0, 55), (224, 263), (0, 0, 255), 2)
            #print(cls)
            if cls == 'Peel_the_fruit':
                #print('******1*******')
                #print(cls)
                cls = 'banane'
                #cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
                #print('香蕉皮')
                #print(cls)
                #print('******2*******')
            elif cls == 'pop_top_can':
                #print(cls)
                cls = 'bottle'
                #cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
                #print('瓶子1')
            elif cls == 'drink_bottle':
                cls = 'bottle'
                #cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
                #print('瓶子2')
            elif cls == 'carton_carton':
                #print(cls)
                cls = 'CARDBOARD'
                #cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
                #print('纸箱')
            elif cls == 'Drink_box':
                cls = 'CARDBOARD'
                #cv2.rectangle(image, (a, b), (c, d), (0, 0, 255), 2)
            else:
                pass
            if cls == 'banane' or cls == 'bottle' or cls == 'CARDBOARD':
                f.write(cls + " " + '0.00' + " " + '0' + " " + '0.0' + " " + str(xmin) + " "
                        + str(ymin) + " " + str(xmax) + " " + str(ymax) + " " +
                        '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + " " + '0.0' + '\n')

# object_class_list = []  # ['trafficsignal', 'car', 'person', 'trafficlight', 'bicycle', 'motorbike', 'bus']

for i in tqdm(range(len(xml_list))):
    #image_name = xml_list[i].replace('xml', 'jpg')
    #image = cv2.imread(image_name)
    #cv2.rectangle(image, (0, 55), (224, 263), (0, 0, 255), 2)
    convert_annotation(xml_list[i])
    #cv2.imwrite(image_name.replace('.jpg', '-box.jpg'), image)
    #print('原始',xml_list[i])
    #print('最后', image_name, xml_list[i])
    # print(i)
#print(clslist)
# print(object_class_list)

生成标注图源码如下

 # 作 者:Leo
# 时 间:2022/11/21 21:14
import os
from tqdm import tqdm
import cv2
'''
base_img_dir为未打框图片的文件夹路径
base_label_dir为kitti标签格式的文件夹路径
op_img_dir为打框后的图片输出的文件夹路径,需要在输出钱创建好
'''
base_img_dir = "D:\\PyProject\\tools\\wrong\\image\\"
base_label_dir = "D:\\PyProject\\tools\\wrong\\kitti\\"
op_img_dir = "D:\\PyProject\\tools\\wrong\\img\\"
img_list = os.listdir(base_img_dir)
label_list = os.listdir(base_label_dir)
def draw_imgbox(image, label):
	for line in open(label, "r", encoding='UTF-8'):
		line_list = []
		line_list = line.split(' ')
		line_list = line_list[0:1] + line_list[4:8]
		print(line_list)
		cv2.rectangle(img_file, (int(line_list[1]), int(line_list[2])), (int(line_list[3]), int(line_list[4])), (0, 0, 255), 2)

for i in tqdm(range(len(img_list))):
	print('第' + str(i) + '张')
	img_file = cv2.imread(base_img_dir + img_list[i])
	label_file = label_list[i]
	draw_imgbox(img_file, base_label_dir + label_file)
	cv2.imwrite(op_img_dir + img_list[i].replace('.jpg', '-box.jpg'), img_file)

踩坑 & 建议

1. 如图 3-3 文件夹形式一样设置好自己的形式,保证数据纯净。

2. 大批量处理图片,建议文件名带有明显的顺序。

3. 图片与标签务必!!!

务必!!!

务必!!!

要一一对应!!!不能乱,不能多,不能少

否则 kitti 的 txt 标签无法对于,从而导致标注图与实际标注不对应。

我参加 NVIDIA Sky Hackathon--- 浅谈数据集处理的心得和教训_第11张图片

因为这个原因,我给 400 + 图片反复做了四次标记(我没哭!)

4. 打完标记得看看标签,以免类突然切换,而标签忘记切换,一路错下去。

5. 一定要检查标注图!!!

不然歪了都不造,脏数据很丢人的!

6. 做数据集前务必清洗数据,人工清洗那些模糊、抽象、训练意义不大的图片。

数据集的标注对模型至关重要,它可以教会模型去识别哪些物体忽略哪些物体。

心得体会

数据集制作过程,不管是采样,还是说标记,亦或是清洗,都是非常辛苦的。一整个流程下来,更加感觉到公开数据集的珍贵,也体会到开源分析者背后付出的汗水和做出的努力。

以前是一直坐不住,特别好动,没有耐心和毅力去做一些枯燥乏味的机械性工作,抗压能力也非常糟糕,心理防线很容易崩溃。但这段时间处理数据集,标记数据锻炼了抗压能力,提高了心理素质,培养了耐心和毅力。

在数据集处理中,也认识到三个方面重要性。

建立范式

  1. 没有规范意识,一开始音频采样,没有去注意要求,包括采样率、声道、格式这些,以致于我负责的小团队,做出来的上百条音频数据不符合声道要求,需要重新录制。
  2. 工作流程没有建立范式,没有预案,都是走一步看一步,没有全局意识。
  3. 做标签文件的时候,第一个没有认真检查,然后导致后面是一直错的。

团队协作

1. 没有认真去阅读对方发来的消息,所以导致工作内容出现纰漏。

2. 传递教程文件时,没有检查,也没有从自己角度去提出可能存在的问题并回答。

3. 合作完成任务时,没有沟通清楚各自的工作内容。

探索试点

对于有大量内容的待执行任务,可以预先做一份小样本,执行全流程去探索试错,从而积累经验,为后续全盘推进积累经验。

你可能感兴趣的:(比赛复盘,deep,learning,python)