概述
tfrecords介绍
说明:tfrecords是一种二进制编码文件,读取效率高且跨平台,最重要的是当训练数据过大时采用直接读取数据是不能的,所以可以用tfrecords来读取数据。
tfrecords原理:将数据放入一个内存队列,在内存队列前还有一个文件名队列,每次从内存队列里读取数据使用,并且数据读入内存与计算是多线程,大大提高了效率。
tfrecords制作
这部分全部写入函数 write_tfrecords(filename='pre_data')
#将数据处理为tfrecords
def write_tfrecords(filename='pre_data'):
pass
训练数据读取
训练数据的文件
获取数据目录,这里的TRAINING_CHUNK_RE是用来匹配训练数据的文件名,获取到这种格式的文件名,因为这个文件夹里还有其他格式的文件
import os
import tensorflow as tf
import numpy as np
#将数据处理为tfrecords
def write_tfrecords(filename='pre_data'):
#训练目录正则表达式
TRAINING_CHUNK_RE = re.compile(r"traind+.chunk.gz")
#获取目录
train_dataset=[os.path.join(filename,fname) for fname in os.listdir(filename) if TRAINING_CHUNK_RE.match(fname)]
tfrecords文件写入
这里就是写入tfrecords的开头部分,先是打开这个格式的文件,没有会创建一个
#写入tfrecords
i=0
with tf.io.TFRecordWriter(os.path.join(filename,'data.tfrecords')) as writer:
pass
这里加了一个for循环遍历这个目录的每个包,这里有个DataSet.read_data()函数是自己写的用来解压每个包并将数据返回为np.array格式。所以就只用理解为这是为了的到每个包的数据就行了,并且每个包都有4096条数据,每条数据都是三维的。所以train_data就是一个np.array,是一个多维的数组。后面的num_pos就是训练的x值,num_next是y值,并且num_pos的shape是[4096,9,9,28],num_next的shape是[4096,81]
with tf.io.TFRecordWriter(os.path.join(filename,'data.tfrecords')) as writer:
for _ in train_dataset:
print('正在处理第',i,'个包...')
train_data=DataSet.read_data(_)
#4096条x与y值
num_pos=train_data.pos_features
num_next=train_data.next_moves
但是我做的卷积神经网络输入的shape为[9,9,28],输出的shape为[81],所以保存的tfrecords也要按这个格式,故这里还要加一个for循环来处理每个包,使每条数据切分开,得到n条输入为[9,9,28],输出为[81]的数据。这里的zip()函数就是让两个值进行配对哦,不懂得小伙伴可以百度查一下哦。然后这里就分别得到每个包train_x与train_y。shape分别为[9.9,28],[81]
#写入tfrecords
i=0
with tf.io.TFRecordWriter(os.path.join(filename,'data.tfrecords')) as writer:
for _ in train_dataset:
print('正在处理第',i,'个包...')
train_data=DataSet.read_data(_)
#4096条x与y值
num_pos=train_data.pos_features
num_next=train_data.next_moves
#x与y一一对应,并一一取出
for train_x,train_y in zip(num_pos,num_next):
pass
到这步就要先讲下写入tfrecords需要用到的一个特征字典,先上代码。
#制作特征字典
features = tf.train.Features(
feature={
"train_x": tf.train.Feature(
bytes_list=tf.train.BytesList(value=[train_x.astype(np.int32).tostring()])),
"train_y": tf.train.Feature(
bytes_list=tf.train.BytesList(value=[train_y.astype(np.int32).tostring()]))
}
)
↑↑↑上面的features可以理解为写入tfrecords需要的一个参数,tf.train.Features将字典包装成了一个这样参数的数据格式。而feature就是一个字典写出了这个tfrecords存入数据的名字(key值)以及它的格式。这里tf.train提供了3种数据格式,为BytesList,Int64List,FloatList。
简单来说就是存入的数据必须是这三种类型的。而我的数据train_x,train_y的格式是numpy.array。所以这里的关键就是要进行数据处理,这里我选用BytesList方式存入,为什么不用其他的,我之后说明。由于我训练数据全是整数,所以先将它转成np的数据类型np.int32。如果数据类型是float,那么同样你只要转成np提供的一些float格式就行了。然后再用tostring转成字节,注意这里的tostring()转成的是bytes类型的数据。这样feature字典就做好了。
再来说下我的数据都是整数为什么不用Int64List?我试过将train_x用tf.train.Int64List强制转化一下,最后的结果是报错提醒我传入的数据是np.array不能使用Int64List。我没试过FloatList,但我想结果是一样的。
但是不管你的数据是那种格式,都是可以用这种转化字节方法那存储的。
之后就是部分函数剩下部分的完成了。将features对象传入tf.train.Example就行了。之后序列化写入文件,在关闭文件就完成了这个tfrecords文件的建立了。
#写入tfrecords
i=0
with tf.io.TFRecordWriter(os.path.join(filename,'data.tfrecords')) as writer:
for _ in train_dataset:
print('正在处理第',i,'个包...')
train_data=DataSet.read_data(_)
#4096条x与y值
num_pos=train_data.pos_features
num_next=train_data.next_moves
#x与y一一对应,并一一取出
for train_x,train_y in zip(num_pos,num_next):
#制作特征字典
features = tf.train.Features(
feature={
"train_x": tf.train.Feature(
bytes_list=tf.train.BytesList(value=[train_x.astype(np.int32).tostring()])),
"train_y": tf.train.Feature(
bytes_list=tf.train.BytesList(value=[train_y.astype(np.int32).tostring()]))
}
)
example = tf.train.Example(features=features) # 通过字典建立 Example
writer.write(example.SerializeToString()) # 将Example序列化并写入 TFRecord 文件
i=i+1
writer.close()
这是我做好的tfrecords文件。
下面是这个建立tfrecords函数完整的代码:
#将数据处理为tfrecords
def write_tfrecords(filename='pre_data'):
#获取目录
train_dataset=[os.path.join(filename,fname) for fname in os.listdir(filename) if TRAINING_CHUNK_RE.match(fname)]
#写入tfrecords
i=0
with tf.io.TFRecordWriter(os.path.join(filename,'data.tfrecords')) as writer:
for _ in train_dataset:
print('正在处理第',i,'个包...')
train_data=DataSet.read_data(_)
#4096条x与y值
num_pos=train_data.pos_features
num_next=train_data.next_moves
#x与y一一对应,并一一取出
for train_x,train_y in zip(num_pos,num_next):
#转为bytes
'''train_x=train_x.astype(np.int64).tostring()
train_y=train_y.astype(np.int64).tostring()'''
#制作特征字典
features = tf.train.Features(
feature={
"train_x": tf.train.Feature(
bytes_list=tf.train.BytesList(value=[train_x.astype(np.int32).tostring()])),
"train_y": tf.train.Feature(
bytes_list=tf.train.BytesList(value=[train_y.astype(np.int32).tostring()]))
}
)
example = tf.train.Example(features=features) # 通过字典建立 Example
writer.write(example.SerializeToString()) # 将Example序列化并写入 TFRecord 文件
i=i+1
writer.close()
从tfrecords中读取数据并训练
全部代码放入函数read_tfrecords()。
#读取tfrecords文件
def read_tfrecords():
pass
首先获得文件目录,再用tf提供的函数来读取tfrecords文件
#读取tfrecords文件
def read_tfrecords():
#读取文件
tfrecord_file = 'pre_data/data.tfrecords'
dataset = tf.data.TFRecordDataset(tfrecord_file) # 读取 TFRecord 文件
之后用map函数解析数据。这里map需要传入一个自定义函数来解析,相当于把之前的转换在逆进行一次。简单来说就是告诉map函数这个文件该如何解码。这里的read_and_decode就是我写的这个文件的解码方式。下面讲解这个函数。
dataset = dataset.map(decode_tfrecords) # 解析数据
下面就是这个函数的全部,理解起来很简单。这个example参数就是dataset,看我上面的写法就知道了。
第一步写出这个tfrecords文件的数据是怎样的,所以要写一个特征字典,按这个格式把数据提出来。这里tf.io.FixedLenFeature需要传入两个参数,第一个是数据维度,第二个是类型。由于之前用了tostring()转成了字节码的序列,所以格式为tf.string。同样由于数据np.array被我用类型转换成了字节码,而我之前的数据是int型np.arrray(),故我必须把类型转回去再改维度。所以维度先写成一维就好了,之后再处理。
第二步就是调用tf.io.parse_single_example()来解码了,传入example,还有特征字典。
最后一步的重点就是tf.io.decode_raw()这个函数,这是可以解码字节码的函数,将它转成想要的类型。tf.io还有多种解码函数,大部分都是处理图像的,感兴趣的可以试下。利用这个函数成功将数据提取了出来,最后改成之前的维度就好了。
#将tfrecords数据解析出来
def decode_tfrecords(example):
# 定义Feature结构,告诉解码器每个Feature的类型是什么
feature_description = {
'train_x': tf.io.FixedLenFeature([], tf.string),
'train_y': tf.io.FixedLenFeature([], tf.string)
}
#按照feature_description解码
feature_dict = tf.io.parse_single_example(example, feature_description)
#由bytes码转化为tf.int32
train_x=(tf.io.decode_raw(feature_dict['train_x'],out_type=tf.int32))
#修改维度为编码前
train_x=tf.reshape(train_x,[9,9,28])
train_y=tf.io.decode_raw(feature_dict['train_y'],out_type=tf.int32)
train_y=tf.reshape(train_y,[81])
return train_x,train_y
下面是这部分函数
#读取tfrecords文件
def read_tfrecords():
#读取文件
tfrecord_file = 'pre_data/data.tfrecords'
dataset = tf.data.TFRecordDataset(tfrecord_file) # 读取 TFRecord 文件
dataset = dataset.map(read_and_decode) # 解析数据
利用tfrecords文件进行模型训练
模型训练的部分代码不多,我就直接放入read_tfrecords()函数了
首先是设定batch,及利用这个队列一次训练放入多少数据,我这个训练数据量太大,所以一次就放入了1000。这个量可以视情况而定。
之后的repeat()函数是这批数据重复,可以指定参数,不写参数是无数次。写这个的目的是当队列里最后一批数据(1000)不足时可以补,不然会出现个报错 “OutOfRangeError: End of sequence”
后面的函数prefetch是可以减少GPU空闲时间,提前加载后面批次的数据,参数是GPU预读取的数据数量,这里调成根据GPU状态动态调整。
dataset_batch=dataset.batch(1000)
#数据重复
dataset_batch=dataset_batch.repeat()
#根据GPU动态调整并行调用的数量
AUTOTUNE = tf.data.experimental.AUTOTUNE
#预先取数据,使得下一批次或者多个批次提前加载
dataset_batch = dataset_batch.prefetch(buffer_size=AUTOTUNE)
模型训练
这里就是用我做好的模型进行训练了,其中nb_epoch就是epoch,表示所有数据的训练次数,steps_per_epoch相当于有多少批次的数据从队列传过来,data_size是数据的数量,在整除1000就相当于所有数据跑一次了。用整除也是为了防止之前说的那个报错。后面的参数就是验证集的设置了,就不在阐述了。
#模型训练
model.fit(dataset_batch, nb_epoch=50,steps_per_epoch=data_size//1000,validation_data=(val_x,val_y),validation_steps=4)
最后
以上就是负责保温杯为你收集整理的tensorflow2.0(tf2.0) 多维numpy.array数据写入tfrecords文件并且从中读取数据参与训练,以及相关参数的说明tfrecords介绍tfrecords制作从tfrecords中读取数据并训练利用tfrecords文件进行模型训练的全部内容,希望文章能够帮你解决tensorflow2.0(tf2.0) 多维numpy.array数据写入tfrecords文件并且从中读取数据参与训练,以及相关参数的说明tfrecords介绍tfrecords制作从tfrecords中读取数据并训练利用tfrecords文件进行模型训练所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复