1 实现颜色分类

1.1 提出问题

大家知道卷积神经网络可以在图像分类上发挥作用,而一般的图像都是彩色的,也就是说卷积神经网络应该可以判别颜色的。这一节中我们来测试一下颜色分类问题,也就是说,不管几何图形是什么样子的,只针对颜色进行分类。

先看一下样本数据,如图18-14。

图18-14 颜色分类样本数据图

在样本数据中,一共有6种颜色,分别是:

  • 红色 red
  • 绿色 green
  • 蓝色 blue
  • 青色(蓝+绿) cyan
  • 黄色(红+绿) yellow
  • 粉色(红+蓝) pink

而这6种颜色是分布在5种形状之上的:

  • 圆形
  • 菱形
  • 直线
  • 矩形
  • 三角形

我们看看神经网络能否排除形状的干扰,而单独把颜色区分开来。

1.2 用前馈神经网络解决问题

数据处理

由于输入图片是三通道的彩色图片,我们先把它转换成灰度图,

class GeometryDataReader(DataReader_2_0):def ConvertToGray(self, data):(N,C,H,W) = data.shapenew_data = np.empty((N,H*W))if C == 3: # colorfor i in range(N):new_data[i] = np.dot([0.299,0.587,0.114], data[i].reshape(3,-1)).reshape(1,784)elif C == 1: # graynew_data[i] = data[i,0].reshape(1,784)#end ifreturn new_data

向量[0.299,0.587,0.114]的作用是,把三通道的彩色图片的RGB值与此向量相乘,得到灰度图,三个因子相加等于1,这样如果原来是[255,255,255]的话,最后的灰度图的值还是255。如果是[255,255,0]的话,最后的结果是:

Y=0.299⋅R+0.586⋅G+0.114⋅B=0.299⋅255+0.586⋅255+0.114⋅0=225.675(1)\begin{aligned} Y &= 0.299 \cdot R + 0.586 \cdot G + 0.114 \cdot B \\ &= 0.299 \cdot 255 + 0.586 \cdot 255 + 0.114 \cdot 0 \\ &=225.675 \end{aligned} \tag{1} Y​=0.299⋅R+0.586⋅G+0.114⋅B=0.299⋅255+0.586⋅255+0.114⋅0=225.675​(1)

也就是说粉色的数值本来是(255,255,0),变成了单一的值225.675。六种颜色中的每一种都会有不同的值,所以即使是在灰度图中,也会保留部分“彩色”信息,当然会丢失一些信息。这从公式1中很容易看出来,假设B=0B=0B=0,不同组合的R、GR、GR、G的值有可能得到相同的最终结果,因此会丢失彩色信息。

在转换成灰度图后,立刻用reshape(1,784)把它转变成矢量,该矢量就是每个样本的784维的特征值。

搭建模型

我们搭建的前馈神经网络模型如下:

def dnn_model():num_output = 6max_epoch = 100batch_size = 16learning_rate = 0.01params = HyperParameters_4_2(learning_rate, max_epoch, batch_size,net_type=NetType.MultipleClassifier,init_method=InitialMethod.MSRA,optimizer_name=OptimizerName.SGD)net = NeuralNet_4_2(params, "color_dnn")f1 = FcLayer_2_0(784, 128, params)net.add_layer(f1, "f1")r1 = ActivationLayer(Relu())net.add_layer(r1, "relu1")f2 = FcLayer_2_0(f1.output_size, 64, params)net.add_layer(f2, "f2")r2 = ActivationLayer(Relu())net.add_layer(r2, "relu2")f3 = FcLayer_2_0(f2.output_size, num_output, params)net.add_layer(f3, "f3")s3 = ClassificationLayer(Softmax())net.add_layer(s3, "s3")return net

这就是一个普通的三层网络,两个隐层,神经元数量分别是128和64,一个输出层,最后接一个6分类Softmax。

运行结果

训练100个epoch后,得到如下损失函数图。

图18-15 训练过程中的损失函数值和准确度变化曲线

从损失函数曲线可以看到,此网络已经有些轻微的过拟合了,如果重复多次运行训练过程,会得到75%到85%之间的一个准确度值,并不是非常稳定,但偏差也不会太大,这与样本的噪音有很大关系,比如一条很细的红色直线,可能会给训练带来一些不确定因素。

最后我们考察一下该模型在测试集上的表现:

......
epoch=99, total_iteration=28199
loss_train=0.005832, accuracy_train=1.000000
loss_valid=0.593325, accuracy_valid=0.804000
save parameters
time used: 30.822062015533447
testing...
0.816

在图18-16的可视化结果,一共64张图,是测试集中1000个样本的前64个样本,每张图上方的标签是预测的结果。

