Краткое руководство OneFlow «Глубокое приложение»

глубокое обучение

В реальности сложных систем не бывает
-- "Минимализм" Парадигма 1: На самом деле все очень просто

0. Введение

Зачем писать эту статью?

  1. Это не реклама, автор не большой V, никто не связывался, чтобы написать рукопись, будьте уверены, есть.

  2. Это не кусок аналитического текста, а уровень автора ограничен и не может дать глубокую интерпретацию.zhuanlan.zhihu.com/p/85111240Анализ TF2.0 в этой статье очень короткий, что всех рассмешило.

  3. Это можно рассматривать как техническую статью, в которой сравнивается сложность OneFlow с основными средами глубокого обучения за счет установки OneFlow и легкого начала работы.

Краткий анализ статус-кво фреймворков глубокого обучения:

Хотя это не аналитическая статья, в ней все же есть некоторый анализ фреймворка глубокого обучения. Можно сказать, что текущими основными средами глубокого обучения (за исключением сред вывода) являются TensorFlow, PyTorch и MXNet, На самом деле, это также конкуренция за капитал и ресурсы, стоящие за ними. TensorFlow по-прежнему находится в выгодном положении благодаря своей полноте и накоплению в развертывании, что вынуждает PyTorch, MXNet и другие нишевые фреймворки жертвовать ONNX, чтобы разрушить монополию развертывания TensorFlow. PyTorch успешно отобрал у TensorFlow большую часть научного сообщества, во многом благодаря своему правильному направлению: вместо того, чтобы бороться штыком с точки зрения преимуществ TensorFlow, он сосредоточился на болевых точках TensorFlow, чтобы привлечь пользователей за счет простоты использования. MXNet сложно конкурировать с TensorFlow и PyTorch, а некоторые преимущества самой MXNet не являются болевым синдромом TensorFlow и PyTorch, поэтому пользователям трудно мотивировать переход.

С другой стороны, PaddlePaddle от Baidu, несмотря на то, что открытый исходный код появился очень рано, находится в прохладном состоянии. Это правда, что отечественная структура не может конкурировать с основной международной структурой, и разрыв все еще огромен. Но в этом году четыре отечественных учреждения или компании выбрали открытый исходный код: MineSpore от Huawei, Jittor от Tsinghua, MegEngine от Questyle и лидирующую на сегодняшний день технологию OneFlow. Несмотря на то, что это не очень конкурентоспособно, в условиях торговых трений между Китаем и США независимым правам собственности уделяется все больше и больше внимания.

На самом деле, по моему скромному мнению, разработчиков волнует не то, какой фреймворк они используют, а больше полнота и простота использования этого фреймворка. В то время крупные разработчики, перешедшие с TensorFlow1.x на PyTorch, могут показать, что бренд не очень важен для разработчиков, а важно, хорош фреймворк или нет. Поэтому автор по-прежнему положительно и оптимистично относится к отечественному фреймворку с открытым исходным кодом.Если вы сделаете его хорошо, у вас будет поддержка пользователей.

Далее давайте посмотрим, как это делает OneFlow.

1. Начать

Некоторые из следующих элементов взяты из документации по разработке OneFlow:docs.oneflow.org/index.html

1.0 Краткое введение

Что такое OneFlow?

OneFlow — это новая архитектура с открытым исходным кодом, ведущая в мире универсальная среда глубокого обучения промышленного уровня.

В чем преимущество OneFlow?

  • Новый опыт распределенного обучения, несколько машин и несколько карт так же просто, как одна машина и одна карта
  • Идеально подходит для универсальной платформы (k8s + докер)
  • Встроенная поддержка очень больших моделей
  • Почти нулевые накладные расходы во время выполнения, линейное ускорение
  • Гибкая поддержка нескольких компиляторов глубокого обучения
  • Точность автоматического смешивания
  • Нейтралитет и открытость, широкое сотрудничество
  • Постоянно улучшаемый набор операторов и библиотека моделей

1.1 Руководство по установке

Установите стабильную версию OneFlow

Системные требования: установлен обязательный драйвер Nvidia и CUDA

  • Python >= 3.5
  • Nvidia Linux x86_64 driver version >= 440.33

