Microsoft Cognitive Toolkit - Краткое руководство

В этой главе мы узнаем, что такое CNTK, его особенности, разница между версиями 1.0 и 2.0 и важные особенности версии 2.7.

Что такое Microsoft Cognitive Toolkit (CNTK)?

Microsoft Cognitive Toolkit (CNTK), ранее известный как Computational Network Toolkit, представляет собой бесплатный, простой в использовании набор инструментов коммерческого уровня с открытым исходным кодом, который позволяет нам обучать алгоритмы глубокого обучения, чтобы учиться подобно человеческому мозгу. Это позволяет нам создавать популярные системы глубокого обучения, напримерfeed-forward neural network time series prediction systems and Convolutional neural network (CNN) image classifiers.

Для оптимальной производительности функции его фреймворка написаны на C ++. Хотя мы можем вызывать его функцию с помощью C ++, но наиболее часто используемый подход - это использование программы Python.

Особенности CNTK

Ниже приведены некоторые функции и возможности, предлагаемые в последней версии Microsoft CNTK:

Встроенные компоненты

  • CNTK имеет хорошо оптимизированные встроенные компоненты, которые могут обрабатывать многомерные плотные или разреженные данные из Python, C ++ или BrainScript.

  • Мы можем внимательно реализовать CNN, FNN, RNN, Batch Normalization и Sequence-to-Sequence.

  • Он предоставляет нам возможность добавлять новые определяемые пользователем основные компоненты на GPU из Python.

  • Он также обеспечивает автоматическую настройку гиперпараметров.

  • Мы можем реализовать обучение с подкреплением, генеративные состязательные сети (GAN), контролируемое и неконтролируемое обучение.

  • Для массивных наборов данных CNTK имеет встроенные оптимизированные считыватели.

Эффективное использование ресурсов

  • CNTK обеспечивает параллелизм с высокой точностью на нескольких графических процессорах / машинах через 1-битный SGD.

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

Легко выражайте наши собственные сети

  • CNTK имеет полные API-интерфейсы для определения вашей собственной сети, учащихся, читателей, обучения и оценки на Python, C ++ и BrainScript.

  • Используя CNTK, мы можем легко оценивать модели с помощью Python, C ++, C # или BrainScript.

  • Он предоставляет как высокоуровневые, так и низкоуровневые API.

  • Основываясь на наших данных, он может автоматически формировать вывод.

  • Он имеет полностью оптимизированные символьные циклы рекуррентной нейронной сети (RNN).

Измерение производительности модели

  • CNTK предоставляет различные компоненты для измерения производительности создаваемых вами нейронных сетей.

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

Версия 1.0 против версии 2.0

Следующая таблица сравнивает CNTK версии 1.0 и 2.0:

Версия 1.0 Версия 2.0
Он был выпущен в 2016 году. Это значительная переработка версии 1.0, выпущенная в июне 2017 года.
Он использовал собственный язык сценариев под названием BrainScript. Его каркасные функции можно вызывать с помощью C ++, Python. Мы легко можем загрузить наши модули на C # или Java. BrainScript также поддерживается версией 2.0.
Он работает как в системах Windows, так и в Linux, но не непосредственно в Mac OS. Он также работает в системах Windows (Win 8.1, Win 10, Server 2012 R2 и новее) и Linux, но не непосредственно в Mac OS.

Важные особенности версии 2.7

Version 2.7это последняя основная выпущенная версия Microsoft Cognitive Toolkit. Имеет полную поддержку ONNX 1.4.1. Ниже приведены некоторые важные моменты этой последней выпущенной версии CNTK.

  • Полная поддержка ONNX 1.4.1.

  • Поддержка CUDA 10 для систем Windows и Linux.

  • Он поддерживает расширенный цикл рекуррентных нейронных сетей (RNN) в экспорте ONNX.

  • Он может экспортировать модели объемом более 2 ГБ в формате ONNX.

  • Он поддерживает FP16 в обучающем действии языка сценариев BrainScript.

Здесь мы разберемся с установкой CNTK в Windows и Linux. Кроме того, в главе объясняется установка пакета CNTK, шаги по установке Anaconda, файлы CNTK, структура каталогов и организация библиотеки CNTK.

Предпосылки

Чтобы установить CNTK, на наших компьютерах должен быть установлен Python. Вы можете перейти по ссылкеhttps://www.python.org/downloads/и выберите последнюю версию для вашей ОС, то есть Windows и Linux / Unix. Базовое руководство по Python можно найти по ссылкеhttps://www.tutorialspoint.com/python3/index.htm.

CNTK поддерживается как для Windows, так и для Linux, поэтому мы рассмотрим их оба.

Установка в Windows

Чтобы запустить CNTK в Windows, мы будем использовать Anaconda versionPython. Мы знаем, что Anaconda - это перераспределение Python. Он включает дополнительные пакеты, такие какScipy иScikit-learn которые используются CNTK для выполнения различных полезных вычислений.

Итак, сначала давайте посмотрим, как установить Anaconda на ваш компьютер -

Step 1−Сначала загрузите установочные файлы с общедоступного веб-сайта https://www.anaconda.com/distribution/.

Step 2 - После того, как вы скачали файлы установки, запустите установку и следуйте инструкциям по ссылке. https://docs.anaconda.com/anaconda/install/.

Step 3- После установки Anaconda также установит некоторые другие утилиты, которые автоматически включат все исполняемые файлы Anaconda в переменную PATH вашего компьютера. Мы можем управлять нашей средой Python из этого приглашения, можем устанавливать пакеты и запускать сценарии Python.

Установка пакета CNTK

После завершения установки Anaconda вы можете использовать наиболее распространенный способ установки пакета CNTK через исполняемый файл pip, используя следующую команду:

pip install cntk

Существуют различные другие методы установки Cognitive Toolkit на ваш компьютер. У Microsoft есть аккуратный набор документации, в которой подробно объясняются другие методы установки. Пройдите по ссылкеhttps://docs.microsoft.com/en-us/cognitive-toolkit/Setup-CNTK-on-your-machine.

Установка в Linux

Установка CNTK в Linux немного отличается от его установки в Windows. Здесь для Linux мы собираемся использовать Anaconda для установки CNTK, но вместо графического установщика для Anaconda мы будем использовать установщик на основе терминала в Linux. Хотя программа установки будет работать практически со всеми дистрибутивами Linux, мы ограничились описанием Ubuntu.

Итак, сначала давайте посмотрим, как установить Anaconda на ваш компьютер -

Шаги по установке Anaconda

Step 1- Перед установкой Anaconda убедитесь, что система полностью обновлена. Чтобы проверить, сначала выполните следующие две команды внутри терминала -

sudo apt update
sudo apt upgrade

Step 2 - После обновления компьютера получите URL-адрес с общедоступного веб-сайта. https://www.anaconda.com/distribution/ для последних установочных файлов Anaconda.

Step 3 - После копирования URL-адреса откройте окно терминала и выполните следующую команду -

wget -0 anaconda-installer.sh url SHAPE \* MERGEFORMAT 
     y

	
	
	             f
 
 
      x
	  
|                     }

Заменить url заполнитель с URL-адресом, скопированным с веб-сайта Anaconda.

Step 4 - Затем с помощью следующей команды мы можем установить Anaconda -

sh ./anaconda-installer.sh

Приведенная выше команда по умолчанию установит Anaconda3 внутри нашего домашнего каталога.

Установка пакета CNTK

После завершения установки Anaconda вы можете использовать наиболее распространенный способ установки пакета CNTK через исполняемый файл pip, используя следующую команду:

pip install cntk

Изучение файлов CNTK и структуры каталогов

После того, как CNTK установлен как пакет Python, мы можем проверить структуру его файлов и каталогов. Это вC:\Users\ \Anaconda3\Lib\site-packages\cntk, как показано ниже на скриншоте.

Проверка установки CNTK

После установки CNTK как пакета Python вы должны убедиться, что CNTK установлен правильно. Из командной оболочки Anaconda запустите интерпретатор Python, введяipython. Затем импортируйте CNTK введя следующую команду.

import cntk as c

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

print(c.__version__)

Интерпретатор ответит установленной версией CNTK. Если он не отвечает, значит, проблема с установкой.

Библиотечная организация CNTK

CNTK, технически пакет Python, состоит из 13 подпакетов высокого уровня и 8 более мелких подпакетов. В следующей таблице представлены 10 наиболее часто используемых пакетов:

Старший Нет Название и описание пакета
1

cntk.io

Содержит функции для чтения данных. Например: next_minibatch ()

2

cntk.layers

Содержит высокоуровневые функции для создания нейронных сетей. Например: Плотный ()

3

cntk.learners

Содержит функции для обучения. Например: sgd ()

4

cntk.losses

Содержит функции для измерения ошибки обучения. Например: squared_error ()

5

cntk.metrics

Содержит функции для измерения ошибки модели. Например: classificatoin_error

6

cntk.ops

Содержит низкоуровневые функции для создания нейронных сетей. Например: tanh ()

7

cntk.random

Содержит функции для генерации случайных чисел. Например: normal ()

8

cntk.train

Содержит обучающие функции. Например: train_minibatch ()

9

cntk.initializer

Содержит инициализаторы параметров модели. Например: normal () и uniform ()

10

cntk.variables

Содержит низкоуровневые конструкции. Например: Parameter () и Variable ()

Microsoft Cognitive Toolkit предлагает две разные версии сборки: только для ЦП и только для графического процессора.

Версия сборки только для ЦП

Версия CNTK для сборки только для ЦП использует оптимизированный Intel MKLML, где MKLML является подмножеством MKL (Math Kernel Library) и выпущен вместе с Intel MKL-DNN как завершенная версия Intel MKL для MKL-DNN.

Версия сборки только для GPU

С другой стороны, версия CNTK для сборки только для GPU использует высоко оптимизированные библиотеки NVIDIA, такие как CUB и cuDNN. Он поддерживает распределенное обучение на нескольких графических процессорах и нескольких машинах. Для еще более быстрого распределенного обучения в CNTK версия для GPU-сборки также включает:

  • SGD с 1-битным квантованием, разработанный MSR.

  • Блочно-импульсные алгоритмы параллельного обучения SGD.

Включение графического процессора с CNTK в Windows

В предыдущем разделе мы увидели, как установить базовую версию CNTK для использования с ЦП. Теперь давайте обсудим, как мы можем установить CNTK для использования с графическим процессором. Но, прежде чем углубляться в это, сначала у вас должна быть поддерживаемая видеокарта.

В настоящее время CNTK поддерживает видеокарты NVIDIA с поддержкой как минимум CUDA 3.0. Чтобы убедиться, вы можете проверить наhttps://developer.nvidia.com/cuda-gpus поддерживает ли ваш графический процессор CUDA.

Итак, давайте посмотрим, как включить графический процессор с CNTK в ОС Windows -

Step 1 - В зависимости от видеокарты, которую вы используете, сначала вам необходимо установить последние версии драйверов GeForce или Quadro для вашей видеокарты.

Step 2 - После того, как вы загрузили драйверы, вам необходимо установить инструментарий CUDA версии 9.0 для Windows с веб-сайта NVIDIA. https://developer.nvidia.com/cuda-90-download-archive?target_os=Windows&target_arch=x86_64. После установки запустите установщик и следуйте инструкциям.

Step 3 - Затем вам необходимо установить двоичные файлы cuDNN с веб-сайта NVIDIA. https://developer.nvidia.com/rdp/form/cudnn-download-survey. С версией CUDA 9.0 cuDNN 7.4.1 работает хорошо. По сути, cuDNN - это слой поверх CUDA, используемый CNTK.

Step 4 - После загрузки двоичных файлов cuDNN вам необходимо распаковать zip-файл в корневую папку установки вашего набора инструментов CUDA.

Step 5- Это последний шаг, который позволит использовать GPU внутри CNTK. Выполните следующую команду в командной строке Anaconda в ОС Windows -

pip install cntk-gpu

Включение графического процессора с CNTK в Linux

Давайте посмотрим, как мы можем включить графический процессор с CNTK в ОС Linux -

Скачивание инструментария CUDA

Во-первых, вам необходимо установить набор инструментов CUDA с веб-сайта NVIDIA https://developer.nvidia.com/cuda-90-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1604&target_type = runfilelocal .

Запуск установщика

Теперь, когда у вас есть двоичные файлы на диске, запустите установщик, открыв терминал и выполнив следующую команду и инструкцию на экране -

sh cuda_9.0.176_384.81_linux-run

Изменить скрипт профиля Bash

После установки набора инструментов CUDA на вашем компьютере с Linux вам необходимо изменить сценарий профиля BASH. Для этого сначала откройте файл $ HOME / .bashrc в текстовом редакторе. Теперь в конце скрипта добавьте следующие строки -

export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}} export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64\ ${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
Installing

Установка библиотек cuDNN

Наконец, нам нужно установить двоичные файлы cuDNN. Его можно скачать с сайта NVIDIA.https://developer.nvidia.com/rdp/form/cudnn-download-survey. С версией CUDA 9.0 cuDNN 7.4.1 работает хорошо. По сути, cuDNN - это слой поверх CUDA, используемый CNTK.

После загрузки версии для Linux распакуйте ее в папку /usr/local/cuda-9.0 папку с помощью следующей команды -

tar xvzf -C /usr/local/cuda-9.0/ cudnn-9.0-linux-x64-v7.4.1.5.tgz

При необходимости измените путь к имени файла.

В этой главе мы подробно узнаем о последовательностях в CNTK и их классификации.

Тензоры

Концепция, по которой работает CNTK, tensor. В основном, входы, выходы и параметры CNTK организованы какtensors, который часто рассматривается как обобщенная матрица. Каждый тензор имеетrank -

  • Тензор ранга 0 - скаляр.

  • Тензор ранга 1 - это вектор.

  • Тензор 2-го ранга - аматрикс.

Здесь эти разные размеры называются axes.

Статические оси и динамические оси

Как следует из названия, статические оси имеют одинаковую длину на протяжении всего срока службы сети. С другой стороны, длина динамических осей может варьироваться от экземпляра к экземпляру. Фактически, их длина обычно не известна до представления каждой мини-партии.

Динамические оси похожи на статические, потому что они также определяют значимую группировку чисел, содержащихся в тензоре.

пример

Чтобы было понятнее, давайте посмотрим, как минипакет коротких видеоклипов представлен в CNTK. Предположим, что разрешение всех видеоклипов составляет 640 * 480. Кроме того, клипы снимаются в цвете, который обычно кодируется с помощью трех каналов. Это также означает, что наша мини-партия имеет следующее -

  • 3 статические оси длиной 640, 480 и 3 соответственно.

  • Две динамические оси; длина видео и оси мини-пакета.

Это означает, что если в мини-пакете 16 видео, каждое из которых имеет длину 240 кадров, это будет представлено как 16*240*3*640*480 тензоры.

Работа с последовательностями в CNTK

Давайте разберемся с последовательностями в CNTK, сначала узнав о сети долгосрочной памяти.

Сеть долгосрочной краткосрочной памяти (LSTM)

Сети долговременной краткосрочной памяти (LSTM) были представлены Hochreiter & Schmidhuber. Это решило проблему получения базового повторяющегося слоя, чтобы запоминать вещи на долгое время. Архитектура LSTM приведена выше на схеме. Как мы видим, у него есть входные нейроны, ячейки памяти и выходные нейроны. Чтобы бороться с проблемой исчезающего градиента, сети долговременной памяти используют явную ячейку памяти (хранящую предыдущие значения) и следующие ворота -

  • Forget gate- Как следует из названия, он указывает ячейке памяти забыть предыдущие значения. Ячейка памяти хранит значения до тех пор, пока вентиль, то есть «ворота забыть», не скажет ему забыть их.

  • Input gate - Как следует из названия, он добавляет в ячейку новый материал.

  • Output gate - Как следует из названия, выходной элемент решает, когда перейти по векторам от ячейки к следующему скрытому состоянию.

Работать с последовательностями в CNTK очень просто. Давайте посмотрим на это с помощью следующего примера -

import sys
import os
from cntk import Trainer, Axis
from cntk.io import MinibatchSource, CTFDeserializer, StreamDef, StreamDefs,\
   INFINITELY_REPEAT
from cntk.learners import sgd, learning_parameter_schedule_per_sample
from cntk import input_variable, cross_entropy_with_softmax, \
   classification_error, sequence
from cntk.logging import ProgressPrinter
from cntk.layers import Sequential, Embedding, Recurrence, LSTM, Dense
def create_reader(path, is_training, input_dim, label_dim):
   return MinibatchSource(CTFDeserializer(path, StreamDefs(
      features=StreamDef(field='x', shape=input_dim, is_sparse=True),
      labels=StreamDef(field='y', shape=label_dim, is_sparse=False)
   )), randomize=is_training,
   max_sweeps=INFINITELY_REPEAT if is_training else 1)
def LSTM_sequence_classifier_net(input, num_output_classes, embedding_dim,
LSTM_dim, cell_dim):
   lstm_classifier = Sequential([Embedding(embedding_dim),
      Recurrence(LSTM(LSTM_dim, cell_dim)),
      sequence.last,
      Dense(num_output_classes)])
return lstm_classifier(input)
def train_sequence_classifier():
   input_dim = 2000
   cell_dim = 25
   hidden_dim = 25
   embedding_dim = 50
   num_output_classes = 5
   features = sequence.input_variable(shape=input_dim, is_sparse=True)
   label = input_variable(num_output_classes)
   classifier_output = LSTM_sequence_classifier_net(
   features, num_output_classes, embedding_dim, hidden_dim, cell_dim)
   ce = cross_entropy_with_softmax(classifier_output, label)
   pe =      classification_error(classifier_output, label)
   rel_path = ("../../../Tests/EndToEndTests/Text/" +
      "SequenceClassification/Data/Train.ctf")
   path = os.path.join(os.path.dirname(os.path.abspath(__file__)), rel_path)
   reader = create_reader(path, True, input_dim, num_output_classes)
input_map = {
   features: reader.streams.features,
   label: reader.streams.labels
}
lr_per_sample = learning_parameter_schedule_per_sample(0.0005)
progress_printer = ProgressPrinter(0)
trainer = Trainer(classifier_output, (ce, pe),
sgd(classifier_output.parameters, lr=lr_per_sample),progress_printer)
minibatch_size = 200
for i in range(255):
   mb = reader.next_minibatch(minibatch_size, input_map=input_map)
trainer.train_minibatch(mb)
   evaluation_average = float(trainer.previous_minibatch_evaluation_average)
   loss_average = float(trainer.previous_minibatch_loss_average)
return evaluation_average, loss_average
if __name__ == '__main__':
   error, _ = train_sequence_classifier()
   print(" error: %f" % error)
average  since  average  since  examples
loss     last   metric   last
------------------------------------------------------
1.61    1.61    0.886     0.886     44
1.61     1.6    0.714     0.629    133
 1.6    1.59     0.56     0.448    316
1.57    1.55    0.479      0.41    682
1.53     1.5    0.464     0.449   1379
1.46     1.4    0.453     0.441   2813
1.37    1.28     0.45     0.447   5679
 1.3    1.23    0.448     0.447  11365

error: 0.333333

Подробное объяснение вышеуказанной программы будет рассмотрено в следующих разделах, особенно когда мы будем создавать рекуррентные нейронные сети.

В этой главе рассматривается построение модели логистической регрессии в CNTK.

Основы модели логистической регрессии

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

пример

Давайте разберемся с концепцией логистической регрессии математически с помощью другого примера -

Предположим, мы хотим спрогнозировать кредитоспособность заявки на получение кредита; 0 означает отклонить, а 1 означает одобрить, в зависимости от кандидатаdebt , income и credit rating. Мы представляем долг с X1, доход с X2 и кредитный рейтинг с X3.

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

Теперь предположим,

X1 = 3.0
X2 = -2.0
X3 = 1.0

И предположим, мы определяем вес и смещение следующим образом:

W1 = 0.65, W2 = 1.75, W3 = 2.05 and b = 0.33

Теперь для прогнозирования класса нам нужно применить следующую формулу -

Z = (X1*W1)+(X2*W2)+(X3+W3)+b
i.e. Z = (3.0)*(0.65) + (-2.0)*(1.75) + (1.0)*(2.05) + 0.33
= 0.83

Далее нам нужно вычислить P = 1.0/(1.0 + exp(-Z)). Здесь функция exp () - это число Эйлера.

P = 1.0/(1.0 + exp(-0.83)
= 0.6963

Значение P можно интерпретировать как вероятность того, что класс равен 1. Если P <0,5, прогноз равен class = 0, иначе прогноз (P> = 0,5) равен class = 1.

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

Пример реализации модели LR

Для этой модели LR мы собираемся использовать следующий набор данных -

1.0, 2.0, 0
3.0, 4.0, 0
5.0, 2.0, 0
6.0, 3.0, 0
8.0, 1.0, 0
9.0, 2.0, 0
1.0, 4.0, 1
2.0, 5.0, 1
4.0, 6.0, 1
6.0, 5.0, 1
7.0, 3.0, 1
8.0, 5.0, 1

Чтобы начать реализацию этой модели LR в CNTK, нам нужно сначала импортировать следующие пакеты:

import numpy as np
import cntk as C

Программа структурирована с помощью функции main () следующим образом:

def main():
print("Using CNTK version = " + str(C.__version__) + "\n")

Теперь нам нужно загрузить данные обучения в память следующим образом:

data_file = ".\\dataLRmodel.txt"
print("Loading data from " + data_file + "\n")
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[0,1])
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[2], ndmin=2)

