看到Rstudio的aiblog发出的一个文章,说R语言的torch来了,这个不像是之前的tensorflow的r版本,这个中间没有使用任何胶水语言,将R和c++直接连接。
翻译的🔗 https://blogs.rstudio.com/ai/posts/2020-09-29-introducing-torch-for-r/
下面是翻译的内容(没有获得授权):
今天,我们很高兴推出一个R包,torch,这个可以使用原生的R来实现pytorch功能,但是不需要安装python,torch包是构建在c++提供的libtorch库,可以使用向量计算和自动查分实现神经网络。
在rstudio::conf上,Daniel介绍了一系列工作去丰富tensorflow的生态。在QA环节,被问到是否会支持PyTorch?他犹豫了,虽然已经写了,但是写的还不够好。因为他希望这个pytorch可以实现下面的功能,并且减少对reticulate的依赖。
之前,使用R版本的tensorlofw都是使用reticulate包,python做个桥梁。而在这个torch里面,我们直接使用由c++写的libtorch包做神经网络的向量计算和自动差分。而神经网络里面的层、激活函数和优化器都直接使用的R编写。这样做有两个好处:第一个是精简软件的栈的堆叠,减少安装问题和故障排除问题,第二点是在不需要使用python后,torch的用户不再需要改变系统环境去安装python。在许多公司,不允许员工在电脑上修改他们的软件环境。
那么为啥Daniel被问到的时候犹豫😔了?因为他不知道在某些操作系统上针对libtorch编译是否会带来严重的困难(可以做到,但是相当困难),,,,,,
不想翻译了,我不想捧吹Daniel了🤪🤪。大神,我respect。下面直接进入正文吧!!!
安装:
两个方法:
# way 1install.packages("torch")# way 2devtools::install_github("mlverse/torch")
安装的时候,会自动检测你是否有cuda的环境,如果有就给你安装gpu版本的。没有就是cpu版本的。(我的window10有cuda哇,不知道怎么也安装的是cpu版本的)。
最好还要安装torchvision
install.packages("torchvision") # 实际上这个我没安装成功。#目前的安装方法是:remotes::install_github("mlverse/torchvision")
数据加载和预处理:
library(torch)library(torchvision)
数据集:
数据使用的是一个类似于mnist的数据集(🔗 https://github.com/rois-codh/kmnist)下面这个图是32个字,每个字的大小是28x28。
下面这块代码将要下载数据(下载的很慢,除非可以科学的上网),并且对数据拆分为训练数据和测试数据。并且对数据作出转换。
train_ds ".", download = TRUE, train = TRUE, transform = transform_to_tensor)test_ds ".", download = TRUE, train = FALSE, transform = transform_to_tensor)
上面的transform_to_tensor对数据有两个转换:首先是将数据标准化,转换到0-1区间内,然后再增加一个纬度(这个纬度不是batch,而是一个纬度,因为这个图片目前只有width和height,还没有通道,在width和height前面加个纬度也就是代表channel的意思,我也是小白😂)。
实际上,要检查上面的元素是非常简单的:(我这里rstudio总是崩溃)
train_ds[1]
上面会出现train_ds的第一个元素,是一个R的列表,包含两个向量分别对应的是输入和target(人话就是输入是x,target是y)。
也可以检察输入的向量的shape或者size。
train_ds[1][[1]]$size()
注意到我们已经有了数据,接下来就是将数据喂给model。是分批喂给模型还是全部都喂给模型。这个是dataloader函数的任务了。
DATA LOADER
要给训练和测试制作他们各自的data loader,代码如下:
train_dl test_dl
为了看这个dataloader做的行不行,简单的两行代码就可以看出来了:
train_iter train_iter$.next()
上面这个步骤是非常有必要的,尤其是当处理未知数据集的时候,
接下来展示第一批(32个图片)。
par(mfrow = c(4,8), mar = rep(0, 4))images images %>% purrr::array_tree(1) %>% purrr::map(as.raster) %>% purrr::iwalk(~{plot(.x)})
Network部分
如果用过keras或者pytorch,下面的写法你肯定不陌生,在这里使用的是nn_module模块。这个是一个R6的类,用来保存network。
net "KMNIST-CNN", initialize = function() { # in_channels, out_channels, kernel_size, stride = 1, padding = 0 self$conv1 self$conv2 self$dropout1 self$dropout2 self$fc1 self$fc2 }, forward = function(x) { x %>% self$conv1() %>% nnf_relu() %>% self$conv2() %>% nnf_relu() %>% nnf_max_pool2d(2) %>% self$dropout1() %>% torch_flatten(start_dim = 2) %>% self$fc1() %>% nnf_relu() %>% self$dropout2() %>% self$fc2() })model model$to(device = "cuda")
上面的每一层的具体不再解释了,具体的看帮助文档吧。
Training部分
设置优化器去调整网络的参数:
optimizer
设置每一batch的损失函数:
然后放到for♻️里面:
for (epoch in 1:5) { l for (b in enumerate(train_dl)) { # make sure each batch's gradient updates are calculated from a fresh start optimizer$zero_grad() # get model predictions output # calculate loss loss # calculate gradient loss$backward() # apply weight updates optimizer$step() # track losses l } cat(sprintf("Loss at epoch %d: %3f\n", epoch, mean(l)))}
会出现下面的结果:
Evaluation部分:
要将模型设置为eval模式告诉模型不要计算梯度和反向传播了。
model$eval()
接下来在test数据上计算误差:
test_losses total correct for (b in enumerate(test_dl)) { output labels loss test_losses # torch_max returns a list, with position 1 containing the values # and position 2 containing the respective indices predicted total # add number of correct classifications in this batch to the aggregate correct }mean(test_losses)test_accuracy test_accuracy
想要学到更多,可以看下面的链接:
https://mlverse.github.io/torch/
https://mlverse.github.io/tohttps://mlverse.github.io/torch/articles/getting-started/tensors.html
https://mlverse.github.io/torch/articles/getting-started/tensors-and-autograd.html
https://mlverse.github.io/torch/articles/tensor-creation.html
如果想贡献代码,可以和作者联系(看github)
写的比较垃圾,大神们还是看原网站吧。