欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于R语言的Kaggle案例分析学习笔记(九)

程序员文章站 2022-04-10 20:58:52
...
手写图片识别
本案例大纲
1、卷积神经网络的介绍
2、案例背景
3、R语言实现

1、卷积神经网络的介绍

针对黑白图片:

1)局部链接

     基于R语言的Kaggle案例分析学习笔记(九)

    如上图所示,图片是由像素组成,而像素又是由很多数字组成,最左边的方框是4*4的像素图片,展开成那条橙黄色的长度的为16的向量,以4个像素为一个单位,映射到隐藏层的一个神经元,每个像素映射都有权重,每个被 映射的神经元都有一个常数b0。以input层的1、2、4、5像素为例,这4个像素映射到隐藏层的0号神经元,权重分别是w1、w2、w3、w4,常数为b0,相应的映射函数为:Y0=x0*w1+x2*w2+x4*w3+x5*w4+b0

2)空间共享性

基于R语言的Kaggle案例分析学习笔记(九)


      空间共享性是指任何像素组映射到卷积层的权重及常数项都是相等,例如现在红色方框框的是0、1、4、5这几个像素,下一步方框向右移动一步,框住1、2、5、6这几个元素,这几个元素对应橙黄色16个元素的向量分别也是1、2、5、6元素,这1、2、5、6元素映射到卷积层的1号神经元,有4个权重分别是w5、w6、w7、w8,这几个权重与w1、w2、w3、w4相同,常数项b0也相同。

3)输出表达

基于R语言的Kaggle案例分析学习笔记(九)

基于R语言的Kaggle案例分析学习笔记(九)

卷积层可以是向量也可以是一个矩阵,输出可以是向量的形式,也可以输出成一个矩阵,这样就形成了一张图片。

关于彩色图片的简单介绍:

          原理与黑白图片类似,不同的是多了一个维度,黑白图片只有长宽两个维度,彩色图片还有深度这个维度。

基于R语言的Kaggle案例分析学习笔记(九)

             如上图所示,彩色图片是三维的,由红绿蓝三个图层组成,每个图层的作用原理与黑白图片类似,单个图层的各个像素单元权重是共享的,但是不同图层的权重是独立的。

 关于zero padding:

      从以上关于黑白照片的详细介绍中可知,卷积层的神经元个数是小于输入的图片像素的,不断卷积,卷积层就不断减小,这样就会损坏图片像素,所以需要在卷积层外加多一层zero padding。如下图所示外围的小圆圈就是zero padding。

基于R语言的Kaggle案例分析学习笔记(九)

             padding的大小可以根据以下的公式计算:
                                                    

                                                      Feature Map=(input_size+2*padding_size-filter_size)/stride+1

          其中Feature Map的大小等于input_size。以上面图片为例,设padding_size为x,Feature Map=input_size=4,filter_size=3,stride=1,stide是步长,带入计算公式:

4=(4+2*x-3)/1+1,则可求出x=1.

关于形状、概念抓取:
基于R语言的Kaggle案例分析学习笔记(九)
基于R语言的Kaggle案例分析学习笔记(九)
         先观察第一个图,一开始形成6个2*2的卷积层,这6个卷积层又可以再次进行卷积,形成3个4*4的卷积层,就像第二个图,一开始识别出来的是一些图片棱角,接着识别出眼睛鼻子,最后能识别出整张人脸。
 多个filter:
基于R语言的Kaggle案例分析学习笔记(九)
         filter指如上图所示的小方块,单一的Filter只能映射出单层卷积层,多个filter可以映射出多层卷积层,这样图片色彩更清晰。
加入非线性:
        卷积神经网络与其他网络类似,也会加入非线性函数,这样识别率更高。
关于卷积神经网络的参数:

基于R语言的Kaggle案例分析学习笔记(九)
基于R语言的Kaggle案例分析学习笔记(九)
           参数不做详细介绍了,基本是跟前面介绍的概念对应,第二个图表示的意思是卷积层的每个输出都是权重与输入的乘积。
池化层:
        池化方法很多,这里主要介绍最大池化法。
          基于R语言的Kaggle案例分析学习笔记(九)
         如上图所示,左图为卷积层,用一个2*2的filter去对卷积层切片,例如第一次切的4个元素分别是1、1、5、6,其中最大的是6,所以把这个6当作这4个元素的代表,放到池化层的第一个元素的位置。池化层的作用主要是降噪,去除一些噪音,获取关键信息。以下解释为什么要进行池化:
基于R语言的Kaggle案例分析学习笔记(九)
        如上图所示,第一行为原始图片,第二行为卷积层,第三行为池化结果,池化结果显示每个图片的最大值为3,如果没有进行池化,而是不断进行卷积,那么最后得到的结果也是3,但是这样会让卷积神经网络的深度更深,浪费更多空间和训练时间,所以池化可以降噪、提高运算速度。
一般的卷积神经网络结构:
基于R语言的Kaggle案例分析学习笔记(九)

          原图片->非线性卷积->池化->非线性卷积->池化->全连接。
2、案例背景介绍
        对手写图片的识别。

3、R语言代码实现

        这里主要使用亚马逊开发的用于深度学习的R语言包:mxnet包,数据下载地址:链接:http://pan.baidu.com/s/1nv5NMhb 密码:za7u

#下载安装
cran <- getOption("repos")
cran["dmlc"] <- "https://s3-us-west-2.amazonaws.com/apache-mxnet/R/CRAN/"
options(repos = cran)
install.packages("mxnet")
library(mxnet)
#加载数据
train <- read.csv("train.csv")
test <- read.csv("test.csv")

# Set up train and test datasets
train <- data.matrix(train)#变成矩阵
train_x <- t(train[, -1])#除第一列以外都作为输入值
train_y <- train[, 1]#目标列
train_array <- train_x
dim(train_array) <- c(28, 28, 1, ncol(train_x))#创建三维数组,因为手写图片是黑白图片,且大小为28*28的矩阵,一列代表一个数字,一共有ncol(train_x)数字
test_x <- t(test)
test_array <- test_x
dim(test_array) <- c(28, 28, 1, ncol(test_x))

#画个图
plot.digit<-function(x){
train.plot<-t(train[x,-1])#x代表画第几个图片
train.plot2<-matrix((train.plot),ncol=28)变成矩阵形式
image(train.plot2,col=grey.colors(225),axes=F)

}

data <- mx.symbol.Variable('data')#把数据变成mx规定的格式
# 第一层卷积层
conv_1 <- mx.symbol.Convolution(data = data, kernel = c(5, 5), num_filter = 20)#kernael就是filter,num_filter表示filter个数
tanh_1 <- mx.symbol.Activation(data = conv_1, act_type = "tanh")
#数据来自于卷积层,act_type**函数为非线性函数即双曲正切函数
pool_1 <- mx.symbol.Pooling(data = tanh_1, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))
#池化层,数据来自非线性**函数,pool_type="max"最大池化法,stride表示移动步长
# 第二层卷积
conv_2 <- mx.symbol.Convolution(data = pool_1, kernel = c(5, 5), num_filter = 50)#护具来自第一层的池化层
tanh_2 <- mx.symbol.Activation(data = conv_2, act_type = "tanh")
pool_2 <- mx.symbol.Pooling(data=tanh_2, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))
# 第一层全连接
flatten <- mx.symbol.Flatten(data = pool_2)#Flatten将矩阵变成一个向量,数据来自于第二层池化层
fc_1 <- mx.symbol.FullyConnected(data = flatten, num_hidden = 500)#全连接,全连接的数据来自上一层的flatten
tanh_3 <- mx.symbol.Activation(data = fc_1, act_type = "tanh")#加一层非线性**函数,数据来自上一层的全连接
# 第二层全连接
fc_2 <- mx.symbol.FullyConnected(data = tanh_3, num_hidden = 40)#来自上层非线性的结果
#输出,因为这是多分类问题,所以用softmax函数
NN_model <- mx.symbol.SoftmaxOutput(data = fc_2)

# 设置种子,使结果具备可重复性
mx.set.seed(100)

# 使用cpu设备
devices <- mx.cpu()
# 训练
model <- mx.model.FeedForward.create(NN_model,
                                     X = train_array,
                                     y = train_y,
                                     ctx = devices,#设备
                                     num.round = 25,#迭代次数
                                     array.batch.size = 40,#批处理规模
                                     learning.rate = 0.01,#学习率
                                     momentum = 0.9,#当误差平面趋近于平面的话加快计算速度
                                     eval.metric = mx.metric.accuracy,#评价指标
                                     epoch.end.callback = mx.callback.log.train.metric(100))#回调函数,观察程序运行情况

#测试
predicted <- predict(model, test_array)
predicted_labels <- max.col(t(predicted)) - 1
res<-data.frame(ImageId=seq(1:length(predicted_labels)),Label=predicted_labels)
write.csv(res,"Submission.csv",row.names = F)