Теперь мы будем создавать программу обучения, которая создает модель логистической регрессии, совместимую с данными обучения -

features_dim = 2
labels_dim = 1
X = C.ops.input_variable(features_dim, np.float32)
y = C.input_variable(labels_dim, np.float32)
W = C.parameter(shape=(features_dim, 1)) # trainable cntk.Parameter
b = C.parameter(shape=(labels_dim))
z = C.times(X, W) + b
p = 1.0 / (1.0 + C.exp(-z))
model = p

Теперь нам нужно создать Lerner и трейнер следующим образом:

ce_error = C.binary_cross_entropy(model, y) # CE a bit more principled for LR
fixed_lr = 0.010
learner = C.sgd(model.parameters, fixed_lr)
trainer = C.Trainer(model, (ce_error), [learner])
max_iterations = 4000

Обучение модели LR

После того, как мы создали модель LR, пора начать процесс обучения -

np.random.seed(4)
N = len(features_mat)
for i in range(0, max_iterations):
row = np.random.choice(N,1) # pick a random row from training items
trainer.train_minibatch({ X: features_mat[row], y: labels_mat[row] })
if i % 1000 == 0 and i > 0:
mcee = trainer.previous_minibatch_loss_average
print(str(i) + " Cross-entropy error on curr item = %0.4f " % mcee)

Теперь, с помощью следующего кода, мы можем распечатать веса и смещение модели:

np.set_printoptions(precision=4, suppress=True)
print("Model weights: ")
print(W.value)
print("Model bias:")
print(b.value)
print("")
if __name__ == "__main__":
main()

Обучение модели логистической регрессии - полный пример

import numpy as np
import cntk as C
   def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
data_file = ".\\dataLRmodel.txt" # provide the name and the location of data file
print("Loading data from " + data_file + "\n")
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[0,1])
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[2], ndmin=2)
features_dim = 2
labels_dim = 1
X = C.ops.input_variable(features_dim, np.float32)
y = C.input_variable(labels_dim, np.float32)
W = C.parameter(shape=(features_dim, 1)) # trainable cntk.Parameter
b = C.parameter(shape=(labels_dim))
z = C.times(X, W) + b
p = 1.0 / (1.0 + C.exp(-z))
model = p
ce_error = C.binary_cross_entropy(model, y) # CE a bit more principled for LR
fixed_lr = 0.010
learner = C.sgd(model.parameters, fixed_lr)
trainer = C.Trainer(model, (ce_error), [learner])
max_iterations = 4000
np.random.seed(4)
N = len(features_mat)
for i in range(0, max_iterations):
row = np.random.choice(N,1) # pick a random row from training items
trainer.train_minibatch({ X: features_mat[row], y: labels_mat[row] })
if i % 1000 == 0 and i > 0:
mcee = trainer.previous_minibatch_loss_average
print(str(i) + " Cross-entropy error on curr item = %0.4f " % mcee)
np.set_printoptions(precision=4, suppress=True)
print("Model weights: ")
print(W.value)
print("Model bias:")
print(b.value)
if __name__ == "__main__":
  main()

Вывод

Using CNTK version = 2.7
1000 cross entropy error on curr item = 0.1941
2000 cross entropy error on curr item = 0.1746
3000 cross entropy error on curr item = 0.0563
Model weights:
[-0.2049]
   [0.9666]]
Model bias:
[-2.2846]

Прогнозирование с использованием обученной модели LR

После обучения модели LR мы можем использовать ее для прогнозирования следующим образом:

Прежде всего, наша программа оценки импортирует пакет numpy и загружает обучающие данные в матрицу функций и матрицу меток классов так же, как и программа обучения, которую мы реализуем выше -

import numpy as np
def main():
data_file = ".\\dataLRmodel.txt" # provide the name and the location of data file
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=(0,1))
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=[2], ndmin=2)

Затем пришло время установить значения весов и смещения, которые были определены нашей программой обучения -

print("Setting weights and bias values \n")
weights = np.array([0.0925, 1.1722], dtype=np.float32)
bias = np.array([-4.5400], dtype=np.float32)
N = len(features_mat)
features_dim = 2

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

print("item pred_prob pred_label act_label result")
for i in range(0, N): # each item
   x = features_mat[i]
   z = 0.0
   for j in range(0, features_dim):
   z += x[j] * weights[j]
   z += bias[0]
   pred_prob = 1.0 / (1.0 + np.exp(-z))
  pred_label = 0 if pred_prob < 0.5 else 1
   act_label = labels_mat[i]
   pred_str = ‘correct’ if np.absolute(pred_label - act_label) < 1.0e-5 \
    else ‘WRONG’
  print("%2d %0.4f %0.0f %0.0f %s" % \ (i, pred_prob, pred_label, act_label, pred_str))

Теперь давайте продемонстрируем, как делать прогнозы -

x = np.array([9.5, 4.5], dtype=np.float32)
print("\nPredicting class for age, education = ")
print(x)
z = 0.0
for j in range(0, features_dim):
z += x[j] * weights[j]
z += bias[0]
p = 1.0 / (1.0 + np.exp(-z))
print("Predicted p = " + str(p))
if p < 0.5: print("Predicted class = 0")
else: print("Predicted class = 1")

Полная программа оценки прогнозов

import numpy as np
def main():
data_file = ".\\dataLRmodel.txt" # provide the name and the location of data file
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=(0,1))
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=[2], ndmin=2)
print("Setting weights and bias values \n")
weights = np.array([0.0925, 1.1722], dtype=np.float32)
bias = np.array([-4.5400], dtype=np.float32)
N = len(features_mat)
features_dim = 2
print("item pred_prob pred_label act_label result")
for i in range(0, N): # each item
   x = features_mat[i]
   z = 0.0
   for j in range(0, features_dim):
     z += x[j] * weights[j]
   z += bias[0]
   pred_prob = 1.0 / (1.0 + np.exp(-z))
   pred_label = 0 if pred_prob < 0.5 else 1
   act_label = labels_mat[i]
   pred_str = ‘correct’ if np.absolute(pred_label - act_label) < 1.0e-5 \
     else ‘WRONG’
  print("%2d %0.4f %0.0f %0.0f %s" % \ (i, pred_prob, pred_label, act_label, pred_str))
x = np.array([9.5, 4.5], dtype=np.float32)
print("\nPredicting class for age, education = ")
print(x)
z = 0.0
for j in range(0, features_dim):
   z += x[j] * weights[j]
z += bias[0]
p = 1.0 / (1.0 + np.exp(-z))
print("Predicted p = " + str(p))
if p < 0.5: print("Predicted class = 0")
else: print("Predicted class = 1")
if __name__ == "__main__":
  main()

Вывод

Установка весов и значений смещения.

Item  pred_prob  pred_label  act_label  result
0   0.3640         0             0     correct
1   0.7254         1             0      WRONG
2   0.2019         0             0     correct
3   0.3562         0             0     correct
4   0.0493         0             0     correct
5   0.1005         0             0     correct
6   0.7892         1             1     correct
7   0.8564         1             1     correct
8   0.9654         1             1     correct
9   0.7587         1             1     correct
10  0.3040         0             1      WRONG
11  0.7129         1             1     correct
Predicting class for age, education =
[9.5 4.5]
Predicting p = 0.526487952
Predicting class = 1

В этой главе рассматриваются концепции нейронной сети в отношении CNTK.

Как мы знаем, несколько слоев нейронов используются для создания нейронной сети. Но возникает вопрос, как в CNTK можно моделировать слои NN? Это можно сделать с помощью функций слоя, определенных в модуле слоя.

Функция слоя

Фактически, в CNTK работа со слоями имеет отчетливое ощущение функционального программирования. Функция слоя выглядит как обычная функция и создает математическую функцию с набором предопределенных параметров. Давайте посмотрим, как мы можем создать самый простой тип слоя, Dense, с помощью функции слоя.

пример

С помощью следующих основных шагов мы можем создать самый простой тип слоя -

Step 1 - Во-первых, нам нужно импортировать функцию Dense layer из пакета слоев CNTK.

from cntk.layers import Dense

Step 2 - Далее из корневого пакета CNTK нам нужно импортировать функцию input_variable.

from cntk import input_variable

Step 3- Теперь нам нужно создать новую входную переменную с помощью функции input_variable. Нам также необходимо указать его размер.

feature = input_variable(100)

Step 4 - Наконец, мы создадим новый слой, используя функцию Dense вместе с указанием количества нейронов, которое мы хотим.

layer = Dense(40)(feature)

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

Полный пример реализации

from cntk.layers import Dense
from cntk import input_variable
feature= input_variable(100)
layer = Dense(40)(feature)

Настройка слоев

Как мы видели, CNTK предоставляет нам довольно хороший набор значений по умолчанию для построения сетевых сетей. На основеactivationфункция и другие настройки, которые мы выбираем, поведение и производительность NN отличаются. Это еще один очень полезный алгоритм стемминга. Поэтому хорошо понимать, что мы можем настроить.

Шаги по настройке плотного слоя

Каждый слой в NN имеет свои уникальные параметры конфигурации, и когда мы говорим о плотном слое, мы должны определить следующие важные параметры:

  • shape - Как следует из названия, он определяет выходную форму слоя, которая дополнительно определяет количество нейронов в этом слое.

  • activation - Он определяет функцию активации этого слоя, поэтому он может преобразовывать входные данные.

  • init- Он определяет функцию инициализации этого слоя. Он инициализирует параметры слоя, когда мы начнем обучать NN.

Давайте посмотрим шаги, с помощью которых мы можем настроить Dense слой -

Step1 - Во-первых, нам нужно импортировать Dense Layer function из пакета слоев CNTK.

from cntk.layers import Dense

Step2 - Далее из пакета CNTK ops нам нужно импортировать sigmoid operator. Он будет использоваться для настройки в качестве функции активации.

from cntk.ops import sigmoid

Step3 - Теперь из пакета инициализатора нам нужно импортировать glorot_uniform инициализатор.

from cntk.initializer import glorot_uniform

Step4 - Наконец, мы создадим новый слой, используя функцию Dense вместе с указанием количества нейронов в качестве первого аргумента. Также предоставьтеsigmoid оператор как activation функция и glorot_uniform как init функция для слоя.

layer = Dense(50, activation = sigmoid, init = glorot_uniform)

Полный пример реализации -

from cntk.layers import Dense
from cntk.ops import sigmoid
from cntk.initializer import glorot_uniform
layer = Dense(50, activation = sigmoid, init = glorot_uniform)

Оптимизация параметров

До сих пор мы видели, как создать структуру NN и как настроить различные параметры. Здесь мы увидим, как мы можем оптимизировать параметры NN. С помощью комбинации двух компонентов, а именноlearners и trainers, мы можем оптимизировать параметры сети.

компонент тренера

Первый компонент, который используется для оптимизации параметров NN, - это trainerсоставная часть. Он в основном реализует процесс обратного распространения ошибки. Если говорить о его работе, он передает данные через NN для получения прогноза.

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

компонент учащегося

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

Учащиеся включены в библиотеку CNTK

Ниже приводится список некоторых из интересных учеников, включенных в библиотеку CNTK.

  • Stochastic Gradient Descent (SGD) - Этот учащийся представляет базовый стохастический градиентный спуск без каких-либо дополнительных функций.

  • Momentum Stochastic Gradient Descent (MomentumSGD) - С SGD этот учащийся применяет импульс, чтобы преодолеть проблему локальных максимумов.

  • RMSProp - Этот учащийся, чтобы контролировать скорость спуска, использует снижающуюся скорость обучения.

  • Adam - Этот ученик, чтобы уменьшить скорость снижения с течением времени, использует затухающий импульс.

  • Adagrad - Этот учащийся, как для часто, так и для редко встречающихся функций, использует разные скорости обучения.

CNTK - Создание первой нейронной сети

В этой главе подробно рассматривается создание нейронной сети в CNTK.

Постройте сетевую структуру

Чтобы применить концепции CNTK для построения нашей первой NN, мы собираемся использовать NN для классификации видов цветов ириса на основе физических свойств ширины и длины чашелистиков, а также ширины и длины лепестков. Набор данных, который мы будем использовать, набор данных ириса, описывающий физические свойства различных сортов цветов ириса -

  • Длина чашелистики
  • Ширина чашелистника
  • Длина лепестка
  • Ширина лепестка
  • Сорт, т. Е. Iris setosa, iris versicolor или iris virginica

Здесь мы будем строить обычную NN, называемую NN прямого распространения. Давайте посмотрим на шаги реализации для построения структуры NN -

Step 1 - Во-первых, мы импортируем необходимые компоненты, такие как типы наших слоев, функции активации и функцию, которая позволяет нам определять входную переменную для нашей NN из библиотеки CNTK.

from cntk import default_options, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import log_softmax, relu

Step 2- После этого мы создадим нашу модель, используя последовательную функцию. После создания мы будем кормить его нужными слоями. Здесь мы собираемся создать два отдельных слоя в нашей сети; один с четырьмя нейронами и другой с тремя нейронами.

model = Sequential([Dense(4, activation=relu), Dense(3, activation=log_sogtmax)])

Step 3- Наконец, чтобы скомпилировать NN, мы привяжем сеть к входной переменной. Он имеет входной слой с четырьмя нейронами и выходной слой с тремя нейронами.

