点击上方关注,All in AI中国
从我的学前时代开始,我记得花了很多时间在我最喜欢的Game Boy(Game Boy家系是任天堂发售的掌上游戏机家系)上玩游戏。我最喜欢的两个平台游戏是Mario(马里奥)和Wario(瓦里奥)。我记得当我的祖母看了我正在玩的游戏时,问我这是什么。我解释说这是超级马里奥。一段时间后,当她看到我再次播放时,她看着屏幕说道:“马里奥又来了?这场比赛有多长时间?”但实际上,这是一场完全不同的比赛,是瓦里奥。这段记忆激发了我对图像识别的尝试,并试着看看我是否可以训练出一个能够准确识别一些截图的分类器。
在本文中,我使用两种方法。基本的是逻辑回归,而更高级的是卷积神经网络(使用tensorflow后端和Keras)。我不会特别解释算法背后的逻辑或数学,因为在这方面已经有大量的文章。相反,我将展示如何把一个简单、随机的想法快速转换为数据科学项目。
为了简洁起见,会只发布一些代码片段。文末放上全部的代码内容。
数据准备
根据我童年的记忆,我为这个实验选择了两个游戏:《超级马里奥大陆2-6金币》和《超级马里奥大陆3-瓦里奥大陆》我选择这些游戏,是因为它们当时是我的最爱,也是在检查时发现游戏的图像在视觉上非常相似,这会使任务更难!
我想知道从这些游戏中获取大量屏幕截图的最佳方式是什么,于是决定从Youtube上播放的视频中“抓取”它们。 Python的pytube库可以帮助完成这项任务,我可以毫不费力地用几行代码就下载整个视频。
下一步是从视频中剪切帧。为此,我迭代所有帧(使用OpenCV库)并只将第n帧保存到指定的文件夹。并决定使用10k图像(每场5k)。在这两种方法中,我将使用80-20的相同训练测试分组来确保可比性。
在抓取帧时,会跳过视频的前60秒,其中主要包含开场序列和菜单(我不会在视频结尾处这样做,因此可能会包含一些噪音,但我们会看到!)
在查看预览之后,很明显图像的大小不同。这就是我将它们重新缩放为64x64像素的原因。此外,对于逻辑回归,我将图像转换为灰度以减少模型的特征数量(CNN将处理3个颜色通道)。
逻辑回归
我将从更简单的模型开始,逻辑回归是基本二元分类器之一,即,使用一组预测器,它分配两个类中的一个。
话虽如此,要使用逻辑回归来解决图像分类问题,首先需要准备数据。输入应与Scikit-Learn中的其他模型完全相同,即特征矩阵X和标签y。
由于本文的目的是展示如何为特定问题构建图像分类器,因此我不专注于调整算法并使用逻辑回归的默认设置。直接跳到结果!
上面我在测试集上显示结果,因此模型不能用于训练的部分数据(20%的数据)。这看起来非常棒,实际上可能有点太好了。让我们来检查一些正确、错误分类图像的情况。
5个图像中有4个错误分类的逻辑非常明显。这些是一些过渡屏幕,模型实际上无法做任何事情。第二个屏幕来自超级马里奥的水平地图,它与游戏的其他部分明显不同(这里不是平台游戏)。但是,我们还可以看到模型正确地分类了另一个地图(图像3来自正确分类的图像)。
卷积神经网络
这部分显然比逻辑回归更复杂一些。第一步涉及以特定方式存储图像,因此Keras可以做到这一点:
此目录树显示了我如何为此特定项目构建文件夹和文件。下一部分是数据增强。我们的想法是对可用图像应用一些随机变换,以使网络能够看到更多用于训练的独特图像。这应该可以防止过度拟合并导致更好的泛化。我只使用了一些转换:
- rescale - 在任何其他处理之前将数据相乘,原始图像由0-255范围内的RGB系数组成。这些值对于模型来说可能太高(具有典型的学习速率),因此乘以因子1/255会将变量重新调整为0-1范围
- shear_range - 用于随机应用剪切变换
- zoom_range - 用于随机缩放图片内部
- horizontal_flip - 用于水平地随机翻转一半图像(当没有水平不对称假设时,例如真实世界的图片)。我决定不使用此功能,因为在视频游戏截图的情况下这没有意义(数字等)
在指定图像的路径时,我还确定了要提供给神经网络的图像的大小(64x64,与逻辑回归相同)。
下面我展示了应用一些变换后的图像示例,我们看到了图像在两侧伸展。
现在是定义CNN的时候了。首先,初始化3个卷积层,在第一个中,还需要指定输入图像的形状(64x64,3个RGB通道)。之后,Keras自动处理大小,对于所有这些都使用ReLU(整流线性单元)激活功能。
卷积层变平后。由于最后两层基本上是常规ANN分类器,需要将卷积层中的数据转换为1D向量。在两个密集层之间,我也使用了drop,简而言之,在训练期间,drop忽略了指定数量的神经元(随机选择)。这是一种防止过度拟合的方法。最后一个密集层使用sigmoid激活函数,并返回给定观察属于其中一个类的概率。最后一步基本上是逻辑回归的作用。
现在是时候运行CNN了(这可能需要一段时间......)。我使用ADAM作为优化器,选择二进制交叉熵作为此二进制分类任务的损失函数,并使用准确度来评估结果(不需要使用不同的度量,因为在这种特殊情况下,准确性是我感兴趣的部分)。
那么神经网络是如何运作的呢?让我们来看看!
嗯,准确性低于逻辑回归的情况,但对于这种快速构建的模型来说仍然非常好。可以通过改变卷积/密集层的数量,改变drop,对图像执行额外的转换等来微调网络。也可能是转换隐藏了图像中的一些数据(例如图像底部的摘要栏)。实际上,我最初怀疑这个栏可能在识别图像方面发挥重要作用,因为它几乎存在于所有截图中,并且两个游戏之间略有不同。
现在是时候检查一些正确/错误分类的图像的例子了。乍一看不同的是,在这种情况下,没有像屏幕转换这样明显的错误分类示例。
用LIME解释分类
作为奖励,我尝试用LIME(Local Interpretable Model-Agnostic Explanations)解释CNN的图像分类。与模型无关意味着LIME可以应用于任何机器学习模型。它基于修改单个观察的特征值并观察对预测的影响的想法。
下面我展示了对图像应用LIME解释的结果。绿色区域表示对预测类别的积极影响,红色为负。从正确分类的案例中我们看到角色总是在绿色区域,这符合逻辑。但是,对于不正确的否定情况,一些图像上只有一种颜色。这提供了一些见解,但我认为可以通过额外的修补从LIME解释中提取更多信息。
结论
在本文中,我介绍了如何快速将随机想法转换为图像分类项目。两种被考虑过的方法在数据集上都表现良好,我相信CNN可以在一些调整后获得更好的分数。
还有一些进一步改进的想法:
- 添加更多游戏来研究模型在多级环境中的表现
- 不同的数据准备方法 - 我可以通过从当前图像的中间切割它们来拍摄更大的图像(128x128,因为两个视频都具有更大的分辨率)。这也可以解决底部汇总栏的潜在问题。
- 在CNN的数据生成步骤中添加额外的图像变换
- 尝试在图像中检测马里奥/瓦里奥(物体检测问题)
附上全部的代码地址:https://github.com/erykml/mario_vs_wario
閱讀更多 AI中國 的文章