图18-16 可视化结果

可以看到有很多直线的颜色被识别错了,比如最后一行的第1、3、5、6列,颜色错误。另外有一些大色块也没有识别对,比如第3行最后一列和第4行的头尾两个,都是大色块识别错误。也就是说,对两类形状上的颜色判断不准:

  • 很细的线
  • 很大的色块

这是什么原因呢?笔者分析:

  1. 针对细直线,由于带颜色的像素点的数量非常少,被拆成向量后,这些像素点就会在1x784的矢量中彼此相距很远,特征不明显,很容易被判别成噪音;
  2. 针对大色块,由于带颜色的像素点的数量非常多,即使被拆成向量,也会占据很大的部分,这样特征点与背景点的比例失衡,导致无法判断出到底哪个是特征点。

笔者认为以上两点是前馈神经网络在训练上的不稳定,以及最后准确度不高的主要原因。

当然有兴趣的读者也可以保留输入样本的三个彩色通道信息,把一个样本数据变成1x3x784=2352的向量进行试验,看看是不是可以提高准确率。

1.3 用卷积神经网络解决问题

下面我们看看卷积神经网络的表现。我们直接使用三通道的彩色图片,不需要再做数据转换了。

搭建模型

def cnn_model():num_output = 6max_epoch = 20batch_size = 16learning_rate = 0.1params = HyperParameters_4_2(learning_rate, max_epoch, batch_size,net_type=NetType.MultipleClassifier,init_method=InitialMethod.MSRA,optimizer_name=OptimizerName.SGD)net = NeuralNet_4_2(params, "color_conv")c1 = ConvLayer((3,28,28), (2,1,1), (1,0), params)net.add_layer(c1, "c1")r1 = ActivationLayer(Relu())net.add_layer(r1, "relu1")p1 = PoolingLayer(c1.output_shape, (2,2), 2, PoolingTypes.MAX)net.add_layer(p1, "p1") c2 = ConvLayer(p1.output_shape, (3,3,3), (1,0), params)net.add_layer(c2, "c2")r2 = ActivationLayer(Relu())net.add_layer(r2, "relu2")p2 = PoolingLayer(c2.output_shape, (2,2), 2, PoolingTypes.MAX)net.add_layer(p2, "p2") params.learning_rate = 0.1f3 = FcLayer_2_0(p2.output_size, 32, params)net.add_layer(f3, "f3")bn3 = BnLayer(f3.output_size)net.add_layer(bn3, "bn3")r3 = ActivationLayer(Relu())net.add_layer(r3, "relu3")f4 = FcLayer_2_0(f3.output_size, num_output, params)net.add_layer(f4, "f4")s4 = ClassificationLayer(Softmax())net.add_layer(s4, "s4")return net

表18-1展示了在这个模型中各层的作用和参数。

表18-1 模型各层的参数

ID 类型 参数 输入尺寸 输出尺寸
1 卷积 2x1x1, S=1 3x28x28 2x28x28
2 激活 Relu 2x28x28 2x28x28
3 池化 2x2, S=2, Max 2x14x14 2x14x14
4 卷积 3x3x3, S=1 2x14x14 3x12x12
5 激活 Relu 3x12x12 3x12x12
6 池化 2x2, S=2, Max 3x12x12 3x6x6
7 全连接 32 108 32
8 归一化 32 32
9 激活 Relu 32 32
10 全连接 6 32 6
11 分类 Softmax 6 6

为什么第一梯队的卷积用2个卷积核,而第二梯队的卷积核用3个呢?只是经过调参试验的结果,是最小的配置。如果使用更多的卷积核当然可以完成问题,但是如果使用更少的卷积核,网络能力就不够了,不能收敛。

运行结果

经过20个epoch的训练后,得到的结果如图18-17。

图18-17 训练过程中的损失函数值和准确度变化曲线

以下是打印输出的最后几行:

......
epoch=19, total_iteration=5639
loss_train=0.005293, accuracy_train=1.000000
loss_valid=0.106723, accuracy_valid=0.968000
save parameters
time used: 17.295073986053467
testing...
0.963

可以看到我们在测试集上得到了96.3%的准确度,比前馈神经网络模型要高出很多,这也证明了卷积神经网络在图像识别上的能力。

图18-18是测试集中前64个测试样本的预测结果。

图18-18 测试结果

在这一批的样本中,只有左下角的一个绿色直线被预测成蓝色了,其它的没发生错误。

18.1.4 1x1卷积

读者可能还记得在GoogLeNet的Inception模块中,有1x1的卷积核。这初看起来是一个非常奇怪的做法,因为1x1的卷积核基本上失去了卷积的作用,并没有建立在同一个通道上的相邻像素之间的相关性。