feature= input_variable(4)
z = model(feature)

Применение функции активации

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

На выходном слое

Выбор activation функция на уровне вывода будет зависеть от типа проблемы, которую мы собираемся решить с помощью нашей модели.

  • Для задачи регрессии мы должны использовать linear activation function на выходном слое.

  • Для задачи двоичной классификации мы должны использовать sigmoid activation function на выходном слое.

  • Для задачи классификации на несколько классов мы должны использовать softmax activation function на выходном слое.

  • Здесь мы собираемся построить модель для прогнозирования одного из трех классов. Значит, нам нужно использоватьsoftmax activation function на выходном слое.

На скрытом слое

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

  • В задаче классификации нам необходимо предсказать вероятность принадлежности выборки к определенному классу. Вот почему нам нуженactivation functionчто дает нам вероятностные значения. Чтобы достичь этой цели,sigmoid activation function может нам помочь.

  • Одна из основных проблем, связанных с сигмоидной функцией, - проблема исчезающего градиента. Чтобы преодолеть такую ​​проблему, мы можем использоватьReLU activation function который сводит все отрицательные значения к нулю и работает как сквозной фильтр для положительных значений.

Выбор функции потерь

Как только у нас есть структура для нашей модели NN, мы должны ее оптимизировать. Для оптимизации нам понадобитсяloss function. в отличиеactivation functions, у нас гораздо меньше функций потерь на выбор. Однако выбор функции потерь будет зависеть от типа проблемы, которую мы собираемся решить с помощью нашей модели.

Например, в задаче классификации мы должны использовать функцию потерь, которая может измерить разницу между предсказанным классом и фактическим классом.

функция потерь

Для проблемы классификации мы собираемся решить с помощью нашей модели NN, categorical cross entropyфункция потерь - лучший кандидат. В CNTK это реализовано какcross_entropy_with_softmax который можно импортировать из cntk.losses пакет, как показано ниже:

label= input_variable(3)
loss = cross_entropy_with_softmax(z, label)

Метрики

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

cntk.metrics

CNTK имеет пакет с именем cntk.metricsиз которого мы можем импортировать метрики, которые собираемся использовать. При построении модели классификации мы будем использоватьclassification_error матрица, которая даст число от 0 до 1. Число от 0 до 1 указывает процент правильно предсказанных выборок -

Во-первых, нам нужно импортировать метрику из cntk.metrics пакет -

from cntk.metrics import classification_error
error_rate = classification_error(z, label)

Вышеупомянутой функции на самом деле нужен вывод NN и ожидаемая метка в качестве ввода.

CNTK - Обучение нейронной сети

Здесь мы разберемся с обучением нейронной сети в CNTK.

Обучение модели в CNTK

В предыдущем разделе мы определили все компоненты для модели глубокого обучения. Пришло время его потренировать. Как мы обсуждали ранее, мы можем обучить модель NN в CNTK, используя комбинациюlearner и trainer.

Выбор ученика и настройка обучения

В этом разделе мы будем определять learner. CNTK предоставляет несколькоlearnersвыбирать из. Для нашей модели, определенной в предыдущих разделах, мы будем использоватьStochastic Gradient Descent (SGD) learner.

Для обучения нейронной сети настроим learner и trainer с помощью следующих шагов -

Step 1 - Во-первых, нам нужно импортировать sgd функция от cntk.lerners пакет.

from cntk.learners import sgd

Step 2 - Далее нам нужно импортировать Trainer функция от cntk.train.trainer пакет.

from cntk.train.trainer import Trainer

Step 3 - Теперь нам нужно создать learner. Его можно создать, вызвавsgd функция вместе с предоставлением параметров модели и значения скорости обучения.

learner = sgd(z.parametrs, 0.01)

Step 4 - Наконец, нам нужно инициализировать trainer. Должна быть предусмотрена сеть, комбинацияloss и metric вместе с learner.

trainer = Trainer(z, (loss, error_rate), [learner])

Скорость обучения, которая контролирует скорость оптимизации, должна быть небольшим числом от 0,1 до 0,001.

Выбор учащегося и настройка обучения - Полный пример

from cntk.learners import sgd
from cntk.train.trainer import Trainer
learner = sgd(z.parametrs, 0.01)
trainer = Trainer(z, (loss, error_rate), [learner])

Загрузка данных в трейнер

После того, как мы выбрали и настроили трейнер, пришло время загрузить набор данных. Мы сохранилиiris набор данных как файл.CSV файл, и мы будем использовать пакет обработки данных с именем pandas для загрузки набора данных.

Шаги по загрузке набора данных из файла .CSV

Step 1 - Во-первых, нам нужно импортировать pandas пакет.

from import pandas as pd

Step 2 - Теперь нам нужно вызвать функцию с именем read_csv функция для загрузки файла .csv с диска.

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, 
‘petal_length’, ‘petal_width’, index_col=False)

После загрузки набора данных нам нужно разделить его на набор функций и метку.

Шаги по разделению набора данных на объекты и подписи

Step 1- Во-первых, нам нужно выбрать все строки и первые четыре столбца из набора данных. Это можно сделать, используяiloc функция.

x = df_source.iloc[:, :4].values

Step 2- Затем нам нужно выбрать столбец видов из набора данных ирисов. Мы будем использовать свойство values ​​для доступа к базовомуnumpy массив.

x = df_source[‘species’].values

Шаги по кодированию столбца видов в числовое векторное представление

Как мы обсуждали ранее, наша модель основана на классификации, она требует числовых входных значений. Следовательно, здесь нам нужно кодировать столбец видов в числовое векторное представление. Давайте посмотрим, как это сделать -

Step 1- Во-первых, нам нужно создать выражение списка для перебора всех элементов в массиве. Затем выполните поиск в словаре label_mapping для каждого значения.

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 2- Затем преобразуйте это преобразованное числовое значение в вектор с горячим кодированием. Мы будем использоватьone_hot функционируют следующим образом -

def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result

Step 3 - Наконец, нам нужно превратить этот преобразованный список в numpy массив.

y = np.array([one_hot(label_mapping[v], 3) for v in y])

Шаги по обнаружению переобучения

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

Step 1 - Во-первых, из sklearn пакет, импортируйте train_test_split функция от model_selection модуль.

from sklearn.model_selection import train_test_split

Step 2 - Затем нам нужно вызвать функцию train_test_split с функциями x и метками y следующим образом:

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0-2, 
stratify=y)

Мы указали test_size равным 0,2, чтобы выделить 20% всех данных.

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Шаги по загрузке обучающего набора и набора проверки в нашу модель

Step 1 - Чтобы обучить нашу модель, сначала мы будем вызывать train_minibatchметод. Затем дайте ему словарь, который сопоставляет входные данные с входной переменной, которую мы использовали для определения NN и связанной с ней функции потерь.

trainer.train_minibatch({ features: X_train, label: y_train})

Step 2 - Далее звоните train_minibatch используя следующий цикл for -

for _epoch in range(10):
trainer.train_minbatch ({ feature: X_train, label: y_train})
print(‘Loss: {}, Acc: {}’.format(
trainer.previous_minibatch_loss_average,
trainer.previous_minibatch_evaluation_average))

Загрузка данных в трейнер - Полный пример

from import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, index_col=False)
x = df_source.iloc[:, :4].values
x = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
y = np.array([one_hot(label_mapping[v], 3) for v in y])
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0-2, stratify=y)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
trainer.train_minibatch({ features: X_train, label: y_train})
for _epoch in range(10):
trainer.train_minbatch ({ feature: X_train, label: y_train})
print(‘Loss: {}, Acc: {}’.format(
trainer.previous_minibatch_loss_average,
trainer.previous_minibatch_evaluation_average))

Измерение производительности NN

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

Итак, чтобы измерить производительность модели с использованием тестовых данных, мы можем вызвать test_minibatch метод на trainer следующим образом -

trainer.test_minibatch({ features: X_test, label: y_test})

Прогнозирование с помощью NN

После того как вы обучили модель глубокого обучения, самое важное - делать прогнозы с ее помощью. Чтобы сделать прогноз на основе обученной выше NN, мы можем выполнить следующие шаги:

Step 1 - Во-первых, нам нужно выбрать случайный элемент из тестового набора, используя следующую функцию -

np.random.choice

Step 2 - Затем нам нужно выбрать образцы данных из набора тестов, используя sample_index.

Step 3 - Теперь, чтобы преобразовать числовой вывод в NN в фактическую метку, создайте инвертированное отображение.

Step 4 - Теперь используйте выбранный sampleданные. Сделайте прогноз, вызвав NN z как функцию.

Step 5- Теперь, когда вы получили предсказанный результат, возьмите индекс нейрона, который имеет наибольшее значение, в качестве предсказанного значения. Это можно сделать с помощьюnp.argmax функция от numpy пакет.

Step 6 - Наконец, преобразуйте значение индекса в реальную метку, используя inverted_mapping.

Прогнозирование с помощью NN - Полный пример

sample_index = np.random.choice(X_test.shape[0])
sample = X_test[sample_index]
inverted_mapping = {
   1:’Iris-setosa’,
   2:’Iris-versicolor’,
   3:’Iris-virginica’
}
prediction = z(sample)
predicted_label = inverted_mapping[np.argmax(prediction)]
print(predicted_label)

Вывод

После обучения указанной выше модели глубокого обучения и ее запуска вы получите следующий результат:

Iris-versicolor

CNTK - в памяти и большие наборы данных

В этой главе мы узнаем, как работать с хранящимися в памяти и большими наборами данных в CNTK.

Обучение с небольшими наборами данных в памяти

Когда мы говорим о загрузке данных в тренер CNTK, может быть много способов, но это будет зависеть от размера набора данных и формата данных. Наборы данных могут быть небольшими в памяти или большими наборами данных.

В этом разделе мы собираемся работать с наборами данных в памяти. Для этого мы будем использовать следующие два фреймворка -

  • Numpy
  • Pandas

Использование массивов Numpy

Здесь мы будем работать со случайно сгенерированным набором данных на основе numpy в CNTK. В этом примере мы собираемся смоделировать данные для задачи двоичной классификации. Предположим, у нас есть набор наблюдений с 4 функциями и мы хотим предсказать две возможные метки с помощью нашей модели глубокого обучения.

Пример реализации

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

Step 1 - Импортировать numpy пакет следующим образом -

import numpy as np
num_samples = 20000

Step 2 - Затем сгенерируйте сопоставление меток с помощью np.eye функционируют следующим образом -

label_mapping = np.eye(2)

Step 3 - Теперь с помощью np.random.choice функция, соберите 20000 случайных выборок следующим образом -

y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)

Step 4 - Теперь, наконец, используя функцию np.random.random, сгенерируйте массив случайных значений с плавающей запятой следующим образом:

x = np.random.random(size=(num_samples, 4)).astype(np.float32)

После того, как мы сгенерируем массив случайных значений с плавающей запятой, нам нужно преобразовать их в 32-битные числа с плавающей запятой, чтобы его можно было сопоставить с форматом, ожидаемым CNTK. Чтобы сделать это, выполните следующие действия:

Step 5 - Импортируйте функции плотного и последовательного слоя из модуля cntk.layers следующим образом:

from cntk.layers import Dense, Sequential

Step 6- Теперь нам нужно импортировать функцию активации для слоев в сети. Давайте импортируемsigmoid как функция активации -

from cntk import input_variable, default_options
from cntk.ops import sigmoid

Step 7- Теперь нам нужно импортировать функцию потерь для обучения сети. Давайте импортируемbinary_cross_entropy как функция потерь -

from cntk.losses import binary_cross_entropy

Step 8- Далее нам нужно определить параметры сети по умолчанию. Здесь мы предоставимsigmoidфункция активации по умолчанию. Кроме того, создайте модель с помощью функции последовательного слоя следующим образом:

with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])

Step 9 - Затем инициализируйте input_variable с 4 входными функциями, которые служат входом для сети.

features = input_variable(4)

Step 10 - Теперь, чтобы завершить его, нам нужно подключить переменную features к NN.

z = model(features)

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

Step 11 - Чтобы обучить эту NN, сначала нам нужно импортировать ученика из cntk.learnersмодуль. Мы импортируемsgd ученик следующим образом -

from cntk.learners import sgd

Step 12 - Наряду с этим импортировать ProgressPrinter из cntk.logging модуль тоже.

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

Step 13 - Затем определите новую входную переменную для меток следующим образом -

labels = input_variable(2)

Step 14 - Затем, чтобы обучить модель NN, нам нужно определить потери, используя binary_cross_entropyфункция. Также укажите модель z и переменную меток.

loss = binary_cross_entropy(z, labels)

Step 15 - Затем инициализируйте sgd ученик следующим образом -

learner = sgd(z.parameters, lr=0.1)

Step 16- Наконец, вызовите метод поезда для функции потерь. Также предоставьте ему входные данные,sgd ученик и progress_printer.−

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

Полный пример реализации

import numpy as np
num_samples = 20000
label_mapping = np.eye(2)
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid
from cntk.losses import binary_cross_entropy
with default_options(activation=sigmoid):
   model = Sequential([Dense(6),Dense(2)])
features = input_variable(4)
z = model(features)
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(2)
loss = binary_cross_entropy(z, labels)
learner = sgd(z.parameters, lr=0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

Вывод

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average   since   average   since examples
loss      last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.52      1.52      0         0     32
1.51      1.51      0         0     96
1.48      1.46      0         0    224
1.45      1.42      0         0    480
1.42       1.4      0         0    992
1.41      1.39      0         0   2016
1.4       1.39      0         0   4064
1.39      1.39      0         0   8160
1.39      1.39      0         0  16352

Использование Pandas DataFrames

Массивы Numpy очень ограничены в том, что они могут содержать, и являются одним из самых основных способов хранения данных. Например, один n-мерный массив может содержать данные одного типа. Но с другой стороны, для многих реальных случаев нам нужна библиотека, которая может обрабатывать более одного типа данных в одном наборе данных.

Одна из библиотек Python под названием Pandas упрощает работу с такими наборами данных. Он вводит концепцию DataFrame (DF) и позволяет нам загружать наборы данных с диска, хранящиеся в различных форматах как DF. Например, мы можем читать DF, хранящиеся как CSV, JSON, Excel и т. Д.

Вы можете изучить библиотеку Python Pandas более подробно на https://www.tutorialspoint.com/python_pandas/index.htm.

Пример реализации

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

from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)

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

Далее мы будем использовать train метод и lossфункция для обучения сети. Для этого сначала мы должны загрузить и предварительно обработать набор данных радужной оболочки, чтобы он соответствовал ожидаемому макету и формату данных для NN. Это можно сделать с помощью следующих шагов -

Step 1 - Импортировать numpy и Pandas пакет следующим образом -

import numpy as np
import pandas as pd

Step 2 - Далее используйте read_csv функция для загрузки набора данных в память -

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’,
 ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)

Step 3 - Теперь нам нужно создать словарь, который будет отображать метки в наборе данных с их соответствующим числовым представлением.

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 4 - Теперь, используя iloc индексатор на DataFrame, выберите первые четыре столбца следующим образом -

x = df_source.iloc[:, :4].values

Step 5−Далее нам нужно выбрать столбцы видов в качестве меток для набора данных. Это можно сделать следующим образом -

y = df_source[‘species’].values

Step 6 - Теперь нам нужно сопоставить метки в наборе данных, что можно сделать с помощью label_mapping. Также используйтеone_hot кодирование для преобразования их в массивы горячего кодирования.

y = np.array([one_hot(label_mapping[v], 3) for v in y])

Step 7 - Затем, чтобы использовать функции и сопоставленные метки с CNTK, нам нужно преобразовать их оба в числа с плавающей запятой -

x= x.astype(np.float32)
y= y.astype(np.float32)

Как мы знаем, метки хранятся в наборе данных как строки, и CNTK не может работать с этими строками. По этой причине ему нужны векторы с горячим кодированием, представляющие метки. Для этого мы можем определить функцию, скажемone_hot следующим образом -

def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result

Теперь у нас есть массив numpy в правильном формате, с помощью следующих шагов мы можем использовать их для обучения нашей модели:

Step 8- Во-первых, нам нужно импортировать функцию потерь для обучения сети. Давайте импортируемbinary_cross_entropy_with_softmax как функция потерь -

from cntk.losses import binary_cross_entropy_with_softmax

Step 9 - Чтобы обучить эту NN, нам также нужно импортировать ученика из cntk.learnersмодуль. Мы импортируемsgd ученик следующим образом -

from cntk.learners import sgd

Step 10 - Наряду с этим импортировать ProgressPrinter из cntk.logging модуль тоже.

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

Step 11 - Затем определите новую входную переменную для меток следующим образом -

labels = input_variable(3)

Step 12 - Затем, чтобы обучить модель NN, нам нужно определить потери, используя binary_cross_entropy_with_softmaxфункция. Также укажите модель z и переменную меток.

loss = binary_cross_entropy_with_softmax (z, labels)

Step 13 - Затем инициализируйте sgd ученик следующим образом -

learner = sgd(z.parameters, 0.1)

Step 14- Наконец, вызовите метод поезда для функции потерь. Также предоставьте ему входные данные,sgd ученик и progress_printer.

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=
[progress_writer],minibatch_size=16,max_epochs=5)

Полный пример реализации

