Чому TensorFlow 2 набагато повільніше, ніж TensorFlow 1?


137

Багато користувачів це наводить як причину переходу на Pytorch, але я ще не знайшов виправдання / пояснення для того, щоб пожертвувати найважливішою практичною якістю, швидкістю для нетерплячого виконання.

Нижче наведено ефективність бенчмаркінгу коду, TF1 проти TF2 - TF1 працює десь від 47% до 276% швидше .

Моє запитання: що на графічному чи апаратному рівні дає таке значне уповільнення?


Шукаєте детальну відповідь - я вже знайомий із широкими поняттями. Відповідний Git

Технічні характеристики : CUDA 10.0.130, cuDNN 7.4.2, Python 3.7.4, Windows 10, GTX 1070


Результати порівняння :


ОНОВЛЕННЯ : Відключення швидкого виконання за кодом нижче не допомагає. Однак поведінка суперечлива: іноді біг у графічному режимі значно допомагає, в іншому випадку він працює повільніше відносно Eager.

Оскільки TF Devs не з’являється ніде, я сам буду займатися цим питанням - можу слідкувати за прогресом у пов'язаній проблемі з Github.

ОНОВЛЕННЯ 2 : тонни експериментальних результатів для спільного використання та пояснення; слід зробити сьогодні.


Код орієнтиру :

# use tensorflow.keras... to benchmark tf.keras; used GPU for all above benchmarks
from keras.layers import Input, Dense, LSTM, Bidirectional, Conv1D
from keras.layers import Flatten, Dropout
from keras.models import Model
from keras.optimizers import Adam
import keras.backend as K
import numpy as np
from time import time

batch_shape = (32, 400, 16)
X, y = make_data(batch_shape)

model_small = make_small_model(batch_shape)
model_small.train_on_batch(X, y)  # skip first iteration which builds graph
timeit(model_small.train_on_batch, 200, X, y)

K.clear_session()  # in my testing, kernel was restarted instead

model_medium = make_medium_model(batch_shape)
model_medium.train_on_batch(X, y)  # skip first iteration which builds graph
timeit(model_medium.train_on_batch, 10, X, y)

Використовувані функції :

def timeit(func, iterations, *args):
    t0 = time()
    for _ in range(iterations):
        func(*args)
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_small_model(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 400, strides=4, padding='same')(ipt)
    x     = Flatten()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_medium_model(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Bidirectional(LSTM(512, activation='relu', return_sequences=True))(ipt)
    x     = LSTM(512, activation='relu', return_sequences=True)(x)
    x     = Conv1D(128, 400, strides=4, padding='same')(x)
    x     = Flatten()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), np.random.randint(0, 2, (batch_shape[0], 1))

Чи використовували ви коли-небудь такий інструмент cProfile, щоб проаналізувати, яка частина робить їх настільки різними?
zihaozhihao

@zihaozhihao я маю , хоча не для цього конкретно; за попереднім посиланням і написанням користувальницького оптимізатора я вже знайомий з різницями в дзвінках, але не розумію, чому хтось повільніше, ніж інший - і не може будь-який експерт, що не стосується TF, зрозуміти це з джерела, що, крім того, заплутаний безлад, не підтверджує відносних дій. Потрібна інформація про графік / апаратний рівень, яку профілери не нададуть (наскільки я можу ними користуватися)
OverLordGoldDragon

чи нумерова версія однакова в обох тестах?
чабір

Ой .... Якщо один старий Керас був уже значно повільніше, ніж PyTorch, уявіть тепер.
Даніель

чи масштабується проблема з розміром моделі? Ви також намагалися запустити той же показник в інших ОС?
okawo

Відповіді:


76

ОНОВЛЕННЯ 2/18/2020 : я скупчив 2.1 та 2.1 ночі; результати змішані. Усі конфігурації, крім однієї (розмір моделі та даних), настільки ж швидкі або набагато швидші, ніж найкращі з TF2 та TF1. Той, що повільніше і різко повільніше, - великий-великий - особливо. у графічному виконанні ( 1.6x до 2.5x повільніше ).

Крім того, існують надзвичайні відмінності відтворюваності між Графіком та Eager для великої тестованої нами моделі - однієї не можна пояснити через випадковість / обчислення-паралелізм. В даний час я не можу представити відтворюваний код для цих претензій за часові обмеження, тому натомість настійно рекомендую перевірити це для власних моделей.

