我正在对常规TF操作进行基准测试,因此,为了建立基线,我试图弄清楚用训练数据的单次通过来训练简单的逻辑回归的速度。我的输入是一个TFRecord文件,其中包含860,000个稀疏行,并具有164,000个一键编码功能。底部的数据处理。
像这样配置的预制tf.estimator.Estimator可以在 932秒中容纳一次数据传递:
feature_columns = [tf.feature_column.numeric_column(key='features',shape=164000)]
custom_config = tf.estimator.RunConfig(save_summary_steps=None,
save_checkpoints_steps=None)
estimator = tf.estimator.LinearClassifier(
feature_columns = feature_columns,
model_dir = os.path.join(MODELDIR,f'PremadeLinearClassifier_{currtime()}'),
config = custom_config
)
如果我将数据读入numpy数组并从from_tensor_slices()
创建数据集,我可以将其缩短至 467秒。
如果我构建自己的训练功能,则可以在 66.6 秒内从磁盘读取一次数据。
class LogisticModel(object):
def __init__(self):
self.W = tf.Variable(tf.random_normal([164000,1],mean=0, stddev=0.1))
self.B = tf.Variable(tf.random_normal([],mean=0.0,stddev=0.1))
def __call__(self, x):
return tf.sparse_tensor_dense_matmul(x,self.W) + self.B
def grad_fn(model, inputs, targets):
with tf.GradientTape() as t:
loss_val = loss_fn(model, inputs, targets)
return t.gradient(loss_val, [model.W, model.B])
def loss_fn(model, inputs, targets):
target_size = targets.shape.as_list()[0]
return (tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels = tf.reshape(targets,[target_size,1]),
logits = model(inputs)))
)
def perform_train(model, optim, dataset):
step = 0
for x, y in dataset:
grads = grad_fn(lm, x, y)
optimizer.apply_gradients(zip(grads, [lm.W, lm.B]),
global_step = tf.train.get_or_create_global_step())
if step % 20 == 0:
print(f"Step {step}: {loss_fn(lm,x,y)}")
step += 1
1)造成这种巨大速度差异的原因是什么?估算器中的开销重大吗? 2)如果不读入内存,是否可以进一步改进自定义功能?内部基于C ++的库仍然快一个数量级。
数据生成:
def ex_to_tensors(ex, tensor_size):
feature_spec = {'sparse': tf.SparseFeature(index_key='indices',
value_key='values',
dtype=tf.int64,
size=tensor_size),
'label': tf.FixedLenFeature([], tf.int64, default_value=0)
}
parsed_dict = tf.parse_single_example(ex, feature_spec)
return tf.cast(parsed_dict['sparse'],tf.float32), tf.cast(parsed_dict['label'],tf.float32)
def ex_input_fn(*filenames,batch_size=1000, feature_size=int(1e6)):
def parseTensors(x):
return ex_to_tensors(x,feature_size)
dataset = (tf.data.TFRecordDataset(filenames)
.map(parseTensors)
.batch(batch_size)
)
return dataset