Skip to main content
 Web开发网 » 站长学院 » 浏览器插件

涛哥系列文章(26):利用mxnet进行深度学习

2021年11月04日5680百度已收录

多年来,深度学习一直是研究的活跃领域,图像和语言理解等方面取得了突破。在本文中,我们介绍MXNetR,这是一个R包,可带来快速的GPU计算和最新的深度学习。MXNet允许您灵活地配置由快速CPU和GPU后端支持的最新深度学习模型。

这篇文章将涵盖以下主题:

在五分钟内训练您的第一个神经网络使用MXNet进行手写数字分类比赛使用最新的深度学习模型对现实世界图像进行分类。在五分钟内训练您的第一个神经网络分类任务

让我们使用一个演示数据来演示mxnet的基本语法和参数。 首先,我们加载数据:

require(mlbench)## Loading required package: mlbenchrequire(mxnet)## Loading required package: mxnet## Loading required package: methodsdata(Sonar, package="mlbench") Sonar[,61] = as.numeric(Sonar[,61])-1train.ind = c(1:50, 100:150)train.x = data.matrix(Sonar[train.ind, 1:60])train.y = Sonar[train.ind, 61]test.x = data.matrix(Sonar[-train.ind, 1:60])test.y = Sonar[-train.ind, 61]接下来,我们将使用多层感知器作为分类器。 在mxnet中,我们提供了一个名为mx.mlp的函数,以便用户可以构建通用的多层神经网络来进行分类或回归。

我们必须将几个参数提供给mx.mlp:

训练数据和标签。每个隐藏层中的隐藏节点数。输出层中的节点数。激活类型。输出损失函数的类型。要训练的设备(GPU或CPU)。mx.model.FeedForward.create的其他参数。以下代码段显示了使用mx.mlp的可能方法:

mx.set.seed(0)model <- mx.mlp(train.x, train.y,hidden_node=10, out_node=2,out_activation="softmax",                num.round=20, array.batch.size=15,learning.rate=0.07, momentum=0.9,eval.metric=mx.metric.accuracy)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第1张

请注意,mx.set.seed是控制mxnet中随机过程的正确函数。

原因是大多数MXNet随机数生成器可以在不同的设备(例如GPU)上运行。

我们需要在GPU上使用大规模并行PRNG来获得快速的随机数生成。 播种这些PRNG可能也非常昂贵。

因此,我们引入了mx.set.seed来控制MXNet中的随机数。

您可以从训练过程中看到准确性。 进行预测和评估也很容易。

preds = predict(model, test.x)## Auto detect layout of input matrix, use rowmajor..pred.label = max.col(t(preds))-1table(pred.label, test.y)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第2张

请注意,对于多类别预测,mxnet输出n类 x n样本,并且每一行对应于该类别的概率。

具有结构配置的回归任务

现在让我们学习一些新知识。 我们使用以下代码加载和处理数据:

data(BostonHousing, package="mlbench")train.ind = seq(1, 506, 3)train.x = data.matrix(BostonHousing[train.ind, -14])train.y = BostonHousing[train.ind, 14]test.x = data.matrix(BostonHousing[-train.ind, -14])test.y = BostonHousing[-train.ind, 14]尽管我们可以通过更改out_activation再次使用mx.mlp进行回归,但是这次我们将介绍一种灵活的方法来在mxnet中配置神经网络。 该配置由mxnet中的“ Symbol”系统完成,该系统负责节点之间的链接,激活,丢失率等。要配置多层神经网络,我们可以通过以下方式进行:

# Define the input datadata <- mx.symbol.Variable("data")# A fully connected hidden layer# data: input source# num_hidden: number of neurons in this layerfc1 <- mx.symbol.FullyConnected(data, num_hidden=1)# Use linear regression for the output layerlro <- mx.symbol.LinearRegressionOutput(fc1)对于回归任务重要的是最后一个函数。 它使新网络能够针对平方损耗进行优化。 现在,我们可以训练这个简单的数据集。在此配置中,我们删除了隐藏层,因此输入层直接连接到输出层。 有关mxnet中符号操作的更多信息,请查看我们关于此主题的教程。

接下来,我们可以使用mx.model.FeedForward.create使用此结构和其他参数进行预测:

