Визуализация процесса обучения нейронной сети средствами TensorFlowKit

    Hint
    Перед прочтением этой статьи советую ознакомиться с предыдущей статьей о TensorFlowKit и поставить star репозиторию.

    Я не люблю читать статьи, сразу иду на GitHub
    GitHub: TensorFlowKit
    GitHub: Example
    GitHub: Другое
    TensorFlowKit API
    Посeтив репозиторий, добавьте его в «Stars» это поможет мне написать больше статей на эту тему.

    image

    Начиная работать в сфере машинного обучения, мне было тяжело переходить от объектов и их поведений к векторам и пространствам. Сперва все это достаточно тяжело укладывалось в голове и далеко не все процессы казались прозрачными и понятными с первого взгляда. По этой причине все, что происходило внутри моих наработок, я пробовал визуализировать: строил 3D модели, графики, диаграммы, изображения и тд.

    Говоря об эффективной разработке систем машинного обучения, всегда поднимается вопрос контроля скорости обучения, анализа процесса обучения, сбора различных метрик обучения и тд. Особая сложность заключается в том, что мы (люди) привыкли оперировать 2х и 3х мерными пространствами, описывая различные процессы вокруг нас. Процессы внутри нейронных сетей происходят в многомерных пространствах, что серьезно усложняет их понимание. Осознавая это, инженеры по всему миру стараются разработать различные подходы к визуализации или трансформации многомерных данных в более простые и понятные формы.

    Существуют целые сообщества, решающие такого рода задачи, например Distill, Welch Labs, 3Blue1Brown.


    TensorBoard


    Еще до начала работы с TensorFlow я начал работать с TensorBoard пакетом. Оказалось, что это очень удобное, кросплатформенное решение для визуализации разного рода данных. Потребовалось пару дней, чтоб “научить” swift приложение создавать отчеты в формате TensorBoard и интегрировать в мою нейронную сеть.

    Разработка TensorBoard началась еще в середине 2015 года в рамках одной из лабораторий Google. В конце 2015го Google открыл исходный код и работа над проектом стала публичной.
    Текущая версия TensorBoard — это python пакет, созданный в помощь TensorFlow, который позволяет визуализировать несколько типов данных:

    • Скалярные данные в разрезе времени, с возможностью сглаживания;
    • Изображения, в том случае, если ваши данные можно представить в 2D, например: веса сверточной сети (они же фильтры);
    • Непосредственно граф вычислений (в виде интерактивного представления);
    • 2D изменение значения тензора во времени;
    • 3D Гистограмма — изменение распределения данных в тензоре во времени;
    • Текст;
    • Audio;

    Кроме того, существует еще проектор (projector) и возможность расширять TensorBoard при помощи плагинов, но об этом я рассказать не успею в этой статье.

    Для работы нам понадобится TensorBoard на нашем компьютере (Ubuntu или Mac). У нас должен быть установлен python3. Я советую установить TensorBoard как часть TensorFlow пакета для python.

    Linux:
    $ sudo apt-get install python3-pip python3-dev
    $ pip3 install tensorflow
    
    MacOS:
    $ brew install python3
    $ pip3 install tensorflow
    

    Запускаем TensorBoard, указав папку в которой мы будем хранить отчеты:

    $ tensorboard --logdir=/tmp/example/
    

    Открываем http://localhost:6006/


    TensorFlowKit


    Пример на GitHub
    Не забудьте поставить «start» репозиторию.

    Рассмотрим несколько случаев уже непосредственно на примере. Создание отчетов (summary) в формате TensorBoard происходит в момент конструирования графа вычислений. В TensorFlowKit я постарался максимально повторить python подходы и интерфейс, чтобы в дальнейшем можно было пользоваться общей документацией.

    Как я уже сказал выше, каждый наш отчет мы собираем в summary. Это контейнер, в котором хранится массив value, каждый из которых представляет какое — либо событие, которое мы хотим визуализировать.

    Summary в дальнейшем будет сохранен в файл на файловой системе, где его и прочтет TensorBoard.

    image

    Таким образом, нам необходимо создать FileWriter, указав граф, который мы хотим визуализировать и создать Summary, в который мы будем складывать наши значения.

    let summary = Summary(scope: scope)
    let fileWriter = try FileWriter(folder: writerURL, identifier: "iMac", graph: graph)
    

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

    image

    Далее, мы хотим видеть изменение некой скалярной величины во времени, например значение функции потерь (loss function or cost function) и accuracy нашей нейронной сети. Для этого добавляем выходы наших операций в summary:

    try summary.scalar(output: accuracy, key: "scalar-accuracy")
    try summary.scalar(output: cross_entropy, key: "scalar-loss")
    

    Таким образом, после каждого шага вычислений нашей сессии, TensorFlow автоматически вычитает значения наших операций и передаст их на вход результирующего Summary, который мы сохраним в FileWriter (как это сделать я опишу ниже).

    image

    Также у нас в нейросети есть большее количество весов и предубеждений (bias). Как правило это различные матрицы достаточно большой размерности и анализировать их значения распечатывая крайне сложно. Будет лучше, если мы построим график распределений (distribution). Добавим в наш Summary еще и информацию о величине изменений весов, которую проделывает наша сеть после каждого шага обучения.

    try summary.histogram(output: bias.output, key: "bias")
    try summary.histogram(output: weights.output, key: "weights")
    try summary.histogram(output: gradientsOutputs[0], key: "GradientDescentW")
    try summary.histogram(output: gradientsOutputs[1], key: "GradientDescentB")
    

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

    image

    image

    Но это еще не все. Давайте действительно заглянем в устройство нашей нейронной сети.
    Каждая картинка рукописного текста, полученная на вход, находит некое отражение в соответствующих ей весах. То есть, поданная на вход картинка умеет активировать определенные нейроны, тем самым имеет некий отпечаток внутри нашей сети. Напомню, что мы имеем 784 веса на каждый нейрон из 10. Таким образом, у нас 7840 весов. Все они представлены в виде матрицы 784x10. Попробуем развернуть всю матрицу в вектор и после этого “вытащить” веса, которые относятся к каждому отдельному классу:

    let flattenConst = try scope.addConst(values: [Int64(7840)], dimensions: [1], as: "flattenShapeConst")
    
    let imagesFlattenTensor = try scope.reshape(operationName: "FlattenReshape",
         tensor: weights.variable,
         shape: flattenConst.defaultOutput,
         tshape: Int64.self)
    
    try extractImage(from: imagesFlattenTensor, scope: scope, summary: summary, atIndex: 0)
    try extractImage(from: imagesFlattenTensor, scope: scope, summary: summary, atIndex: 1)
    …
    try extractImage(from: imagesFlattenTensor, scope: scope, summary: summary, atIndex: 8)
    try extractImage(from: imagesFlattenTensor, scope: scope, summary: summary, atIndex: 9)
    

    Для этого добавим в граф еще несколько операций stridedSlice и reshape. Теперь, каждый полученный вектор добавим в Summary как картинку:

    try summary.images(name: "Image-\(String(index))", output: imagesTensor, maxImages: 255, badColor: Summary.BadColor.default)
    

    В разделе Images в TensorBoard мы теперь видим “отпечатки” весов, такими какими они были во время процесса обучения.

    image

    Осталось только обработать наш Summary. Для этого нам надо соединить все созданные Summary в один и обработать его во время обучения сети.

    let _ = try summary.merged(identifier: "simple")
    

    В момент работы нашей сети:

    let resultOutput = try session.run(inputs: [x, y],
         values: [xTensorInput, yTensorInput],
         outputs: [loss, applyGradW, applyGradB, mergedSummary, accuracy],
         targetOperations: [])
    
    let summary = resultOutput[3]
    try fileWriter?.addSummary(tensor: summary, step: Int64(index))
    

    Прошу обратить внимание, что в этом примере я не рассматриваю вопрос вычисления accuracy, он вычисляется на данных обучения. Вычислять его на данных для обучения неверно.

    image

    image

    В следующей статье я постараюсь рассказать, как собрать одну нейросеть и запустить ее на Ubuntu, MacOS, iOS из одного репозитория.

    Only registered users can participate in poll. Log in, please.

    О какой теме Вы бы хотели почитать в следующий раз?

    • 24.3%Градиентный спуск средствами TensorFlow27
    • 30.6%Как сделать одну нейросеть для Linux, iOS, MacOS, tvOS34
    • 35.1%Больше примеров возможностей TensorFlowKit39
    • 9.9%Так и не получил ответ на вопрос о смысле жизни!11
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 14

      0
      А вы пробовали пользоваться tf.summary.tensor_summary? Или я не понимаю для чего оно предназначено или оно не работет. Можете подсказать как с этой штукой работать?
        0
        Вы говорите, о вызове метода на языке Python. Вся статья (как и предыдущая) рассказывает о том, как использовать TensorFlow в языке Swift.
          0
          Да, я понимаю, но ведь в Swift-библиотеке есть аналог этого метода? Приходилось вам им пользоваться?
            0
            О какой swift библиотеке вы говорите? Не существует официальной реализации (как и полноценной не официальной) TensorFlow для Swift.
            Именно по этой причине я написал свою реализацию — TensorFlowKit.
              0
              Да, я её и имею в виду, но по сути это не так и важно, вопрос в равной степени относится и к самому tensorflow.
              Вы пишите что
              В TensorFlowKit я постарался максимально повторить python подходы и интерфейс, чтобы в дальнейшем можно было пользоваться общей документацией.

              Соответственно меня и интересует есть ли в вашей библиотеке аналог tf.summary.tensor_summary, пробовали ли вы им пользоваться и есть ли там какие-то нюансы?
                0
                Да, в бибилиотеке TensorFlowKit (автором которой являюсь я), реализован аналог Python API (tf.summary.tensor_summary) класс Summary. Об этом статья и написана.
                У меня складывается впечатление, что Вы не владеете темой TensorFlow in other languages. Советюую ознакомится с этой статьей.

                  +1
                  А у вас получалось сохранять для tensorboard какие-нибудь данные через этот метод? Дело в том что теже .scalar .histogram работают отлично и отображаются через tensorboard а вот с tensor_summary у меня не получилось вывести данные. Если вас не затруднит можете показать пример?
                    0
                    Да, все что вы видите в этой статье реализовано полностью средствами Swift.
                    Скажите, на каком языке Вы пробовали и если можно, покажите пример того, что не работает.
                      0
                      Я пробовал на python:
                      train_writer = tf.summary.FileWriter(a.log_dir, sess.graph)
                      tf.summary.scalar('cross_entropy', cross_entropy)
                      tf.summary.tensor_summary('outputs', y_s)
                      tf.summary.tensor_summary('expected', y_)
                      merged = tf.summary.merge_all()
                              ....
                      summary, _cross_entropy, _y_s = sess.run([merged, cross_entropy, y_s], feed_dict={x: x_validation_matrix, y_: y_validation_matrix})
                      train_writer.add_summary(summary, chunk_num)
                      


                      При этом cross_entropy отображается также как и у вас — в виде графика, а вот тензоры я нигде не вижу.
                        0
                        Скорее всего, Вы имеете в виду Histogram:

                        tf.summary.histogram('histogram', var)
                        


                        Но это «свернутое» отображение в виде распределения:
                        The TensorBoard Histogram Dashboard displays how the distribution of some Tensor in your TensorFlow graph has changed over time. It does this by showing many histograms visualizations of your tensor at different points in time.


                        Так, что будьте внимательны.
                          0
                          Нет histogram это другой метод, я имею ввиду tensor_summary
                            0
                            Что непосредственно вы хотите видеть, как это должно выглядеть?
                            У вас есть тенсор n*m (скорее всего вектор, n*1). Он изменяется во времени.
                            В TensodBoard нет представления для такой конструкции. Можно конечно поиграться с image. Но скорее всего ваши данные нельзя представить в виде image.

                            В идеале что — то такое должно быть.
                            image
                            Но такого нет.
                              0

                              Нет, я просто хочу сохранить тензор с данными (также как мы, например, сохраняем промежуточные изображения) чтобы потом через tensorboard посмотреть этот тензор просто в виде вектора/матрицы и т.п.
                              Я допускаю что я мог просто не так понять предназначение этого метода. Думал, может вы сталкивались и знаете зачем он нужен и как правильно пользоваться.

                      0
                      Сам summary это только контейнер для SummaryValue.

                      # То есть Вам надо создать value:
                      tf.summary.scalar("Reward", episode_reward)
                      tf.summary.scalar("Reward2", episode_reward2)
                      
                      # Смержить все Summary в один Output
                      summary_op = tf.summary.merge_all()
                      
                      # Добавить summary на "просчет" в сессию.
                      summary_str = session.run(summary_op)
                      
                      # Передать результат в контроллер которые сохранит в файл.
                      ...
                      writer = writer_summary(summary_dir + "/tmp/", session.graph)
                      writer.add_summary(summary_str, float(T))
                      

        Only users with full accounts can post comments. Log in, please.