from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
import numpy as np
import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
x = df_source.iloc[:, :4].values
y = df_source[‘species’].values
y = np.array([one_hot(label_mapping[v], 3) for v in y])
x= x.astype(np.float32)
y= y.astype(np.float32)
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
from cntk.losses import binary_cross_entropy_with_softmax
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(3)
loss = binary_cross_entropy_with_softmax (z, labels)
learner = sgd(z.parameters, 0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer],minibatch_size=16,max_epochs=5)

Вывод

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average    since    average   since   examples
loss        last     metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.1         1.1        0       0      16
0.835     0.704        0       0      32
1.993      1.11        0       0      48
1.14       1.14        0       0     112
[………]

Обучение с большими наборами данных

В предыдущем разделе мы работали с небольшими наборами данных в памяти, используя Numpy и pandas, но не все наборы данных такие маленькие. Особенно большие наборы данных, содержащие изображения, видео, звуковые образцы.MinibatchSource- это компонент, который может загружать данные по частям, предоставляемый CNTK для работы с такими большими наборами данных. Некоторые особенностиMinibatchSource компоненты следующие -

  • MinibatchSource может предотвратить переобучение NN, автоматически рандомизируя выборки, считываемые из источника данных.

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

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

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

Создание экземпляра MinibatchSource

В предыдущем разделе мы использовали пример цветка ириса и работали с небольшим набором данных в памяти, используя Pandas DataFrames. Здесь мы заменим код, использующий данные из pandas DF, наMinibatchSource. Во-первых, нам нужно создать экземплярMinibatchSource с помощью следующих шагов -

Пример реализации

Step 1 - Во-первых, из cntk.io модуль импортирует компоненты для источника мини-пакетов следующим образом:

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
 INFINITY_REPEAT

Step 2 - Теперь, используя StreamDef class, создайте определение потока для меток.

labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)

Step 3 - Затем создайте для чтения функций, поданных из входного файла, создайте еще один экземпляр StreamDef следующим образом.

feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)

Step 4 - Теперь нам нужно предоставить iris.ctf файл в качестве ввода и инициализировать deserializer следующим образом -

deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=
label_stream, features=features_stream)

Step 5 - Наконец, нам нужно создать экземпляр minisourceBatch используя deserializer следующим образом -

Minibatch_source = MinibatchSource(deserializer, randomize=True)

Создание экземпляра MinibatchSource - полный пример реализации

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True)

Создание файла MCTF

Как вы видели выше, мы берем данные из файла iris.ctf. Он имеет формат файла, называемый текстовым форматом CNTK (CTF). Обязательно создать файл CTF для получения данных дляMinibatchSourceэкземпляр, который мы создали выше. Давайте посмотрим, как мы можем создать файл CTF.

Пример реализации

Step 1 - Во-первых, нам нужно импортировать пакеты pandas и numpy следующим образом:

import pandas as pd
import numpy as np

Step 2- Затем нам нужно загрузить в память наш файл данных, т.е. iris.csv. Затем сохраните его вdf_source переменная.

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)

Step 3 - Теперь, используя ilocindexer в качестве функций, возьмите содержимое первых четырех столбцов. Кроме того, используйте данные из столбца видов следующим образом:

features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values

Step 4- Затем нам нужно создать соответствие между именем метки и ее числовым представлением. Это можно сделать, создавlabel_mapping следующим образом -

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 5 - Теперь преобразуйте метки в набор векторов с горячим кодированием следующим образом:

labels = [one_hot(label_mapping[v], 3) for v in labels]

Теперь, как и раньше, создайте служебную функцию с именем one_hotдля кодирования этикеток. Это можно сделать следующим образом -

def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result

Поскольку мы загрузили и предварительно обработали данные, пора сохранить их на диске в формате файла CTF. Мы можем сделать это с помощью следующего кода Python -

With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))

Создание файла MCTF - Полный пример реализации

import pandas as pd
import numpy as np
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
labels = [one_hot(label_mapping[v], 3) for v in labels]
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))

Подача данных

Как только вы создадите MinibatchSource,Например, нам нужно обучить его. Мы можем использовать ту же логику обучения, что и при работе с небольшими наборами данных в памяти. Здесь мы будем использоватьMinibatchSource instance в качестве входа для метода поезда для функции потерь следующим образом:

Пример реализации

Step 1 - Чтобы записать результат тренировки, сначала импортируйте ProgressPrinter из cntk.logging модуль следующим образом -

from cntk.logging import ProgressPrinter

Step 2 - Затем, чтобы настроить тренировку, импортируйте trainer и training_session из cntk.train модуль следующим образом -

from cntk.train import Trainer,

Step 3 - Теперь нам нужно определить некоторый набор констант, например minibatch_size, samples_per_epoch и num_epochs следующим образом -

minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30

Step 4 - Затем, чтобы узнать, как CNTK читать данные во время обучения, нам нужно определить отображение между входной переменной для сети и потоками в источнике мини-пакета.

input_map = {
     features: minibatch.source.streams.features,
     labels: minibatch.source.streams.features
}

Step 5 - Затем, чтобы записать результат тренировочного процесса, инициализируйте progress_printer переменная с новым ProgressPrinter пример следующим образом -

progress_writer = ProgressPrinter(0)

Step 6 - Наконец, нам нужно вызвать метод поезда для потери следующим образом -

train_history = loss.train(minibatch_source,
parameter_learners=[learner],
  model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)

Подача данных - полный пример реализации

from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
input_map = {
   features: minibatch.source.streams.features,
   labels: minibatch.source.streams.features
}
progress_writer = ProgressPrinter(0)
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)

Вывод

-------------------------------------------------------------------
average   since   average   since  examples
loss      last     metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.21      1.21      0        0       32
1.15      0.12      0        0       96
[………]

CNTK - Измерение производительности

В этой главе объясняется, как измерить производительность модели в CNKT.

Стратегия проверки производительности модели

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

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

Набор данных удержания

Это один из самых простых способов создания набора данных для проверки NN. Как следует из названия, в этом методе мы будем удерживать один набор образцов от обучения (скажем, 20%) и использовать его для проверки производительности нашей модели машинного обучения. На следующей диаграмме показано соотношение между обучающей и проверочной выборками.

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

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

Ниже приведен пример, в котором мы создаем собственный набор данных удержания, используя train_test_split функция от scikit-learn библиотека.

пример

from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
y = iris.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
# Here above test_size = 0.2 represents that we provided 20% of the data as test data.
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
classifier_knn = KNeighborsClassifier(n_neighbors=3)
classifier_knn.fit(X_train, y_train)
y_pred = classifier_knn.predict(X_test)
# Providing sample data and the model will make prediction out of that data
sample = [[5, 5, 3, 2], [2, 4, 3, 5]]
preds = classifier_knn.predict(sample)
pred_species = [iris.target_names[p] for p in preds] print("Predictions:", pred_species)

Вывод

Predictions: ['versicolor', 'virginica']

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

  • На алгоритмы глубокого обучения сильно влияют генераторы случайных чисел.

  • Порядок, в котором мы предоставляем образцы NN во время обучения, сильно влияет на его производительность.

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

K-кратная перекрестная проверка

Чтобы сделать нашу модель машинного обучения более надежной, существует метод, называемый перекрестной проверкой K-fold. В природе метод перекрестной проверки в K-кратном порядке такой же, как и предыдущий, но он повторяется несколько раз - обычно от 5 до 10 раз. Следующая диаграмма представляет его концепцию -

Работа K-кратной перекрестной проверки

Работу K-кратной перекрестной проверки можно понять с помощью следующих шагов:

Step 1- Как и в методе раздаточного набора данных, в методе перекрестной проверки в K-кратном порядке сначала нам нужно разделить набор данных на обучающий и тестовый набор. В идеале соотношение составляет 80-20, т.е. 80% обучающего набора и 20% тестового набора.

Step 2 - Далее нам нужно обучить нашу модель с помощью обучающей выборки.

Step 3−Наконец, мы будем использовать тестовый набор для измерения производительности нашей модели. Единственная разница между методом удержания набора данных и методом k-перекрестной проверки заключается в том, что описанный выше процесс повторяется обычно от 5 до 10 раз, и в конце рассчитывается среднее значение по всем показателям производительности. Это среднее значение будет окончательным показателем производительности.

Давайте посмотрим на пример с небольшим набором данных -

пример

from numpy import array
from sklearn.model_selection import KFold
data = array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0])
kfold = KFold(5, True, 1)
for train, test in kfold.split(data):
   print('train: %s, test: %s' % (data[train],(data[test]))

Вывод

train: [0.1 0.2 0.4 0.5 0.6 0.7 0.8 0.9], test: [0.3 1. ]
train: [0.1 0.2 0.3 0.4 0.6 0.8 0.9 1. ], test: [0.5 0.7]
train: [0.2 0.3 0.5 0.6 0.7 0.8 0.9 1. ], test: [0.1 0.4]
train: [0.1 0.3 0.4 0.5 0.6 0.7 0.9 1. ], test: [0.2 0.8]
train: [0.1 0.2 0.3 0.4 0.5 0.7 0.8 1. ], test: [0.6 0.9]

Как мы видим, благодаря использованию более реалистичного сценария обучения и тестирования метод перекрестной проверки в k-кратном размере дает нам гораздо более стабильное измерение производительности, но, с другой стороны, проверка моделей глубокого обучения занимает много времени.

CNTK не поддерживает проверку k-cross, поэтому для этого нам нужно написать собственный скрипт.

Выявление недостаточного и переоборудования

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

Обнаружение переобучения

Явление, называемое переобучением, - это ситуация, когда наша модель машинного обучения исключительно хорошо моделирует обучающие данные, но не работает на тестовых данных, т.е. не может предсказать тестовые данные.

Это происходит, когда модель машинного обучения изучает определенный паттерн и шум из обучающих данных до такой степени, что это отрицательно влияет на способность этой модели делать обобщения от обучающих данных к новым, то есть невидимым данным. Здесь шум - это нерелевантная информация или случайность в наборе данных.

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

  • Модель переобучения будет хорошо работать на тех же образцах, которые мы использовали для обучения, но она будет работать очень плохо на новых образцах, то есть на образцах, отличных от обучающих.

  • Модель переоборудована во время проверки, если метрика на тестовом наборе ниже, чем та же метрика, которую мы используем в нашем обучающем наборе.

Обнаружение недостаточного оснащения

Еще одна ситуация, которая может возникнуть в нашем машинном обучении, - это недостаточная подготовка. Это ситуация, когда наша модель машинного обучения плохо моделирует обучающие данные и не может предсказать полезный результат. Когда мы начнем тренироваться в первую эпоху, наша модель будет неадекватной, но по мере продвижения обучения она будет становиться все менее пригодной.

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

CNTK - Классификация нейронных сетей

В этой главе мы изучим, как классифицировать нейронную сеть с помощью CNTK.

Введение

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

С другой стороны, математически это задача аппроксимации функции отображения, скажем, f от входных переменных говорят X до выходных переменных говорят Y.

Классическим примером проблемы классификации может быть обнаружение спама в электронных письмах. Очевидно, что может быть только две категории вывода: «спам» и «нет спама».

Чтобы реализовать такую ​​классификацию, нам сначала нужно провести обучение классификатора, в котором электронные письма «спам» и «нет спама» будут использоваться в качестве обучающих данных. После успешного обучения классификатора его можно использовать для обнаружения неизвестного адреса электронной почты.

Здесь мы собираемся создать 4-5-3 NN, используя набор данных цветов ириса, имеющий следующее:

  • 4-входные узлы (по одному для каждого значения предиктора).

  • 5-скрытые узлы обработки.

  • 3-выходных узла (потому что в наборе данных радужки есть три возможных вида).

Загрузка набора данных

Мы будем использовать набор данных цветов ириса, из которого мы хотим классифицировать виды цветов ириса на основе физических свойств ширины и длины чашелистика, а также ширины и длины лепестков. Набор данных описывает физические свойства различных сортов цветов ириса -

  • Длина чашелистики

  • Ширина чашелистника

  • Длина лепестка

  • Ширина лепестка

  • Сорт, т. Е. Iris setosa, iris versicolor или iris virginica

У нас есть iris.CSVфайл, который мы также использовали ранее в предыдущих главах. Его можно загрузить с помощьюPandasбиблиотека. Но перед его использованием или загрузкой для нашего классификатора нам необходимо подготовить файлы обучения и тестирования, чтобы его можно было легко использовать с CNTK.

Подготовка файлов для обучения и тестирования

Набор данных Iris - один из самых популярных наборов данных для проектов машинного обучения. Он имеет 150 элементов данных, а необработанные данные выглядят следующим образом:

5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
…
7.0 3.2 4.7 1.4 versicolor
6.4 3.2 4.5 1.5 versicolor
…
6.3 3.3 6.0 2.5 virginica
5.8 2.7 5.1 1.9 virginica

Как было сказано ранее, первые четыре значения в каждой строке описывают физические свойства различных разновидностей, например, длину чашелистиков, ширину чашелистиков, длину лепестков, ширину лепестков цветков ириса.

Но нам нужно преобразовать данные в формат, который может легко использоваться CNTK, и этот формат представляет собой файл .ctf (мы также создали один iris.ctf в предыдущем разделе). Это будет выглядеть следующим образом -

|attribs 5.1 3.5 1.4 0.2|species 1 0 0
|attribs 4.9 3.0 1.4 0.2|species 1 0 0
…
|attribs 7.0 3.2 4.7 1.4|species 0 1 0
|attribs 6.4 3.2 4.5 1.5|species 0 1 0
…
|attribs 6.3 3.3 6.0 2.5|species 0 0 1
|attribs 5.8 2.7 5.1 1.9|species 0 0 1

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

|ID 001 |attribs 5.1 3.5 1.4 0.2|species 1 0 0 |#setosa
|ID 002 |attribs 4.9 3.0 1.4 0.2|species 1 0 0 |#setosa
…
|ID 051 |attribs 7.0 3.2 4.7 1.4|species 0 1 0 |#versicolor
|ID 052 |attribs 6.4 3.2 4.5 1.5|species 0 1 0 |#versicolor
…

Всего в наборе данных iris имеется 150 элементов данных, и для этого примера мы будем использовать правило набора данных 80-20, т.е. 80% (120 элементов) элементов данных для целей обучения и оставшиеся 20% (30 элементов) элементов данных для тестирования. цель.

Построение классификационной модели

Во-первых, нам нужно обработать файлы данных в формате CNTK, и для этого мы собираемся использовать вспомогательную функцию с именем create_reader следующим образом -

def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='attribs', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='species', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src

Теперь нам нужно установить аргументы архитектуры для нашей NN, а также указать расположение файлов данных. Это можно сделать с помощью следующего кода Python -

def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 5
output_dim = 3
train_file = ".\\...\\" #provide the name of the training file(120 data items)
test_file = ".\\...\\" #provide the name of the test file(30 data items)

Теперь, с помощью следующей строки кода наша программа создаст необученную NN -

X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
nnet = oLayer
model = C.ops.softmax(nnet)

Теперь, когда мы создали двойную необученную модель, нам нужно настроить объект алгоритма Learner, а затем использовать его для создания обучающего объекта Trainer. Мы собираемся использовать учащийся SGD иcross_entropy_with_softmax функция потерь -

tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 2000
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])

Закодируйте алгоритм обучения следующим образом -

max_iter = 2000
batch_size = 10
lr_schedule = C.learning_parameter_schedule_per_sample([(1000, 0.05), (1, 0.01)])
mom_sch = C.momentum_schedule([(100, 0.99), (0, 0.95)], batch_size)
learner = C.fsadagrad(nnet.parameters, lr=lr_schedule, momentum=mom_sch)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])

Теперь, когда мы закончили с объектом Trainer, нам нужно создать функцию чтения для чтения обучающих данных -

rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }

Пришло время обучить нашу модель NN -

for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) * 100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))

После того, как мы закончили обучение, давайте оценим модель, используя элементы тестовых данных -

print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 30
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test)) * 100
print("Classification accuracy = %0.2f%%" % acc)

После оценки точности нашей обученной модели NN мы будем использовать ее для прогнозирования невидимых данных -

np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[6.4, 3.2, 4.5, 1.5]], dtype=np.float32)
print("\nPredicting Iris species for input features: ")
print(unknown[0]) pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities are: ")
print(pred_prob[0])

Полная модель классификации

