Предварительная оценка Tensorflow намного медленнее, чем обычные? - PullRequest
0 голосов
/ 06 марта 2019

Я тестирую общие операции 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
...