mx.set.seed(0)model <- mx.model.FeedForward.create(lro, X=train.x, y=train.y, ctx=mx.cpu(), num.round=50, array.batch.size=20, learning.rate=2e-6, momentum=0.9, eval.metric=mx.metric.rmse)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第3张

进行预测也很容易。

preds = predict(model, test.x)## Auto detect layout of input matrix, use rowmajor..sqrt(mean((preds-test.y)^2))## [1] 7.800502在这里,我们还更改了eval.metric以进行回归。 当前,我们有四个预定义的度量标准“accuracy”,“ rmse”,“ mae”和“ rmsle”。 有人可能想知道如何自定义评估指标。 mxnet为用户提供了定义自己的兴趣度量的接口:

demo.metric.mae <- mx.metric.custom("mae", function(label, pred) { res <- mean(abs(label-pred)) return(res)})这是平均绝对误差的示例。 我们可以简单地将其插入训练功能中:

mx.set.seed(0)model <- mx.model.FeedForward.create(lro, X=train.x, y=train.y, ctx=mx.cpu(), num.round=50, array.batch.size=20, learning.rate=2e-6, momentum=0.9, eval.metric=demo.metric.mae)手写数字分类比赛MNIST是Yann LeCun创建的手写数字图像数据集。每个数字由28×28的图像表示。它已成为在简单图像输入上测试分类器的标准数据集。神经网络无疑是图像分类的强大模型。使用此数据集在Kaggle上进行了长期的托管竞赛。

我们将介绍mxnet的基本用法以应对这一挑战。

数据输入

首先,让我们从 /文件夹下。

然后,我们可以在R中读取它们并将其转换为矩阵。

require(mxnet)## Loading required package: mxnet## Loading required package: methodstrain <- read.csv('data/train.csv', header=TRUE)test <- read.csv('data/test.csv', header=TRUE)train <- data.matrix(train)test <- data.matrix(test)train.x <- train[,-1]train.y <- train[,1]在这里,每张图像在训练/测试中都表示为一行。 每个图像的灰度范围在[0,255]范围内,我们可以将其线性变换为[0,1]

train.x <- t(train.x/255)test <- t(test/255)我们还将输入矩阵转置为n像素 x n样本,这是mxnet接受的列主要格式(以及R的约定)。

在标签部分,我们看到每个数字的数量是偶数:

table(train.y)网络配置

现在我们有了数据。 下一步是配置我们的网络结构。

data <- mx.symbol.Variable("data")fc1 <- mx.symbol.FullyConnected(data, name="fc1", num_hidden=128)act1 <- mx.symbol.Activation(fc1, name="relu1", act_type="relu")fc2 <- mx.symbol.FullyConnected(act1, name="fc2", num_hidden=64)act2 <- mx.symbol.Activation(fc2, name="relu2", act_type="relu")fc3 <- mx.symbol.FullyConnected(act2, name="fc3", num_hidden=10)softmax <- mx.symbol.SoftmaxOutput(fc3, name="sm")1.在mxnet中,我们使用其自己的数据类型symbol来配置网络。 data <-mx.symbol.Variable(“ data”)使用数据表示输入数据,即输入层。

2.然后,我们通过fc1 <-mx.symbol.FullyConnected(data,name =“ fc1”,num_hidden = 128)设置第一个隐藏层。 该层具有data作为输入,其名称和隐藏神经元的数量。

3.通过act1 <-mx.symbol.Activation(fc1,name =“ relu1”,act_type =“ relu”)设置激活函数。 激活函数从第一隐藏层fc1获取输出。

4.第二个隐藏层将act1的结果作为输入,其名称为“ fc2”,隐藏神经元数为64。

5.第二次激活与act1几乎相同,除了我们有不同的输入源和名称。

6.这里是输出层。 由于只有10位数字,因此我们将神经元数设置为10。

7.最后,我们将激活设置为softmax以获得概率预测。

训练

我们几乎准备好接受训练。 在开始计算之前,让我们确定我们应该使用哪种设备。

devices <- mx.cpu()在这里,我们将CPU分配给mxnet。 完成所有这些准备后,您可以运行以下命令来训练神经网络! 再次注意,mx.set.seed是控制mxnet中随机过程的正确函数。