Я ще не відкривав питання Git щодо цих питань, але я коментував оригінал - відповіді поки немає. Я оновлю відповідь (и), коли буде досягнутий прогрес.


ВЕРДИКТ : Це не так , якщо ви знаєте, що робите. Але якщо ви цього не зробите , це може коштувати вам багато, - в середньому за допомогою декількох оновлень GPU та декількох гірших процесорів.


ЦЕ ВІДПОВІДЬ : спрямована на надання опису на високому рівні, а також настанови щодо того, як визначитись з конфігурацією тренувань, що відповідає вашим потребам. Детальний опис на низькому рівні, який включає всі результати бенчмаркінгу + використаний код, дивіться мою іншу відповідь.

Я буду оновлювати свою (-и) відповідь (-ів) з додатковою інформацією, якщо я навчусь такою - можу зробити закладку / "зірочку" це питання для довідки.


ПІДСУМКОВА ІНФОРМАЦІЯ : як підтвердив розробник TensorFlow, Q. Скотт Чжу, TF2 зосередили розробку на Eager виконанні та тісній інтеграції з Керасом, що передбачало значні зміни у джерелі TF - у тому числі на рівні графіка. Переваги: ​​значно розширені можливості обробки, розповсюдження, налагодження та розгортання. Однак деякі з них - швидкість.

Справа, однак, досить складна. Це не лише TF1 проти TF2 - фактори, що призводять до значних відмінностей у швидкості поїзда, включають:

  1. TF2 проти TF1
  2. Режим Eager vs. Graph
  3. keras vs. tf.keras
  4. numpyvs. tf.data.Datasetvs. ...
  5. train_on_batch() vs. fit()
  6. GPU vs. CPU
  7. model(x)vs. model.predict(x)vs. ...

На жаль, майже жодне з перерахованих вище не є незалежним від інших, і кожен може принаймні подвоїти час виконання відносно іншого. На щастя, ви можете визначити, що найкраще працюватиме систематично, і за допомогою кількох ярликів - як я покажу.


ЩО Я ПОВИНЕН ЗРОБИТИ? Наразі єдиний спосіб - експеримент для вашої конкретної моделі, даних та обладнання. Жодна конфігурація не завжди буде найкраще працювати, але є спроби пошуку, а це не потрібно:

>> ДО:

  • train_on_batch()+ numpy+ tf.keras+ TF1 + Eager / Graph
  • train_on_batch()+ numpy+ tf.keras+ TF2 + Графік
  • fit()+ numpy+ tf.keras+ TF1 / TF2 + Графік + велика модель та дані

>> НЕ:

  • fit()+ numpy+ kerasдля малих та середніх моделей та даних
  • fit()+ numpy+ tf.keras+ TF1 / TF2 + Eager
  • train_on_batch()+ numpy+ keras+ TF1 + Eager

  • [Майор] tf.python.keras ; він може працювати 10-100x повільніше, з ж / великою кількістю помилок; більше інформації

    • Це включає в себе layers, models, optimizers, і пов'язані з «поза коробки» імпорту використання; ops, утиліти та пов'язаний з ними "приватний" імпорт - це добре, але, щоб бути впевненим, перевірте, чи існує alt, чи вони використовуютьсяtf.keras

Зверніться до коду внизу моєї іншої відповіді для прикладу налаштування бенчмаркінгу. Список, наведений вище, ґрунтується, головним чином, на таблицях "BENCHMARKS" в іншій відповіді.


ОБМЕЖЕННЯ вищезазначених DO і & DON'T:

  • Це питання має назву "Чому TF2 набагато повільніше, ніж TF1?", І хоча його орган стосується тренувань явно, справа не обмежується ним; Висновок теж підлягає великій різниці швидкостей, навіть у тій же версії TF, імпорті, форматі даних тощо - див. цю відповідь .
  • RNN, ймовірно, помітно змінить сітку даних в іншій відповіді, оскільки вони були покращені в TF2
  • В основному використовуються моделі Conv1Dі Dense- відсутні RNN, розріджені дані / цілі, 4 / 5D входи та інші конфігурації
  • Вхідні дані обмежені numpyта tf.data.Dataset, хоча існує багато інших форматів; див. іншу відповідь
  • Використовувався GPU; результати будуть відрізнятися на процесорі. Насправді, коли я задавав питання, мій CUDA не був правильно налаштований, і деякі результати були засновані на процесорі.