Import numpy as np
Import cntk as C
def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='attribs', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='species', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 5
output_dim = 3
train_file = ".\\...\\" #provide the name of the training file(120 data items)
test_file = ".\\...\\" #provide the name of the test file(30 data items)
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
nnet = oLayer
model = C.ops.softmax(nnet)
tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 2000
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
max_iter = 2000
batch_size = 10
lr_schedule = C.learning_parameter_schedule_per_sample([(1000, 0.05), (1, 0.01)])
mom_sch = C.momentum_schedule([(100, 0.99), (0, 0.95)], batch_size)
learner = C.fsadagrad(nnet.parameters, lr=lr_schedule, momentum=mom_sch)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) * 100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 30
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test)) * 100
print("Classification accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[7.0, 3.2, 4.7, 1.4]], dtype=np.float32)
print("\nPredicting species for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities: ")
print(pred_prob[0])
if __name__== ”__main__”:
main()

Вывод

Using CNTK version = 2.7
batch 0: mean loss = 1.0986, mean accuracy = 40.00%
batch 500: mean loss = 0.6677, mean accuracy = 80.00%
batch 1000: mean loss = 0.5332, mean accuracy = 70.00%
batch 1500: mean loss = 0.2408, mean accuracy = 100.00%
Evaluating test data
Classification accuracy = 94.58%
Predicting species for input features:
[7.0 3.2 4.7 1.4]
Prediction probabilities:
[0.0847 0.736 0.113]

Сохранение обученной модели

В этом наборе данных Iris всего 150 элементов данных, следовательно, обучение модели классификатора NN займет всего несколько секунд, но обучение на большом наборе данных, содержащем сотни или тысячи элементов данных, может занять часы или даже дни.

Мы можем сохранить нашу модель, чтобы нам не пришлось сохранять ее с нуля. С помощью следующего кода Python мы можем сохранить нашу обученную NN -

nn_classifier = “.\\neuralclassifier.model” #provide the name of the file
model.save(nn_classifier, format=C.ModelFormat.CNTKv2)

Ниже приводятся аргументы save() функция, использованная выше -

  • Имя файла - это первый аргумент save()функция. Его также можно записать вместе с путем к файлу.

  • Другой параметр - это format параметр, имеющий значение по умолчанию C.ModelFormat.CNTKv2.

Загрузка обученной модели

После того, как вы сохранили обученную модель, ее очень легко загрузить. Нам нужно только использоватьload ()функция. Давайте проверим это в следующем примере -

import numpy as np
import cntk as C
model = C.ops.functions.Function.load(“.\\neuralclassifier.model”)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[7.0, 3.2, 4.7, 1.4]], dtype=np.float32)
print("\nPredicting species for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities: ")
print(pred_prob[0])

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

CNTK - двоичная классификация нейронных сетей

Давайте разберемся, что такое бинарная классификация нейронных сетей с использованием CNTK, в этой главе.

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

Загрузка набора данных

Для реализации обоих этих методов с использованием NN мы будем использовать набор данных банкнот. Набор данных можно загрузить из репозитория машинного обучения UCI, который доступен по адресуhttps://archive.ics.uci.edu/ml/datasets/banknote+authentication.

В нашем примере мы будем использовать 50 аутентичных элементов данных с классом forgery = 0 и первые 50 поддельных элементов с классом forgery = 1.

Подготовка файлов для обучения и тестирования

Полный набор данных содержит 1372 элемента данных. Необработанный набор данных выглядит следующим образом -

3.6216, 8.6661, -2.8076, -0.44699, 0
4.5459, 8.1674, -2.4586, -1.4621, 0
…
-1.3971, 3.3191, -1.3927, -1.9948, 1
0.39012, -0.14279, -0.031994, 0.35084, 1

Теперь сначала нам нужно преобразовать эти необработанные данные в формат двухузлового CNTK, который будет следующим:

|stats 3.62160000 8.66610000 -2.80730000 -0.44699000 |forgery 0 1 |# authentic 
|stats 4.54590000 8.16740000 -2.45860000 -1.46210000 |forgery 0 1 |# authentic 
. . .
|stats -1.39710000 3.31910000 -1.39270000 -1.99480000 |forgery 1 0 |# fake 
|stats 0.39012000 -0.14279000 -0.03199400 0.35084000 |forgery 1 0 |# fake

Вы можете использовать следующую программу на Python для создания данных в формате CNTK из необработанных данных:

fin = open(".\\...", "r") #provide the location of saved dataset text file.
for line in fin:
   line = line.strip()
   tokens = line.split(",")
   if tokens[4] == "0":
    print("|stats %12.8f %12.8f %12.8f %12.8f |forgery 0 1 |# authentic" % \
(float(tokens[0]), float(tokens[1]), float(tokens[2]), float(tokens[3])) )
   else:
    print("|stats %12.8f %12.8f %12.8f %12.8f |forgery 1 0 |# fake" % \
(float(tokens[0]), float(tokens[1]), float(tokens[2]), float(tokens[3])) )
fin.close()

Двухузловая модель двоичной классификации

Существует очень небольшая разница между классификацией с двумя узлами и классификацией с несколькими классами. Здесь нам сначала нужно обработать файлы данных в формате CNTK, и для этого мы собираемся использовать вспомогательную функцию с именемcreate_reader следующим образом -

def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='stats', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='forgery', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src

Теперь нам нужно установить аргументы архитектуры для нашей NN, а также указать расположение файлов данных. Это можно сделать с помощью следующего кода Python -

def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 10
output_dim = 2
train_file = ".\\...\\" #provide the name of the training file
test_file = ".\\...\\" #provide the name of the test file

Теперь, с помощью следующей строки кода наша программа создаст необученную NN -

X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
nnet = oLayer
model = C.ops.softmax(nnet)

Теперь, когда мы создали двойную необученную модель, нам нужно настроить объект алгоритма Learner, а затем использовать его для создания обучающего объекта Trainer. Мы собираемся использовать SGD-ученик и функцию потерь cross_entropy_with_softmax -

tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 500
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])

Теперь, когда мы закончили с объектом Trainer, нам нужно создать функцию чтения для чтения данных обучения -

rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
banknote_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }

Теперь пора обучить нашу модель NN -

for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) * 100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))

После завершения обучения давайте оценим модель, используя элементы тестовых данных -

print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
banknote_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test)) * 100
print("Classification accuracy = %0.2f%%" % acc)

После оценки точности нашей обученной модели NN мы будем использовать ее для прогнозирования невидимых данных -

np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[0.6, 1.9, -3.3, -0.3]], dtype=np.float32)
print("\nPredicting Banknote authenticity for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities are: ")
print(pred_prob[0])
if pred_prob[0,0] < pred_prob[0,1]:
  print(“Prediction: authentic”)
else:
  print(“Prediction: fake”)

Полная модель классификации с двумя узлами

def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='stats', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='forgery', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 10
output_dim = 2
train_file = ".\\...\\" #provide the name of the training file
test_file = ".\\...\\" #provide the name of the test file
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
withC.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
nnet = oLayer
model = C.ops.softmax(nnet)
tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 500
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
banknote_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) * 100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
banknote_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test)) * 100
print("Classification accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[0.6, 1.9, -3.3, -0.3]], dtype=np.float32)
print("\nPredicting Banknote authenticity for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities are: ")
print(pred_prob[0])
if pred_prob[0,0] < pred_prob[0,1]:
print(“Prediction: authentic”)
else:
print(“Prediction: fake”)
if __name__== ”__main__”:
main()

Вывод

Using CNTK version = 2.7
batch 0: mean loss = 0.6928, accuracy = 80.00%
batch 50: mean loss = 0.6877, accuracy = 70.00%
batch 100: mean loss = 0.6432, accuracy = 80.00%
batch 150: mean loss = 0.4978, accuracy = 80.00%
batch 200: mean loss = 0.4551, accuracy = 90.00%
batch 250: mean loss = 0.3755, accuracy = 90.00%
batch 300: mean loss = 0.2295, accuracy = 100.00%
batch 350: mean loss = 0.1542, accuracy = 100.00%
batch 400: mean loss = 0.1581, accuracy = 100.00%
batch 450: mean loss = 0.1499, accuracy = 100.00%
Evaluating test data
Classification accuracy = 84.58%
Predicting banknote authenticity for input features:
[0.6 1.9 -3.3 -0.3]
Prediction probabilities are:
[0.7847 0.2536]
Prediction: fake

Модель двоичной классификации с одним узлом

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

Мы можем использовать встроенную функцию CNTK classification_error (), но в случае классификации с одним узлом CNTK не поддерживает функцию classification_error (). Это причина, по которой нам нужно реализовать программную функцию следующим образом:

def class_acc(mb, x_var, y_var, model):
num_correct = 0; num_wrong = 0
x_mat = mb[x_var].asarray()
y_mat = mb[y_var].asarray()
for i in range(mb[x_var].shape[0]):
   p = model.eval(x_mat[i]
   y = y_mat[i]
   if p[0,0] < 0.5 and y[0,0] == 0.0 or p[0,0] >= 0.5 and y[0,0] == 1.0:
num_correct += 1
 else:
  num_wrong += 1
return (num_correct * 100.0)/(num_correct + num_wrong)

С этим изменением давайте посмотрим полный пример классификации с одним узлом -

Полная модель классификации с одним узлом

import numpy as np
import cntk as C
def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='stats', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='forgery', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
def class_acc(mb, x_var, y_var, model):
num_correct = 0; num_wrong = 0
x_mat = mb[x_var].asarray()
y_mat = mb[y_var].asarray()
for i in range(mb[x_var].shape[0]):
  p = model.eval(x_mat[i]
  y = y_mat[i]
  if p[0,0] < 0.5 and y[0,0] == 0.0 or p[0,0] >= 0.5 and y[0,0] == 1.0:
  num_correct += 1
 else:
  num_wrong += 1
return (num_correct * 100.0)/(num_correct + num_wrong)
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 10
output_dim = 1
train_file = ".\\...\\" #provide the name of the training file
test_file = ".\\...\\" #provide the name of the test file
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
model = oLayer
tr_loss = C.cross_entropy_with_softmax(model, Y)
max_iter = 1000
batch_size = 10
learn_rate = 0.01
learner = C.sgd(model.parameters, learn_rate)
trainer = C.Trainer(model, (tr_loss), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
banknote_input_map = {X : rdr.streams.x_src, Y : rdr.streams.y_src }
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 100 == 0:
mcee=trainer.previous_minibatch_loss_average
ca = class_acc(curr_batch, X,Y, model)
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, ca))
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
banknote_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map)
acc = class_acc(all_test, X,Y, model)
print("Classification accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[0.6, 1.9, -3.3, -0.3]], dtype=np.float32)
print("\nPredicting Banknote authenticity for input features: ")
print(unknown[0])
pred_prob = model.eval({X:unknown})
print("Prediction probability: ")
print(“%0.4f” % pred_prob[0,0])
if pred_prob[0,0] < 0.5:
  print(“Prediction: authentic”)
else:
  print(“Prediction: fake”)
if __name__== ”__main__”:
   main()

Вывод

Using CNTK version = 2.7
batch 0: mean loss = 0.6936, accuracy = 10.00%
batch 100: mean loss = 0.6882, accuracy = 70.00%
batch 200: mean loss = 0.6597, accuracy = 50.00%
batch 300: mean loss = 0.5298, accuracy = 70.00%
batch 400: mean loss = 0.4090, accuracy = 100.00%
batch 500: mean loss = 0.3790, accuracy = 90.00%
batch 600: mean loss = 0.1852, accuracy = 100.00%
batch 700: mean loss = 0.1135, accuracy = 100.00%
batch 800: mean loss = 0.1285, accuracy = 100.00%
batch 900: mean loss = 0.1054, accuracy = 100.00%
Evaluating test data
Classification accuracy = 84.00%
Predicting banknote authenticity for input features:
[0.6 1.9 -3.3 -0.3]
Prediction probability:
0.8846
Prediction: fake

CNTK - Регрессия нейронной сети

Эта глава поможет вам понять регресс нейронной сети в отношении CNTK.

Введение

Как мы знаем, чтобы предсказать числовое значение из одной или нескольких переменных-предикторов, мы используем регрессию. Давайте возьмем пример прогнозирования средней стоимости дома, скажем, в одном из 100 городов. Для этого у нас есть данные, которые включают -

  • Статистика преступности для каждого города.

  • Возраст домов в каждом городе.

  • Мера расстояния от каждого города до главного места.

  • Соотношение учеников и учителей в каждом городе.

  • Расовая демографическая статистика для каждого города.

  • Средняя стоимость дома в каждом городе.

На основе этих пяти переменных-предикторов мы хотели бы спрогнозировать среднюю стоимость дома. И для этого мы можем создать модель линейной регрессии по линиям:

Y = a0+a1(crime)+a2(house-age)+(a3)(distance)+(a4)(ratio)+(a5)(racial)

В приведенном выше уравнении -

Y прогнозируемое медианное значение

a0 - константа и

a1 через a5 все константы, связанные с пятью предикторами, которые мы обсуждали выше.

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

Здесь мы будем создавать регрессионную модель нейронной сети с помощью CNTK.

Загрузка набора данных

Чтобы реализовать регрессию нейронной сети с использованием CNTK, мы будем использовать набор данных о стоимости домов в Бостоне. Набор данных можно загрузить из репозитория машинного обучения UCI, который доступен по адресуhttps://archive.ics.uci.edu/ml/machine-learning-databases/housing/. В этом наборе данных всего 14 переменных и 506 экземпляров.

Но для нашей программы реализации мы собираемся использовать шесть из 14 переменных и 100 экземпляров. Из 6, 5 как предсказатели и один как значение для предсказания. Из 100 экземпляров мы будем использовать 80 для обучения и 20 для тестирования. Величина, которую мы хотим спрогнозировать, - это средняя цена дома в городе. Давайте посмотрим на пять предикторов, которые мы будем использовать -

  • Crime per capita in the town - Мы ожидаем, что с этим предсказателем будут связаны меньшие значения.

  • Proportion of owner - жилые дома, построенные до 1940 г. - Мы ожидаем, что меньшие значения будут связаны с этим предсказателем, потому что большее значение означает более старый дом.

  • Weighed distance of the town to five Boston employment centers.

  • Area school pupil-to-teacher ratio.

  • An indirect metric of the proportion of black residents in the town.

Подготовка файлов для обучения и тестирования

Как и раньше, сначала нам нужно преобразовать необработанные данные в формат CNTK. Мы собираемся использовать первые 80 элементов данных для целей обучения, поэтому формат CNTK с разделителями-табуляторами выглядит следующим образом:

|predictors 1.612820 96.90 3.76 21.00 248.31 |medval 13.50
|predictors 0.064170 68.20 3.36 19.20 396.90 |medval 18.90
|predictors 0.097440 61.40 3.38 19.20 377.56 |medval 20.00
. . .

Следующие 20 предметов, также преобразованных в формат CNTK, будут использованы для тестирования.

Построение регрессионной модели

Во-первых, нам нужно обработать файлы данных в формате CNTK, и для этого мы собираемся использовать вспомогательную функцию с именем create_reader следующим образом -

def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='predictors', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='medval', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src

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

def mb_accuracy(mb, x_var, y_var, model, delta):
   num_correct = 0
   num_wrong = 0
   x_mat = mb[x_var].asarray()
   y_mat = mb[y_var].asarray()
for i in range(mb[x_var].shape[0]):
  v = model.eval(x_mat[i])
  y = y_mat[i]
if np.abs(v[0,0] – y[0,0]) < delta:
   num_correct += 1
else:
   num_wrong += 1
return (num_correct * 100.0)/(num_correct + num_wrong)

Теперь нам нужно установить аргументы архитектуры для нашей NN, а также указать расположение файлов данных. Это можно сделать с помощью следующего кода Python -

def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 5
hidden_dim = 20
output_dim = 1
train_file = ".\\...\\" #provide the name of the training file(80 data items)
test_file = ".\\...\\" #provide the name of the test file(20 data items)

Теперь, с помощью следующей строки кода наша программа создаст необученную NN -

X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
model = C.ops.alias(oLayer)

Теперь, когда мы создали двойную необученную модель, нам нужно настроить объект алгоритма Learner. Мы собираемся использовать учащийся SGD иsquared_error функция потерь -

tr_loss = C.squared_error(model, Y)
max_iter = 3000
batch_size = 5
base_learn_rate = 0.02
sch=C.learning_parameter_schedule([base_learn_rate, base_learn_rate/2], minibatch_size=batch_size, epoch_size=int((max_iter*batch_size)/2))
learner = C.sgd(model.parameters, sch)
trainer = C.Trainer(model, (tr_loss), [learner])

Теперь, когда мы закончили с объектом алгоритма обучения, нам нужно создать функцию чтения для чтения данных обучения -

rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }

Теперь пора обучить нашу модель NN -

for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=boston_input_map) trainer.train_minibatch(curr_batch)
if i % int(max_iter/10) == 0:
mcee = trainer.previous_minibatch_loss_average
acc = mb_accuracy(curr_batch, X, Y, model, delta=3.00)
print("batch %4d: mean squared error = %8.4f, accuracy = %5.2f%% " \ % (i, mcee, acc))

После того, как мы закончили обучение, давайте оценим модель, используя элементы тестовых данных -

print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=boston_input_map)
acc = mb_accuracy(all_test, X, Y, model, delta=3.00)
print("Prediction accuracy = %0.2f%%" % acc)

После оценки точности нашей обученной модели NN мы будем использовать ее для прогнозирования невидимых данных -

