TensorFlow数据集API的R接口
概述
TensorFlow数据集API提供了为TensorFlow模型创建可伸缩输入管道的各种工具,包括:
从各种格式读取数据,包括CSV文件和TFRecords文件(TensorFlow训练数据的标准二进制格式)。
以各种方式转换数据集,包括针对数据集映射任意函数。
在多个时代中洗牌、批处理和重复数据集。
数据流接口,用于读取任意大的数据集。
读取和转换数据是TensorFlow图操作,因此在c++中执行,并与模型训练并行。
TensorFlow数据集的R接口提供了对Dataset API的访问,包括方便与kerasR包。
安装
使用tfdatasets你需要同时安装R包和TensorFlow本身。
首先,从GitHub安装tfdatasets R包,如下所示:
devtools::install_github(“英格兰vs伊朗让球rstudio / tfdatasets”)
然后,使用install_tensorflow ()
函数来安装TensorFlow:
图书馆(tfdtasets)install_tensorflow()
创建数据集
方法之一可创建数据集创建数据集功能。数据集可以从分隔的文本文件创建,TFRecords文件,以及从内存中的数据。
文本文件
例如,要从文本文件创建数据集,首先创建如何从文件解码记录的规范,然后调用text_line_dataset ()
与要读取的文件和规范:
图书馆(tfdatasets)#创建解析示例文件记录的规范iris_spec < -csv_record_spec(“iris.csv”)#读取数据集数据集< -text_line_dataset(“iris.csv”,record_spec =iris_spec)#浏览一下数据集str(数据集)
在上面的例子中,csv_record_spec ()
函数传递一个示例文件,该文件用于自动检测列名和类型(通过读取文件的前1000行完成)。方法还可以提供显式列名和/或数据类型的名字
而且类型
参数(注意在本例中我们没有传递一个示例文件):
#显式提供列名和类型iris_spec < -csv_record_spec(名称=c(“SepalLength”,“SepalWidth”,“PetalLength”,“PetalWidth”,“物种”),类型=c(“替身”,“替身”,“替身”,“替身”,“整数”),跳过=1)#读取数据集数据集< -text_line_dataset(“iris.csv”,record_spec =iris_spec)
注意,我们还指定了Skip = 1
表示应该跳过CSV中包含列名的第一行。
卡塔尔世界杯欧洲预选赛赛程表支持的列类型为整数、双精度和字符。你也可以提供类型
在更紧凑的形式中使用单字母缩写(例如;类型= "dddi"
)。例如:
mtcars_spec < -csv_record_spec(“mtcars.csv”,类型=“dididddiiii”)
并行解码
将文本行解码为记录在计算上是非常昂贵的。方法可以并行化这些计算parallel_records
参数。例如:
数据集< -text_line_dataset(“iris.csv”,record_spec =iris_spec,parallel_records =4)
还可以通过请求对记录缓冲区进行级配来并行化从存储器读取数据的过程。你用这个dataset_prefetch ()
函数。例如:
数据集< -text_line_dataset(“iris.csv”,record_spec =iris_spec,parallel_records =4)% > %dataset_batch(128)% > %dataset_prefetch(1)
这段代码将导致在后台线程上预取单批数据(即与训练操作并行)。
如果您有多个输入文件,您还可以跨多台机器(分片)和/或在每台机器的多个线程上并行读取这些文件(通过交错并行读取)。参见有关读取多个文件下面是更多的细节。
TFRecords文件
您可以从TFRecords文件使用tfrecord_dataset ()
函数。
在许多情况下,您希望将数据集中的记录映射到一组命名列中。可以使用dataset_map ()
函数与tf parse_single_example美元()
函数。例如:
创建一个数据集,从两个文件中读取所有的示例,并进行提取#图片和标签功能。文件名< -c(“/ var /数据/ file1.tfrecord”,“/ var /数据/ file2.tfrecord”)数据集< -tfrecord_dataset(文件名)% > %dataset_map(函数(example_proto) {< -特点列表(形象=特遣部队$FixedLenFeature(形状(),特遣部队$字符串),标签=特遣部队$FixedLenFeature(形状(),特遣部队$int32))特遣部队$parse_single_example(example_proto特性)})
方法可以并行读取TFRecord文件num_parallel_reads
选项,例如:
文件名< -c(“/ var /数据/ file1.tfrecord”,“/ var /数据/ file2.tfrecord”)数据集< -tfrecord_dataset(文件名,num_parallel_reads =4)
SQLite数据库
方法可以从SQLite数据库读取数据集sqlite_dataset ()
函数。使用sqlite_dataset ()
您提供数据库的文件名、要执行的SQL查询和sql_record_spec ()
它描述了查询中列的名称和TensorFlow类型。例如:
图书馆(tfdatasets)record_spec < -sql_record_spec(名称=c(“disp”,“诅咒”,“与”,“装备”,“英里”,“qsec”,“惠普”,“我”,“wt”,“碳水化合物”,“共青团”),类型=c(特遣部队$float64,特遣部队$int32,特遣部队$float64,特遣部队$int32,特遣部队$float64,特遣部队$float64,特遣部队$float64,特遣部队$int32,特遣部队$int32,特遣部队$int32,特遣部队$int32))数据集< -sqlite_dataset(“数据/ mtcars.sqlite3”,select * from mtcars,record_spec)数据集
< MapDataset形状:{disp:(),咒骂:(),vs:(),齿轮:(),英里/加仑:(),qsec:(),惠普:(),问:()、wt:(),碳水化合物:(),共青团:()},类型:{disp: tf。Float64, drat: tf.int32, vs: tf.int32。float64,gear: tf.int32, mpg: tf.float64, qsec: tf.float64, hp: tf.float64, am: tf.int32, wt: tf.int32, carb: tf.int32, cyl: tf.int32}>
注意,对于浮点数据必须使用tf float64美元
(阅读tf float32美元
不支持SQLi卡塔尔世界杯欧洲预选赛赛程表te数据库)。
转换
映射
方法可以将任意转换函数映射到数据集记录上dataset_map ()
函数。例如,要将“物种”列转换为一个单热编码向量,你可以这样做:
数据集< -数据集% > %dataset_map(函数(记录){记录$物种< -特遣部队$one_hot(记录$物种,3 l)记录})
注意,当dataset_map ()
是用R函数定义的,在这个函数上有一些特殊的约束,允许它执行不在R范围内而是在TensorFlow图中。
方法创建的数据集csv_dataset ()
函数,传递的记录将被命名为张量列表(数据集的每列一个)。返回值应该是另一组从TensorFlow函数创建的张量。tf one_hot美元
如上所示)。该函数将被转换为TensorFlow图操作,在本机代码中执行转换。
并行映射
方法可以在多个线程上执行这些转换num_parallel_calls
参数。例如:
数据集< -数据集% > %dataset_map(num_parallel_calls =4,函数(记录){记录$物种< -特遣部队$one_hot(记录$物种,3 l)记录})
类并行处理时,可以控制缓冲的已处理元素的最大数量dataset_prefetch ()
转换。例如:
数据集< -数据集% > %dataset_map(num_parallel_calls =4,函数(记录){记录$物种< -特遣部队$one_hot(记录$物种,3 l)记录})% > %datset_prefetch(1)
如果要对训练用的数据进行批处理,则可以使用dataset_map_and_batch ()
函数(将映射和批处理操作融合在一起)。例如:
数据集< -数据集% > %dataset_map_and_batch(batch_size =128,函数(记录){记录$物种< -特遣部队$one_hot(记录$物种,3 l)记录})% > %datset_prefetch(1)
过滤
方法可以筛选数据集的元素dataset_filter ()
函数,它取a谓词
函数,返回应包含记录的布尔张量。例如:
数据集< -csv_dataset(“mtcars.csv”)% > %dataset_filter(函数(记录){记录$英里/加仑> =20.})数据集< -csv_dataset(“mtcars.csv”)% > %dataset_filter(函数(记录){记录$英里/加仑> =20.&记录$共青团> =6 l})
注意,谓词内部使用的函数必须是张量操作(例如:tf not_equal美元
,tf美元少
等)。为关系运算符(例如<、>、<=等)和逻辑运算符(例如!、&、|等)提供了R通用方法,因此您可以对大多数常见的比较使用简写语法(如上所述)。
特点及回应
一个常见的转换是使用一个面向列的数据集(例如由csv_dataset ()
或tfrecord_dataset ()
),并将其转换为包含特征(“x”)和响应(“y”)的两个元素列表。您可以使用dataset_prepare ()
函数来进行这种类型的转换。例如:
mtcars_dataset < -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_prepare(x =c(disp mpg),y =摘要iris_dataset < -text_line_dataset(“iris.csv”,record_spec =iris_spec)% > %dataset_prepare(x =-物种,y =物种)
的dataset_prepare ()
函数也接受标准的R公式语法来定义特征和响应:
mtcars_dataset < -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_prepare摘要~英里/加仑+disp)
如果要对训练用的数据进行批处理,则需要添加一个batch_size
参数融合在一起dataset_prepare ()
而且dataset_batch ()
步骤(这通常会导致更快的训练)。例如:
mtcars_dataset < -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_prepare摘要~英里/加仑+disp,batch_size =16)
洗牌和批处理
有几个函数控制如何从数据集中提取批。例如,以下指定数据将从1000条记录的打乱窗口中批量提取128条,并且数据集将重复10个epoch:
数据集< -数据集% > %dataset_shuffle(1000)% > %dataset_repeat(10)% > %dataset_batch(128)% > %
方法将打乱和重复操作融合到单个步骤中,可以优化性能dataset_shuffle_and_repeat ()
函数。例如:
数据集< -数据集% > %dataset_shuffle_and_repeat(buffer_size =1000,数=10)% > %dataset_batch(128)
预取
之前我们提到过dataset_prefetch ()
函数,该函数使您能够确保并行预取给定数量的记录(或批记录),以便在处理下一批记录时可以使用它们。例如:
数据集< -数据集% > %dataset_map_and_batch(batch_size =128,函数(记录){记录$物种< -特遣部队$one_hot(记录$物种,3 l)记录})% > %dataset_prefetch(1)
如果你使用GPU进行训练,你也可以使用dataset_prefetch_to_device ()
函数,指定并行预取操作阶段的数据直接进入GPU内存。例如:
数据集< -数据集% > %dataset_map_and_batch(batch_size =128,函数(记录){记录$物种< -特遣部队$one_hot(记录$物种,3 l)记录})% > %dataset_prefetch_to_device(“/ gpu: 0”)
在这种情况下,预取的缓冲区大小是自动确定的(您可以使用buffer_size
参数)。
完整的示例
下面是一起使用各种数据集转换函数的完整示例。我们会读mtcars
数据集,过滤一些阈值,映射到x
而且y
组件用于建模,并指定所需的洗牌和批处理迭代行为:
数据集< -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_filter(函数(记录){记录$英里/加仑> =20.&记录$共青团> =6 l})% > %dataset_shuffle_and_repeat(buffer_size =1000,数=10)% > %dataset_prepare摘要~英里/加仑+disp,batch_size =128)% > %dataset_prefetch(1)
阅读数据集
从TensorFlow数据集读取数据的方法取决于您使用的API来构建模型。如果您正在使用keras,那么TensorFlow数据集可以像内存中的R矩阵和数组一样使用。如果您正在使用较低级别的tensorflow核心API,那么您将使用显式的数据集迭代函数。
下面的部分提供了每个受支持api的更多详细信息和示例。卡塔尔世界杯欧洲预选赛赛程表
keras包
重要提示:使用TensorFlow数据集与Keras要求您正在运行最新版本的Keras (v2.2)和TensorFlow (v1.9)。你可以确保你拥有核心Keras和TensorFlow库的最新版本:
图书馆(keras)install_keras()
训练Keras模型的方法通常是将内存中的数组直接传递给适合
函数。例如:
模型% > %适合(x_train y_train,时代=30.,batch_size =128)
然而,这需要在调用fit之前将数据加载到R数据帧或矩阵中。您可以使用train_on_batch ()
函数一次处理一批数据,但是输入数据的读取和处理仍然是在本机代码之外串行完成的。
或者,Keras允许您直接将数据集作为x
参数符合()
而且evaluate ()
.下面是一个完整的例子,使用数据集从包含MNIST数字的TFRecord文件中读取:
图书馆(keras)图书馆(tfdatasets)batch_size =128steps_per_epoch =500读取并预处理数据集mnist_dataset < -函数(文件名){数据集< -tfrecord_dataset(文件名)% > %dataset_map(函数(example_proto) {#解析记录< -特点特遣部队$parse_single_example(example_proto,特点=列表(image_raw =特遣部队$FixedLenFeature(形状(),特遣部队$字符串),标签=特遣部队$FixedLenFeature(形状(),特遣部队$int64)))#预处理图像图片< -特遣部队$decode_raw(功能$image_raw,特遣部队$uint8)图片< -特遣部队$投(图片,特遣部队$float32)/255#转换标签为one-hot标签< -特遣部队$one_hot(特遣部队$投(功能$标签,特遣部队$int32), 10 l)#返回列表(图片,标签)})% > %dataset_repeat()% > %dataset_shuffle(1000)% > %dataset_batch(batch_sizedrop_remainder =真正的)% > %dataset_prefetch(1)}模型< -keras_model_sequential()% > %layer_dense(单位=256,激活=“relu”,input_shape =c(784))% > %layer_dropout(率=0.4)% > %layer_dense(单位=128,激活=“relu”)% > %layer_dropout(率=0.3)% > %layer_dense(单位=10,激活=“softmax”)模型% > %编译(损失=“categorical_crossentropy”,优化器=optimizer_rmsprop(),指标=c(“准确性”))< -历史模型% > %适合(mnist_dataset(“mnist / train.tfrecords”),steps_per_epoch =steps_per_epoch,时代=20.,validation_data =mnist_dataset(“mnist / validation.tfrecords”),validation_steps =steps_per_epoch)分数< -模型% > %评估(mnist_dataset(“mnist / test.tfrecords”),步骤=steps_per_epoch)打印(分数)
注意,所有的数据预处理(例如响应变量的单热编码)都是在dataset_map ()
操作。
还要注意,我们通过了drop_remainder = TRUE
到dataset_batch ()
函数(这是为了确保所有批次的大小相等,这是对Keras张量输入的要求)。
tensorflow包
通过使用产生下一批数据的张量,可以从数据集中读取数据批。你可以从数据集中通过make_iterator_one_shot ()
而且iterator_get_next ()
功能。例如:
数据集< -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_prepare摘要~英里/加仑+disp)% > %dataset_shuffle(20.)% > %dataset_batch(5)iter < -make_iterator_one_shot(数据集)next_batch < -iterator_get_next(iter)next_batch
$x张量("IteratorGetNext_13:0", shape=(?,2), dtype=float32) $y Tensor("IteratorGetNext_13:1", shape=(?,), dtype=int32)
如你所见next_batch
不是数据本身,而是一个张量,当它被求值时将产生下一批数据:
$ x [1] [2] [1] 160 [2] 21.0 160 21.0 108 22.8 [3] [4] [5] 18.7 360 258 21.4 y [1] 6 6 4 6 8
如果您正在使用这些函数迭代数据集,您将需要确定在什么点停止迭代。方法之一是使用dataset_repeat ()
函数创建一个生成无限值的数据集。例如:
图书馆(tfdatasets)捐< -特遣部队$会话()mtcars_spec < -csv_record_spec(“mtcars.csv”)数据集< -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_shuffle(5000)% > %dataset_repeat()#无限重复dataset_prepare(x =c(disp mpg),y =摘要% > %dataset_batch(128)% > %iter < -make_iterator_one_shot(数据集)next_batch < -iterator_get_next(iter)步骤< -200为(我在1:步骤){#使用next_batch进行训练等。#(注意你需要实际使用next_batch,例如通过传递它给一个#函数消耗一个张量或通过显式运行它#提前到下一批)}
在这种情况下步骤
变量用于确定何时停止绘制新的训练数据批次(我们可以同样包含代码来检测学习平台期或任何其他确定何时停止训练的自定义方法)。
另一种方法是检测何时从数据集中生成了所有批次。当数据集迭代器到达结束时,将发生超出范围的运行时错误。当错误发生时,可以使用out_of_range_handler
随着错误
参数tryCatch ()
.例如:
图书馆(tfdatasets)捐< -特遣部队$会话()mtcars_spec < -csv_record_spec(“mtcars.csv”)数据集< -text_line_dataset(“mtcars.csv”,record_spec =mtcars_spec)% > %dataset_prepare(x =c(disp mpg),y =摘要% > %dataset_batch(128)% > %dataset_repeat(10)iter < -make_iterator_one_shot(数据集)next_batch < -iterator_get_next(iter)tryCatch({而(真正的) {批< -捐$运行(next_batch)str(批处理)}},错误=out_of_range_handler)
方法可以更优雅地编写此迭代until_out_of_range ()
函数,该函数自动处理错误并提供而(真)
围绕一个短语:
until_out_of_range({批< -捐$运行(next_batch)str(批处理)})
当在紧急执行下运行时,您组织代码的方式有点不同(因为您不需要显式地这样做run ()
张量):
iter < -make_iterator_one_shot(数据集)until_out_of_range({批< -iterator_get_next(iter)str(批处理)})
读取多个文件
如果你有多个输入文件,你可以跨机器并行处理它们(分片)和/或在每台机器的多个线程上并行处理它们(并行读取和交错)。的read_file ()
函数提供了并行文件读取的高级接口。
的read_file ()
函数接受一组文件和一个read函数,以及编排并行读取的各种选项。方法读取目录中的所有CSV文件text_line_dataset ()
功能:
数据集< -read_file(“数据/ * . csv”text_line_dataset,record_spec =mtcars_spec,parallel_files =4,parallel_interleave =16)% > %dataset_prefetch(5000)% > %dataset_shuffle_and_repeat(buffer_size =1000,数=3.)% > %dataset_batch(128)
的parallel_files
参数请求并行处理4个文件parallel_interleave
参数请求将每个文件的16个连续记录块交错在结果数据集中。
请注意,因为我们正在并行地处理文件不通过parallel_records
参数text_line_dataset ()
,因为我们已经在文件级别进行了并行。
多台机器
如果您在多台机器上进行培训,并且培训主管将一个碎片索引传递给您的培训脚本,您还可以通过对文件列表进行分片来并行读取。例如:
#训练脚本的命令行标志(shard信息通过训练传递执行脚本的监控器旗帜< -旗帜(flag_integer(“num_shards”,1),flag_integer(“shard_index”,1))#转发分片信息到read_files数据集< -read_file(“数据/ * . csv”text_line_dataset,record_spec =mtcars_spec,parallel_files =4,parallel_interleave =16,num_shards =旗帜$num_shards,shard_index =旗帜$shard_index)% > %dataset_shuffle_and_repeat(buffer_size =1000,数=3.)% > %dataset_batch(128)% > %dataset_prefetch(1)