利用hadoop分布式生成tfrecord格式文件
由于到处理的数据量较大,亿为单位的数据条数,所以提前利用hadoop的分布式的优势处理成tfrecord格式供tf训练。
hadoop streaming执行的是mapper reduce流处理。
完整脚本文件放在了github上,
input data format:([one,another' 'label],split(',' and ' '))
1 2 3 4 5 6 7 0 8 9 10,1 2 3 4 5 6 7 0 8 9 10 0
mapper
shuffle data
利用mapper的自动排序功能做数据shuffle。
也就是在每一条数据前增加一个随机数,然后使用其自动排序的机制达到shuffle数据的功能。
def mapper():
for line in sys.stdin:
print('{} {}'.format(random.random(), line.strip()))
reducer
generate tfrecord
其中有一个小技巧就是所有的reducer任务是在集群上的机器上运行的,在执行生成tfrecord文件后,要使用hadoop fs -put .....
命令将本机生成的文件上传到hadoop上。
def reducer(save_path, hadoop_path):
writer = tf.python_io.TFRecordWriter(save_path)
for line in sys.stdin:
line = line.strip().split(' ')
if len(line) != 3:
print(line)
continue
#info = np.array(line[1],dtype='int') #not work
#label = np.array(line[2],dtype='int')
info = line[1].strip().split(',')
pair_info = []
label_info = []
for i in xrange(len(info)):
one_info = info[i].strip().split(' ')
one_info_str = []
for j in xrange(len(one_info)):
one_info_str.append(float(one_info[j]))
pair_info.append(one_info_str)
info = np.array(pair_info, np.float32)
label = line[2].strip()
label_info = int(label)
example = tf.train.Example(
features=tf.train.Features(
feature={'pair' : bytes_feature(info.tobytes()),
'label' : int64_feature(label_info)}))
writer.write(example.SerializeToString())
writer.close()
os.system('hadoop fs -put '+save_path+' '+hadoop_path)
问题记录
在reducer阶段,直接将stdin的数据转np.array
后用tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
转换后是能够生成tfrecord文件的,但是在模型训练输入阶段却解析不出来,不知道为啥。
#info = np.array(line[1],dtype='int') #not work
#label = np.array(line[2],dtype='int')
因此选择将stdin的数据切分开之后再转换,就能用了。
Amazing!