如何使用深度学习来优化Keras的电子商务业务流程?
点击上方关注,All in AI中国
问题介绍
在讨论问题细节之前,我想先介绍一下业务流程,Avito.ma是一个行业领先的摩洛哥电子商务广告平台,用户可以在其中发布广告,销售二手商品或新产品,如手机、笔记本电脑、汽车、摩托车等。
现在,让我们讨论这个问题:为了发布广告、销售产品,你首先必须填写一个表单,描述你的产品概况,设定价格,并上传其相应的照片。在成功填写这些字段后,你必须等待大约60分钟,以便在网站相关管理人员审核验证这些图片后,再发布你提交的广告。
如今,在深度学习和计算机视觉的时代,通过人工检查网页内容这被认为是一种缺陷,并且非常耗时,而且它可能产生许多错误。例如下面这个错误,网站审核人员发布了列在电话类别中的笔记本电脑广告,这是错误的,并将影响搜索引擎质量,而这项工作可以通过深度学习模型在一秒钟内完成。
笔记本广告发布在手机类链接中
在这篇博文中,我将介绍如何通过使用Keras框架构建一个简单的卷积神经网络来优化此过程,该框架可以分析上传的图像是用于手机广告还是笔记本电脑广告,并告诉我们图像是否与广告类别匹配。
博客文章将这个案例分为5个具体步骤。
- 数据收集
- 数据预处理
- 数据建模
- 使用TensorBoard分析模型
模型部署和评估
1.数据收集
就像任何数据科学项目一样,我们应该寻找的第一个组件是数据,在这种情况下,我们将处理的数据从同一网站Avito.ma中删除的一组图像,用于笔记本电脑和手机两类产品,结果文件夹将包含两个子目录分别称为“笔记本电脑”和“电话”,下载的图像大小在120×90到67×90之间,每个子目录有3个RGB通道。以下是执行此任务的代码的快照,而笔记本中提供了完整代码。(https://github.com/PaacMaan/avito_upload_classifier/blob/master/avito_image_classifier.ipynb)
一旦这个过程完成,我们得到了2097张笔记本电脑图像和2180张手机图像。为了使分类更准确并且没有偏差,我们需要验证几乎相同的观察数量的这两个类,因为我们可以从下面的图中实现可视化,两个类的数量大致相当平衡。
图像分布在类上
2.数据预处理
对于预处理任务,我们将其分为三个子任务,如下所示:
2.1删除噪声数据
当人工检查下载的图像时,会注意到存在一些与相关类无关的噪声图像,例如下面的那些(手机充电器、手机包、虚拟现实眼镜)能够在手机文件夹中观察到:
手机图像中发现噪声图像
不幸的是,没有自动的方法来解决这个问题,因此我们必须人工查看它们,并开始删除它们以仅保留与相应类相关的图像。
2.2图像大小调整
此步骤完全取决于采用的深度学习架构,例如,当使用Alexnet模型对图像进行分类时,输入图像大小应为22×227,而对于VGG-19,输入图像大小为224×224。
由于我们不打算采用任何预先构建的架构,将构建自己的卷积神经网络模型,其输入大小为64 ×64,如下面的代码快照所示。
要执行此任务,我们在两个子目录phone和laptop中创建另一个名为preprocessed_data的目录,然后我们循环raw_data原始文件夹中的每个图像以调整其大小,并将其保存在新创建的目录中。
因此,我们最终得到了两个类的新生成数据集,其格式为64×64。
2.3数据拆分
在调整数据集大小后,我们将其拆分为80%用于训练集,并保留其余部分进行验证。为了执行此任务,我们创建了一个名为data的新目录,其中我们设置了train和validation另外两个新目录,我们将为手机和笔记本电脑设置两个类图像。
更明确地,我们定义当前目标和目标目录,然后我们将训练集的比率固定为0.8,将验证的比率固定为0.2,以测量我们将从原始路径移动到目标路径的图像数量。
执行数据拆分的代码快照
需要很好地可视化文件夹层次结构,这是项目树视图:
全局项目结构
3.数据建模
现在我们到了这一管道的主要步骤,即数据建模,为此我们将建立一个卷积神经网络,将对我们之前处理过的几千部手机和笔记本电脑图像进行训练。
在计算机视觉中,卷积运算是卷积神经网络的基本构建块之一,需要4个必需组件:
卷积神经网络的主要组成部分
对于这个模型,我们将讨论每个组件如何使用Keras实现它以及从卷积到完全连接层的自己的参数,但首先,让我们发现内置模型的完整架构。
卷积神经网络(CNN)模型架构
卷积层
在将顺序对象实例化为模型之后,我们使用add方法添加一个名为Conv2D的卷积层,其中第一个参数是过滤器,它是输出数量的维数,如模型摘要所示,第一层输出的形状为(None, 62, 62, 32)。
对于第二个参数,kernel_size指定了1D卷积窗口的长度,这里我们选择3×3的窗口大小来卷积输入卷。
第三个参数代表input_shape,它是分别与image_width x image_height x color channels (RGB)相关的64×64×3的大小,最后但并非最不重要的是activation_function,它负责添加非线性转换。在这种情况下,我们选择relu激活功能。
使用kernel_size =(3,3)进行卷积运算的插图
最大池层
在卷积之后添加最大池化层的原因是减少我们之前应用的卷积层提取的特征量,换句话说,我们对这些特征的位置感兴趣。
为了对其高度进行概括,如果有一个从x到y的垂直边缘,将图像的垂直边缘降到图像的2/3的高度。
所有这一过程都在Keras的一行代码中恢复:
在这里,我们使用add方法注入另一层名为MaxPooling2D的Maximum Pooling,其中pool_size是(2,2)的窗口,默认情况下strides = None和padding ='valid'。
最大池与pool_size =(2,2)的图示
展平输出
在结束卷积神经网络(CNN)模型时,将最大池展平输出为连续的一维向量是必需的步骤。
Keras在这里所做的,只是在网络中添加一个Flatten图层,它简单地相当于使用'C'排序重塑numpy中的函数。
全连接层
最后,我们将最后一层注入到全连接层的网络中,您可以将其视为学习从先前卷积中提取的特征的非线性组合的廉价方法。
Keras通过将Dense功能添加到网络中很容易实现,它只需要两个参数units和activation,它们分别代表我们将拥有的输出单元的数量,因为我们正在进行二进制分类,因此它取值为2并激活功能使用。
编译网络
最后,我们必须通过调用编译函数来编译我们刚刚构建的网络,这是使用Keras构建的每个模型的必需步骤。
loss参数,因为我们有一个二元分类,其中类M的数量等于2,交叉熵可以计算为:
二元交叉熵的目标函数
其中p是预测概率,y是二进制指示符(0或1)。
为了最小化这个目标函数,我们需要调用优化器,例如adam,这是Adaptive Moment Estimation的简称,默认情况下,其学习速率设置为0.001,但不会关闭超参数调整窗口。为了总结我们所做的事情,下面是内置模型的完整代码。
加载图像和数据转换
为了将图像提供给我们编译的模型,我们调用ImageDataGenerator函数,它将帮助我们生成具有实时数据增强的批量张量图像数据。数据将循环(批量)。
现在我们已经创建了两个ImageDataGenerator实例,我们需要使用分类类模式为训练和验证数据集提供正确的路径。
一旦训练(train)和验证(validation)集准备好为网络提供信息,我们就会调用fit_generator方法将它们提供给模型。
通常我们准备另一个测试数据集,除了评估最终训练模型的验证,但为了保持简单性,并且只在验证集上进行评估。
模型评估
完成训练后,我们的准确率达到87.7%左右,仍然有0.352的高损失率,但具有高精度并不一定意味着我们有良好的模型质量。我们需要在时间内跟踪和可视化模型的行为,为此,我们使用Keras提供的TensorBoard作为与TensorFlow后端一起运行的回调函数。
4.使用TensorBoard分析模型
在这一步骤中,我们将看到如何使用TensorBoard分析我们的模型行为。TensorBoard是使用TensorFlow后端构建的模型的工具,帮助我们基本上可视化我们的模型随时间的训练,以及观察准确性与验证准确度或损失与验证损失的关系。
使用Keras,可以通过调用TensorBoard函数仅在一行代码中恢复此步骤,并在拟合数据时将其作为回调注入。
损失(Loss)
训练和验证集的损失直方图
从上图可以清楚地看出,对于从0.39到0.13的训练线,损失显著下降,而对于验证线,从0.42开始并且花费25个周期达到0.35,它逐渐减少。
就个人而言,每当我想评估模型时,都会看到验证损失,我们可以在这里看到的是,在19个周期之后,验证损失开始稍微增加,这可能会导致模型记住许多输入样本,验证这个假设,我们更好地检查准确性直方图。
准确性
训练和验证集的准确度直方图的演变
正如我们所看到的,验证准确性一直在增加,直到第19个周期它变得有些稳定,并且具有预期的下降和上升,这可以通过从同一时期开始增加时的验证损失行为来解释。
为了保持良好的模型质量,建议在这种情况下使用早期停止回调,这将迫使模型在验证损失开始增加或精度下降时以一定的容差停止训练。
5.采用Flask进行模型部署
在转移到部署细节之前,我们首先需要保存我们之前训练过的模型,为此我们调用save方法,如下所示:
一旦我们的模型被保存,我们可以在以后使用它来预测新的图像类。
为什么采用Flask?
Flask是一个Python的微框架,其灵感来自于引用“Do Thing and Do It Well”,这就是我选择Flask作为REST API提供模型的原因。
Flask应用程序由2个主要组件组成:python应用程序(app.py)和HTML模板,对于app.py,它将包含执行预测的逻辑代码,该代码将作为HTTP响应发送。该文件包含三个主要组件,可以显示如下:
- 加载保存的模型。
- 转换上传的图像。
- 使用加载的模型预测其适当的类。
在下一节中,我们将讨论这些方面最重要的组成部分。
回到主要问题
当用户选择作为广告类别的笔记本电脑时,预计他必须上传笔记本电脑的图像,但正在发生的事情是不同的。正如我们之前看到的那样,有许多广告,其中图片包含标注手机类别的笔记本电脑。
在运行应用程序并假设模型已成功加载后,用户可以上传不同大小的图像,而我们的模型只能预测64×64×3的图像,因此我们需要将它们转换为正确的大小,以便我们的模型可以很好地预测它。
处理上传图像的代码快照
转换上传的图像后,我们将其作为参数发送到加载的模型,以便进行预测并将HTTP响应作为JSON对象返回,其中模式如下:
第一个属性是图像预测类,第二个属性是布尔值,表示从用户中选择的类别是否与上传的图像匹配。下面我展示了执行此工作的代码逻辑的快照。
应用演示
要运行应用程序,我们只需切换到创建app.py的文件夹,然后运行以下命令:
然后我们浏览控制台上显示的以下URL:http://127.0.0.1:5000 /,一旦显示索引页面,选择广告类别并上传其相关照片,在幕后将请求发送到路径/上传将照片保存在目录中以预测其适当的类。
这是现场演示我们在本项目结束时能够建立的内容。
Web应用程序演示
如果选择的和预测的类都匹配,那么你会得到一条成功消息,说明一切正常,否则会收到一条警告消息,选择框将自动更改为相应的预测类。
结论
最后,本博客文章通过构建深度学习模型来展示完整的计算机视觉管道,该模型可以预测应用于电子商务场景的上传图像的类别,从数据收集到数据建模,并通过模型部署作为Web完成应用程序。
改善的方法:
1.通过为两个类删除更多图像来增加数据大小并删除噪声。
2.针对学习率和beta值的超参数调整。
3.尝试其他架构,如Lenet-5。(yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf)
4.在完全连接(密集)层上使用Dropout。
有用的链接:
完整项目+笔记本+数据集:
https://github.com/PaacMaan/avito_upload_classifier
Flask Web应用程序:
https://github.com/PaacMaan/avito_upload_classifier/tree/master/flask_app