Чому TF2 пожертвував найбільш практичною якістю, швидкістю для нетерплячого виконання? Ні, зрозуміло - графік все ще доступний. Але якщо питання "чому взагалі прагнути":

  • Покращена налагодження : ви, швидше за все, стикаєтеся з безліччю запитань із запитаннями "як мені отримати результати проміжного шару" або "як я перевіряю ваги"; з нетерплячим, це (майже) так просто, як .__dict__. Графік, навпаки, вимагає ознайомлення зі спеціальними функціями резервного копіювання - значно ускладнюючи весь процес налагодження та самоаналізу.
  • Швидше прототипування : за ідеями, подібними до вище; швидше розуміння = більше часу залишається на фактичну DL.

ЯК РОЗКЛЮЧАТИ / ВИМКНУТИ ЕГЕР?

tf.enable_eager_execution()  # TF1; must be done before any model/tensor creation
tf.compat.v1.disable_eager_execution() # TF2; above holds

ДОДАТКОВІ ІНФОРМАЦІЇ :

  • Обережно з _on_batch()методами в TF2; на думку розробника TF, вони все ще використовують повільнішу реалізацію, але не навмисно - тобто це потрібно виправити. Детальну інформацію див. В іншій відповіді.

ЗАПИТАННЯ ДО ТЕНЗОРУВАННЯ ПРИСТРОЙ :

  1. Виправте train_on_batch(), а також ефективність виклику fit()ітеративно; Спеціальні петлі поїздів важливі для багатьох, особливо для мене.
  2. Додайте документацію / документознавство про ці відмінності в продуктивності для знань користувачів.
  3. Підвищити загальну швидкість виконання, щоб не переходити від переходу на Pytorch.

ПОЗНАЧЕННЯ : Завдяки