mx.set.seed(0)model <- mx.model.FeedForward.create(softmax, X=train.x, y=train.y, ctx=devices, num.round=10, array.batch.size=100, learning.rate=0.07, momentum=0.9, eval.metric=mx.metric.accuracy, initializer=mx.init.uniform(0.07), epoch.end.callback=mx.callback.log.train.metric(100))涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第4张

预测与提交

为了做出预测,我们可以简单地写

preds <- predict(model, test)dim(preds)#10 28000它是一个具有10行和28000列的矩阵,其中包含输出层中所需的分类概率。 为了提取每一行的最大标签,我们可以在R中使用max.col:

pred.label <- max.col(t(preds)) - 1table(pred.label)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第5张

只需花费一些额外的精力来编写csv文件,我们就可以提交给竞赛!

submission <- data.frame(ImageId=1:ncol(test), Label=pred.label)write.csv(submission, file='submission.csv', row.names=FALSE, quote=FALSE)LeNet

接下来,我们将介绍一个新的网络结构:LeNet。Yann LeCun提议识别手写数字。现在,我们将演示如何在mxnet中构建和训练LeNet。

首先,我们构建网络:

# inputdata <- mx.symbol.Variable('data')# first convconv1 <- mx.symbol.Convolution(data=data, kernel=c(5,5), num_filter=20)tanh1 <- mx.symbol.Activation(data=conv1, act_type="tanh")pool1 <- mx.symbol.Pooling(data=tanh1, pool_type="max", kernel=c(2,2), stride=c(2,2))# second convconv2 <- mx.symbol.Convolution(data=pool1, kernel=c(5,5), num_filter=50)tanh2 <- mx.symbol.Activation(data=conv2, act_type="tanh")pool2 <- mx.symbol.Pooling(data=tanh2, pool_type="max", kernel=c(2,2), stride=c(2,2))# first fullcflatten <- mx.symbol.Flatten(data=pool2)fc1 <- mx.symbol.FullyConnected(data=flatten, num_hidden=500)tanh3 <- mx.symbol.Activation(data=fc1, act_type="tanh")# second fullcfc2 <- mx.symbol.FullyConnected(data=tanh3, num_hidden=10)# losslenet <- mx.symbol.SoftmaxOutput(data=fc2)然后让我们将矩阵重塑为数组:

train.array <- train.xdim(train.array) <- c(28, 28, 1, ncol(train.x))test.array <- testdim(test.array) <- c(28, 28, 1, ncol(test))接下来,我们将比较不同设备上的训练速度,因此首先定义设备:

