R语言 在mnist数据集使用torch建立卷积神经网络

如果你在使用R语言,想要用R语言建立一个深度神经网络,那将是非常困难的。因为好多的深度神经网络的架构,都是在python上,而关于R语言的非常少。如nnet包,RSNNS包等,受之于激活函数的影响,以及只能使用一个cpu进行单线程计算,并且这些包也没有提供建立卷积神经网络的功能。

几年前,我被 R tensorflow 包短暂地吸引住了,但我无法建立一个可靠的工作流程,因为它的 Python 后端不断地挡路。 (许多令人恼火的小时都在徒劳地尝试配置我的 GPU)。

Torch 是一个使用 C++ 后端 libtorch,作为运算的底层,而不是 Python 。

然而,torch 仍然处于起步阶段,尽管它能够完成大多数成熟的深度学习框架可以做的事情,但它没有提供那种让初学者可以直观地掌握的高级 API 这篇文章的目的是帮助读者熟悉torch包。 

现在我们以mnist手写数字数据集,使用R语言的torch包,建立一个卷积神经网络,作为torch的教学。

安装torch包

install.packages("torch")

library(torch)

  # install_torch()   #一般情况下该行代码是不需要运行的,在library之后,会下载安装torch需要的底层架构,如果没有成功安装,就需要你手动运行这行代码。如果失败:请找把梯子。

#以及需要配置其它的系统环境,根据提示进行配置

如果没有mnist数据集,可以通过下面的网址进行下载,格式是csv文件。数据集下载:

https://pjreddie.com/media/files/mnist_train.csv

https://pjreddie.com/media/files/mnist_test.csv

1.mnist数据的读取以及后续处理工作

torch::nn_conv2d所需要的数据形式是(n,channel,height,width)

所以我们需要将minist同样处理成该数据形式。

#训练集

dfminist2<-read.csv("mnist_train.csv",header=F)

dfminist2[,1]<-dfminist2[,1]+1

xminist2<-as.matrix(dfminist2[,2:785])

xminist2<-xminist2/255

xarray2<-array(0,dim=c(60000,1,28,28))

for(i in 1:60000){

xarray2[i,1,,]<-matrix(xminist2[i,],nrow=28,byrow=T)}

#测试集

dfminist<-read.csv("mnist_test.csv",header=F)

dfminist[,1]<-dfminist[,1]+1

xminist<-as.matrix(dfminist[,2:785])

xminist<-xminist/255

xarray<-array(0,dim=c(10000,1,28,28))

for(i in 1:10000){

xarray[i,1,,]<-matrix(xminist[i,],nrow=28,byrow=T)}

2.torch dataset数据索引:

Dataset 有点像传统的 data.frame,但它有一些特殊功能,可以更轻松地进行深度学习。 与其将其视为静态电子表格,不如将其视为一个函数,它将以一口大小的块或批次将数据输入我们的网络。

我们使用 dataset 函数创建一个 Dataset 对象。 它本质上是我们可以从数据集访问的属性和方法列表。

minist_dataset<-dataset(

initialize=function(xarray,label){

self$x<-torch_tensor(xarray,dtype=torch_float())

self$y<-torch_tensor(label,dtype=torch_long())},

.getitem=function(index){

list(x=self$x[index,,,],y=self$y[index])},

.length=function(){length(self$y)})

3.生成训练集和测试集的dataset数据索引

ministdsta<-minist_dataset(xarray2,label=dfminist2[,1])

ministdste<-minist_dataset(xarray,label=dfminist[,1])

4.dataloader,数据加载器

我们有我们的训练和验证数据集。 我们需要对数据做的最后一件事是创建数据加载器对象。 数据加载器通过网络提供批量数据。 我们对训练集进行洗牌,以便在每个时期(学习阶段的迭代)重新洗牌数据。

ministdlta<-dataloader(ministdsta,batch_size=32,shuffle=T)

ministdlte<-dataloader(ministdste,batch_size=32,shuffle=T)

5.创建神经网络结构

net <- nn_module(

  initialize = function() {

    self$conv1 <- nn_conv2d(1,32, kernel_size=3)#卷积层

    self$conv2 <- nn_conv2d(32,64,kernel_size=3)

    self$conv3 <- nn_conv2d(64,128, kernel_size=3)

    self$conv4 <- nn_conv2d(128,256,kernel_size=3)

    self$fc1 <- nn_linear(4*4*256, 128)#线性层

    self$fc2 <- nn_linear(128,10)

    self$dropout1<-nn_dropout(0.25)#随机丢失,用来防止过拟合

    self$dropout2<-nn_dropout(0.25)

    self$dropout3<-nn_dropout(0.25)

  },

  forward = function(x) {

    x %>%

      self$conv1() %>%

      nnf_relu() %>%

      self$conv2() %>%

      nnf_relu() %>%

      nnf_avg_pool2d(2) %>%

      self$dropout1()%>%

      self$conv3() %>%

      nnf_relu() %>%

      self$conv4() %>%

      nnf_relu() %>%

      nnf_avg_pool2d(2) %>%

      self$dropout2()%>%

      torch_flatten(start_dim = 2) %>%

      self$fc1() %>%

      nnf_selu() %>%

      self$dropout3()%>%

      self$fc2()

})

model<-net()

该网络进行了连续2步卷积,1次池化;接着又是连续2步卷积,1次池化,最后将图片特征提取成256*4*4的结果,输入全连接层,进行分类。

6.模型训练

torch神经网络的训练主要有以下4步:

                1. 将梯度设置为零。

                2. 定义和计算成本和优化器

                3. 在网络上传播错误。

                4. 应用梯度优化。

optimizer <- optim_adam(model$parameters)#优化器

n_epochs <-10#迭代步数

model$train()# 设置成训练模型

for(epoch in 1:n_epochs) {

  train_losses <- c()

  coro::loop(for(b in ministdlta) {

    optimizer$zero_grad()

    output <- model(b[[1]])

    loss <- nnf_cross_entropy(output, b[[2]])

    loss$backward()

    optimizer$step()

    train_losses <- c(train_losses, loss$item())

  })

cat(sprintf("Epoch %d: train loss: %3f\n",

epoch, mean(train_losses)))

}

我只训练了17步:

R语言 在mnist数据集使用torch建立卷积神经网络_第1张图片

7.模型评价:

训练集的表现:

# Evaluate

model$eval()#设置预测模型

pre<-c()

true<-c()

coro::loop(for(b in ministdlta) {#测试集的情况

    output <- model(b[[1]])

    pred <- torch_max(output, dim = 2)[[2]]

    pre<-c(pre,as.numeric(pred))

    true<-c(true,as.numeric(b[[2]]))

      })

ma<-table(true,pre)

ma

sum(diag(ma))/sum(ma)

R语言 在mnist数据集使用torch建立卷积神经网络_第2张图片

 测试集表现:

# Evaluate

model$eval()#设置预测模型

pre<-c()

true<-c()

coro::loop(for(b in ministdlte) {#训练集的情况

    output <- model(b[[1]])

    pred <- torch_max(output, dim = 2)[[2]]

    pre<-c(pre,as.numeric(pred))

    true<-c(true,as.numeric(b[[2]]))

      })

ma<-table(true,pre)

ma

sum(diag(ma))/sum(ma)

R语言 在mnist数据集使用torch建立卷积神经网络_第3张图片

8.结论,可以看出,通过使用卷积神经网络,可以将mnist数据集的预测集,分类正确率提高到99.43%,而传统的方法,却很难达到这样的水平。

   

你可能感兴趣的:(神经网络,cnn,r语言,卷积神经网络,深度学习)