Инструкции по установке OneFlow с устаревшей CUDA следующие:

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu102 --user

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu101 --user

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu100 --user

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu92 --user

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu91 --user

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu90 --user

Как проверить родную версию драйвера Nvidia Linux x86_64? Вы можете увидеть версию драйвера автора: 450.57

(base) song@songxpc:~$ nvidia-smi

+-----------------------------------------------------------------------------+

| NVIDIA-SMI 450.57       Driver Version: 450.57       CUDA Version: 11.0     |

|-------------------------------+----------------------+----------------------+

| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |

| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |

|===============================+======================+======================|

|   0  GeForce RTX 208...  Off  | 00000000:01:00.0 Off |                  N/A |

| 47%   54C    P2    80W / 257W |   5136MiB / 11019MiB |     38%      Default |

+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+

|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |

|=============================================================================|

|    0   N/A  N/A      1668      G   /usr/bin/totem                     10MiB |

|    0   N/A  N/A      1974      G   /usr/lib/xorg/Xorg                857MiB |

|    0   N/A  N/A      2128      G   /usr/bin/gnome-shell              331MiB |

|    0   N/A  N/A      2563      G   ...token=2514374358980620094      376MiB |

|    0   N/A  N/A     14664      C   python                           2531MiB |

|    0   N/A  N/A     27295      G   ...AAAAAAAAA= --shared-files      872MiB |

|    0   N/A  N/A     31690      G   ...token=3577040725527546973      149MiB |

+-----------------------------------------------------------------------------+

Как проверить родную версию cuda? Вы можете видеть, что Cuda автора 10.2

(base) song@songxpc:~$ nvcc -V

nvcc: NVIDIA (R) Cuda compiler driver

Copyright (c) 2005-2019 NVIDIA Corporation

Built on Wed_Oct_23_19:24:38_PDT_2019

Cuda compilation tools, release 10.2, V10.2.89

Затем установите инфраструктуру OneFlow через Conda, Conda рекомендует установить miniconda.

Введите последовательно:

conda create --name OF python=3.7 -y

conda install cudatoolkit=10.2 cudnn=7 -y

pip install --find-links https://oneflow-inc.github.io/nightly oneflow_cu102 --user

Протестируйте установку с помощью следующей команды:

(OF) song@songxpc:~$ python

Python 3.7.8 | packaged by conda-forge | (default, Jul 31 2020, 02:25:08) 

Type "help", "copyright", "credits" or "license" for more information.

Начните через 3 минуты

В этой статье описывается, как быстро начать работу с OneFlow, мы можем выполнить полный процесс обучения нейронной сети за 3 минуты.

запустить пример

Если OneFlow уже установлен, вы можете загрузить его с помощью следующей командыРепозиторий документациисерединаmlp_mnist.pyскрипт и запустите.

wget https://docs.oneflow.org/code/quick_start/mlp_mnist.py 

Вы получите вывод, аналогичный следующему:

Выход представляет собой строку чисел, и каждое число представляет значение потери после каждого раунда обучения Цель обучения состоит в том, что чем меньше значение потери, тем лучше. На данный момент вы завершили обучение полной нейронной сети с помощью OneFlow.

Интерпретация кода

Ниже приведен полный код.

import oneflow.typing as tp

@flow.global_function(type="train")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

