Тренировочный цикл while в Tensorflow - PullRequest
0 голосов
/ 16 апреля 2019

Я попытался преобразовать обучающий цикл на стороне Python в Tensorflow, чтобы (гипотетически) ускорить выполнение кода - без необходимости постоянно передавать управление процессору.Тем не менее, я не могу управлять с помощью tf.while_loop.

Вот код, который работает:

import numpy as np
import tensorflow as tf

from tqdm import tqdm
from sklearn.datasets import load_iris
from sklearn.preprocessing import RobustScaler

x, y = load_iris(True)
x = RobustScaler().fit_transform(x)

shape = (10, 10)
max_epochs = 1000


graph = tf.Graph()
sess = tf.Session(graph=graph)

x = x.astype(np.float64)


# Construct graph
with graph.as_default():
    weights = tf.get_variable(
        'weights', shape, initializer=tf.constant_initializer, dtype=tf.float64
    )
    curr_epoch = tf.placeholder(dtype=tf.int64, shape=())

    with tf.name_scope('data'):
        data = tf.data.Dataset.from_tensor_slices(x)
        data = data.shuffle(buffer_size=10000)
        data = data.repeat(max_epochs)
        data = data.batch(1)
        data = data.make_one_shot_iterator().get_next()

    with tf.name_scope('update'):
        update_op = make_update_op(weights)

    init = tf.global_variables_initializer()


sess.run(init)

for i in tqdm(range(max_epochs)):
    for _ in range(x.shape[0]):
        sess.run(update_op, feed_dict={
            curr_epoch: i
        })

np_weights = sess.run(weights)
print(np_weights) # Correctly prints an array of 150's.

Теперь, если я создаю функцию обновления для передачи tf.while_loop, ошибкаБрошенныйпроисходит даже после прочтения документации.weights это Variable в конце концов.Что можно сделать, чтобы правильно сделать тренировочный цикл?

Ответы [ 2 ]

0 голосов
/ 16 апреля 2019

Оказывается, все, чего не хватало, так это того, что нельзя присвоить переменную внутри цикла, как Влад указал .Вместо этого можно вернуть новое значение переменной.

def make_update_op(w):
    return w + 0.001

new_w = tf.while_loop(lambda _: True, make_update_op, (weights,), maximum_iterations=x.shape[0])
update_op = weights.assign(new_w)

Чтобы использовать больше переменных, потребуется вернуть ту же сумму из функции и распаковать их в Python, но принцип тот же.

def make_update_op(w, d):
    return w + 0.001, d

new_w, _ = tf.while_loop(lambda *_: True, make_update_op, (weights, data), maximum_iterations=x.shape[0])
update_op = weights.assign(new_w)
0 голосов
/ 16 апреля 2019

Тензор, который вы пытаетесь присвоить новому значению в цикле while, является результатом последовательности нескольких операций-тензоров (операция - это узел в графе, а тензор - это направленное ребро). В частности, цикл while выдаст:

Variable/Read-->while/Enter-->while/Merge-->while/Switch-->while/Identity

Здесь вы пытаетесь присвоить тензор while/Identity.

tf.while_loop обычно используется для итерации по измерениям тензора (также по None - неизвестному измерению). Вы пытаетесь перебрать переменные, которые полностью определены. Вам не нужно создавать tf.while_loop для этого. Просто создайте операции, которые обновляют каждую переменную, и сгруппируйте эти операции вместе:

update_ops = [w.assign(w + 0.001) for w in weights]
update_op = tf.group(update_ops)

Теперь, когда вы выполните update_op с интерфейсом tf.Session(), он обновит все переменные.

Пример:

import tensorflow as tf

v1 = tf.Variable(tf.ones((1, 2), dtype=tf.float32))
v2 = tf.Variable(2*tf.ones((1, 3), dtype=tf.float32))

update_ops = [w.assign(w + 0.001) for w in [v1, v2]]
update_op = tf.group(update_ops)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print('before update:')
    print(v1.eval(), v2.eval())
    print('after update:')
    sess.run(update_op) # <-- update your variables
    print(v1.eval(), v2.eval())

    # before update:
    # [[1. 1.]] [[2. 2. 2.]]
    # after update:
    # [[1.001 1.001]] [[2.001 2.001 2.001]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...