Мое впечатление о курсе Tensorflow в Стэнфорде: задание 1
Первое задание этого курса охватывает 3 основные проблемы. Первый - это просто заполнение недостающих фрагментов кода для решения простых задач. Второй - реализация модели глубокой нейронной сети, которая дает точность 97% + на наборе данных MNIST. И третий - реализация модели CBOW. Вы можете найти задание здесь.
№1. Проблема 1
Эта часть в первую очередь проверяет ваши базовые знания Tensorflow.
а) Проблема: создайте два случайных 0-мерных тензора x и y любого распределения. Создайте объект TensorFlow, который возвращает x + y, если x ›y, и x - y в противном случае. Подсказка: найдите tf.cond ()
Решение:
Ссылка: tf.cond ()
б) Проблема: создайте два 0-мерных тензора x и y, случайно выбранных из диапазона [-1, 1). Вернуть x + y, если x ‹y, x - y, если x› y, 0 в противном случае. Подсказка: найдите tf.case ().
Решение:
Ссылка: tf.case ()
c) Проблема: создайте тензор x значения [[0, -2, -1], [0, 1, 2]] и y как тензор нулей с одинаковыми форма как x. Возвращает логический тензор, который дает Истину, если x равно y поэлементно. Подсказка: найдите tf.equal ().
Решение:
Ссылка: tf.zeros_like () и tf.equal ()
г) Задача: создайте тензор x значения [29.05088806, 27.61298943, 31.19073486, 29.35532951, 30.97266006, 26.67541885, 38.08450317, 20.74983215, 34.94445419, 34.45999146, 30.061648605327, 36.0.5999146, 29.061648605327, 36.0, 29.061648602327, 36 , 29.51215172, 33.71149445, 28.59134293, 36.05556488, 28.66994858]. Получите индексы элементов в x, значения которых больше 30. Подсказка: используйте tf.where (). Затем извлеките элементы, значения которых больше 30. Совет: используйте tf.gather ().
Решение:
д) Проблема: создайте диагональный двумерный тензор размером 6 x 6 с диагональными значениями 1, 2,…, 6. Совет: используйте tf.range () и tf. diag ().
Решение:
Ссылка: tf.diag ()
е) Проблема: создайте случайный двумерный тензор размером 10 x 10 из любого распределения. Вычислите его определитель. Подсказка: посмотрите на tf.matrix_determinant ().
Решение:
Ссылка: tf.random_uniform и tf.matrix_determinant () - объяснение определителя матрицы.
ж) Проблема: создайте тензор x со значением [5, 2, 3, 5, 10, 6, 2, 3, 4, 2, 1, 1, 0, 9]. Вернуть уникальные элементы в x. Подсказка: используйте tf.unique (). Имейте в виду, что tf.unique () возвращает кортеж.
Решение:
Ссылка: tf.unique ()
h) Проблема: Создайте два тензора x и y формы 300 из любого нормального распределения, если они принадлежат одному и тому же распределению. Используйте tf.cond () для возврата:
- среднеквадратичная ошибка (x - y), если среднее значение всех элементов в (x - y) отрицательно, или
- сумма абсолютных значений всех элементов тензора (x - y) в противном случае.
Совет: см. функцию потерь Хубера на слайдах лекции 3.
Решение:
№2. Проблема 2
Эта задача состоит из 2 частей: улучшить модель логистической регрессии для достижения точности 97% + для набора данных MNIST или построить новую модель логистической регрессии для набора данных, отличного от MNIST.
Я начал настраивать гиперпараметры этой модели с кода примера. Я также изменил функции активации и сделал другие небольшие улучшения. К сожалению, ни одна из моих попыток не привела к результату 97% + на тестовых данных. Если вам удастся найти соответствующие изменения, я буду рад видеть их в разделе комментариев.
Итак, я поискал модели, которые дают наилучшие результаты, и нашел этот красивый список, который вдохновил меня на попытку создать простую трехслойную сверточную нейронную сеть.
Теперь я объясню полную реализацию ниже. Имейте в виду, что вам это может показаться черным ящиком, но вы получите лучшее понимание сверточных нейронных сетей в моей следующей статье.
Этот код ниже следует за этим примером Tensorflow.
Начнем шаг за шагом:
- Импортировать библиотеки
numpy и tensorflow должны быть достаточно знакомы, utils используется для загрузки набора данных MNIST. В общем, utils используется для сбора наиболее распространенных функций и операций, используемых в Python.
- Создайте сверточную нейронную сеть
Он состоит из 2 сверточных слоев, за каждым из которых следует слой максимального пула, а в конце - плотный слой.
Сверточный слой - создает карты характеристик после применения окна фильтра к входным данным (изначально это само изображение).
Уровень объединения - используется для уменьшения размера представления изображения во время обучения.
Плотный слой - это последний слой в модели, который является результатом полного соединения между всеми нейронами в предыдущем слое.
Здесь вы можете найти разницу между этими слоями. Дополнительно здесь - краткое объяснение CNN.
# 0. Наша модельная функция получает входные данные (изображения) и метки в качестве параметров. Кроме того, мы добавляем mode, который используется для Tensorflow Estimator, о чем я расскажу ниже.
№1. Изменить форму ввода
Мы изменяем данные в соответствии с концепцией: [batch_size, image_width, image_height, num_channels]. Поскольку изображения имеют оттенки серого, num_channels равно 1. batch_size имеет значение -1, что означает, что это измерение должно динамически вычисляться на основе количества входных значений.
№2. Первый сверточный слой
Мы используем функцию Tensorflow tf.layers.conv2d (). Позвольте мне быстро объяснить, что означает каждый параметр:
- input_layer - текущая матрица ввода, это может быть исходное изображение или его реформированная версия.
- фильтры - после свертки ввода с окном размера (размер_ядра) мы получаем новую матрицу, где его (ширина, высота) = (input_layer.width - kernel_size.width + 1, input_layer.height— kernel_size.height + 1). Фильтры определяют количество матриц указанного выше размера, сложенных вместе.
- kernel_size - размер окна, которое будет перемещаться по входной матрице.
- padding - тип заполнения, который нам нужно использовать при достижении краев окна входной матрицы. Более подробную информацию смотрите здесь.
- активация - применить функцию relu, которая преобразует значение каждого нейрона (если меньше 0, перейти в 0, в противном случае остается прежним)
№3. Первый максимальный уровень пула
Мы используем Tensorflow tf.layers.max_pooling2d для выполнения уровня максимального пула, который уменьшает размер матрицы conv1.
- pool_size - размер окна, из которого мы выбираем наибольшее значение.
- strides - количество ячеек, которое нам нужно провести по матрице conv1.
№4. Второй сверточный слой
То же, что и первый сверточный слой, с той лишь разницей, что количество фильтров - 64.
№5. Второй максимальный слой пула
№6. Плотный слой
Это последний уровень в CNN.
- Сначала мы сглаживаем второй слой максимального пула, преобразовывая его в двумерный массив, имеющий 7 (ширина) * 7 (высота) * 64 (глубина) = 3136 нейронов.
- Используем типичный плотный слой с размерностью вывода 1024. Подробнее здесь.
- Применение отсева на плотном слое, которое случайным образом удаляет 40% (коэффициент = 0,4) единиц, чтобы предотвратить переоснащение.
- В итоге мы получаем последний плотный слой с 10 единицами - количеством разных цифр от 0 до 9.
- Используйте tf.argmax для получения классов.
- Нормализуйте логиты, чтобы они находились в диапазоне (0, 1).
№7. Потери и оптимизатор
Давайте рассмотрим функцию потерь:
- Если мы находимся в режиме прогнозирования, просто верните оценщик с прогнозом (см. Ниже объяснение оценщика TF).
- Если мы находимся в режиме обучения, создайте onehot_labels на основе ожидаемых значений модели. Понять, как происходит это преобразование, можно здесь.
- Наконец, мы вычисляем функцию потерь, используя softmax_cross_entropy с ожидаемыми значениями в виде onehot_labels и прогнозируемыми значениями в виде логитов. Если название softmax_cross_entropy звучит для вас неоднозначно, взгляните на этот ответ Quora о разнице между softmax (тип функции активации) и cross_entropy (функция потерь).
Теперь посмотрим на оптимизатор:
Он используется для обновления весов в направлении, которое минимизирует функцию потерь. Global_step предназначен только для отслеживания количества пакетов.
- Мы выполняем описанные выше действия только в режиме обучения.
- В качестве оптимизатора мы используем обычный оптимизатор градиентного спуска со скоростью обучения 0,001. Вот красивый список со всеми отличительными оптимизаторами градиентов.
- Наконец, мы минимизируем функцию потерь.
В случае режима оценки мы просто возвращаем, как часто метки соответствуют прогнозам, используя tf.metric.accuracy.
Основная цель функции потерь и оптимизатора - настроить веса нашей сети так, чтобы ошибка между нашими предсказанными значениями (логиты) а фактические результаты (метки) сведены к минимуму, а прогноз максимально приближен к истине.
№8. Оценщик тензорного потока
API-интерфейс Tensorflow высокого уровня, который помогает обучать, оценивать и тестировать вашу модель. Подробнее об этом вы можете прочитать в документации. Ниже я объясню, как наша модель использует этот Оценщик:
- Один из типов использования: tf.estimator.ModeKeys, который может быть TRAIN, EVAL, PREDICT и определяет текущий режим.
- Другой тип: tf.estimator.EstimatorSpec, который предоставляет информацию о текущем состоянии модели основному объекту оценщика.
- Вы также можете увидеть создание основного объекта Оценщика с помощью tf.estimator.Estimator, который принимает представление модели.
- Наконец, функция tf.estimator.inputs.numpy_input_fn дает представление данных и, используя .train и .evaluate, мы получаем результаты нашей модели.
№3. Проблема 3
Эта задача состоит из 3 частей, наиболее важной из которых является 3c, которая просит вас реализовать модель CBOW, настроив предоставленный код для skip-граммы. В этой статье я только покажу, как реализовать 3c. Если у вас возникли трудности с выполнением 3a и 3b, оставьте комментарий внизу, и мы сможем обсудить это.
Мы будем модифицировать код скип-граммы, изменив следующие функции:
- _create_embedding (строка 54):
Из скип-грамма:
Из CBOW:
- _create_loss (строка 64):
Из скип-грамма:
Из CBOW:
По любым вопросам, касающимся изменений в коде, оставляйте комментарии ниже или пишите мне по электронной почте: simeon dot kostadinoff at gmail dot com.