CNN | 01实现颜色分类
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行的头尾两个,都是大色块识别错误。也就是说,对两类形状上的颜色判断不准:
- 很细的线
- 很大的色块
这是什么原因呢?笔者分析:
- 针对细直线,由于带颜色的像素点的数量非常少,被拆成向量后,这些像素点就会在1x784的矢量中彼此相距很远,特征不明显,很容易被判别成噪音;
- 针对大色块,由于带颜色的像素点的数量非常多,即使被拆成向量,也会占据很大的部分,这样特征点与背景点的比例失衡,导致无法判断出到底哪个是特征点。
笔者认为以上两点是前馈神经网络在训练上的不稳定,以及最后准确度不高的主要原因。
当然有兴趣的读者也可以保留输入样本的三个彩色通道信息,把一个样本数据变成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的卷积核的数值是学习出来的,而不是人为指定的。
这样做可以达到两个目的:
- 跨通道信息整合
- 降维以减少学习参数
所以1x1的卷积核关注的是不同通道的相同位置的像素之间的相关性,而不是同一通道内的像素的相关性,在本例中,意味着它关心的彩色通道信息,通过不同的卷积核,把彩色通道信息转变成另外一种表达方式,在保留原始信息的同时,还实现了降维。
在本例中,第一层卷积如果使用3个卷积核,输出尺寸是3x28x28,和输入尺寸一样,达不到降维的作用。所以,一般情况下,会使用小于输入通道数的卷积核数量,比如输入通道为3,则使用2个或1个卷积核。在上例中,如果使用2个卷积核,则输出两张9x9的特征图,这样才能达到降维的目的。如果想升维,那么使用4个以上的卷积核就可以了。
1.5 颜色分类可视化解释
在这里笔者根据自己的理解,解释一下针对这个颜色分类问题,卷积神经网络是如何工作的。
图18-20 颜色分类问题的可视化解释
如图18-20所示:
第一行是原始彩色图片,三通道28x28,特意挑出来都是矩形的6种颜色。
第二行是第一卷积组合梯队的第1个1x1的卷积核在原始图片上的卷积结果。由于是1x1的卷积核,相当于用3个浮点数分别乘以三通道的颜色值所得到和,只要是最后的值不一样就可以了,因为对于神经网络来说,没有颜色这个概念,只有数值。从人的角度来看,6张图的前景颜色是不同的(因为原始图的前景色是6种不同颜色)。
第三行是第一卷积组合梯队的第2个1x1的卷积核在原始图片上的卷积结果。与2相似,只不过3个浮点数的数值不同而已,也是得到6张前景色不同的图。
第四行是第二卷积组合梯队的三个卷积核的卷积结果图,把三个特征图当作RGB通道后所生成的彩色图。单独看三个特征图的话,人类是无法理解的,所以我们把三个通道变成假的彩色图,仍然可以做到6个样本不同色,但是出现了一些边框,可以认为是卷积层从颜色上抽取出的“特征”,也就是说卷积网络“看”到了我们人类不能理解的东西。
第五行是第二卷积组合梯队的激活函数结果,和原始图片相差很大。
如果用人类的视觉神经系统做类比,两个1x1的卷积核可以理解为两只眼睛上的视网膜上的视觉神经细胞,把彩色信息转变成神经电信号传入大脑的过程。最后由全连接层做分类,相当于大脑中的视觉知识体系。
回到神经网络的问题上,只要ReLU的输出结果中仍然含有“颜色”信息(用假彩色图可以证明这一点),并且针对原始图像中的不同的颜色,会生成不同的假彩色图,最后的全连接网络就可以有分辨的能力。
举例来说,从图18-20看,第一行的红色到了第五行变成了黑色,绿色变成了淡绿色,等等,是一一对应的关系。如果红色和绿色都变成了黑色,那么将分辨不出区别来。
代码位置
ch18, Level1
思考与练习
- 从彩色图转换成灰度图会损失一些信息,有可能会导致DNN准确度不高。请尝试用2352(=784x3)的矢量做为样本特征值,送入DNN进行训练。
- 从结果上看细线和大色块对DNN的影响较大,请尝试去掉细线样本,看看DNN的准确度是否可以提高。
- 读者可以尝试使用4个以上的1x1卷积核,看看是否能提高准确度。
- 读者可以尝试不使用第二层卷积,看看是否能完成任务。
CNN | 01实现颜色分类相关推荐
- [Python图像识别] 五十.Keras构建AlexNet和CNN实现自定义数据集分类详解
该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...
- 《LeetCode力扣练习》第75题 颜色分类 Java
<LeetCode力扣练习>第75题 颜色分类 Java 一.资源 题目: 给定一个包含红色.白色和蓝色.共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按 ...
- TensorFlow使用CNN实现中文文本分类
TensorFlow使用CNN实现中文文本分类 读研期间使用过TensorFlow实现过简单的CNN情感分析(分类),当然这是比较low的二分类情况,后来进行多分类情况.但之前的学习基本上都是在英文词 ...
- (转!)利用Keras实现图像分类与颜色分类
2018-07-19 全部谷歌渣翻加略微修改 大家将就的看哈 建议大佬们还是看看原文 点击收获原文 其中用到的示例文件 multi-output-classification 大家可以点击 下载 . ...
- 基于CNN的音乐流派分类
文章目录 写在前面 正文开始 梅尔频谱图 收集和预处理数据 CNN是怎么做到的? 更深入的观察 蓝调还是爵士? 雷鬼还是嘻哈? 这是摇滚吗? 这告诉我们什么? 一个自然的问题 写在前面 笔者的上一篇翻 ...
- 【飞桨】卷积神经网络(CNN)实现猫狗分类
目录 什么是卷积神经网络? 一.数据准备 二.网络配置 1. 定义网络 2. 定义输入数据的格式 3. 定义损失函数和准确率 4. 定义优化方法 三.模型训练&评估 四.模型预测 五.完整代码 ...
- 综述:CNN在脑肿瘤分类的应用(2015-2022)
CNN在脑肿瘤分类的应用 论文名称 Convolutional Neural Network T echniques for Brain Tumor Classification (from 2015 ...
- 卷积神经网络(CNN)实现CIFAR100类别分类
卷积神经网络(CNN)实现CIFAR100类别分类 1. CIFAR100数据集介绍 这个数据集就像CIFAR-10,除了它有100个类,每个类包含600个图像.,每类各有500个训练图像和100个测 ...
- 基于CNN的图像缺陷分类
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|新机器视觉 来源:博客园 原文地址:https://w ...
- python 三指针解决颜色分类
颜色分类 给定一个包含红色.白色和蓝色,一共 n 个元素的数组, 原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列.此题中,我们使用整数 0. 1 和 2 分别表示红色.白色 ...
最新文章
- [云炬商业计划书阅读分享]校园快递创业计划书
- Android NDK学习笔记2:数组
- C语言转义字符介绍和示例
- Linux expect脚本使用详细说明及示例
- 《机器学习与数据科学(基于R的统计学习方法)》——2.15 小结
- 实现LAYERED窗口
- 北大计算机博士毕业难度,北京大学博士毕业要求
- Eigen内存分配器aligned_allocator
- 关于低功耗IPC市场介绍之原厂介绍
- zzulioj1134: 字符串转换
- 【自动化测试】推荐一款超好用的ui自动化工具--uiautomator2
- 介绍一个全局最优化的方法:随机游走算法(Random Walk)
- 软工-第一次团队展示
- 【SQL】递归展BOM全阶,含半成品,用量累乘,如半成品用量2,下阶用量需要乘以2
- 帝国CMS7.5仿励志一生文章网站源码 带手机版+火车头采集
- Wpf使用Behaviors包
- 最新动脑学院java课程分享
- 【Flutter】Flutter异常:The following assertion was thrown during performResize(),SliverGeometry is not v
- 新钉钉,又对「协同」下了手
- 网络电话可随意选取去电号码 400骚扰电话换个马甲又来了