Я тестирую общие операции 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
)
Если я прочту данные в массивы и создам набор данных из 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