n.gpu <- 1device.cpu <- mx.cpu()device.gpu <- lapply(0:(n.gpu-1), function(i) { mx.gpu(i)})如您所见,我们可以传递设备列表,要求mxnet在多个GPU上进行训练(您可以为cpu做类似的事情,

但是由于cpu的内部计算已经是多线程的,因此获得的收益要少于使用GPU的收益。

我们首先从CPU训练开始。 由于这样做会花费一些时间,因此我们仅将其运行一次迭代。

mx.set.seed(0)tic <- proc.time()model <- mx.model.FeedForward.create(lenet, X=train.array, y=train.y, ctx=device.cpu, num.round=1, array.batch.size=100, learning.rate=0.05, momentum=0.9, wd=0.00001, eval.metric=mx.metric.accuracy, epoch.end.callback=mx.callback.log.train.metric(100))print(proc.time() - tic)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第6张

在GPU上训练

mx.set.seed(0)tic <- proc.time()model <- mx.model.FeedForward.create(lenet, X=train.array, y=train.y, ctx=device.gpu, num.round=5, array.batch.size=100, learning.rate=0.05, momentum=0.9, wd=0.00001, eval.metric=mx.metric.accuracy, epoch.end.callback=mx.callback.log.train.metric(100))我的笔记本只有Intel集成显卡,不支持cuda运算。这方面就不演示了。反正大家都知道,,使用GPU,我们可以获得更快的训练速度!

最后,我们可以将结果再次提交给Kaggle,以查看排名的提高!

preds <- predict(model, test.array)pred.label <- max.col(t(preds)) - 1submission <- data.frame(ImageId=1:ncol(test), Label=pred.label)write.csv(submission, file='submission.csv', row.names=FALSE, quote=FALSE)使用预训练模型对真实世界图像进行分类在MNIST示例之后,您准备好进一步了吗? 深度学习最酷的事情之一

算法可以做的就是对现实世界的图像进行分类。

在此示例中,我们将展示如何使用预训练的Inception-BatchNorm网络来预测真实世界的图像。 网络架构在[1]中描述。

可以从此链接下载预训练的Inception-BatchNorm网络该模型提供了图像网络数据集上最新的预测精度。

加载包

首先,我们通过以下方式加载mxnet软件包,在此示例中,我们还需要imager包来加载和预处理R中的图像。

require(mxnet)require(imager)加载预训练模型

确保在当前文件夹中解压缩预训练的模型。 我们可以使用模型加载函数将模型加载到R中。

model = mx.model.load("Inception/Inception_BN", iteration=39)我们还需要加载均值图像,该图像用于使用mx.nd.load进行预处理。

mean.img = as.array(mx.nd.load("Inception/mean_224.nd")[["mean_img"]])加载并预处理图像

现在我们准备对真实图像进行分类。 在此示例中,我们仅使用来自imager的鹦鹉图像。但是您始终可以将其更改为其他图像。 首先,我们将在华盛顿州北部的Mt. Baker山的照片上对其进行测试。

加载并绘制图像:

im <- load.image("Pics/MtBaker.jpg")plot(im)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第7张

在将图像馈入深网之前,我们需要进行一些预处理,使图像适合deepnet的输入要求。 预处理包括裁剪和减去均值。

因为mxnet和R高度整合,所以我们可以在R函数中进行所有处理。

预处理函数:

preproc.image <- function(im, mean.image) { # crop the image shape <- dim(im) short.edge <- min(shape[1:2]) xx <- floor((shape[1] - short.edge) / 2) yy <- floor((shape[2] - short.edge) / 2) cropped <- crop.borders(im, xx, yy) # resize to 224 x 224, needed by input of the model. resized <- resize(cropped, 224, 224) # convert to array (x, y, channel) arr <- as.array(resized) * 255 dim(arr) <- c(224, 224, 3) # subtract the mean normed <- arr - mean.img # Reshape to format needed by mxnet (width, height, channel, num) dim(normed) <- c(224, 224, 3, 1) return(normed)}我们使用定义的预处理函数来获取标准化图像。

normed <- preproc.image(im, mean.img)分类图像现在我们准备对图像进行分类! 我们可以使用预测功能来获得类的概率。

prob <- predict(model, X=normed)dim(prob)#1000 1如您所见,概率是1000乘以1的数组,这给出了概率输入的1000个图像类。

我们可以提取前五类的索引。

max.idx <- order(prob[,1], decreasing = TRUE)[1:5]max.idx## [1] 981 971 980 673 975这些指数没有太大意义。 因此,让我们看看它真正代表什么。

我们可以从以下文件中读取类的名称。

synsets <- readLines("Inception/synset.txt")让我们打印相应的行:

print(paste0("Predicted Top-classes: ", synsets[max.idx]))Mt. Baker确实是个火山。 我们还可以看到第二个最可能的猜测“ alp”也是正确的。

让我们看看它在其他图像上是否仍然表现出色。 下图是在温哥华市中心拍摄的。

im <- load.image("Pics/Vancouver.jpg")plot(im)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第8张

normed <- preproc.image(im, mean.img)prob <- predict(model, X=normed)max.idx <- order(prob[,1], decreasing = TRUE)[1:5]print(paste0("Predicted Top-classes: ", synsets[max.idx]))涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第9张

这张照片确实是在湖边拍摄的。

在铁力士山上拍摄的这张照片怎么样:

im <- load.image("Pics/Switzerland.jpg")plot(im)涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第10张

normed <- preproc.image(im, mean.img)prob <- predict(model, X=normed)max.idx <- order(prob[,1], decreasing = TRUE)[1:5]print(paste0("Predicted Top-classes: ", synsets[max.idx]))涛哥系列文章(26):利用mxnet进行深度学习  Mxnet教程 第11张

这次,主要元素很小,无法从“嘈杂”的背景中脱颖而出。 这次的结果并不完美。

现在,为什么不拍张照片然后问mxnet告诉您其中包含什么? 玩得开心!

尝试并贡献

您可以在github上找到MXNet。 除R外,MXNet还支持python和Julia,并允许在不同语言绑定之间插入模型和分析结果。MXNet由活跃的用户社区构建。

评论列表暂无评论
发表评论
微信