在本例中,为了识别颜色,我们也使用了1x1的卷积核,并且能够完成颜色分类的任务,这是为什么呢?

我们以三通道的数据举例。

图18-19 1x1卷积核的工作原理

假设有一个三通道的1x1的卷积核,其值为[1,2,-1],则相当于把每个通道的同一位置的像素值乘以卷积核,然后把结果相加,作为输出通道的同一位置的像素值。以左上角的像素点为例:

1×1+1×2+1×(−1)=21 \times 1 + 1 \times 2 + 1 \times (-1)=2 1×1+1×2+1×(−1)=2

相当于把上图拆开成9个样本,其值为:

[1,1,1] # 左上角点
[3,3,0] # 中上点
[0,0,0] # 右上角点
[2,0,0] # 左中点
[0,1,1] # 中点
[4,2,1] # 右中点
[1,1,1] # 左下角点
[2,1,1] # 下中点
[0,0,0] # 右下角点

上述值排成一个9行3列的矩阵,然后与一个3行1列的向量(1,2,−1)T(1,2,-1)^T(1,2,−1)T相乘,得到9行1列的向量,然后再转换成3x3的矩阵。当然在实际过程中,这个1x1的卷积核的数值是学习出来的,而不是人为指定的。

这样做可以达到两个目的:

  1. 跨通道信息整合
  2. 降维以减少学习参数

所以1x1的卷积核关注的是不同通道的相同位置的像素之间的相关性,而不是同一通道内的像素的相关性,在本例中,意味着它关心的彩色通道信息,通过不同的卷积核,把彩色通道信息转变成另外一种表达方式,在保留原始信息的同时,还实现了降维。

在本例中,第一层卷积如果使用3个卷积核,输出尺寸是3x28x28,和输入尺寸一样,达不到降维的作用。所以,一般情况下,会使用小于输入通道数的卷积核数量,比如输入通道为3,则使用2个或1个卷积核。在上例中,如果使用2个卷积核,则输出两张9x9的特征图,这样才能达到降维的目的。如果想升维,那么使用4个以上的卷积核就可以了。

1.5 颜色分类可视化解释

在这里笔者根据自己的理解,解释一下针对这个颜色分类问题,卷积神经网络是如何工作的。

图18-20 颜色分类问题的可视化解释

如图18-20所示:

  1. 第一行是原始彩色图片,三通道28x28,特意挑出来都是矩形的6种颜色。

  2. 第二行是第一卷积组合梯队的第1个1x1的卷积核在原始图片上的卷积结果。由于是1x1的卷积核,相当于用3个浮点数分别乘以三通道的颜色值所得到和,只要是最后的值不一样就可以了,因为对于神经网络来说,没有颜色这个概念,只有数值。从人的角度来看,6张图的前景颜色是不同的(因为原始图的前景色是6种不同颜色)。

  3. 第三行是第一卷积组合梯队的第2个1x1的卷积核在原始图片上的卷积结果。与2相似,只不过3个浮点数的数值不同而已,也是得到6张前景色不同的图。

  4. 第四行是第二卷积组合梯队的三个卷积核的卷积结果图,把三个特征图当作RGB通道后所生成的彩色图。单独看三个特征图的话,人类是无法理解的,所以我们把三个通道变成假的彩色图,仍然可以做到6个样本不同色,但是出现了一些边框,可以认为是卷积层从颜色上抽取出的“特征”,也就是说卷积网络“看”到了我们人类不能理解的东西。

  5. 第五行是第二卷积组合梯队的激活函数结果,和原始图片相差很大。

如果用人类的视觉神经系统做类比,两个1x1的卷积核可以理解为两只眼睛上的视网膜上的视觉神经细胞,把彩色信息转变成神经电信号传入大脑的过程。最后由全连接层做分类,相当于大脑中的视觉知识体系。

回到神经网络的问题上,只要ReLU的输出结果中仍然含有“颜色”信息(用假彩色图可以证明这一点),并且针对原始图像中的不同的颜色,会生成不同的假彩色图,最后的全连接网络就可以有分辨的能力。

举例来说,从图18-20看,第一行的红色到了第五行变成了黑色,绿色变成了淡绿色,等等,是一一对应的关系。如果红色和绿色都变成了黑色,那么将分辨不出区别来。

代码位置

ch18, Level1

思考与练习

  1. 从彩色图转换成灰度图会损失一些信息,有可能会导致DNN准确度不高。请尝试用2352(=784x3)的矢量做为样本特征值,送入DNN进行训练。
  2. 从结果上看细线和大色块对DNN的影响较大,请尝试去掉细线样本,看看DNN的准确度是否可以提高。
  3. 读者可以尝试使用4个以上的1x1卷积核,看看是否能提高准确度。
  4. 读者可以尝试不使用第二层卷积,看看是否能完成任务。

