Через 2 дня начал прикасаться к фреймворку Tensorflow. Начинаю писать свой опыт. Конечно, он следует учебнику по tensorlow, но я стараюсь делать цифры и важные моменты для новичков, как и я (просто/легче для понимания).

Установка простым способом

Anaconda2 + Python 2.7 — мой выбор, так как установка в Anaconda создает изолированную среду, любое обновление или удаление пакетов не повлияет на библиотеки Python. Кроме того, мне также нравится новейшая версия Jupyter.

В настоящее время версия Tensorflow по умолчанию — 1.4. Чтобы запустить все официальные руководства по Tensorflow, нам нужен Tensorflow 1.5 → просто обновите его.

В моем случае Ubuntu, Python 2.7, используйте GPU, уже есть Tensorflow 1.4 по умолчанию для Anaconda2. Довольно простая одна команда.

pip install --ignore-installed --upgrade \
https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.5.0-cp27-none-linux_x86_64.whl

Но CUDA 9.1 — это последняя версия накопителя, если вы установите Tensorflow 1.5, он сможет использовать только CUDA 9.0. Не забудьте понизить / повторно связать Cuda и перепроверить

nvcc --version

Следуйте первому руководству по Tensorflow на официальном сайте.

я по этой ссылке

Тем не менее, немного утомительно изучать новый фреймворк (стиль кодирования), пытаясь запустить его из командной строки и начать читать исходный код.

  • Я уже портирую исходный код premade_estimator.py по частям в блокнот Jupyter. Конечно, результаты похожи, но мы можем запустить части по отдельности и посмотреть, какие переменные внутри.
  • Для ленивых запоминающих можно посмотреть: https://github.com/nguyenv7/tensor-flow/blob/master/tensorflow_iris.ipynb

Вкратце, этот урок показывает, как классифицировать 3 типа цветов ириса (Setosa, Versicolor. Virginica) в легендарных данных Iris. Эти данные содержат 120 обучающих и 30 тестовых выборок соответственно. Каждая выборка данных описывается четырьмя признаками: длиной чашелистика, шириной чашелистика, длиной лепестка и шириной лепестка. Наконец, классификатор создается двухслойной плотной сетью.

В этом руководстве мы попытаемся дать простое объяснение для предоставленного исходного кода. Конечно, он закодирован в высокоуровневых API-интерфейсах Tensorflow, поэтому мы познакомимся с готовым оценщиком и сравним его с подходом кодирования пользовательского оценщика.

Уведомления Tensorflow

Во-первых, фреймворки Tensorflow будут ОПРЕДЕЛЯТЬ СНАЧАЛА, ЗАПУСКАТЬ ПОЗЖЕ.

  • Все определения переменных, вычислительные операторы должны быть определены в первую очередь. При вызове их, как в Numpy или Python, возвращаемых значений нет.
  • На этапе выполнения данные будут переданы в определение модели, запущены и возвращены выходные данные.
  • В API высокого уровня вам не нужно учитывать явные обучающие выборки чисел, размер матрицы/тензора в слоях нейронной сети. Tensorflow сделает/организует это автоматически. Вам нужно ввести гипер — параметры, такие как размер пакета, шаги обучения, количество скрытых единиц.
  • Все входные данные необходимо преобразовать/привести к «тензорной» форме. К счастью, столбец tf.feature_column также предоставляет функции для преобразования категориальных/других типов входных данных в числовые/хешированные данные.

Во-вторых, есть 3 основные структуры, чтобы входной тензор следовал нашей навигации:

  • tf.data.Dataset: возьмите необработанные данные и создайте тип данных «Tensor».
  • tf.feature_column: общий дескриптор входной функции для преобразования многих типов входных данных, информирования о его типе в модели машинного обучения, чтобы убедиться, что модель неизменна для обработки новых входных данных.
  • tf.estimator: определение модели и обучение/оценка/прогнозирование модели.

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

[premade_estimator.py] Анализирует ход программы

Есть 3 основных шага, очевидно, что только tf.estimator состоит из двух.

  • Конвейер данных
  • Определение модели
  • Исполнение модели

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

(train_x, train_y), (test_x, test_y)

train_input_fn() принимает (train_x, train_y, args.batch_size) в качестве входных данных. Очевидно, что tf.data.Dataset.from_tensor_slices играет наиболее важную роль в создании TensorSliceDataset из dict функций (train_x). Поскольку данные поезда состоят из 120 выборок, нам нужно повторить их, чтобы получить достаточно данных для пакетов.

#Source: #https://github.com/tensorflow/models/blob/master/samples/core/get_started/iris_data.py
def train_input_fn(features, labels, batch_size):    
"""An input function for training"""    
# Convert the inputs to a Dataset.
dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))     
# Shuffle, repeat, and batch the examples.    
dataset = dataset.shuffle(1000).repeat().batch(batch_size)   
 
# Return the dataset.    
return dataset

Функция eval_input_fn() почти такая же, за исключением того, что ей нужно объявить, доступна ли метка данных или нет. Это предназначено для случая прогнозирования меток для новых данных или просто для целей тестирования (конечно, метки данных предоставляются). Поскольку на этом этапе нет обучения, нет необходимости перемешивать или группировать данные.