ОНОВЛЕННЯ :

  • 14.11.19 - знайшла модель (в моєму реальному застосуванні), яка працює повільніше на TF2 для всіх * конфігурацій без вхідних даних. Відмінності становили 13-19%, в середньому 17%. Відмінності між kerasі tf.keras, однак, були більш драматичними: 18-40% , сер. 32% (обидва TF1 та 2). (* - за винятком Eager, для якого TF2 OOM'd)

  • 17.11.197 - розробники оновили on_batch()методи в нещодавньому фіксації , заявляючи, що покращена швидкість - випускається в TF 2.1 або доступна зараз як tf-nightly. Оскільки я не в змозі запустити останній запуск, затримка стенду до 2.1.

  • 2/20/20 - показники прогнозування також варті порівняння; наприклад, у TF2, час прогнозування процесора може включати періодичні сплески

3
Про що fit_generator? ... Я практично ніколи не хочу, train_on_batchа керування власним циклом тренувань через партії - це величезний, величезний антидіапазон, якого слід уникати навіть великою ціною.
ely

@ely Це залишається пройти тестування, як було зазначено в іншій моїй відповіді, - але якщо що-небудь, я прогнозую, що це буде fitневелика додаткова обробка даних. Щодо циклів поїздів, я написав власний спеціальний, який в кінцевому рахунку перетворився на свого роду API; fit_generatorне вистачає самоаналізу, настроюваності та збереження / завантаження - тож для мене абсолютна думка. Зрештою, я опублікую свій навчальний цикл на Github.
OverLordGoldDragon

Відсутність самоаналізу та настроюваності - це особливість для мене, а не помилка. IDK, на що йдеться про коментар збереження / завантаження? Проміжне збереження / завантаження під час циклу, який не контролюється генератором даних? (Я також особисто радий, покладаючись лише на зворотні дзвінки для цього, і бачив би потребу в будь-якій іншій налаштуваннях як запах коду, що мій тренувальний цикл розроблений неправильно).
ely

@ely Це не просто, але це необхідно для навчання w / складних конвеєрів вхідних даних, об'єктивних функцій та конфігурацій моделі, що не належить API (наприклад, ансамблі). Інтроспекція необхідна для багатьох інженерних цілей налагодження та функцій. Не вистачає зовнішньої економії / завантаження, а також призупинення та відновлення циклу поїздів для обчислювально дорогих моделей - кошмар. Незалежно від цього, в кінцевому рахунку, залежить від ваших конкретних потреб та виходу з теми; найнадійніший спосіб перевірити продуктивність з / fit_generatorза вашої програми - це, ну, протестувати її.
OverLordGoldDragon

47

ЦІЙ ВІДПОВІДЬ : спрямований на те, щоб надати детальний опис випуску на рівні графіка / обладнання - включаючи шлейфи поїздів TF2 проти TF1, процесори введення даних та виконання режиму Eager vs. Graph. Для підсумків та рекомендацій щодо вирішення проблеми дивіться мою іншу відповідь.


ВЕРДИКА ДІЯЛЬНОСТІ : іноді одна швидша, інша - залежно від конфігурації. Що стосується TF2 проти TF1, то вони в середньому приблизно на рівні, але існують значні відмінності на основі конфігурацій, і TF1 козирує TF2 частіше, ніж навпаки. Див. "БЕНХМАРКІНГ" нижче.


EAGER VS. GRAPH : м'ясо цієї всієї відповіді для деяких: прагнення TF2 повільніше, ніж TF1, згідно з моїм тестуванням. Детальніше далі.

Принципова відмінність між ними полягає в тому, що Graph налаштовує обчислювальну мережу проактивно і виконує, коли "їм сказано" - тоді як Eager виконує все при створенні. Але історія тільки починається тут:

  • Нетерплячий НЕ позбавлений Графіка , і насправді може бути переважно Графіком, всупереч очікуванням. Що це в значній мірі - це виконаний графік - це включає ваги моделі та оптимізатора, що складають велику частину графіка.

  • Eager відновлює частину власного графіка при виконанні ; Прямий наслідок не повністю побудованого графіка - див. результати профілера. Це обчислювальні витрати.

  • Захист - це повільніші введення / вхідні вводи ; відповідно до цього коментаря та коду Git , Numpy вхідні дані в Eager включають накладні витрати на копіювання тензорів з процесора в GPU. Переглядаючи вихідний код, відмінності в обробці даних очевидні; Eager безпосередньо передає Numpy, тоді як Graph передає тензори, які потім оцінюють Numpy; невідомий точний процес, але останні повинні включати оптимізацію рівня GPU

  • TF2 Eager повільніше, ніж TF1 Eager - це ... несподівано. Дивіться результати бенчмаркінгу нижче. Відмінності охоплюють від незначних до значних, але є послідовними. Не впевнений, чому це так - якщо роз'яснений розробник TF, відповідь буде оновлено.


TF2 проти TF1 : цитування відповідних частин розробника TF, Q. Скотта Чжу, відповідь - з / б мій акцент та переформулювання:

У нетерпінні час виконання повинен виконувати ops та повертати числове значення для кожного рядка коду python. Характер виконання одного кроку призводить до того, що воно відбувається повільно .

У TF2 Керас використовує tf.function для складання свого графіка для тренувань, оцінювання та прогнозування. Ми називаємо їх «функцією виконання» для моделі. У TF1 "функцією виконання" була FuncGraph, яка поділяла деякий загальний компонент як функцію TF, але має іншу реалізацію.

Під час процесу ми якось залишили неправильну реалізацію для train_on_batch (), test_on_batch () та predict_on_batch () . Вони все ще є чисельно правильними , але функція виконання для x_on_batch - це чиста функція python, а не функція, що обгорнула функцію python. Це спричинить повільність

У TF2 ми перетворюємо всі вхідні дані в tf.data.Dataset, за допомогою якого ми можемо уніфікувати нашу функцію виконання для обробки одного типу входів. Можливо, у конверсії набору даних буде деяка накладна оплата , і я думаю, що це разова накладні витрати, а не витрати на одну партію

З останнім реченням останнього абзацу вище та останнім пунктом нижче абзацу:

Щоб подолати повільність у режимі нетерпіння, у нас є @ tf.function, яка перетворить функцію пітона в графік. Коли числове значення подачі, як np масив, тіло функції tf.function перетворюється в статичний графік, оптимізуючи його, і повертає кінцеве значення, яке є швидким і повинно мати аналогічні показники, як графічний режим TF1.

Я не згоден - за моїми результатами профілювання, які показують, що обробка вхідних даних Eager є значно повільнішою, ніж у Graph. Крім того, не впевнені, tf.data.Datasetзокрема, але Eager неодноразово викликає кілька одних і тих же методів перетворення даних - див. Профілер.

Нарешті, пов’язана програма dev: Значна кількість змін для підтримки циклів Keras v2 .


Шлейфи поїздів : залежно від (1) Eager vs. Graph; (2) формат вхідних даних, навчання буде проходити в с виразним контуром поїзда - в TF2, _select_training_loop(), training.py , один з:

training_v2.Loop()
training_distributed.DistributionMultiWorkerTrainingLoop(
              training_v2.Loop()) # multi-worker mode
# Case 1: distribution strategy
training_distributed.DistributionMultiWorkerTrainingLoop(
            training_distributed.DistributionSingleWorkerTrainingLoop())
# Case 2: generator-like. Input is Python generator, or Sequence object,
# or a non-distributed Dataset or iterator in eager execution.
training_generator.GeneratorOrSequenceTrainingLoop()
training_generator.EagerDatasetOrIteratorTrainingLoop()
# Case 3: Symbolic tensors or Numpy array-like. This includes Datasets and iterators 
# in graph mode (since they generate symbolic tensors).
training_generator.GeneratorLikeTrainingLoop() # Eager
training_arrays.ArrayLikeTrainingLoop() # Graph

Кожен по-різному обробляє розподіл ресурсів і несе наслідки для продуктивності та можливостей.


Поїзд Loops: fitпроти train_on_batch, kerasпротиtf.keras : кожен з чотирьох використань різних контурів поїзда, хоча , можливо , не у всіх можливих комбінаціях. keras' fit, наприклад, використовує форму fit_loop, наприклад training_arrays.fit_loop(), і його train_on_batchможе використовувати K.function(). tf.kerasмає більш складну ієрархію, описану в частині попереднього розділу.


Поїзд циклів: документація - відповідний джерело docstring про деякі з різних методів виконання:

На відміну від інших операцій TensorFlow, ми не перетворюємо числові входи python в тензори. Крім того, для кожного окремого числового значення пітона формується новий графік

function створює окремий графік для кожного унікального набору вхідних форм і типів даних .

Одному об'єкту tf.function може знадобитися зіставити декілька обчислювальних графіків під кришкою. Це повинно бути видно лише як продуктивність (графіки відстеження мають ненульову обчислювальну та пам’ятну вартість )


Процесори вхідних даних : аналогічно вище, процесор вибирається в кожному конкретному випадку, залежно від внутрішніх прапорів, встановлених відповідно до конфігурацій виконання (режим виконання, формат даних, стратегія розподілу). Найпростіший випадок з Eager, який працює безпосередньо з масивами Numpy. Деякі конкретні приклади дивіться у цій відповіді .


РОЗМІР МОДЕЛІ, РОЗМІР ДАНИХ:

  • Є вирішальним; жодна конфігурація не увінчалася всіма розмірами моделі та даних.
  • Розмір дані щодо розміру моделі має важливе значення; для невеликих даних та моделі передача даних (наприклад, процесор до GPU) може домінувати накладні витрати. Крім того, невеликі накладні процесори можуть працювати повільніше на великих даних за домінуючий час перетворення даних (див. convert_to_tensorУ розділі "ПРОФІЛЕР")
  • Швидкість різниться за різними засобами обробки ресурсів для процесорів вхідних та вхідних даних.

БЕНЧМАРКИ : м'ясо, що перемелюється. - Word Document - таблиця Excel


Термінологія :

  • % без чисел - всі секунди
  • % обчислено як (1 - longer_time / shorter_time)*100; обґрунтування: нас цікавить , який фактор швидший за інший; shorter / longerнасправді є нелінійним відношенням, не корисним для прямого порівняння
  • Визначення знаку%:
    • TF2 проти TF1: +якщо TF2 швидше
    • GvE (Graph vs. Eager): +якщо графік швидший
  • TF2 = TensorFlow 2.0.0 + Keras 2.3.1; TF1 = TensorFlow 1.14.0 + Keras 2.2.5

ПРОФІЛЕР :


ПРОФІЛЕР - Пояснення : Профілер IDE Spyder 3.3.6.

  • Деякі функції повторюються в гніздах інших; отже, важко відстежити точний поділ між функціями "обробка даних" та "навчанням", тому буде певне збіг - як це виражено в останньому результаті.

  • % цифр обчислюється wrt час виконання мінус час складання

  • Час побудови обчислюється шляхом підсумовування всіх (унікальних) час виконання, які були названі 1 або 2 рази
  • Навчайте час, що обчислюється, підсумовуючи всі (унікальні) тривалість виконання, які називались у той самий # раз, як ітерації, і деякі з них.
  • На жаль, функції функціонують відповідно до їхніх оригінальних назв (тобто вони _func = funcматимуть профіль як func), що змішується під час збирання - звідси необхідність виключити його

ТЕСТОВА ОКОЛНІСТЬ :

  • Виконаний код внизу w / мінімальні фонові завдання, що виконуються
  • Графічний процесор був "розігрітий" без декількох ітерацій перед тимчасовими ітераціями, як пропонується в цьому дописі
  • CUDA 10.0.130, cuDNN 7.6.0, TensorFlow 1.14.0 та TensorFlow 2.0.0, створені з джерела, плюс Анаконда
  • Python 3.7.4, Spyder 3.3.6 IDE
  • GTX 1070, Windows 10, 24 Гб оперативної пам'яті DDR4 2,4 МГц, процесор i7-7700HQ 2,8 ГГц

МЕТОДОЛОГІЯ :

  • Орієнтовний показник "малий", "середній" та "великий" модель та розміри даних
  • Виправте # параметрів для кожного розміру моделі, незалежно від розміру вхідних даних
  • "Більша" модель має більше параметрів і шарів
  • "Більші" дані мають більш довгу послідовність, але однакові batch_sizeіnum_channels
  • Моделі використовують тільки Conv1D, Dense«Ті, що навчаються» шари; Уникнути RNN на реалізацію TF-версії. відмінності
  • Завжди проїжджав один поїзд, розташований поза шлейфом тестування, щоб опустити побудову моделі та оптимізатора
  • Не використовуються розріджені дані (наприклад layers.Embedding()) або розріджені цілі (наприклад,SparseCategoricalCrossEntropy()

ОБМЕЖЕННЯ : "повна" відповідь пояснювала б кожен можливий цикл поїзда та ітератор, але це, безумовно, поза моїми можливостями в часі, неіснуюча зарплата або загальна необхідність. Результати настільки ж хороші, як і методологія - інтерпретувати відкрито.


КОД :

import numpy as np
import tensorflow as tf
import random
from termcolor import cprint
from time import time

from tensorflow.keras.layers import Input, Dense, Conv1D
from tensorflow.keras.layers import Dropout, GlobalAveragePooling1D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras.backend as K
#from keras.layers import Input, Dense, Conv1D
#from keras.layers import Dropout, GlobalAveragePooling1D
#from keras.models import Model 
#from keras.optimizers import Adam
#import keras.backend as K

#tf.compat.v1.disable_eager_execution()
#tf.enable_eager_execution()

def reset_seeds(reset_graph_with_backend=None, verbose=1):
    if reset_graph_with_backend is not None:
        K = reset_graph_with_backend
        K.clear_session()
        tf.compat.v1.reset_default_graph()
        if verbose:
            print("KERAS AND TENSORFLOW GRAPHS RESET")

    np.random.seed(1)
    random.seed(2)
    if tf.__version__[0] == '2':
        tf.random.set_seed(3)
    else:
        tf.set_random_seed(3)
    if verbose:
        print("RANDOM SEEDS RESET")

print("TF version: {}".format(tf.__version__))
reset_seeds()

def timeit(func, iterations, *args, _verbose=0, **kwargs):
    t0 = time()
    for _ in range(iterations):
        func(*args, **kwargs)
        print(end='.'*int(_verbose))
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_model_small(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 40, strides=4, padding='same')(ipt)
    x     = GlobalAveragePooling1D()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_medium(batch_shape):
    ipt = Input(batch_shape=batch_shape)
    x = ipt
    for filters in [64, 128, 256, 256, 128, 64]:
        x  = Conv1D(filters, 20, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_large(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(64,  400, strides=4, padding='valid')(ipt)
    x     = Conv1D(128, 200, strides=1, padding='valid')(x)
    for _ in range(40):
        x = Conv1D(256,  12, strides=1, padding='same')(x)
    x     = Conv1D(512,  20, strides=2, padding='valid')(x)
    x     = Conv1D(1028, 10, strides=2, padding='valid')(x)
    x     = Conv1D(256,   1, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)    
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), \
           np.random.randint(0, 2, (batch_shape[0], 1))

def make_data_tf(batch_shape, n_batches, iters):
    data = np.random.randn(n_batches, *batch_shape),
    trgt = np.random.randint(0, 2, (n_batches, batch_shape[0], 1))
    return tf.data.Dataset.from_tensor_slices((data, trgt))#.repeat(iters)

batch_shape_small  = (32, 140,   30)
batch_shape_medium = (32, 1400,  30)
batch_shape_large  = (32, 14000, 30)

batch_shapes = batch_shape_small, batch_shape_medium, batch_shape_large
make_model_fns = make_model_small, make_model_medium, make_model_large
iterations = [200, 100, 50]
shape_names = ["Small data",  "Medium data",  "Large data"]
model_names = ["Small model", "Medium model", "Large model"]

def test_all(fit=False, tf_dataset=False):
    for model_fn, model_name, iters in zip(make_model_fns, model_names, iterations):
        for batch_shape, shape_name in zip(batch_shapes, shape_names):
            if (model_fn is make_model_large) and (batch_shape is batch_shape_small):
                continue
            reset_seeds(reset_graph_with_backend=K)
            if tf_dataset:
                data = make_data_tf(batch_shape, iters, iters)
            else:
                data = make_data(batch_shape)
            model = model_fn(batch_shape)

            if fit:
                if tf_dataset:
                    model.train_on_batch(data.take(1))
                    t0 = time()
                    model.fit(data, steps_per_epoch=iters)
                    print("Time/iter: %.4f sec" % ((time() - t0) / iters))
                else:
                    model.train_on_batch(*data)
                    timeit(model.fit, iters, *data, _verbose=1, verbose=0)
            else:
                model.train_on_batch(*data)
                timeit(model.train_on_batch, iters, *data, _verbose=1)
            cprint(">> {}, {} done <<\n".format(model_name, shape_name), 'blue')
            del model

test_all(fit=True, tf_dataset=False)

Я не впевнений, що ваш код правильний. Я думаю, що ваші моделі завжди працюють у графічному режимі, оскільки ви телефонуєте model.compileбез run_eagerly=Trueаргументів. Якщо в режимі нетерпіння, ви можете запустити частину коду в графічному режимі, використовуючи tf.function. Тому я вважаю, що реалізація за замовчуванням compile- це створити обчислювальний графік, а не запускати його охоче з міркувань продуктивності. Також зауважте, що якщо ваша модель є звивистою, то ви не бачите прискорення в графічному режимі, оскільки взаємодія пітона мінімальна. Якщо у вас багато можливостей з математики, це може призвести до значних змін (також у використанні пам'яті).
користувач2781994

@OverLordGoldDragon, але в TF 2 режим нетерпіння за замовчуванням, але model.compileбез run_eagerly=Trueзабезпечення режиму графіків, чи ні?
користувач2781994

@OverLordGoldDragon Я погоджуюся, що не всі імпортовані методи працюють у графічному режимі, але я вважаю, що model.compileабо model.fitповинен забезпечити, щоб навчання проходило у графічному режимі всередині.
користувач2781994

@ OverLordGoldDragon TRUE - "tf.keras.Model.compile бере три важливі аргументи: ... Крім того, щоб переконатися, що модель тренується та оцінюється працездатно, ви можете переконатися, що вона передається run_eagerly=Trueяк параметр для компіляції." (джерело tensorflow.org/guide/keras/overview ) Тому я, якщо ви не передаєтеrun_eagerly=True модель, МОЖЕ запускатись у графічному режимі. Я не впевнений, що є вирішальним фактором, але чому б він не працював у графічному режимі, якщо він більш ефективний, ніж прагнутий.
користувач2781994

Ви хочете більше доказів? :) "За замовчуванням ми спробуємо скомпілювати вашу модель до статичного графіка, щоб забезпечити найкращі показники виконання." ( github.com/tensorflow/tensorflow/blob/r2.0/tensorflow/python/… )
користувач2781994
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.