CNN | 01实现颜色分类相关推荐

  1. [Python图像识别] 五十.Keras构建AlexNet和CNN实现自定义数据集分类详解

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  2. 《LeetCode力扣练习》第75题 颜色分类 Java

    <LeetCode力扣练习>第75题 颜色分类 Java 一.资源 题目: 给定一个包含红色.白色和蓝色.共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按 ...

  3. TensorFlow使用CNN实现中文文本分类

    TensorFlow使用CNN实现中文文本分类 读研期间使用过TensorFlow实现过简单的CNN情感分析(分类),当然这是比较low的二分类情况,后来进行多分类情况.但之前的学习基本上都是在英文词 ...

  4. (转!)利用Keras实现图像分类与颜色分类

    2018-07-19 全部谷歌渣翻加略微修改 大家将就的看哈 建议大佬们还是看看原文 点击收获原文 其中用到的示例文件 multi-output-classification 大家可以点击 下载 . ...

  5. 基于CNN的音乐流派分类

    文章目录 写在前面 正文开始 梅尔频谱图 收集和预处理数据 CNN是怎么做到的? 更深入的观察 蓝调还是爵士? 雷鬼还是嘻哈? 这是摇滚吗? 这告诉我们什么? 一个自然的问题 写在前面 笔者的上一篇翻 ...

  6. 【飞桨】卷积神经网络(CNN)实现猫狗分类

    目录 什么是卷积神经网络? 一.数据准备 二.网络配置 1. 定义网络 2. 定义输入数据的格式 3. 定义损失函数和准确率 4. 定义优化方法 三.模型训练&评估 四.模型预测 五.完整代码 ...

  7. 综述:CNN在脑肿瘤分类的应用(2015-2022)

    CNN在脑肿瘤分类的应用 论文名称 Convolutional Neural Network T echniques for Brain Tumor Classification (from 2015 ...

  8. 卷积神经网络(CNN)实现CIFAR100类别分类

    卷积神经网络(CNN)实现CIFAR100类别分类 1. CIFAR100数据集介绍 这个数据集就像CIFAR-10,除了它有100个类,每个类包含600个图像.,每类各有500个训练图像和100个测 ...

  9. 基于CNN的图像缺陷分类

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|新机器视觉 来源:博客园  原文地址:https://w ...

  10. python 三指针解决颜色分类

    颜色分类 给定一个包含红色.白色和蓝色,一共 n 个元素的数组, 原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列.此题中,我们使用整数 0. 1 和 2 分别表示红色.白色 ...

最新文章

  1. [云炬商业计划书阅读分享]校园快递创业计划书
  2. Android NDK学习笔记2:数组
  3. C语言转义字符介绍和示例
  4. Linux expect脚本使用详细说明及示例
  5. 《机器学习与数据科学(基于R的统计学习方法)》——2.15 小结
  6. 实现LAYERED窗口
  7. 北大计算机博士毕业难度,北京大学博士毕业要求
  8. Eigen内存分配器aligned_allocator
  9. 关于低功耗IPC市场介绍之原厂介绍
  10. zzulioj1134: 字符串转换
  11. 【自动化测试】推荐一款超好用的ui自动化工具--uiautomator2
  12. 介绍一个全局最优化的方法:随机游走算法(Random Walk)
  13. 软工-第一次团队展示
  14. 【SQL】递归展BOM全阶,含半成品,用量累乘,如半成品用量2,下阶用量需要乘以2
  15. 帝国CMS7.5仿励志一生文章网站源码 带手机版+火车头采集
  16. Wpf使用Behaviors包
  17. 最新动脑学院java课程分享
  18. 【Flutter】Flutter异常:The following assertion was thrown during performResize(),SliverGeometry is not v
  19. 新钉钉,又对「协同」下了手
  20. 网络电话可随意选取去电号码 400骚扰电话换个马甲又来了

热门文章

  1. CCSK认证,提升云安全专业技能,助力职业生涯发展
  2. 攻防世界misc高手进阶区funny_video完整版答案
  3. CTPN算法简单解析
  4. RGB、CMYK、CIE Lab等几种常用颜色空间
  5. 苏州大学计算机复试python_苏州大学计算机考研复试经验总结
  6. 计算机网络基础 习题,计算机网络基础练习题集.pdf
  7. 宏观经济学通识课-读书笔记
  8. 下载Linux系统内文件到Windows
  9. 【学习中】王者荣耀游戏拆解分析(1)
  10. SQLExpress免费版配置本地数据库实例