np.set_printoptions(precision = 2, suppress=True)
unknown = np.array([[0.09, 50.00, 4.5, 17.00, 350.00], dtype=np.float32)
print("\nPredicting median home value for feature/predictor values: ")
print(unknown[0])
pred_prob = model.eval({X: unknown)
print("\nPredicted value is: ")
print(“$%0.2f (x1000)” %pred_value[0,0])

Полная модель регрессии

import numpy as np
import cntk as C
def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='predictors', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='medval', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
def mb_accuracy(mb, x_var, y_var, model, delta):
num_correct = 0
num_wrong = 0
x_mat = mb[x_var].asarray()
y_mat = mb[y_var].asarray()
for i in range(mb[x_var].shape[0]):
   v = model.eval(x_mat[i])
   y = y_mat[i]
if np.abs(v[0,0] – y[0,0]) < delta:
   num_correct += 1
else:
   num_wrong += 1
return (num_correct * 100.0)/(num_correct + num_wrong)
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 5
hidden_dim = 20
output_dim = 1
train_file = ".\\...\\" #provide the name of the training file(80 data items)
test_file = ".\\...\\" #provide the name of the test file(20 data items)
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
model = C.ops.alias(oLayer)
tr_loss = C.squared_error(model, Y)
max_iter = 3000
batch_size = 5
base_learn_rate = 0.02
sch = C.learning_parameter_schedule([base_learn_rate, base_learn_rate/2], minibatch_size=batch_size, epoch_size=int((max_iter*batch_size)/2))
learner = C.sgd(model.parameters, sch)
trainer = C.Trainer(model, (tr_loss), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=boston_input_map) trainer.train_minibatch(curr_batch)
if i % int(max_iter/10) == 0:
   mcee = trainer.previous_minibatch_loss_average
   acc = mb_accuracy(curr_batch, X, Y, model, delta=3.00)
   print("batch %4d: mean squared error = %8.4f, accuracy = %5.2f%% " \ % (i, mcee, acc))
   print("\nEvaluating test data \n")
   rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
   boston_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
   num_test = 20
all_test = rdr.next_minibatch(num_test, input_map=boston_input_map)
acc = mb_accuracy(all_test, X, Y, model, delta=3.00)
print("Prediction accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 2, suppress=True)
unknown = np.array([[0.09, 50.00, 4.5, 17.00, 350.00], dtype=np.float32)
print("\nPredicting median home value for feature/predictor values: ")
print(unknown[0])
pred_prob = model.eval({X: unknown)
print("\nPredicted value is: ")
print(“$%0.2f (x1000)” %pred_value[0,0])
if __name__== ”__main__”:
   main()

Вывод

Using CNTK version = 2.7
batch 0: mean squared error = 385.6727, accuracy = 0.00%
batch 300: mean squared error = 41.6229, accuracy = 20.00%
batch 600: mean squared error = 28.7667, accuracy = 40.00%
batch 900: mean squared error = 48.6435, accuracy = 40.00%
batch 1200: mean squared error = 77.9562, accuracy = 80.00%
batch 1500: mean squared error = 7.8342, accuracy = 60.00%
batch 1800: mean squared error = 47.7062, accuracy = 60.00%
batch 2100: mean squared error = 40.5068, accuracy = 40.00%
batch 2400: mean squared error = 46.5023, accuracy = 40.00%
batch 2700: mean squared error = 15.6235, accuracy = 60.00%
Evaluating test data
Prediction accuracy = 64.00%
Predicting median home value for feature/predictor values:
[0.09 50. 4.5 17. 350.]
Predicted value is:
$21.02(x1000)

Сохранение обученной модели

Этот набор данных о стоимости дома в Бостоне содержит только 506 элементов данных (из которых мы подали в суд только 100). Следовательно, обучение модели регрессора NN займет всего несколько секунд, но обучение на большом наборе данных, содержащем сотни или тысячи элементов данных, может занять часы или даже дни.

Мы можем сохранить нашу модель, чтобы нам не пришлось сохранять ее с нуля. С помощью следующего кода Python мы можем сохранить нашу обученную NN -

nn_regressor = “.\\neuralregressor.model” #provide the name of the file
model.save(nn_regressor, format=C.ModelFormat.CNTKv2)

Ниже приведены аргументы функции save (), использованные выше:

  • Имя файла - это первый аргумент save()функция. Его также можно записать вместе с путем к файлу.

  • Другой параметр - это format параметр, имеющий значение по умолчанию C.ModelFormat.CNTKv2.

Загрузка обученной модели

После того, как вы сохранили обученную модель, ее очень легко загрузить. Нам нужно только использовать функцию load (). Давайте проверим это в следующем примере -

import numpy as np
import cntk as C
model = C.ops.functions.Function.load(“.\\neuralregressor.model”)
np.set_printoptions(precision = 2, suppress=True)
unknown = np.array([[0.09, 50.00, 4.5, 17.00, 350.00], dtype=np.float32)
print("\nPredicting area median home value for feature/predictor values: ")
print(unknown[0])
pred_prob = model.eval({X: unknown)
print("\nPredicted value is: ")
print(“$%0.2f (x1000)” %pred_value[0,0])

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

CNTK - Модель классификации

Эта глава поможет вам понять, как измерить производительность модели классификации в CNTK. Начнем с матрицы путаницы.

Матрица путаницы

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

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

Фактическое мошенничество Фактический нормальный

Predicted fraud

Истинно положительный

Ложный положительный результат

Predicted normal

Ложноотрицательный

Истинно отрицательный

Как мы видим, приведенная выше матрица путаницы содержит 2 столбца: один для мошенничества класса, а другой - для обычного класса. Таким же образом у нас есть 2 строки, одна добавляется для мошенничества класса, а другая добавляется для обычного класса. Ниже приводится объяснение терминов, связанных с матрицей путаницы.

  • True Positives - Когда и фактический класс, и прогнозируемый класс точки данных равны 1.

  • True Negatives - Когда и фактический класс, и прогнозируемый класс точки данных равны 0.

  • False Positives - Когда фактический класс точки данных равен 0, а прогнозируемый класс точки данных равен 1.

  • False Negatives - Когда фактический класс точки данных равен 1, а прогнозируемый класс точки данных равен 0.

Давайте посмотрим, как мы можем вычислить количество разных вещей из матрицы путаницы -

  • Accuracy- Это количество правильных прогнозов, сделанных нашей классификационной моделью ML. Его можно рассчитать с помощью следующей формулы -

  • Precision- Он сообщает нам, сколько выборок было правильно предсказано из всех предсказанных нами выборок. Его можно рассчитать с помощью следующей формулы -

  • Recall or Sensitivity- Напомним, количество положительных результатов, возвращаемых нашей моделью классификации ML. Другими словами, он сообщает нам, сколько случаев мошенничества в наборе данных было фактически обнаружено моделью. Его можно рассчитать с помощью следующей формулы -

  • Specificity- Напротив, он показывает количество негативов, возвращаемых нашей моделью классификации ML. Его можно рассчитать с помощью следующей формулы -

F-мера

Мы можем использовать F-меру как альтернативу матрице путаницы. Основная причина этого в том, что мы не можем одновременно максимизировать отзыв и точность. Между этими показателями существует очень сильная взаимосвязь, и это можно понять с помощью следующего примера:

Предположим, мы хотим использовать модель DL для классификации образцов клеток как злокачественных или нормальных. Здесь для достижения максимальной точности нам нужно уменьшить количество прогнозов до 1. Хотя это может дать нам примерно 100-процентную точность, но отзывчивость станет очень низкой.

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

На практике нам нужно найти способ балансировать между точностью и отзывом. Метрика F-мера позволяет нам сделать это, поскольку она выражает гармоническое среднее между точностью и отзывом.

Эта формула называется F1-мерой, где дополнительный член B устанавливается на 1, чтобы получить равное соотношение точности и полноты. Чтобы подчеркнуть отзыв, мы можем установить коэффициент B равным 2. С другой стороны, чтобы подчеркнуть точность, мы можем установить коэффициент B равным 0,5.

Использование CNTK для измерения эффективности классификации

В предыдущем разделе мы создали модель классификации с использованием набора данных Iris flower. Здесь мы будем измерять его производительность с помощью матрицы ошибок и метрики F-меры.

Создание матрицы путаницы

Мы уже создали модель, поэтому можем начать процесс проверки, который включает confusion matrix, на том же. Во-первых, мы собираемся создать матрицу путаницы с помощьюconfusion_matrix функция от scikit-learn. Для этого нам нужны настоящие метки для наших тестовых образцов и предсказанные метки для тех же тестовых образцов.

Давайте рассчитаем матрицу путаницы, используя следующий код Python -

from sklearn.metrics import confusion_matrix
y_true = np.argmax(y_test, axis=1)
y_pred = np.argmax(z(X_test), axis=1)
matrix = confusion_matrix(y_true=y_true, y_pred=y_pred)
print(matrix)

Вывод

[[10 0 0]
[ 0 1 9]
[ 0 0 10]]

Мы также можем использовать функцию тепловой карты для визуализации матрицы путаницы следующим образом:

import seaborn as sns
import matplotlib.pyplot as plt
g = sns.heatmap(matrix,
     annot=True,
     xticklabels=label_encoder.classes_.tolist(),
     yticklabels=label_encoder.classes_.tolist(),
     cmap='Blues')
g.set_yticklabels(g.get_yticklabels(), rotation=0)
plt.show()

У нас также должен быть единый показатель производительности, который мы можем использовать для сравнения модели. Для этого нам нужно вычислить ошибку классификации, используяclassification_error из пакета метрик в CNTK, как это было сделано при создании модели классификации.

Теперь, чтобы вычислить ошибку классификации, выполните метод проверки функции потерь с набором данных. После этого CNTK возьмет образцы, которые мы предоставили в качестве входных данных для этой функции, и сделает прогноз на основе входных функций X_test.

loss.test([X_test, y_test])

Вывод

{'metric': 0.36666666666, 'samples': 30}

Внедрение F-мер

Для реализации F-мер CNTK также включает функцию, называемую fmeasures. Мы можем использовать эту функцию, обучая NN, заменяя ячейкуcntk.metrics.classification_error, с призывом к cntk.losses.fmeasure при определении функции фабрики критериев следующим образом:

import cntk
@cntk.Function
def criterion_factory(output, target):
   loss = cntk.losses.cross_entropy_with_softmax(output, target)
metric = cntk.losses.fmeasure(output, target)
   return loss, metric

После использования функции cntk.losses.fmeasure мы получим другой вывод для loss.test вызов метода задан следующим образом -

loss.test([X_test, y_test])

Вывод

{'metric': 0.83101488749, 'samples': 30}

CNTK - модель регрессии

Здесь мы изучим измерение производительности в отношении регрессионной модели.

Основы проверки регрессионной модели

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

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

Расчет погрешности

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

Формула для расчета погрешности выглядит следующим образом:

Вот,

Predicted value = указано y шляпой

Real value = предсказано y

Во-первых, нам нужно рассчитать расстояние между прогнозируемым и реальным значением. Затем, чтобы получить общий коэффициент ошибок, нам нужно просуммировать эти квадраты расстояний и вычислить среднее значение. Это называетсяmean squared функция ошибки.

Но если нам нужны показатели производительности, которые выражают погрешность, нам нужна формула, выражающая абсолютную погрешность. Формула дляmean absolute функция ошибок выглядит следующим образом -

Приведенная выше формула берет абсолютное расстояние между прогнозируемым и реальным значением.

Использование CNTK для измерения производительности регрессии

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

Этапы реализации -

Step 1 - Во-первых, нам нужно импортировать необходимые компоненты из cntk пакет следующим образом -

from cntk import default_option, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import relu

Step 2 - Затем нам нужно определить функцию активации по умолчанию, используя default_optionsфункции. Затем создайте новый набор последовательных слоев и предоставьте два плотных слоя с 64 нейронами каждый. Затем мы добавляем дополнительный плотный слой (который будет действовать как выходной слой) в набор последовательных слоев и даем 1 нейрон без активации следующим образом:

with default_options(activation=relu):
model = Sequential([Dense(64),Dense(64),Dense(1,activation=None)])

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

features = input_variable(X.shape[1])

Step 4 - Теперь нам нужно создать еще один input_variable с размером 1. Он будет использоваться для хранения ожидаемого значения для NN.

target = input_variable(1)
z = model(features)

Теперь нам нужно обучить модель, и для этого мы собираемся разделить набор данных и выполнить предварительную обработку, используя следующие шаги реализации:

Step 5-Сначала импортируйте StandardScaler из sklearn.preprocessing, чтобы получить значения от -1 до +1. Это поможет нам избежать взрывоопасных проблем градиента в NN.

from sklearn.preprocessing import StandardScalar

Step 6 - Затем импортируйте train_test_split из sklearn.model_selection следующим образом:

from sklearn.model_selection import train_test_split

Step 7 - Отбрось mpg столбец из набора данных с помощью dropметод. Наконец, разделите набор данных на набор для обучения и проверки, используяtrain_test_split функционируют следующим образом -

x = df_cars.drop(columns=[‘mpg’]).values.astype(np.float32)
y=df_cars.iloc[: , 0].values.reshape(-1, 1).astype(np.float32)
scaler = StandardScaler()
X = scaler.fit_transform(x)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

Step 8 - Теперь нам нужно создать еще одну переменную input_variable с размером 1. Она будет использоваться для хранения ожидаемого значения для NN.

target = input_variable(1)
z = model(features)

Мы разделили и предварительно обработали данные, теперь нам нужно обучить NN. Как и в предыдущих разделах при создании регрессионной модели, нам нужно определить комбинацию потерь иmetric функция для обучения модели.

import cntk
def absolute_error(output, target):
   return cntk.ops.reduce_mean(cntk.ops.abs(output – target))
@ cntk.Function
def criterion_factory(output, target):
   loss = squared_error(output, target)
   metric = absolute_error(output, target)
   return loss, metric

Теперь давайте посмотрим, как использовать обученную модель. Для нашей модели мы будем использовать criterion_factory как комбинацию потерь и метрики.

from cntk.losses import squared_error
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_printer = ProgressPrinter(0)
loss = criterion_factory (z, target)
learner = sgd(z.parameters, 0.001)
training_summary=loss.train((x_train,y_train),parameter_learners=[learner],callbacks=[progress_printer],minibatch_size=16,max_epochs=10)

Полный пример реализации

from cntk import default_option, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import relu
with default_options(activation=relu):
model = Sequential([Dense(64),Dense(64),Dense(1,activation=None)])
features = input_variable(X.shape[1])
target = input_variable(1)
z = model(features)
from sklearn.preprocessing import StandardScalar
from sklearn.model_selection import train_test_split
x = df_cars.drop(columns=[‘mpg’]).values.astype(np.float32)
y=df_cars.iloc[: , 0].values.reshape(-1, 1).astype(np.float32)
scaler = StandardScaler()
X = scaler.fit_transform(x)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
target = input_variable(1)
z = model(features)
import cntk
def absolute_error(output, target):
   return cntk.ops.reduce_mean(cntk.ops.abs(output – target))
@ cntk.Function
def criterion_factory(output, target):
loss = squared_error(output, target)
metric = absolute_error(output, target)
return loss, metric
from cntk.losses import squared_error
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_printer = ProgressPrinter(0)
loss = criterion_factory (z, target)
learner = sgd(z.parameters, 0.001)
training_summary=loss.train((x_train,y_train),parameter_learners=[learner],callbacks=[progress_printer],minibatch_size=16,max_epochs=10)

Вывод

-------------------------------------------------------------------
average  since   average   since  examples
loss     last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.001
690       690     24.9     24.9       16
654       636     24.1     23.7       48
[………]

Чтобы проверить нашу регрессионную модель, нам нужно убедиться, что она обрабатывает новые данные так же хорошо, как и данные обучения. Для этого нам нужно вызватьtest метод на loss и metric комбинация с данными испытаний следующим образом -

loss.test([X_test, y_test])

Выход

{'metric': 1.89679785619, 'samples': 79}

CNTK - Наборы данных вне памяти

В этой главе будет объяснено, как измерить производительность наборов данных с нехваткой памяти.

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

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

Источники мини-пакетов

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

Ниже приведены этапы реализации:

Step 1 - Во-первых, из cntk.Модуль io импортирует компоненты для создания источника мини-пакета следующим образом:

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
 INFINITY_REPEAT

Step 2 - Затем создайте новую функцию с именем say create_datasource. Эта функция будет иметь два параметра, а именно имя файла и ограничение, со значением по умолчанию:INFINITELY_REPEAT.

def create_datasource(filename, limit =INFINITELY_REPEAT)

Step 3 - Теперь внутри функции, используя StreamDefclass crate определение потока для меток, которое считывается из поля меток, имеющего три функции. Нам также нужно установитьis_sparse к False следующим образом -

labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)

Step 4 - Затем создайте для чтения функций, поданных из входного файла, создайте еще один экземпляр StreamDef следующим образом.

feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)

Step 5 - Теперь инициализируйте CTFDeserializerкласс экземпляра. Укажите имя файла и потоки, которые нам нужно десериализовать, следующим образом:

deserializer = CTFDeserializer(filename, StreamDefs(labels=
label_stream, features=features_stream)

Step 6 - Затем нам нужно создать экземпляр minisourceBatch с помощью десериализатора следующим образом:

Minibatch_source = MinibatchSource(deserializer, randomize=True, max_sweeps=limit)
return minibatch_source

Step 7- Наконец, нам нужно предоставить источник для обучения и тестирования, который мы также создали в предыдущих разделах. Мы используем набор данных цветов ириса.

training_source = create_datasource(‘Iris_train.ctf’)
test_source = create_datasource(‘Iris_test.ctf’, limit=1)

Как только вы создадите MinibatchSourceНапример, нам нужно обучить его. Мы можем использовать ту же логику обучения, что и при работе с небольшими наборами данных в памяти. Здесь мы будем использоватьMinibatchSource Например, в качестве входных данных для метода поезда по функции потерь следующим образом:

Ниже приведены этапы реализации:

Step 1 - Чтобы записать результаты тренировки, сначала импортируйте ProgressPrinter из cntk.logging модуль следующим образом -

from cntk.logging import ProgressPrinter

Step 2 - Затем, чтобы настроить тренировку, импортируйте trainer и training_session из cntk.train модуль следующим образом -

from cntk.train import Trainer, training_session

Step 3 - Теперь нам нужно определить некоторый набор констант, например minibatch_size, samples_per_epoch и num_epochs следующим образом -

minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
max_samples = samples_per_epoch * num_epochs

Step 4 - Затем, чтобы знать, как читать данные во время обучения в CNTK, нам нужно определить отображение между входной переменной для сети и потоками в источнике мини-пакета.

input_map = {
   features: training_source.streams.features,
   labels: training_source.streams.labels
}

Step 5 - Рядом с записью результатов тренировочного процесса инициализируйте progress_printer переменная с новым ProgressPrinterпример. Также инициализируйтеtrainer и снабдим его моделью следующим образом:

progress_writer = ProgressPrinter(0)
trainer: training_source.streams.labels

Step 6 - Наконец, чтобы начать тренировочный процесс, нам нужно вызвать training_session функционируют следующим образом -

session = training_session(trainer,
   mb_source=training_source,
   mb_size=minibatch_size,
   model_inputs_to_streams=input_map,
   max_samples=max_samples,
   test_config=test_config)
session.train()

После обучения модели мы можем добавить к этой настройке проверку, используя TestConfig объект и назначить его test_config ключевое слово аргумент train_session функция.

Ниже приведены этапы реализации:

Step 1 - Во-первых, нам нужно импортировать TestConfig класс из модуля cntk.train следующим образом -

from cntk.train import TestConfig

Step 2 - Теперь нам нужно создать новый экземпляр TestConfig с test_source как вход

Test_config = TestConfig(test_source)

Полный пример

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
def create_datasource(filename, limit =INFINITELY_REPEAT)
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(filename, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True, max_sweeps=limit)
return minibatch_source
training_source = create_datasource(‘Iris_train.ctf’)
test_source = create_datasource(‘Iris_test.ctf’, limit=1)
from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
max_samples = samples_per_epoch * num_epochs
input_map = {
   features:   training_source.streams.features,
   labels: training_source.streams.labels
 }
progress_writer = ProgressPrinter(0)
trainer: training_source.streams.labels
session = training_session(trainer,
   mb_source=training_source,
   mb_size=minibatch_size,
   model_inputs_to_streams=input_map,
   max_samples=max_samples,
   test_config=test_config)
session.train()
from cntk.train import TestConfig
Test_config = TestConfig(test_source)

Вывод

-------------------------------------------------------------------
average   since   average   since  examples
loss      last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.57      1.57     0.214    0.214   16
1.38      1.28     0.264    0.289   48
[………]
Finished Evaluation [1]: Minibatch[1-1]:metric = 69.65*30;

Ручная мини-петля

Как мы видим выше, легко измерить производительность нашей модели NN во время и после обучения, используя метрики при обучении с помощью обычных API в CNTK. Но, с другой стороны, при работе с ручным мини-пакетным циклом все будет не так просто.

Здесь мы используем модель, приведенную ниже, с 4 входами и 3 выходами из набора данных Iris Flower, также созданного в предыдущих разделах.

from cntk import default_options, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import log_softmax, relu, sigmoid
from cntk.learners import sgd
model = Sequential([
   Dense(4, activation=sigmoid),
   Dense(3, activation=log_softmax)
])
features = input_variable(4)
labels = input_variable(3)
z = model(features)

Затем потери для модели определяются как комбинация функции кросс-энтропийных потерь и метрики F-меры, использованной в предыдущих разделах. Мы собираемся использоватьcriterion_factory утилита, чтобы создать его как объект функции CNTK, как показано ниже:

import cntk
from cntk.losses import cross_entropy_with_softmax, fmeasure
@cntk.Function
def criterion_factory(outputs, targets):
   loss = cross_entropy_with_softmax(outputs, targets)
   metric = fmeasure(outputs, targets, beta=1)
   return loss, metric
loss = criterion_factory(z, labels)
learner = sgd(z.parameters, 0.1)
label_mapping = {
   'Iris-setosa': 0,
   'Iris-versicolor': 1,
   'Iris-virginica': 2
}

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

Ниже приведены шаги по реализации -

Step 1 - Во-первых, нам нужно импортировать необходимые пакеты, например numpy и pandas для загрузки и предварительной обработки данных.

import pandas as pd
import numpy as np

Step 2 - Затем, чтобы регистрировать информацию во время тренировки, импортируйте ProgressPrinter класс следующим образом -

from cntk.logging import ProgressPrinter

Step 3 - Затем нам нужно импортировать модуль тренера из модуля cntk.train следующим образом:

from cntk.train import Trainer

Step 4 - Затем создайте новый экземпляр ProgressPrinter следующим образом -

progress_writer = ProgressPrinter(0)

Step 5 - Теперь нам нужно инициализировать трейнер с параметрами потери, ученика и progress_writer следующим образом -

trainer = Trainer(z, loss, learner, progress_writer)

Step 6−Далее, чтобы обучить модель, мы создадим цикл, который будет повторять набор данных тридцать раз. Это будет внешний цикл обучения.

for _ in range(0,30):

Step 7- Теперь нам нужно загрузить данные с диска с помощью панд. Затем, чтобы загрузить набор данных вmini-batches, установить chunksize аргумент ключевого слова до 16.

input_data = pd.read_csv('iris.csv',
names=['sepal_length', 'sepal_width','petal_length','petal_width', 'species'],
index_col=False, chunksize=16)

Step 8 - Теперь создайте внутренний цикл обучения для итерации по каждому из mini-batches.

for df_batch in input_data:

Step 9 - Теперь внутри этого цикла прочтите первые четыре столбца, используя iloc индексатор, как features обучить и преобразовать их в float32 -

feature_values = df_batch.iloc[:,:4].values
feature_values = feature_values.astype(np.float32)

Step 10 - Теперь прочтите последний столбец как метки для обучения, а именно:

label_values = df_batch.iloc[:,-1]

Step 11 - Затем мы будем использовать горячие векторы для преобразования строк меток в их числовое представление следующим образом:

label_values = label_values.map(lambda x: label_mapping[x])

Step 12- После этого возьмите цифровое представление этикеток. Затем преобразуйте их в массив numpy, чтобы с ними было легче работать следующим образом:

label_values = label_values.values

Step 13 - Теперь нам нужно создать новый массив numpy, который имеет то же количество строк, что и значения меток, которые мы преобразовали.

encoded_labels = np.zeros((label_values.shape[0], 3))

Step 14 - Теперь, чтобы создать ярлыки с горячим кодированием, выберите столбцы на основе числовых значений ярлыков.

encoded_labels[np.arange(label_values.shape[0]), label_values] = 1.

Step 15 - Наконец, нам нужно вызвать train_minibatch метод на трейнере и предоставьте обработанные функции и метки для мини-партии.

trainer.train_minibatch({features: feature_values, labels: encoded_labels})

Полный пример

from cntk import default_options, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import log_softmax, relu, sigmoid
from cntk.learners import sgd
model = Sequential([
   Dense(4, activation=sigmoid),
   Dense(3, activation=log_softmax)
])
features = input_variable(4)
labels = input_variable(3)
z = model(features)
import cntk
from cntk.losses import cross_entropy_with_softmax, fmeasure
@cntk.Function
def criterion_factory(outputs, targets):
   loss = cross_entropy_with_softmax(outputs, targets)
   metric = fmeasure(outputs, targets, beta=1)
   return loss, metric
loss = criterion_factory(z, labels)
learner = sgd(z.parameters, 0.1)
label_mapping = {
   'Iris-setosa': 0,
   'Iris-versicolor': 1,
   'Iris-virginica': 2
}
import pandas as pd
import numpy as np
from cntk.logging import ProgressPrinter
from cntk.train import Trainer
progress_writer = ProgressPrinter(0)
trainer = Trainer(z, loss, learner, progress_writer)
for _ in range(0,30):
   input_data = pd.read_csv('iris.csv',
      names=['sepal_length', 'sepal_width','petal_length','petal_width', 'species'],
      index_col=False, chunksize=16)
for df_batch in input_data:
   feature_values = df_batch.iloc[:,:4].values
   feature_values = feature_values.astype(np.float32)
   label_values = df_batch.iloc[:,-1]
label_values = label_values.map(lambda x: label_mapping[x])
label_values = label_values.values
   encoded_labels = np.zeros((label_values.shape[0], 3))
   encoded_labels[np.arange(label_values.shape[0]), 
label_values] = 1.
   trainer.train_minibatch({features: feature_values, labels: encoded_labels})

Вывод

-------------------------------------------------------------------
average    since    average   since  examples
loss       last      metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.45       1.45     -0.189    -0.189   16
1.24       1.13     -0.0382    0.0371  48
[………]

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

Теперь, чтобы оценить производительность модели, нам нужно выполнить ту же задачу, что и при обучении модели, но на этот раз нам нужно использовать Evaluatorэкземпляр для проверки модели. Это показано в следующем коде Python:

from cntk import Evaluator
evaluator = Evaluator(loss.outputs[1], [progress_writer])
input_data = pd.read_csv('iris.csv',
   names=['sepal_length', 'sepal_width','petal_length','petal_width', 'species'],
index_col=False, chunksize=16)
for df_batch in input_data:
   feature_values = df_batch.iloc[:,:4].values
   feature_values = feature_values.astype(np.float32)
   label_values = df_batch.iloc[:,-1]
   label_values = label_values.map(lambda x: label_mapping[x])
   label_values = label_values.values
   encoded_labels = np.zeros((label_values.shape[0], 3))
   encoded_labels[np.arange(label_values.shape[0]), label_values] = 1.
   evaluator.test_minibatch({ features: feature_values, labels:
      encoded_labels})
evaluator.summarize_test_progress()

Теперь мы получим что-то вроде следующего:

Вывод

Finished Evaluation [1]: Minibatch[1-11]:metric = 74.62*143;

CNTK - мониторинг модели

В этой главе мы поймем, как отслеживать модель в CNTK.

Введение

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

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

Обратные вызовы в CNTK

Фактически, во время обучения и проверки CNTK позволяет нам указывать обратные вызовы в нескольких местах API. Во-первых, давайте внимательнее посмотрим, когда CNTK вызывает обратные вызовы.

Когда CNTK вызывает обратные вызовы?

CNTK будет вызывать обратные вызовы в моменты набора обучения и тестирования, когда:

  • Мини-партия завершена.

  • Полный просмотр набора данных завершается во время обучения.

  • Минипартия тестирования завершена.

  • Полный анализ набора данных завершается во время тестирования.

Указание обратных вызовов

При работе с CNTK мы можем указывать обратные вызовы в нескольких местах API. Например-

Когда вызвать поезд по функции потерь?

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

training_summary=loss.train((x_train,y_train),
parameter_learners=[learner],
callbacks=[progress_writer]),
minibatch_size=16, max_epochs=15)

При работе с мини-пакетными источниками или с использованием ручного мини-пакетного цикла

В этом случае мы можем указать обратные вызовы для целей мониторинга при создании Trainer следующим образом -

from cntk.logging import ProgressPrinter
callbacks = [
   ProgressPrinter(0)
]
Trainer = Trainer(z, (loss, metric), learner, [callbacks])

Различные инструменты мониторинга

Давайте изучим различные инструменты мониторинга.

ProgressPrinter

Читая это руководство, вы найдете ProgressPrinterкак наиболее часто используемый инструмент мониторинга. Некоторые характеристикиProgressPrinter инструмент мониторинга:

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

Особенно полезно при работе в сценарии распределенного обучения.

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

С помощью следующего кода мы можем создать экземпляр ProgressPrinter-

ProgressPrinter(0, log_to_file=’test.txt’)

Мы получим на выходе то, что видели в предыдущих разделах -

Test.txt
CNTKCommandTrainInfo: train : 300
CNTKCommandTrainInfo: CNTKNoMoreCommands_Total : 300
CNTKCommandTrainBegin: train
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.45 1.45 -0.189 -0.189 16
1.24 1.13 -0.0382 0.0371 48
[………]

TensorBoard

Одним из недостатков использования ProgressPrinter является то, что мы не можем получить четкое представление о том, насколько сложны потери и прогресс показателей с течением времени. TensorBoardProgressWriter - отличная альтернатива классу ProgressPrinter в CNTK.

Перед его использованием нам нужно сначала установить его с помощью следующей команды -

pip install tensorboard

Теперь, чтобы использовать TensorBoard, нам нужно настроить TensorBoardProgressWriter в нашем обучающем коде:

import time
from cntk.logging import TensorBoardProgressWriter
tensorbrd_writer = TensorBoardProgressWriter(log_dir=’logs/{}’.format(time.time()),freq=1,model=z)

Рекомендуется вызывать метод close для TensorBoardProgressWriter Пример после того, как закончили с обучением NNмодель.

Мы можем визуализировать TensorBoard регистрация данных с помощью следующей команды -

Tensorboard –logdir logs

CNTK - сверточная нейронная сеть

В этой главе давайте изучим, как построить сверточную нейронную сеть (CNN) в CNTK.

Введение

Сверточные нейронные сети (CNN) также состоят из нейронов, у которых есть обучаемые веса и смещения. Вот почему в этом смысле они похожи на обычные нейронные сети (NN).

Если мы вспомним работу обычных нейронных сетей, каждый нейрон получает один или несколько входов, принимает взвешенную сумму и проходит через функцию активации для получения окончательного результата. Здесь возникает вопрос: если CNN и обычные NN имеют столько общего, то чем же эти две сети отличаются друг от друга?

Что отличает их от других - это обработка входных данных и типы слоев? Структура входных данных игнорируется в обычном NN, и все данные преобразуются в одномерный массив перед подачей в сеть.

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

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

Архитектура сверточной нейронной сети (CNN)

Архитектура CNN - это, по сути, список слоев, который преобразует трехмерный, то есть ширину, высоту и глубину объема изображения, в трехмерный выходной объем. Здесь следует отметить один важный момент: каждый нейрон в текущем слое подключен к небольшому участку выхода из предыдущего слоя, что похоже на наложение фильтра N * N на входное изображение.

Он использует фильтры M, которые в основном являются экстракторами функций, которые извлекают такие элементы, как края, угол и так далее. Ниже приведены слои [INPUT-CONV-RELU-POOL-FC] которые используются для построения сверточных нейронных сетей (CNN) -

  • INPUT- Как следует из названия, этот слой содержит необработанные значения пикселей. Необработанные значения пикселей означают данные изображения как таковые. Например, INPUT [64 × 64 × 3] представляет собой трехканальное изображение RGB шириной 64, высотой 64 и глубиной 3.

  • CONV- Этот уровень является одним из строительных блоков CNN, поскольку большая часть вычислений выполняется на этом уровне. Пример - если мы используем 6 фильтров на вышеупомянутом INPUT [64 × 64 × 3], это может привести к объему [64 × 64 × 6].

  • RELU-Также называется выпрямленным линейным единичным слоем, который применяет функцию активации к выходным данным предыдущего слоя. В противном случае RELU добавит к сети нелинейность.

  • POOL- Этот уровень, т.е. уровень объединения, является еще одним строительным блоком CNN. Основная задача этого уровня - понижающая дискретизация, что означает, что он работает независимо с каждым фрагментом ввода и изменяет его размер в пространстве.

  • FC- Это называется полностью подключенным слоем или, точнее, выходным слоем. Он используется для вычисления оценки выходного класса, и в результате получается объем размером 1 * 1 * L, где L - число, соответствующее оценке класса.

На диаграмме ниже представлена ​​типичная архитектура CNN:

Создание структуры CNN

Мы увидели архитектуру и основы CNN, теперь мы собираемся построить сверточную сеть с использованием CNTK. Здесь мы сначала увидим, как собрать структуру CNN, а затем посмотрим, как обучить ее параметры.

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

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

  • Мы используем комбинацию слоев свертки и объединения.

  • Один или несколько скрытых слоев в конце сети.

  • Наконец, мы завершаем сеть слоем softmax для целей классификации.

С помощью следующих шагов мы можем построить структуру сети:

Step 1- Во-первых, нам нужно импортировать необходимые слои для CNN.

from cntk.layers import Convolution2D, Sequential, Dense, MaxPooling

Step 2- Далее нам нужно импортировать функции активации для CNN.

from cntk.ops import log_softmax, relu

Step 3- После этого, чтобы позже инициализировать сверточные слои, нам нужно импортировать glorot_uniform_initializer следующим образом -

from cntk.initializer import glorot_uniform

Step 4- Затем, чтобы создать входные переменные, импортируйте input_variableфункция. И импортdefault_option функция, чтобы немного упростить настройку NN.

from cntk import input_variable, default_options

Step 5- Теперь, чтобы сохранить входные изображения, создайте новый input_variable. Он будет содержать три канала: красный, зеленый и синий. У него будет размер 28 на 28 пикселей.

features = input_variable((3,28,28))

Step 6-Далее нам нужно создать еще один input_variable хранить метки для прогнозов.

labels = input_variable(10)

Step 7- Теперь нам нужно создать default_optionдля NN. И нам нужно использоватьglorot_uniform в качестве функции инициализации.

with default_options(initialization=glorot_uniform, activation=relu):

Step 8- Далее, чтобы задать структуру NN, нам нужно создать новый Sequential набор слоев.

Step 9- Теперь нам нужно добавить Convolutional2D слой с filter_shape из 5 и strides установка 1, в пределах Sequentialнабор слоев. Кроме того, включите заполнение, чтобы изображение было заполнено, чтобы сохранить исходные размеры.

model = Sequential([
Convolution2D(filter_shape=(5,5), strides=(1,1), num_filters=8, pad=True),

Step 10- Теперь пора добавить MaxPooling слой с filter_shape из 2, а strides установка 2 для сжатия изображения вдвое.

MaxPooling(filter_shape=(2,2), strides=(2,2)),

Step 11- Теперь, как в шаге 9, нам нужно добавить еще один Convolutional2D слой с filter_shape из 5 и stridesустановка 1, используйте 16 фильтров. Кроме того, включите заполнение, чтобы сохранить размер изображения, созданного предыдущим слоем объединения.

Convolution2D(filter_shape=(5,5), strides=(1,1), num_filters=16, pad=True),

Step 12- Теперь, как в шаге 10, добавьте еще MaxPooling слой с filter_shape из 3 и strides установка 3 для уменьшения изображения до трети.

MaxPooling(filter_shape=(3,3), strides=(3,3)),

Step 13- Наконец, добавьте плотный слой с десятью нейронами для 10 возможных классов, которые сеть может предсказать. Чтобы превратить сеть в модель классификации, используйтеlog_siftmax функция активации.

Dense(10, activation=log_softmax)
])

Полный пример создания структуры CNN

from cntk.layers import Convolution2D, Sequential, Dense, MaxPooling
from cntk.ops import log_softmax, relu
from cntk.initializer import glorot_uniform
from cntk import input_variable, default_options
features = input_variable((3,28,28))
labels = input_variable(10)
with default_options(initialization=glorot_uniform, activation=relu):
model = Sequential([
   Convolution2D(filter_shape=(5,5), strides=(1,1), num_filters=8, pad=True),
MaxPooling(filter_shape=(2,2), strides=(2,2)),
   Convolution2D(filter_shape=(5,5), strides=(1,1), num_filters=16, pad=True),
MaxPooling(filter_shape=(3,3), strides=(3,3)),
Dense(10, activation=log_softmax)
])
z = model(features)

Обучение CNN с изображениями

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

Мы уже создали источники мини-пакетов в предыдущих разделах. Ниже приведен код Python для настройки двух источников мини-пакетов.

Поскольку у нас есть create_datasource Теперь мы можем создать два отдельных источника данных (обучающий и тестовый) для обучения модели.

train_datasource = create_datasource('mnist_train')
test_datasource = create_datasource('mnist_test', max_sweeps=1, train=False)

Теперь, когда мы подготовили изображения, мы можем приступить к обучению нашей NN. Как и в предыдущих разделах, мы можем использовать метод train для функции потерь, чтобы начать обучение. Ниже приведен код для этого -

from cntk import Function
from cntk.losses import cross_entropy_with_softmax
from cntk.metrics import classification_error
from cntk.learners import sgd
@Function
def criterion_factory(output, targets):
loss = cross_entropy_with_softmax(output, targets)
metric = classification_error(output, targets)
return loss, metric
loss = criterion_factory(z, labels)
learner = sgd(z.parameters, lr=0.2)

С помощью предыдущего кода мы настроили потерю и учащегося для NN. Следующий код будет обучать и проверять NN−

from cntk.logging import ProgressPrinter
from cntk.train import TestConfig
progress_writer = ProgressPrinter(0)
test_config = TestConfig(test_datasource)
input_map = {
   features: train_datasource.streams.features,
   labels: train_datasource.streams.labels
}
loss.train(train_datasource,
     max_epochs=10,
     minibatch_size=64,
     epoch_size=60000,
        parameter_learners=[learner],
     model_inputs_to_streams=input_map,
     callbacks=[progress_writer, test_config])

Полный пример реализации

from cntk.layers import Convolution2D, Sequential, Dense, MaxPooling
from cntk.ops import log_softmax, relu
from cntk.initializer import glorot_uniform
from cntk import input_variable, default_options
features = input_variable((3,28,28))
labels = input_variable(10)
with default_options(initialization=glorot_uniform, activation=relu):
model = Sequential([
   Convolution2D(filter_shape=(5,5), strides=(1,1), num_filters=8, pad=True),
MaxPooling(filter_shape=(2,2), strides=(2,2)),
   Convolution2D(filter_shape=(5,5), strides=(1,1), num_filters=16, pad=True),
MaxPooling(filter_shape=(3,3), strides=(3,3)),
Dense(10, activation=log_softmax)
])
z = model(features)
import os
from cntk.io import MinibatchSource, StreamDef, StreamDefs, ImageDeserializer, INFINITELY_REPEAT
import cntk.io.transforms as xforms
def create_datasource(folder, train=True, max_sweeps=INFINITELY_REPEAT):
   mapping_file = os.path.join(folder, 'mapping.bin')
   image_transforms = []
   if train:
    image_transforms += [
     xforms.crop(crop_type='randomside', side_ratio=0.8),
     xforms.scale(width=28, height=28, channels=3, interpolations='linear')
]
   stream_definitions = StreamDefs(
   features=StreamDef(field='image', transforms=image_transforms),
    labels=StreamDef(field='label', shape=10)
)
   deserializer = ImageDeserializer(mapping_file, stream_definitions)
return MinibatchSource(deserializer, max_sweeps=max_sweeps)
train_datasource = create_datasource('mnist_train')
test_datasource = create_datasource('mnist_test', max_sweeps=1, train=False)
from cntk import Function
from cntk.losses import cross_entropy_with_softmax
from cntk.metrics import classification_error
from cntk.learners import sgd
@Function
def criterion_factory(output, targets):
   loss = cross_entropy_with_softmax(output, targets)
   metric = classification_error(output, targets)
return loss, metric
loss = criterion_factory(z, labels)
learner = sgd(z.parameters, lr=0.2)
from cntk.logging import ProgressPrinter
from cntk.train import TestConfig
progress_writer = ProgressPrinter(0)
test_config = TestConfig(test_datasource)
input_map = {
   features: train_datasource.streams.features,
   labels: train_datasource.streams.labels
}
loss.train(train_datasource,
     max_epochs=10,
     minibatch_size=64,
     epoch_size=60000,
        parameter_learners=[learner],
     model_inputs_to_streams=input_map,
     callbacks=[progress_writer, test_config])

Вывод

-------------------------------------------------------------------
average  since  average  since  examples
loss     last   metric   last
------------------------------------------------------
Learning rate per minibatch: 0.2
142      142      0.922   0.922    64
1.35e+06 1.51e+07 0.896   0.883    192
[………]

Преобразования изображений

Как мы видели, сложно обучить NN, используемые для распознавания изображений, и им также требуется много данных для обучения. Еще одна проблема заключается в том, что они имеют тенденцию чрезмерно соответствовать изображениям, используемым во время обучения. Давайте посмотрим на примере, когда у нас есть фотографии лиц в вертикальном положении, нашей модели будет трудно распознать лица, повернутые в другом направлении.

Чтобы преодолеть такую ​​проблему, мы можем использовать увеличение изображения, а CNTK поддерживает определенные преобразования при создании источников мини-пакетов для изображений. Мы можем использовать несколько преобразований следующим образом:

  • Мы можем произвольно обрезать изображения, используемые для обучения, с помощью всего нескольких строк кода.

  • Мы также можем использовать шкалу и цвет.

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

import os
from cntk.io import MinibatchSource, StreamDef, StreamDefs, ImageDeserializer, INFINITELY_REPEAT
import cntk.io.transforms as xforms
def create_datasource(folder, train=True, max_sweeps=INFINITELY_REPEAT):
   mapping_file = os.path.join(folder, 'mapping.bin')
   image_transforms = []
   if train:
   image_transforms += [
     xforms.crop(crop_type='randomside', side_ratio=0.8),
xforms.scale(width=28, height=28, channels=3, interpolations='linear')
]
   stream_definitions = StreamDefs(
   features=StreamDef(field='image', transforms=image_transforms),
labels=StreamDef(field='label', shape=10)
)
   deserializer = ImageDeserializer(mapping_file, stream_definitions)
return MinibatchSource(deserializer, max_sweeps=max_sweeps)

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

CNTK - Рекуррентная нейронная сеть

Теперь давайте поймем, как создать рекуррентную нейронную сеть (RNN) в CNTK.

Введение

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

Что такое рекуррентная нейронная сеть?

Рекуррентные нейронные сети (RNN) можно определить как особую разновидность нейронных сетей, которые способны рассуждать с течением времени. RNN в основном используются в сценариях, где нам нужно иметь дело со значениями, которые меняются во времени, то есть данными временных рядов. Чтобы лучше понять это, давайте проведем небольшое сравнение между обычными нейронными сетями и рекуррентными нейронными сетями -

  • Как мы знаем, в обычной нейронной сети мы можем предоставить только один вход. Это ограничивает результат только одним предсказанием. Например, мы можем выполнить перевод текста с помощью обычных нейронных сетей.

  • С другой стороны, в рекуррентных нейронных сетях мы можем предоставить последовательность выборок, которые приводят к единственному прогнозу. Другими словами, используя RNN, мы можем предсказать выходную последовательность на основе входной последовательности. Например, было довольно много успешных экспериментов с RNN в задачах перевода.

Использование рекуррентной нейронной сети

RNN можно использовать несколькими способами. Некоторые из них следующие -

Прогнозирование одного выхода

Прежде чем углубляться в этапы того, как RNN может предсказать одиночный результат на основе последовательности, давайте посмотрим, как выглядит базовая RNN -

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

Более того, благодаря кольцевому соединению RNN может комбинировать сгенерированный вывод с вводом для следующего элемента в последовательности. Таким образом, RNN создаст память по всей последовательности, которую можно использовать для прогнозирования.

Чтобы сделать прогноз с помощью RNN, мы можем выполнить следующие шаги:

  • Во-первых, чтобы создать начальное скрытое состояние, нам нужно скормить первый элемент входной последовательности.

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

  • Наконец, чтобы создать окончательное скрытое состояние и предсказать результат для RNN, нам нужно взять последний элемент во входной последовательности.

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

Прогнозирование последовательности

Рассмотренная выше базовая модель RNN может быть распространена и на другие варианты использования. Например, мы можем использовать его для прогнозирования последовательности значений на основе одного ввода. В этом сценарии, чтобы сделать прогноз с помощью RNN, мы можем выполнить следующие шаги:

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

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

  • Наконец, чтобы обновить скрытое состояние еще раз и предсказать последний элемент в выходной последовательности, мы подаем образец в другой раз.

Прогнозирование последовательностей

Как мы видели, как предсказать одно значение на основе последовательности и как предсказать последовательность на основе одного значения. Теперь давайте посмотрим, как мы можем предсказать последовательности для последовательностей. В этом сценарии, чтобы сделать прогноз с помощью RNN, мы можем выполнить следующие шаги:

  • Во-первых, чтобы создать начальное скрытое состояние и предсказать первый элемент в выходной последовательности, нам нужно взять первый элемент во входной последовательности.

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

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

Работа РНН

Чтобы понять работу рекуррентных нейронных сетей (RNN), нам нужно сначала понять, как работают повторяющиеся слои в сети. Итак, сначала давайте обсудим, как e может предсказать результат с помощью стандартного повторяющегося слоя.

Прогнозирование вывода со стандартным слоем RNN

Как мы уже обсуждали ранее, базовый уровень в RNN сильно отличается от обычного уровня в нейронной сети. В предыдущем разделе мы также продемонстрировали на схеме базовую архитектуру RNN. Чтобы обновить скрытое состояние для последовательности первого шага, мы можем использовать следующую формулу -

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

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

Затем мы можем повторить процесс обновления скрытого состояния для третьего и последнего шага в последовательности, как показано ниже -

И когда мы обработали все вышеперечисленные шаги в последовательности, мы можем рассчитать результат следующим образом:

Для приведенной выше формулы мы использовали третий набор весов и скрытое состояние из последнего временного шага.

Продвинутые рекуррентные единицы

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

Долговременная память (LSTM)

Сети долговременной краткосрочной памяти (LSTM) были представлены Hochreiter & Schmidhuber. Это решило проблему получения базового повторяющегося слоя, чтобы запоминать вещи на долгое время. Архитектура LSTM приведена выше на схеме. Как мы видим, у него есть входные нейроны, ячейки памяти и выходные нейроны. Чтобы бороться с проблемой исчезающего градиента, сети долговременной памяти используют явную ячейку памяти (хранящую предыдущие значения) и следующие ворота -

  • Forget gate- Как следует из названия, он указывает ячейке памяти забыть предыдущие значения. Ячейка памяти хранит значения до тех пор, пока вентиль, то есть «ворота забыть», не скажет ему забыть их.

  • Input gate- Как следует из названия, он добавляет в ячейку новый материал.

  • Output gate- Как следует из названия, выходной элемент решает, когда перейти по векторам от ячейки к следующему скрытому состоянию.

Закрытые рекуррентные единицы (ГРУ)

Gradient recurrent units(GRUs) - это небольшая вариация сети LSTM. У него на один вентиль меньше, и он немного отличается от LSTM. Его архитектура показана на схеме выше. Он имеет входные нейроны, закрытые ячейки памяти и выходные нейроны. Сеть Gated Recurrent Units имеет следующие два входа:

  • Update gate- Он определяет следующие две вещи:

    • Какой объем информации нужно сохранить из последнего состояния?

    • Какое количество информации нужно впустить с предыдущего слоя?

  • Reset gate- Функциональность шлюза сброса очень похожа на функцию шлюза забывания сети LSTM. Единственное отличие в том, что он расположен немного иначе.

В отличие от сети с долгосрочной памятью, сети Gated Recurrent Unit немного быстрее и проще в эксплуатации.

Создание структуры RNN

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

from cntk.losses import squared_error
from cntk.io import CTFDeserializer, MinibatchSource, INFINITELY_REPEAT, StreamDefs, StreamDef
from cntk.learners import adam
from cntk.logging import ProgressPrinter
from cntk.train import TestConfig
BATCH_SIZE = 14 * 10
EPOCH_SIZE = 12434
EPOCHS = 10

Размещение нескольких слоев

Мы также можем складывать несколько повторяющихся слоев в CNTK. Например, мы можем использовать следующую комбинацию слоев:

from cntk import sequence, default_options, input_variable
from cntk.layers import Recurrence, LSTM, Dropout, Dense, Sequential, Fold
features = sequence.input_variable(1)
with default_options(initial_state = 0.1):
   model = Sequential([
      Fold(LSTM(15)),
      Dense(1)
   ])(features)
target = input_variable(1, dynamic_axes=model.dynamic_axes)

Как мы видим в приведенном выше коде, у нас есть два следующих способа смоделировать RNN в CNTK:

  • Во-первых, если нам нужен только окончательный результат повторяющегося слоя, мы можем использовать Fold Layer в сочетании с повторяющимся слоем, например GRU, LSTM или даже RNNStep.

  • Во-вторых, в качестве альтернативы мы также можем использовать Recurrence блок.

Обучение RNN с данными временных рядов

Когда мы построим модель, давайте посмотрим, как мы можем обучить RNN в CNTK -

from cntk import Function
@Function
def criterion_factory(z, t):
   loss = squared_error(z, t)
   metric = squared_error(z, t)
   return loss, metric
loss = criterion_factory(model, target)
learner = adam(model.parameters, lr=0.005, momentum=0.9)

Теперь, чтобы загрузить данные в процесс обучения, нам нужно десериализовать последовательности из набора файлов CTF. Следующий код имеетcreate_datasource функция, которая является полезной служебной функцией для создания как обучающего, так и тестового источника данных.

target_stream = StreamDef(field='target', shape=1, is_sparse=False)
features_stream = StreamDef(field='features', shape=1, is_sparse=False)
deserializer = CTFDeserializer(filename, StreamDefs(features=features_stream, target=target_stream))
   datasource = MinibatchSource(deserializer, randomize=True, max_sweeps=sweeps)
return datasource
train_datasource = create_datasource('Training data filename.ctf')#we need to provide the location of training file we created from our dataset.
test_datasource = create_datasource('Test filename.ctf', sweeps=1) #we need to provide the location of testing file we created from our dataset.

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

progress_writer = ProgressPrinter(0)
test_config = TestConfig(test_datasource)
input_map = {
   features: train_datasource.streams.features,
   target: train_datasource.streams.target
}
history = loss.train(
   train_datasource,
   epoch_size=EPOCH_SIZE,
   parameter_learners=[learner],
   model_inputs_to_streams=input_map,
   callbacks=[progress_writer, test_config],
   minibatch_size=BATCH_SIZE,
   max_epochs=EPOCHS
)

Мы получим следующий результат:

Выход

average  since  average  since  examples
loss      last  metric  last
------------------------------------------------------
Learning rate per minibatch: 0.005
0.4      0.4    0.4      0.4      19
0.4      0.4    0.4      0.4      59
0.452    0.495  0.452    0.495   129
[…]

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

На самом деле повторение с помощью RNN очень похоже на прогнозирование с помощью любой другой модели CNK. Единственная разница в том, что нам нужно предоставлять последовательности, а не отдельные образцы.

Теперь, когда наша RNN, наконец, закончила обучение, мы можем проверить модель, протестировав ее с использованием последовательности нескольких образцов следующим образом:

import pickle
with open('test_samples.pkl', 'rb') as test_file:
test_samples = pickle.load(test_file)
model(test_samples) * NORMALIZE

Выход

array([[ 8081.7905],
[16597.693 ],
[13335.17 ],
...,
[11275.804 ],
[15621.697 ],
[16875.555 ]], dtype=float32)