Начало работы с TensorFlow
Это руководство поможет вам начать программировать в TensorFlow. Перед использованием этого руководства установите TensorFlow. Чтобы получить максимальную отдачу от этого руководства, вы должны знать следующее:
- Как программировать на Python.
- Хотя бы немного знаний о массивах массивов.
- В идеале что-то о машинном обучении. Однако, если вы очень мало знаете о машинном обучении, это все равно первое руководство, которое вы должны прочитать.
TensorFlow предоставляет несколько API. API самого низкого уровня — ядро TensorFlow — дает вам полный контроль над программированием. Мы рекомендуем TensorFlow Core для исследователей машинного обучения и других лиц, которым необходим детальный контроль над своими моделями. API более высокого уровня построен на основе ядра TensorFlow. Эти API более высокого уровня, как правило, легче изучить и использовать, чем TensorFlow Core. Кроме того, высокоуровневый API упрощает повторяющиеся задачи и делает их более согласованными между разными пользователями. Высокоуровневые API, такие как tf.estimator, могут помочь вам управлять наборами данных, оценщиками, обучением и выводами.
Это руководство начинается с основного руководства по TensorFlow. Позже мы покажем, как реализовать ту же модель в tf.estimator. Знание основных принципов TensorFlow даст вам хорошую ментальную модель того, как работает внутреннее устройство, когда вы используете более компактные API более высокого уровня.
Тензор
Единицей центра обработки данных в TensorFlow является тензор. Тензор состоит из набора примитивных значений, образующих любое количество измерений. Ранг тензора — это его размерность. Вот несколько примеров тензоров:
3 # a rank 0 tensor; a scalar with shape []
[1., 2., 3.] # a rank 1 tensor; a vector with shape [3]
[[1., 2., 3.], [4., 5., 6.]] # a rank 2 tensor; a matrix with shape [2, 3]
[[[1., 2., 3.]], [[7., 8., 9.]]] # a rank 3 tensor with shape [2, 1, 3]
Учебник по ядру TensorFlow
импортировать тензорный поток
Канонический оператор импорта для программы TensorFlow выглядит так:
import tensorflow as tf
Это дает Python доступ ко всем классам, методам и символам TensorFlow. Большинство документации предполагает, что вы уже сделали это.
Вычислительный граф
Вы можете представить, что основная программа TensorFlow состоит из двух отдельных частей:
- Построить вычислительные графики.
- Запустите вычислительный граф.
Вычислительный граф представляет собой серию графовых операций TensorFlow, организованных в узлы. Построим простой вычислительный граф. Каждый узел принимает ноль или более тензоров в качестве входных данных и создает тензоры в качестве выходных данных. Тип узла является константой. Как и все константы TensorFlow, он не принимает входных данных, а выводит внутренне сохраненное значение. Мы можем создать два тензора с плавающей запятой node1 и node2 следующим образом:
node1 = tf.constant(3.0, dtype=tf.float32)
node2 = tf.constant(4.0) # also tf.float32 implicitly
print(node1, node2)
Окончательный оператор печати дает
Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32)
Обратите внимание, что узел печати не выводит значения 3.0, 4.0, как можно было бы ожидать. Вместо этого они являются узлами, которые при оценке дают 3,0 и 4,0 соответственно. Чтобы на самом деле оценить узлы, мы должны запустить вычислительный граф в сеансе. Сеанс инкапсулирует управление и состояние среды выполнения TensorFlow.
Следующий код создает объект Session, а затем вызывает его метод run, чтобы запустить граф вычислений, достаточный для оценки node1 и node2. Запустив вычислительный граф в сеансе следующим образом:
sess = tf.Session()
print(sess.run([node1, node2]))
Видим ожидаемые значения для 3.0 и 4.0:
[3.0, 4.0]
Мы можем построить более сложные вычисления, комбинируя узлы Tensor и операции (операции также являются узлами). Например, мы можем добавить два наших постоянных узла и создать новый график следующим образом:
from __future__ import print_function
node3 = tf.add(node1, node2)
print("node3:", node3)
print("sess.run(node3):", sess.run(node3))
Последние два оператора печати дают
node3: Tensor("Add:0", shape=(), dtype=float32)
sess.run(node3): 7.0
TensorFlow предоставляет утилиту под названием TensorBoard, которая отображает изображения вычислительных графиков. Ниже приведен скриншот, показывающий, как TensorBoard визуализирует график:
В нынешнем виде этот график не представляет особого интереса, поскольку всегда дает постоянный результат. Графики могут быть параметризованы для приема внешних входных данных, называемых заполнителями. Заполнитель — это обещание предоставить значение после.
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b # + provides a shortcut for tf.add(a, b)
Первые три строки похожи на функцию или лямбду, где мы определяем два входных параметра (a и b), а затем работаем с ними. Мы можем оценить этот график, предоставив конкретные значения для нескольких входных данных для заполнителей, используя параметр feed_dict метода запуска.
print(sess.run(adder_node, {a: 3, b: 4.5}))
print(sess.run(adder_node, {a: [1, 3], b: [2, 4]}))
результат на выходе
7,5 [3.7.] В TensorBoard график выглядит так:
Мы можем сделать вычислительный граф более сложным, добавив еще одну операцию. Например,
add_and_triple = adder_node * 3.
print(sess.run(add_and_triple, {a: 3, b: 4.5}))
производить продукцию
22,5 В TensorBoard приведенный выше график вычислений выглядит так:
В машинном обучении нам обычно нужна модель, которая может принимать произвольные входные данные, например модель выше. Чтобы модель была обучаемой, нам нужно иметь возможность модифицировать график, чтобы получать новые выходные данные с теми же входными данными. Переменные позволяют добавлять на график обучаемые параметры. Они строятся с типом и начальным значением:
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
x = tf.placeholder(tf.float32)
linear_model = W*x + b
Константы инициализируются при вызове tf.constant, и их значение никогда не меняется. Напротив, переменные не инициализируются при вызове tf.Variable. Чтобы инициализировать все переменные в программе TensorFlow, вы должны явно вызвать специальную операцию, подобную этой:
init = tf.global_variables_initializer()
sess.run(init)
Важно, чтобы один дескриптор, реализующий подграф initTensorFlow, инициализировал все глобальные переменные. Прежде чем мы вызовем sess.run, переменная не инициализируется.
Поскольку x является заполнителем, мы можем одновременно оценивать несколько значений linear_model, x выглядит так:
print(sess.run(linear_model, {x: [1, 2, 3, 4]}))
производить продукцию
[ 0. 0.30000001 0.60000002 0.90000004]
Мы создали модель, но не знаем, насколько она хороша. Чтобы оценить модель на обучающих данных, нам нужен заполнитель y, чтобы обеспечить желаемое значение, и нам нужно написать функцию потерь.
Функция потерь используется для измерения того, насколько текущая модель отличается от предоставленных данных. Мы будем использовать стандартную модель потерь линейной регрессии, которая добавляет квадрат треугольника между текущей моделью и предоставленными данными. linear_model - y создает вектор, где каждый элемент является приращением ошибки для соответствующего примера. Мы вызываем tf.square, чтобы исправить эту ошибку. Затем мы суммируем все квадраты ошибок, чтобы создать скаляр, который абстрагирует ошибки всех примеров с помощью tf.reduce_sum:
y = tf.placeholder(tf.float32)
squared_deltas = tf.square(linear_model - y)
loss = tf.reduce_sum(squared_deltas)
print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
генерировать потерянную стоимость
23.66
Мы можем вручную переназначить значения этих W и b на -1 и 1 на значения переменных, которые идеально инициализируются значениями, предоставленными tf.Variable , но могут быть изменены с помощью таких операций, как tf.assign . Например, W=-1 и b=1 — лучшие параметры для нашей модели. Мы можем изменить W, b таким образом:
fixW = tf.assign(W, [-1.])
fixb = tf.assign(b, [1.])
sess.run([fixW, fixb])
print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
Окончательный отпечаток показывает, что потери теперь равны нулю.
0.0
Мы угадываем «идеальные» значения W и b, но весь смысл машинного обучения автоматически находит правильные параметры модели. Мы покажем, как это сделать в следующем разделе.
tf.train API
Полное обсуждение машинного обучения выходит за рамки этого руководства. Однако TensorFlow предоставляет оптимизаторы, которые постепенно изменяют каждую переменную, чтобы минимизировать функцию потерь. Самый простой оптимизатор — градиентный спуск. Он изменяет каждую переменную в соответствии с величиной производной потерь по этой переменной. В общем, ручное вычисление символьного вывода утомительно и чревато ошибками. Поэтому TensorFlow может автоматически генерировать производные, описывающие модель, используя только функцию tf.gradients. Для простоты оптимизатор обычно делает это за вас. Например,
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
sess.run(init) # reset values to incorrect defaults.
for i in range(1000):
sess.run(train, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]})
print(sess.run([W, b]))
в результате чего окончательные параметры модели:
[array([-0.9999969], dtype=float32), array([ 0.99999082], dtype=float32)]
Теперь мы закончили с машинным обучением! Хотя эта простая модель линейной регрессии не требует большого количества основного кода TensorFlow, для более сложных моделей и методов ввода данных в модель требуется больше кода. Таким образом, TensorFlow предоставляет абстракции более высокого уровня для общих шаблонов, структур и функций. Мы узнаем, как использовать эти абстракции в следующем разделе.
полная программа Завершенная обучаемая модель линейной регрессии выглядит следующим образом:
import tensorflow as tf
# Model parameters
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W*x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1, 2, 3, 4]
y_train = [0, -1, -2, -3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
sess.run(train, {x: x_train, y: y_train})
# evaluate training accuracy
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x: x_train, y: y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
генерируется во время выполнения
W: [-0.9999969] b: [ 0.99999082] loss: 5.69997e-11
Обратите внимание, что потери очень малы (очень близки к нулю). Если вы запустите эту программу, ваши потери могут быть не такими, как указано выше, потому что модель инициализируется псевдослучайными значениями.
Эту более сложную программу все еще можно визуализировать в TensorBoard.
tf.estimator
tf.estimator — это высокоуровневая библиотека TensorFlow, которая упрощает механику машинного обучения, включая следующее:
- Запустите тренировочный цикл
- Запустите цикл оценки
- Управление наборами данных
tf.estimator определяет множество общих моделей.
Основное использование Обратите внимание, что процедура линейной регрессии намного проще с tf.estimator:
# NumPy is often used to load, manipulate and preprocess data.
import numpy as np
import tensorflow as tf
# Declare list of features. We only have one numeric feature. There are many
# other types of columns that are more complicated and useful.
feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]
# An estimator is the front end to invoke training (fitting) and evaluation
# (inference). There are many predefined types like linear regression,
# linear classification, and many neural network classifiers and regressors.
# The following code provides an estimator that does linear regression.
estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
# TensorFlow provides many helper methods to read and set up data sets.
# Here we use two data sets: one for training and one for evaluation
# We have to tell the function how many batches
# of data (num_epochs) we want and how big each batch should be.
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7, 0.])
input_fn = tf.estimator.inputs.numpy_input_fn(
{"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
{"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
{"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
# We can invoke 1000 training steps by invoking the method and passing the
# training data set.
estimator.train(input_fn=input_fn, steps=1000)
# Here we evaluate how well our model did.
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("train metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)
При запуске что-то вроде
train metrics: {'average_loss': 1.4833182e-08, 'global_step': 1000, 'loss': 5.9332727e-08}
eval metrics: {'average_loss': 0.0025353201, 'global_step': 1000, 'loss': 0.01014128}
Обратите внимание, что наши оценочные данные имеют более высокие потери, но все еще близки к нулю. Это значит, что мы учимся правильно.
индивидуальная модель tf.estimator не привязывает вас к предопределенной модели. Предположим, мы хотим создать пользовательскую модель, не встроенную в TensorFlow. Мы все еще можем сохранить высокоуровневую абстракцию набора данных, кормления, обучения и т. д. tf.estimator. Для иллюстрации мы покажем, как реализовать нашу собственную эквивалентную модель с LinearRegressor, используя наши знания низкоуровневого API TensorFlow.
Чтобы определить подходящую пользовательскую модель tf.estimator, нам нужно использовать tf.estimator.Estimator. tf.estimator.LinearRegressor на самом деле является подклассом tf.estimator.Estimator. Estimator Мы просто предоставляем Estimator функцию model_fn, чтобы проиллюстрировать, как tf.estimator оценивает прогнозы, шаги обучения и потери, а не классификацию. код показывает, как показано ниже:
import numpy as np
import tensorflow as tf
# Declare list of features, we only have one real-valued feature
def model_fn(features, labels, mode):
# Build a linear model and predict values
W = tf.get_variable("W", [1], dtype=tf.float64)
b = tf.get_variable("b", [1], dtype=tf.float64)
y = W*features['x'] + b
# Loss sub-graph
loss = tf.reduce_sum(tf.square(y - labels))
# Training sub-graph
global_step = tf.train.get_global_step()
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = tf.group(optimizer.minimize(loss),
tf.assign_add(global_step, 1))
# EstimatorSpec connects subgraphs we built to the
# appropriate functionality.
return tf.estimator.EstimatorSpec(
mode=mode,
predictions=y,
loss=loss,
train_op=train)
estimator = tf.estimator.Estimator(model_fn=model_fn)
# define our data sets
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7., 0.])
input_fn = tf.estimator.inputs.numpy_input_fn(
{"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
{"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
{"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
# train
estimator.train(input_fn=input_fn, steps=1000)
# Here we evaluate how well our model did.
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("train metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)
генерируется во время выполнения
train metrics: {'loss': 1.227995e-11, 'global_step': 1000}
eval metrics: {'loss': 0.01010036, 'global_step': 1000}
Обратите внимание, что содержимое пользовательской функции model_fn() очень похоже на цикл обучения ручной модели базового API.
Статья переведена в соответствии с официальным английским документом, отсканируйте мой публичный аккаунт WeChat, чтобы учиться вместе.
Публичный аккаунт WeChat: хвастовство разработчиков AndroidПерсональный сайт:
http://chaodongyang.com