Task01:赛题理解
前言
接触深度学习有一定时间了,但是一直以来还是处于学习吸收阶段,学习的知识也比较零散,没有集中做过大型项目,也没有参加过相关比赛,比较缺乏相关的应用经验。因此这是我第一次参加CV赛事,希望自己能够坚持每天学习,坚持每次打卡,积少成多,熟能生巧。
赛题背景
本次赛事的研究对象是街景字符,取自经典数据集SVHN,主要的任务就是识别街道字符图像,相比于最开始学习过的MNIST数据集上的图像识别,我认为这个数据集提供的样本具有以下特点:
- 字符长度不确定 ,下载数据集并浏览了训练集之后发现,街景字符以两位数字居多,也有三位,四位甚至多位的,参考baseline中的设置,可能最高有五位数字出现。赛事组织方给出的建议是用字符X或者[10]填补空位;
- 字符的位置不确定,即需要对原图片中的字符先进行定位,切割再实现逐个识别。不过好在比赛提供了字符的位置数据(字符距离顶部和左边的像素距离以及字符框的高度和宽度),存储在相应的json文件中,可以打开该文件直接对目标字符进行定位。
- 数据集比较庞大,该数据集共有训练集3w张,验证集3w张,测试集A有4w张图片,因此训练和预测会消耗相对较长的时间。
解决思路
- 最简单的思路是转化为定长字符。即一般的字符是0-9,在此基础上讲空位记作第11个字符,例如可以用X代替,这样需要识别的字符类型就有11种。
- 把该问题看做不定长的字符识别问题,比较典型的有CRNN字符识别模型,这部分尚不了解,还需要做进一步研究。
- 先检测再识别,即检测出字符的位置之后再进行识别。目标检测可以参考使用YOLO
潜在困难
- 之前有过用Tensorflow搭建神经网络完成过MNIST数据集的训练,因此对于图像识别有一定的了解,不过本次比赛提供的框架是Pytorch,因此可能需要一段时间去熟悉了解Pytorch的建模思路和常用的技巧。不过听说Pytorch把数据都封装好了,调用也非常简单。看完baseline之后觉得确实很方便。
- 电脑性能比较差,跑一个epoche可能需要花费数小时,关于这个问题尚不知道该如何解决比较好。不知道在GPU上训练会不会快一些,但是我这GEFORCE GT 650M估计也是很老很老了吧,可能也改善不了多少,而且我还没有配置GPU的相关模块,这个也可能需要研究一下。
- 尚未阅读相关的文献,之后可能还是会花一点时间来看看经典的文献,会及时关注学习群里的相关情况。
Baseline理解
以下简单记录对于赛事方提供的baseline的一些理解。
import os, sys, glob, shutil, json
os.environ["CUclass SVHNDataset(Dataset):
def __init__(self, img_path, img_label, transform=None):
self.img_path = img_path
self.img_label = img_label
if transform is not None:
self.transform = transform
else:
self.transform = None
def __getitem__(self, index):
img = Image.open(self.img_path[index]).convert('RGB')
if self.transform is not None:
img = self.transform(img)
# 设置最长的字符长度为5个
lbl = np.array(self.img_label[index], dtype=np.int)
lbl = list(lbl) + (5 - len(lbl)) * [10]
return img, torch.from_numpy(np.array(lbl[:5]))
def __len__(self):
return len(self.img_path)
这一块设置了定长字符是5个字符,其中空位用10代替。SVHNDataset通过PIL读入图片之后,通过transform做一定的图像处理。通过后文可以知道这些处理包括:
- resize:重置图像分辨率
- RandomCrop:依据给定的size随机裁剪
- ColorJitter:修改修改亮度、对比度和饱和度,前三个参数是brightness, contrast, saturation;
- RandomRotation:随机旋转一定角度
- ToTensor:将PIL Image或者 ndarray 转换为tensor,并且归一化至[0-1] ;
- Normalize:对数据按通道进行标准化,即先减均值,再除以标准差。
train_path = glob.glob