with flow.scope.placement("cpu", "0:0"):

        initializer = flow.truncated_normal(0.1)

        reshape = flow.reshape(images, [images.shape[0], -1])

        hidden = flow.layers.dense(

            kernel_initializer=initializer,

        logits = flow.layers.dense(

            hidden, 10, kernel_initializer=initializer, 

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(labels, logits)

    lr_scheduler = flow.optimizer.PiecewiseConstantScheduler([], [0.1])

    flow.optimizer.SGD(lr_scheduler, momentum=0).minimize(loss)

if __name__ == "__main__":

    check_point = flow.train.CheckPoint()

    (train_images, train_labels), (test_images, test_labels) = flow.data.load_mnist(

for i, (images, labels) in enumerate(zip(train_images, train_labels)):

        loss = train_job(images, labels)

Далее давайте кратко представим этот код.

Здесь OneFlow более особенный, чем другие фреймворки глубокого обучения:

@flow.global_function(type="train")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

train_jobэто@flow.global_functionДекорированные функции, часто называемые рабочими функциями. только по@flow.global_functionOneFlow может распознавать только декорированную функцию задания, а тип задания определяется типом: type="train" — задание обучения; type="predict" — задание проверки или прогнозирования.

Для обучения или прогнозирования нейронной сети в OneFlow требуются две части информации:

  • Частью этого является структура и связанные с ней параметры самой нейронной сети, которые определены в упомянутой выше функции работы;
  • Другая часть заключается в том, какая конфигурация используется для обучения сети, напримерlearning rate, метод оптимизации и обновления модели. Эти рабочие функции настраиваются следующим образом:

lr_scheduler = flow.optimizer.PiecewiseConstantScheduler([], [0.1]) flow.optimizer.SGD(lr_scheduler, momentum=0).minimize(loss)

Этот код содержит все элементы для обучения нейронной сети, кроме упомянутой выше функции задания и ее конфигурации:

  • check_point.init(): Инициализировать параметры сетевой модели;
  • flow.data.load_mnist(BATCH_SIZE,BATCH_SIZE): подготавливать и загружать обучающие данные;
  • train_job(images, labels): вернуть значение потерь каждой тренировки;
  • print(loss.mean()): Каждые 20 раз тренировки выведите значение потери.

Выше приведен пример простой сети, гдеРаспознавание рукописного ввода с использованием сверточных нейронных сетейВ , у нас есть более полное и конкретное введение в процесс использования OneFlow. Также см. OneFlowОсновные темыПодробное введение в различные проблемы в обучении. Он также предоставляет некоторые классические сетевыеобразец кодаи данные для справки.

2. Анализ

Распознавание рукописных цифр MNIST

В этой статье мы узнаем:

  • Настройка аппаратной и программной среды с помощью интерфейса oneflow
  • Используйте определение интерфейса oneflow для обучения модели
  • Реализовать функцию обучающей работы oneflow
  • Сохранение и загрузка модели
  • Реализовать функцию задания проверки oneflow

Эта статья знакомит вас с основными аспектами использования OneFlow с использованием модели LeNet и обучения набора данных MNIST Полный пример кода прилагается в конце статьи.

Перед изучением вы также можете просмотреть каждую функцию скрипта с помощью следующей команды (  Работа скрипта зависит от GPU).

Сначала синхронизируйте этот репозиторий документов и переключитесь на соответствующий путь:

git clone https://github.com/Oneflow-Inc/oneflow-documentation.git

cd oneflow-documentation/cn/docs/code/quick_start/
  • обучение модели python lenet_train.py
    Приведенная выше команда обучит набор данных MNIST и сохранит модель.

вывод:

File mnist.npz already exist, path: ./mnist.npz

Обученная модель выглядит следующим образом.lenet_eval.py и lenet_test.py, вы также можете напрямую загрузить и использовать обученную нами модель, пропустив этап обучения

wget https://oneflow-public.oss-cn-beijing.aliyuncs.com/online_document/docs/quick_start/lenet_models_1.zip
  • проверка модели python lenet_eval.py
    Вышеупомянутая команда использует тестовый набор MNIST для проверки только что созданной модели и дает точность.

вывод:

File mnist.npz already exist, path: ./mnist.npz
  • Идентификация изображения
python lenet_test.py ./9.png

Приведенная выше команда будет использовать ранее обученную модель, чтобы предсказать, что находится на подготовленном нами изображении «9.png». Вы также можете скачать насИзвлеченные mnist картинки, чтобы самостоятельно проверить эффект предсказания обученной модели.

Введение в набор данных MNIST

MNIST — это база данных рукописных цифр. Обучающий набор и тестовый набор включены; обучающий набор содержит 60 000 изображений и меток, соответствующих изображениям, а тестовый набор содержит 60 000 изображений и метки теста изображений. Yann LeCun и другие нормализовали и центрировали изображение и упаковали его в виде двоичного файла для загрузки.yann.lecun.com/exdb/mnist/

Определение модели обучения

существует oneflow.nn и oneflow.layersПредоставляет некоторые операторы для построения моделей.

def lenet(data, train=False):

    initializer = flow.truncated_normal(0.1)

    conv1 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool1 = flow.nn.max_pool2d(

        conv1, ksize=2, strides=2, padding="SAME", 

    conv2 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool2 = flow.nn.max_pool2d(

        conv2, ksize=2, strides=2, padding="SAME", 

    reshape = flow.reshape(pool2, [pool2.shape[0], -1])

    hidden = flow.layers.dense(

        kernel_initializer=initializer,

        hidden = flow.nn.dropout(hidden, rate=0.5, )

return flow.layers.dense(hidden, 10, kernel_initializer=initializer, )

В приведенном выше коде мы строим сетевую модель LeNet.

Реализовать функцию задания на обучение

Доступно в OneFlowoneflow.global_functionДекоратор, с помощью которого функцию Python можно превратить в функцию задания обучения.

декоратор global_function

oneflow.global_functionДекоратор принимает тип в качестве параметра для указания типа задания, type="train" указывает тип задания как обучение, а type="predict" указывает тип задания как прогнозирование или проверку. Внутри декоратора также естьfunction_configПараметры объекта используются для определенных типов конфигурации задания.

@flow.global_function(type="train")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

один из них tp.Numpy.Placeholderзаполнитель данных,tp.NumpyУказывает, что при вызове этой функции задания она возвращаетnumpyобъект.

Укажите функции оптимизации

мы можем пройтиflow.optimizerИнтерфейс определяет оптимизируемые параметры и оптимизатор. Таким образом, OneFlow будет использовать указанный способ в качестве цели оптимизации во время каждой итерации задания обучения.

@flow.global_function(type="train")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=True)

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(

            labels, logits, 

    lr_scheduler = flow.optimizer.PiecewiseConstantScheduler([], [0.1])

    flow.optimizer.SGD(lr_scheduler, momentum=0).minimize(loss)

Выше мы проходимflow.nn.sparse_softmax_cross_entropy_with_logitsНайдите потерю и используйте оптимизированную потерю в качестве целевого параметра.

lr_schedulerГрафик скорости обучения установлен, [0,1] указывает, что начальная скорость обучения составляет 0,1;

flow.optimizer.SGDОптимизатор указывается как sgd; loss передается как параметр для минимизации, чтобы указать, что оптимизатор будет стремиться минимизировать потери.

Вызов рабочих функций и взаимодействие

Обучение можно начать, вызвав функцию задания.

Результат, возвращаемый при вызове функции задания, определяется типом возвращаемого значения, указанным при определении функции задания.Он может возвращать один или несколько результатов.

Пример возврата результата

существуетlenet_train.pyОпределите функцию работы в:

@flow.global_function(type="train")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=True)

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(

            labels, logits, 

    lr_scheduler = flow.optimizer.PiecewiseConstantScheduler([], [0.1])

    flow.optimizer.SGD(lr_scheduler, momentum=0).minimize(loss)

Тип возвращаемого значения функции задания:tp.Numpy, то при вызове он вернетnumpyОбъект:

for i, (images, labels) in enumerate(zip(train_images, train_labels)):

            loss = train_job(images, labels)

мы звалиtrain_jobИ печатать 1 раз каждые 20 цикловloss.

Пример возврата нескольких результатов

код в модели проверкиlenet_eval.pyФункция работы определена в:

@flow.global_function(type="predict")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

) -> Tuple[tp.Numpy, tp.Numpy]:

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=False)

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(

            labels, logits, 

Тип возвращаемого значения функции задания:Tuple[tp.Numpy, tp.Numpy], то при вызове он вернетtupleКонтейнер с 2 элементами внутри, каждый элемент представляет собойnumpyОбъект:

for i, (images, labels) in enumerate(zip(test_images, test_labels)):

            labels, logits = eval_job(images, labels)

Мы вызвали функцию задания и вернулиlabelsиlogitsи использовать их для оценки точности модели.

Синхронные и асинхронные вызовы

Все коды в этой статье вызывают функции заданий синхронно. На самом деле OneFlow также поддерживает асинхронный вызов функций заданий. Подробности см.Получить результат работы функцииПодробно описано в статье.

Инициализация модели, сохранение и загрузка

Инициализация и сохранение модели

oneflow.train.CheckPointОбъект, созданный классом, можно использовать для инициализации, сохранения и загрузки модели. Во время обучения мы можем пройтиinitМетод инициализирует модель черезsaveметод сохранения модели. Например:

if __name__ == '__main__':

  check_point = flow.train.CheckPoint()

  check_point.save('./lenet_models_1')

После успешного сохранения мы получим файл с именем «lenet_models_1».содержание, который содержит подкаталоги и файлы, соответствующие параметрам модели.

загрузка модели

В процессе проверки или прогнозирования мы можем пройтиoneflow.train.CheckPoint.loadметод для загрузки существующих параметров модели. Например:

if __name__ == '__main__':

  check_point = flow.train.CheckPoint()

  check_point.load("./lenet_models_1")

load автоматически считывает ранее сохраненную модель и загружает ее.

проверка модели

Функция проверки работы и функция обученияпочти нет разницы, разница в том, что параметры модели в процессе проверки берутся из модели, которая была сохранена, поэтому нет необходимости инициализировать и обновлять параметры модели в процессе итерации.

Написание функции задания проверки

@flow.global_function(type="predict")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

) -> Tuple[tp.Numpy, tp.Numpy]:

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=False)

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(

            labels, logits, 

Выше приведена подготовка функции проверки обучения, которая объявляет, что тип возвращаемого значения —Tuple[tp.Numpy, tp.Numpy], тем самым возвращаяtuple,tupleимеет 2 элемента, каждый из которых равен 1numpyобъект. Мы вызовем функцию задания обучения и рассчитаем точность на основе возвращенных результатов.

Итерационная проверка

следующее accОбщее количество статистических выборок в функции и общее количество правильных проверок, мы будем вызывать функцию задания, чтобы получитьlabels и logits:

    predictions = np.argmax(logits, 1)

    right_count = np.sum(predictions == labels)

    g_total += labels.shape[0]

Вызов функции задания проверки:

if __name__ == "__main__":

    check_point = flow.train.CheckPoint()

    check_point.load("./lenet_models_1")

    (train_images, train_labels), (test_images, test_labels) = flow.data.load_mnist(

for i, (images, labels) in enumerate(zip(test_images, test_labels)):

            labels, logits = eval_job(images, labels)

    print("accuracy: {0:.1f}%".format(g_correct * 100 / g_total))

Выше функция проверки вызывается циклически, и, наконец, выводится показатель точности оценки для тестового набора.

картинка предсказания

Изменив приведенный выше проверочный код так, чтобы проверочные данные поступали из исходного изображения, а не из готового набора данных, мы можем использовать модель для прогнозирования изображения.

    im = Image.open(file).convert("L")

    im = im.resize((28, 28), Image.ANTIALIAS)

    im = np.array(im).reshape(1, 1, 28, 28).astype(np.float32)

    im = (im - 128.0) / 255.0

    im.reshape((-1, 1, 1, im.shape[1], im.shape[2]))

    check_point = flow.train.CheckPoint()

    check_point.load("./lenet_models_1")

    image = load_image(sys.argv[1])

    logits = eval_job(image, np.zeros((1,)).astype(np.int32))

    prediction = np.argmax(logits, 1)

    print("prediction: {}".format(prediction[0]))

if __name__ == "__main__":

полный код

Обучите модель

Код:lenet_train.py

import oneflow.typing as tp

def lenet(data, train=False):

    initializer = flow.truncated_normal(0.1)

    conv1 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool1 = flow.nn.max_pool2d(

        conv1, ksize=2, strides=2, padding="SAME", 

    conv2 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool2 = flow.nn.max_pool2d(

        conv2, ksize=2, strides=2, padding="SAME", 

    reshape = flow.reshape(pool2, [pool2.shape[0], -1])

    hidden = flow.layers.dense(

        kernel_initializer=initializer,

        hidden = flow.nn.dropout(hidden, rate=0.5, )

return flow.layers.dense(hidden, 10, kernel_initializer=initializer, )

@flow.global_function(type="train")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=True)

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(

            labels, logits, 

    lr_scheduler = flow.optimizer.PiecewiseConstantScheduler([], [0.1])

    flow.optimizer.SGD(lr_scheduler, momentum=0).minimize(loss)

if __name__ == "__main__":

    flow.config.gpu_device_num(1)

    check_point = flow.train.CheckPoint()

    (train_images, train_labels), (test_images, test_labels) = flow.data.load_mnist(

for i, (images, labels) in enumerate(zip(train_images, train_labels)):

            loss = train_job(images, labels)

    check_point.save("./lenet_models_1")  

модель проверки

Код:lenet_eval.py

Предварительно обученная модель:lenet_models_1.zip

import oneflow.typing as tp

def lenet(data, train=False):

    initializer = flow.truncated_normal(0.1)

    conv1 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool1 = flow.nn.max_pool2d(

        conv1, ksize=2, strides=2, padding="SAME", 

    conv2 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool2 = flow.nn.max_pool2d(

        conv2, ksize=2, strides=2, padding="SAME", 

    reshape = flow.reshape(pool2, [pool2.shape[0], -1])

    hidden = flow.layers.dense(

        kernel_initializer=initializer,

        hidden = flow.nn.dropout(hidden, rate=0.5, )

return flow.layers.dense(hidden, 10, kernel_initializer=initializer, )

@flow.global_function(type="predict")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

) -> Tuple[tp.Numpy, tp.Numpy]:

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=False)

        loss = flow.nn.sparse_softmax_cross_entropy_with_logits(

            labels, logits, 

    predictions = np.argmax(logits, 1)

    right_count = np.sum(predictions == labels)

    g_total += labels.shape[0]

if __name__ == "__main__":

    check_point = flow.train.CheckPoint()

    check_point.load("./lenet_models_1")

    (train_images, train_labels), (test_images, test_labels) = flow.data.load_mnist(

for i, (images, labels) in enumerate(zip(test_images, test_labels)):

            labels, logits = eval_job(images, labels)

    print("accuracy: {0:.1f}%".format(g_correct * 100 / g_total))

цифровой прогноз

Код:lenet_test.py

Предварительно обученная модель:lenet_models_1.zip

Изображение набора данных MNISTmnist_raw_images.zip

import oneflow.typing as tp

        os.path.basename(sys.argv[0]), os.path.join(".", "9.png")

def lenet(data, train=False):

    initializer = flow.truncated_normal(0.1)

    conv1 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool1 = flow.nn.max_pool2d(

        conv1, ksize=2, strides=2, padding="SAME", 

    conv2 = flow.layers.conv2d(

        kernel_initializer=initializer,

    pool2 = flow.nn.max_pool2d(

        conv2, ksize=2, strides=2, padding="SAME", 

    reshape = flow.reshape(pool2, [pool2.shape[0], -1])

    hidden = flow.layers.dense(

        kernel_initializer=initializer,

        hidden = flow.nn.dropout(hidden, rate=0.5, )

return flow.layers.dense(hidden, 10, kernel_initializer=initializer, )

@flow.global_function(type="predict")

    images: tp.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),

    labels: tp.Numpy.Placeholder((BATCH_SIZE,), dtype=flow.int32),

with flow.scope.placement("gpu", "0:0"):

        logits = lenet(images, train=False)

    im = Image.open(file).convert("L")

    im = im.resize((28, 28), Image.ANTIALIAS)

    im = np.array(im).reshape(1, 1, 28, 28).astype(np.float32)

    im = (im - 128.0) / 255.0

    im.reshape((-1, 1, 1, im.shape[1], im.shape[2]))

    check_point = flow.train.CheckPoint()

    check_point.load("./lenet_models_1")

    image = load_image(sys.argv[1])

    logits = eval_job(image, np.zeros((1,)).astype(np.int32))

    prediction = np.argmax(logits, 1)

    print("prediction: {}".format(prediction[0]))

if __name__ == "__main__":

3. Резюме

Видно, что построение и обучение модели OneFlow по-прежнему очень просты и удобны в использовании, а стоимость перехода на этот фреймворк невелика. Автор собирается сделать перерыв в писательстве и тренировках, надеюсь, у всех будет хорошее тело (~~). .

-1. Ссылка

-10. «Дорога к королю» с 0.1 до 2.0 в одной статье, чтобы прочитать историю борьбы TensorFlow - Минималистский AI Xiao Song - это статья - Знаяzhuanlan.zhihu.com/p/85111240

-11.docs.oneflow.org/build_video/…