#Source: #https://github.com/tensorflow/models/blob/master/samples/core/get_started/iris_data.py
def eval_input_fn(features, labels, batch_size):    
"""An input function for evaluation or prediction"""
features=dict(features)    
if labels is None:       
# No labels, use only features.        
    inputs = features    
else:        
inputs = (features, labels)     
# Convert the inputs to a Dataset.   
dataset = tf.data.Dataset.from_tensor_slices(inputs)     
# Batch the examples    
assert batch_size is not None, "batch_size must not be None"
dataset = dataset.batch(batch_size)     
# Return the dataset.   
return dataset

Определение модели: высокоуровневые API с готовыми моделями от Tensorflow упрощают определение модели: нам нужно выполнить 2 шага:

  • Укажите тип вводимых данных или что внутри полей, здесь вводятся числовые данные, просто скажите tf.feature_column.numeric_column с именами функций. Выглядит немного странно, но помните, что мы уже создали dict(features) в конвейере данных. Это означает, что данные будут доступны по имени ключа (например: train_data[‘PetalLength’] ). Затем вместе с типом объекта нам нужно указать его имя (или ключ). Заметил, что это формальное определение, пока нет передачи данных.
# Feature columns describe what is the input look like.
my_feature_columns = []
for key in train_x.keys():
 my_feature_columns.append(tf.feature_column.numeric_column(key=key))
  • Вызовите предварительно созданный классификатор Tensorflow, нужно только передать my_feature_columns, чтобы сообщить о типе и имени функции, а также о настройке гиперпараметров.
# Build 2 hidden layer DNN with 10, 10 units respectively.
classifier = tf.estimator.DNNClassifier(
    feature_columns=my_feature_columns,
    # Two hidden layers of 10 nodes each.
    hidden_units=[10, 10],
    # The model must choose between 3 classes.
    n_classes=3)

Часть model обучения также коротка с готовой моделью, нотация лямбда позволяет нам передавать входные переменные в функцию (iris_data. train_input_fn) внутри вызова функции (classifier.train). Фактические данные проходят через этот шаг к определению модели и заставляют их все работать.

# Train the Model.
classifier.train(input_fn=lambda:iris_data.train_input_fn(train_x, train_y,args.batch_size),steps=args.train_steps)

Часть оценки тоже элегантна, просто вызывая classifier.evaluate.

# Evaluate the model.
eval_result = classifier.evaluate(input_fn=lambda:iris_data.eval_input_fn(test_x, test_y,args.batch_size))
print('\nTest set accuracy:{accuracy:0.3f}\n'.format(**eval_result))

Готовый оценщик против пользовательского оценщика

Наконец, пример пользовательского оценщика помогает нам понять всю описанную выше процедуру tf.estimator. Продолжаем следить за официальным документом от Tensorflow

  1. Создать структуру сети
def my_model(features, labels, mode, params):
net = tf.feature_column.input_layer(features,params['feature_columns'])
for units in params['hidden_units']:        
    net = tf.layers.dense(net, units=units, activation=tf.nn.relu)
  • tf.feature_column.input_layer создает входной слой из входных данных: фактических объектов данных и «схемы» данных (params['feature_columns'] ) или наши my_feature_columns. Он создает первый слой слоя net только с входными данными.
  • net = tf.layers.dense(net, …) добавляет еще один слой поверх текущего слоя net. Как API высокого уровня, он автоматически упорядочивает матрицы весов и инициализацию.

2. Пересылка данных

# Compute logits (1 per class). 
logits = tf.layers.dense(net, params[‘n_classes’], activation=None)
  • Вызовите tf.layers.dense еще раз, чтобы получить выходные данные сети после пересылки входных данных через слои. Обратите внимание, что логиты — это числа, а не метки классов.

3. Прогноз, оценка

Активен по режиму, например:

assert mode == tf.estimator.ModeKeys.TRAIN

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

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

predicted_classes = tf.argmax(logits, 1)
  • Преобразуйте числа логитов в классы, каждая выборка имеет 3 числа логитов (для данных Iris в соответствии с 3 классами), классы, которые получают самые высокие логиты, являются предсказанным классом.
  • Из logits мы определяем функции loss путем сравнения с входными метками. потеря является критерием для целей обучения, получения градиента, обратного распространения.
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
  • Нам все еще нужно определить критерии оценки, чтобы узнать производительность текущей модели с данными.
# Compute evaluation metrics. accuracy = tf.metrics.accuracy(labels=labels, predictions=predicted_classes, name=’acc_op’)

4. Тренировочная сеть

Получив определение loss, вызовите метод tf.train и минимизируйте потерю :)

# Create training op.    
assert mode == tf.estimator.ModeKeys.TRAIN     
optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)    
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())

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

Резюме

  • Tensorflow требует больше времени для изучения и чтения исходного кода. Тем не менее, более четкая структура, немного «странная» логика, но сначала определите, а потом запустите, более оптимальна с точки зрения всего конвейера обработки данных.
  • API-интерфейсы высокого уровня обеспечивают множество гибких возможностей для взаимодействия/преобразования данных, а также для определения/запуска модели.
  • Это также проще, чем Torch и PyTorch с точки зрения настройки графического процессора и Cuda.