OFRecord 数据集加载
OFRecord 數(shù)據(jù)集加載
在數(shù)據(jù)輸入一文中知道了使用 DataLoader 及相關(guān)算子加載數(shù)據(jù),往往效率更高,并且學(xué)習(xí)了如何使用 DataLoader 及相關(guān)算子。
在 OFrecord 數(shù)據(jù)格式中,學(xué)習(xí)了 OFRecord 文件的存儲(chǔ)格式。
本文,將圍繞 OneFlow 的 OFRecord 數(shù)據(jù)集的加載與制作展開(kāi),主要包括:
? OFRecord 數(shù)據(jù)集的組織形式
? 加載 OFRecord 數(shù)據(jù)集的多種方式
? OFRecord 數(shù)據(jù)集與其它數(shù)據(jù)格式的相互轉(zhuǎn)化
什么是OFRecord數(shù)據(jù)集
在 OFrecord 數(shù)據(jù)格式中已經(jīng)介紹過(guò) OFRecord 文件 的存儲(chǔ)格式,知道了什么是 OFRecord文件。
OFRecord 數(shù)據(jù)集是 OFRecord 文件的集合 。將多個(gè) OFRecord文件,按照 OneFlow 約定的文件名格式,存放在同一個(gè)目錄中,就得到了 OFRecord 數(shù)據(jù)集。
默認(rèn)情況下,OFRecord 數(shù)據(jù)集目錄中的文件,統(tǒng)一以 part-xxx 的方式命名,其中的 “xxx” 是從0開(kāi)始的文件編號(hào),有補(bǔ)齊和不補(bǔ)齊兩種選擇。
以下是沒(méi)有采用補(bǔ)齊的命名風(fēng)格示例:
mnist_kaggle/train/
├── part-0
├── part-1
├── part-10
├── part-11
├── part-12
├── part-13
├── part-14
├── part-15
├── part-2
├── part-3
├── part-4
├── part-5
├── part-6
├── part-7
├── part-8
└── part-9
以下是有補(bǔ)齊的命名風(fēng)格:
mnist_kaggle/train/
├── part-00000
├── part-00001
├── part-00002
├── part-00003
├── part-00004
├── part-00005
├── part-00006
├── part-00007
├── part-00008
├── part-00009
├── part-00010
├── part-00011
├── part-00012
├── part-00013
├── part-00014
├── part-00015
OneFlow 采用此約定,與 spark 的默認(rèn)存儲(chǔ)的文件名一致,方便使用 spark 制作與轉(zhuǎn)化 OFRecord 數(shù)據(jù)。
實(shí)際上,文件名前綴(part-)、文件名編號(hào)是否補(bǔ)齊、按多少位補(bǔ)齊,均可以自行指定,只需要在加載數(shù)據(jù)集(下文會(huì)介紹)時(shí),保持相關(guān)參數(shù)一致即可。
OneFlow 提供了加載 OFRecord 數(shù)據(jù)集的接口,使得只要指定數(shù)據(jù)集目錄的路徑,就可以享受 OneFlow 框架所帶來(lái)的多線程、數(shù)據(jù)流水線等優(yōu)勢(shì)。
加載OFRecord數(shù)據(jù)集的方法
使用 ofrecord_reader 加載并預(yù)處理數(shù)據(jù)集。
在數(shù)據(jù)輸入一文中,已經(jīng)展示了如何使用 ofrecord_reader 接口加載 OFRecord 數(shù)據(jù),并進(jìn)行數(shù)據(jù)預(yù)處理。
代碼見(jiàn):of_data_pipeline.py
ofrecord_reader 的接口如下:
def ofrecord_reader(
ofrecord_dir,
batch_size=1,
data_part_num=1,
part_name_prefix=“part-”,
part_name_suffix_length=-1,
random_shuffle=False,
shuffle_buffer_size=1024,
shuffle_after_epoch=False,
name=None,
)
? ofrecord_dir 指定存放數(shù)據(jù)集的目錄路徑
? batch_size 指定每輪讀取的 batch 大小
? data_part_num 指定數(shù)據(jù)集目錄中一共有多少個(gè) ofrecord 格式的文件,如果這個(gè)數(shù)字大于真實(shí)存在的文件數(shù),會(huì)報(bào)錯(cuò)
? part_name_prefix 指定 ofrecord 文件的文件名前綴, OneFlow 根據(jù)前綴+序號(hào)在數(shù)據(jù)集目錄中定位 ofrecord 文件
? part_name_suffix_length 指定 ofrecord 文件的序號(hào)的對(duì)齊長(zhǎng)度,-1表示不用對(duì)齊
? random_shuffle 表示讀取時(shí)是否需要隨機(jī)打亂樣本順序
? shuffle_buffer_size 指定了讀取樣本的緩沖區(qū)大小
? shuffle_after_epoch 表示每輪讀取完后是否需要重新打亂樣本順序
使用 ofrecord_reader 的好處在于, ofrecord_reader 作為一個(gè)普通算子,參與 OneFlow 構(gòu)圖優(yōu)化,并享有 OneFlow 流水線加速。
對(duì)于與業(yè)務(wù)邏輯耦合的特定操作(如解碼、解壓等),還可以為 ofrecord_reader 定義預(yù)處理 op,讓程序擁有很高的靈活性和擴(kuò)展性。
? 關(guān)于 DataLoader 及相關(guān)算子使用可以參考數(shù)據(jù)輸入
? 關(guān)于自定義 Op 可以參考用戶自定義 op
其它格式數(shù)據(jù)與 OFRecord 數(shù)據(jù)集的相互轉(zhuǎn)化
參考OFrecord數(shù)據(jù)格式中 OFRecord 文件的存儲(chǔ)格式及本文開(kāi)頭介紹的 OFRecord 數(shù)據(jù)集的文件名格式約定,完全可以自己制作 OFRecord 數(shù)據(jù)集。
不過(guò)為了更加方便,提供了 Spark 的 jar 包,方便 OFRecord 與常見(jiàn)數(shù)據(jù)格式(如 TFRecord、json)進(jìn)行相互轉(zhuǎn)化。
spark 的安裝與啟動(dòng)
首先,下載 spark 及 spark-oneflow-connector:
? 在 spark 官網(wǎng)下載spark-2.4.0-bin-hadoop2.7
? 在這里下載 jar 包,spark 需要它來(lái)支持 ofrecord 格式
接著,解壓 spark-2.4.0-bin-hadoop2.7.tgz,并配置環(huán)境變量 SPARK_HOME:
export SPARK_HOME=path/to/spark-2.4.0-bin-hadoop2.7
然后,通過(guò)以下命令啟動(dòng) pyspark shell:
pyspark --master “l(fā)ocal[*]”
–jars spark-oneflow-connector-assembly-0.1.0_int64.jar
–packages org.tensorflow:spark-tensorflow-connector_2.11:1.13.1
…
Welcome to
____ __
/ / ___ / /
\ / _ / _ `/ __/ '/
/ / ._/_,// //_\ version 2.4.0
//
Using Python version 3.6.10 (default, May 8 2020 02:54:21)
SparkSession available as ‘spark’.
在啟動(dòng)的 pyspark shell 中,可以完成 OFRecord 數(shù)據(jù)集與其它數(shù)據(jù)格式的相互轉(zhuǎn)化。
使用 spark 查看 OFRecord 數(shù)據(jù)集
使用以下命令可以查看 OFRecord 數(shù)據(jù):
spark.read.format(“ofrecord”).load(“file:///path/to/ofrecord_file”).show()
默認(rèn)顯示前20條數(shù)據(jù):
±-------------------±-----+
| images|labels|
±-------------------±-----+
|[0.33967614, 0.87…| 2|
|[0.266905, 0.9730…| 3|
|[0.66661334, 0.67…| 1|
|[0.91943026, 0.89…| 6|
|[0.014844197, 0.0…| 6|
|[0.5366513, 0.748…| 4|
|[0.055148937, 0.7…| 7|
|[0.7814437, 0.228…| 4|
|[0.31193638, 0.55…| 3|
|[0.20034336, 0.24…| 4|
|[0.09441255, 0.07…| 3|
|[0.5177533, 0.397…| 0|
|[0.23703437, 0.44…| 9|
|[0.9425567, 0.859…| 9|
|[0.017339867, 0.0…| 3|
|[0.827106, 0.3122…| 0|
|[0.8641392, 0.194…| 2|
|[0.95585227, 0.29…| 3|
|[0.7508129, 0.464…| 4|
|[0.035597708, 0.3…| 9|
±-------------------±-----+
only showing top 20 rows
與 TFRecord 數(shù)據(jù)集的相互轉(zhuǎn)化
以下命令可以將 TFRecord 轉(zhuǎn)化為 OFRecrod:
reader = spark.read.format(“tfrecords”)
dataframe = reader.load(“file:///path/to/tfrecord_file”)
writer = dataframe.write.format(“ofrecord”)
writer.save(“file:///path/to/outputdir”)
以上代碼中的 outputdir 目錄會(huì)被自動(dòng)創(chuàng)建,并在其中保存 ofrecord 文件。在執(zhí)行命令前應(yīng)保證 outputdir 目錄不存在。
此外,還可以使用以下命令,在轉(zhuǎn)化的同時(shí),將數(shù)據(jù)切分為多個(gè) ofrecord 文件:
reader = spark.read.format(“tfrecords”)
dataframe = reader.load(“file:///path/to/tfrecord_file”)
writer = dataframe.repartition(10).write.format(“ofrecord”)
writer.save(“file://path/to/outputdir”)
以上命令執(zhí)行后,在 outputdir 目錄下會(huì)產(chǎn)生10個(gè) part-xxx 格式的ofrecord文件。
將 OFRecord 文件轉(zhuǎn)為 TFRecord 文件的過(guò)程類似,交換讀/寫方的 format 即可:
reader = spark.read.format(“ofrecord”)
dataframe = reader.load(“file:///path/to/ofrecord_file”)
writer = dataframe.write.format(“tfrecords”)
writer.save(“file:///path/to/outputdir”)
與 JSON 格式的相互轉(zhuǎn)化
以下命令可以將 JSON 格式數(shù)據(jù)轉(zhuǎn)為 OFRecord 數(shù)據(jù)集:
dataframe = spark.read.json(“file:///path/to/json_file”)
writer = dataframe.write.format(“ofrecord”)
writer.save(“file:///path/to/outputdir”)
以下命令將 OFRecord 數(shù)據(jù)轉(zhuǎn)為 JSON 文件:
reader = spark.read.format(“ofrecord”)
dataframe = reader.load(“file:///path/to/ofrecord_file”)
dataframe.write.json(“file://path/to/outputdir”)
總結(jié)
以上是生活随笔為你收集整理的OFRecord 数据集加载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OFRecord 数据格式
- 下一篇: OFRecord 图片文件制数据集