下面是使用预训练模型 Alex Net 进行迁移学习的实验和分析总结:
针对个性化图片分类预训练模型准确率较低的问题,采用迁移学习方法。 当训练集照片达到30张时,在测试集上的准确率可以达到80%以上。
一:研究背景
深度学习(DL,Deep)是机器学习(ML)领域的一个新的研究方向。 它被引入到机器学习中,使其更接近最初的目标——人工智能(AI)。
深度学习是学习样本数据的内在模式和表示水平的过程。 在这些学习过程中获得的信息对于解释文本、图像和声音等数据有很大帮助。 其最终目标是使机器具有与人类相同的分析学习能力,识别文本、图像和声音等数据。 深度学习是一种复杂的机器学习算法,在语音和图像识别方面取得了远远超过以往相关技术的效果。
深度学习在搜索技术、数据挖掘、机器学习、机器翻译、自然语言处理、多媒体学习、语音、推荐和个性化技术等相关领域取得了许多成果。深度学习使机器能够模仿人类的活动,例如音频、视频等。视觉和思维,解决了许多复杂的模式识别问题,在人工智能相关技术方面取得了长足进步。
2:预训练模型Alex Net
Alex Net 是由 2012 年竞赛获胜者和他的学生 Alex 设计的。 这对于传统的机器学习分类算法来说已经相当不错了。
Alex Net包含了几个比较新的技术点,也首次成功地将ReLU、LRN等技术应用在CNN中。 同时,Alex Net还利用GPU进行计算加速。 Alex Net继承了LeNet的思想,将CNN的基本原理应用于深度和广度网络。 Alex Net使用的主要新技术如下:
(1)成功使用ReLU作为CNN的激活函数,并验证其效果超过更深层次的网络,成功解决了网络较深时的梯度弥散问题。 虽然ReLU激活函数很早之前就被提出了,但直到Alex Net的出现才被发扬光大。
(2)训练时随机忽略部分神经元,避免模型过拟合。 虽然有单独的论文来讨论,但Alex Net已经将其付诸实践,并通过实践证实了其效果。 在Alex Net中,主要用在最后几个全连接层。
(3) 在CNN中使用重叠最大池化。 此前CNN中普遍使用平均池化,Alex Net均采用最大池化来避免平均池化的模糊效果。 另外,Alex Net提出让步长度小于池化核的大小,这样池化层的输出之间就会有重叠和覆盖,提高了特征的丰富度。
(4)提出LRN层,为局部神经元的活动创建竞争机制,使得响应较大的值变得相对较大,并抑制其他反馈较小的神经元,增强模型的泛化能力。
(5)利用CUDA加速深度卷积网络的训练,利用GPU强大的并行计算能力处理神经网络训练时的大量矩阵运算。 Alex Net 使用两个 GTX 580 GPU 进行训练。 单个 GTX 580 仅具有 3GB 显存,这限制了可训练网络的最大大小。 因此,作者将Alex Net分布在两个GPU上,并将一半的神经元参数存储在每个GPU的显存中。 由于GPU之间通信方便,无需经过主机内存即可访问彼此的显存,因此同时使用多个GPU也非常高效。 同时,Alex Net的设计允许GPU之间的通信仅发生在网络的某些层,控制了通信的性能损失。
(6)数据增强,从原始图像(以及水平翻转的镜子)中随机截取一大一小区域,相当于将数据量增加了2*(256-224)^2=2048倍。 如果没有数据增强,参数较多的CNN仅基于原始数据量就会陷入过拟合。 使用数据增强可以大大减少过度拟合并提高泛化能力。 进行预测时,取图片的四个角加上中间5个位置,左右翻转。 总共获得10张图片,进行预测并计算10张结果的平均值。 同时Alex Net论文中提到,图像的RGB数据会经过PCA处理,对主成分进行标准差为0.1的高斯扰动,添加一些噪声。 这项技术可以将错误率再降低 1%。
三:存在的问题及解决方案
直接应用经过大公司训练有海量数据和强大计算能力的深度学习网络可以轻松直接地对图像进行分类,但也有明显的缺点。 分类的灵活性很低,只能区分模型中的特征。 类别,例如下面实验中使用的 Alex Net 网络模型,有 1000 个类别。 可以想象,如果用于分类的图片不属于这1000个类别,就无法很好地分类。
自己训练深度学习模型非常灵活,但是对用户的知识储备和资源提出了很大的挑战。 首先,用户必须精通构建神经网络模型,知道如何针对不同的数据集构建更好的神经网络结构等。而且,深度学习在一定程度上依赖于海量数据和极其强大的计算能力,而深度学习在一定程度上依赖于海量数据和极其强大的计算能力。模型通过一次又一次的迭代不断改进。
想象一个场景,我们有大量十几种水果的照片。 它们不在现有的训练模型中。 然而,作为学生,我们无法获得海量的图片和强大的计算能力来从头开始训练模型。 深度学习模型。 这时候使用迁移学习就是一个比较好的方法。 在现有训练模型的基础上,我们使用一定数量的现有图片作为训练集来进一步训练模型。 虽然可以满足我们更加个性化的需求,但是使用的图片数量不需要很大,对电脑的消耗也很大。 资源也更少。
其实这种方法的理论分析比较简单。 有许多深度学习模型已经过训练并免费发布。 您可以下载并安装它们以查看每一层。
不难发现,前面的层基本上都是一些卷积层和处理层,用于分离和提取图像元素。 这是我们可以借鉴的一层。 倒数第二层是全连接层,用于将前面提取的图片分离并预测到各个类别中。 最后一层起到标准化的作用。 哪个类别的概率最高,就是该图片被预测的类别。 可以看出,我们需要做的改变是用我们想要的类别创建一个新的全连接层,然后用我们的训练集重新训练这个网络。
四:实验与分析 4.1 图像采集
我想象在实验中添加 12 种水果来测试迁移学习的结果。 这就需要从网上获取比较大量的图片,而手动下载显然是不可能的。 爬虫代码用于爬取照片。
代码如下(参考网络资源):联网时运行即可
import re,os
import requests
from urllib.request import urlretrieve
def download(url,filename,filepath): path=os.path.join(filepath,filename)
try:
urlretrieve(url,path)
except:
print('【错误】当前图片无法下载')
def search(word="",localpath="data/", page=None):
localpath += word
os.makedirs(localpath , exist_ok=True)
url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word={word}&pn={pn}&gsm={gsm:x}&ct=&ic=0&lm=-1&width=0&height=0'.format(word=word, pn=20 * page, gsm=40 + 20 * page)
print("HHHC:0====>page=%d,url=\"%s\"" % (page,url))
try:
html = requests.get(url).text
except:
print("【错误】requests.get 失败")
return False
pic_url = re.findall('"objURL":"(.*?)",', html, re.S)
i = 0;
for url in pic_url:
print(url)
i = i + 1; filename=os.path.split(url)[1].split('?')[0]
if len(filename.split(".")) != 2:
print("【错误】文件名异常:" + filename)
download(url, filename, localpath)
return
def search_20_page(word):
for i in range(1, 20):
search(word, "data/", i)
def test_search_list():
obj_list = [ "菠萝","草莓","车厘子","番石榴","桔子","龙眼","芒果","猕猴桃","苹果","葡萄","山竹","西瓜"]
for obj in obj_list:
search_20_page(obj)
if __name__ =='__main__':
test_search_list()
获取data文件夹及其文件
由于图片是直接从百度搜索获取的,难免存在一些混乱。 例如,苹果的搜索结果中包含一些苹果手机的照片。 实验所用的照片及其标签应真实有效,因此这些不合格的照片需要经过精心挑选。 手动将其删除。 而且由于爬虫运行时有时会出现滞后,所以我重新执行了几次,所以获取到的照片数量不一致。 但至少可以保证80以上。
4.2 使用迁移学习
主体代码及其注释如下:
fruits=imageDatastore('data','IncludeSubfolders',true,'LabelSource','foldernames');
%使用Datastore数据变量储存所有在网页上获得的图片,并储存文件夹名字作为标签名,以作下一步处理。
[fruitTrain1,fruitTest1] = splitEachLabel(fruits,50,'randomized');
%在所有照片中随机选择50张组成训练集,剩余的相片作为测试集
fruitTrain=augmentedImageDatastore([227227],fruitTrain1,'ColorPreprocessing','gray2rgb');
%处理训练集图像大小至深度训练模型要求的227*227*3
fruitTest=augmentedImageDatastore([227227],fruitTest1,'ColorPreprocessing','gray2rgb');
%处理测试集图像大小至深度训练模型要求的227*227*3
anet = Alex Net;%导入alenet深度训练模型
numClasses=numel(categories(fruits.Labels));%获取新的分类个数,在此次实验中为12,但为了普遍性,使用一个函数而不是定值。
layers = anet.Layers;%提取anet的层结构,下做更改
fc=fullyConnectedLayer(numClasses); %创建一个新的全连接层,用于替换原来的模型,进行训练。
layers(23) = fc;%用创建的新全连接层替代原来的全连接层
layers(end)= classificationLayer; %用新的全连接层之后的归一化层替代原来的。
opts=trainingOptions('sgdm','InitialLearnRate',0.001);
%这是一个训练的函数,可以在此指定一些训练时的参数,在实验时指定学习率为0.001,其余使用默认值。
[fruitnet,info]=trainNetwork(fruitTrain,layers,opts);
plot(info.TrainingLoss); %打印损失率
testpreds=classify(fruitnet,fruitTest); %用迁移学习后的模型来进行预测测试集。
nnz(testpreds==fruitTest1.Labels)/numel(testpreds); %计算预测结果在测试集中的成功率。
confusionchart(fruitTest1.Labels,testpreds); %打印出各类预测与真值的‘混淆矩阵’
4.3:运行程序并分析结果
设置默认值为0.8,即使用每个文件夹中所有图像的80%进行训练,其余部分进行测试,以测试之前建立的迁移学习的效果。 运行结果如下:
准确率达到87.89%。 可以看出,机器识别的准确率达到了较为满意的结果。
4.4 是否进行迁移学习的比较
为了探索模型在迁移学习前后识别我们的个性化图片的能力,我首先选择了12张相对清晰且效果好的水果图片进行比较。
要运行经过训练的模型和原始 alenx 模型,请在命令行上运行以下代码:
preds=classify(fruitnet,audtest);
preds1=classify(anet,audstest);
直接查看工作区中pred和pred1变量的值就可以看到结果。 (阅读顺序乱了,但不影响)
毫无疑问,迁移学习后的模型给出了完全正确的答案。 在迁移学习之前的模型中,它对草莓和菠萝的预测也是正确的,但对其他照片的预测结果都是错误的。 可以看出,即使我们有一百张左右的照片,这与深度学习中的大量数据相去甚远,但这样的训练量也能让一个预训练的模型在我们想要的领域取得很好的效果。
4.5 不同训练初始值的训练结果
由于不同种类的水果在网站上下载的图片数量不一致,因此本节将代码的初始值修改为1,2,3,4,5,10,20,30,40,50,训练期间使用了 60 个。 使用70张照片进行训练,分别迁移和学习模型,观察其在测试集上的表现,即混淆矩阵和准确率。 所得结果摘录如下:
1 照片训练结果:
5照片训练结果:
由于混淆矩阵很难看出个体的变化,以训练图像为横坐标,测试集上的准确率为纵坐标,绘制的图像为:
这与我们所了解到的情况是一致的。 一开始,只需少量增加训练量,准确率就能提高很多。 后期需要更多的训练图像来提高准确率。 在实验过程中我们还发现,随着训练的进行,计算时间也明显变长。 可以看出,达到更高的准确率后,同样的准确率提升需要更多的训练图像和更多的计算能力,即付出的代价显着增加。
五、结论
本文提出了一种基于Alex Net模型迁移学习的图像分类方法。 当将预训练的CNN模型迁移到小目标集时,保留原来的卷积层结构,并构建新的全连接层和归一化层来对数据进行分类。 。 设计的水果分类算法可用于十二个类别:苹果、菠萝、猕猴桃、芒果、柑橘、草莓、龙眼、山竹、西瓜、百香果、樱桃和橙子。
训练集和测试集同样使用从百度下载的图片,无论是灯光、拍摄角度还是构图都有很多变化。 在如此大的变化中,非常好的就是照片识别成功率可以达到87左右,具有比较强的通用性。
六、参考文献
[1]《深度学习》词条,百度百科。 [Z]
[2] 连晓芹,程开元,安飒,吴也兰,管文阳。 基于深度学习和迁移学习的水果图像分类[J]. 测控技术, 2019, 38(06): 15-18.
[3]“亚历克斯网”词条,百度百科。 [Z]
[4] - 按关键词抓取百度图片[Z]