Добавить Автора
WeChat и QQ: 862251340
Публичный аккаунт WeChat: coderpai
Пошаговое построение многозадачной модели обучения с помощью TensorFlow
вводить
Почему многозадачное обучение?
Когда вы думаете о новых вещах, они часто используют свой предыдущий опыт и полученные знания, чтобы ускорить текущий процесс обучения. Когда мы изучаем новый язык, особенно родственный язык, мы обычно используем свои знания языка первого уровня, чтобы ускорить процесс изучения нового языка. Этот процесс можно понимать и по-другому: изучение нового языка может помочь вам лучше понимать и выражать свои мысли.
Наш мозг одновременно усваивает много разных задач, и хотим ли мы перевести с английского на китайский или с китайского на немецкий, мы все используем одну и ту же архитектуру мозга, наш собственный мозг. Точно так же в нашей модели машинного обучения, если мы используем одну и ту же сеть для одновременного выполнения обеих задач, мы можем назвать эту задачу «многозадачным обучением».
«Многозадачное обучение» — очень интересная и захватывающая область исследований в последние годы или ближайшие несколько лет, потому что этот режим обучения радикально сокращает объем данных, необходимых для изучения новых понятий. Одна из величайших особенностей глубокого обучения заключается в том, что мы можем использовать совместное использование параметров между моделями для оптимизации наших моделей, и этот подход будет особенно заметен в многозадачном обучении.
Прежде чем мы начали учиться в этой области, я столкнулся с несколькими препятствиями: хотя было легко понять сетевую архитектуру, необходимую для реализации многозадачного обучения, было сложно понять, как реализовать ее в TensorFlow. Все, что мы делаем, кроме стандартных сетей в TensorFlow, требует хорошего понимания того, как это работает, но в большинстве онлайн-руководств нет хорошей обучающей функции. Я надеюсь, что следующие руководства кратко объяснят некоторые ключевые понятия и помогут вам, кто изо всех сил пытается учиться.
что нам делать
- Узнайте о вычислительном графе TensorFlow на примере. Многозадачное обучение с TensorFlow. Если вы уже понимаете вычислительный граф TensorFlow, можете пропустить эту часть.
- Посмотрите, как мы используем вычислительные графы для многозадачного обучения. Мы рассмотрим пример, чтобы проиллюстрировать, как адаптировать простой вычислительный граф для выполнения многозадачного обучения.
Понимание вычислительных графиков на простом примере
Вычислительный граф TensorFlow ускоряет работу TensorFlow, и это важная, хотя и запутанная часть глубокого обучения.
Вычислительные графы могут упростить определение организационной структуры модели, что очень важно для нашего многозадачного обучения. Во-первых, давайте сначала разберемся с некоторыми концепциями многозадачного обучения.
Простой пример: линейные преобразования
Мы проведем простое вычисление на вычислительном графе — линейно преобразуем входные данные и вычислим потерю квадратного корня.
# Import Tensorflow and numpy
import tensorflow as tf
import numpy as np
# ======================
# Define the Graph
# ======================
# Create Placeholders For X And Y (for feeding in data)
X = tf.placeholder("float",[10, 10],name="X") # Our input is 10x10
Y = tf.placeholder("float", [10, 1],name="Y") # Our output is 10x1
# Create a Trainable Variable, "W", our weights for the linear transformation
initial_W = np.zeros((10,1))
W = tf.Variable(initial_W, name="W", dtype="float32")
# Define Your Loss Function
Loss = tf.pow(tf.add(Y,-tf.matmul(X,W)),2,name="Loss")
На изображении выше и в коде есть несколько моментов, которые следует подчеркнуть:
- Если мы запустим этот код сейчас, мы не получим никакого вывода. Помните, что вычислительный граф — это всего лишь шаблон, он ничего не делает с ним. Если нам нужен вывод вычислений, мы должны указать TensorFlow использовать сеанс для его запуска.
- Мы не создали явно объект вычислительного графа. Вы можете ожидать, что нам нужно где-то создать объект изображения, чтобы TensorFlow знал, какой именно вычислительный граф мы хотим создать. Фактически, используя операции TensorFlow, мы можем сообщить TensorFlow, какой код находится в графе.
Совет: Держите вычислительный график отдельно. Обычно вы выполняете значительное количество операций с данными и вычислений вне вычислительного графа, то есть нам нужно различать, какие коды принадлежат вычислительному графу, а какие не принадлежат вычислительному графу. Мне нравится хранить графики вычислений в отдельном файле, чтобы их было легче различать.
Вычисления на вычислительном графе выполняются в сеансе TensorFlow. Чтобы получить результаты сеанса, вам необходимо предоставить две вещи: целевой результат и входные данные.
Целевой результат или действие. Вы можете указать TensorFlow, какие части графа вычислений должны возвращать значения, и он автоматически вычислит результаты внутренних вычислений, которые необходимо выполнить. Например, вы можете вызывать действия для инициализации переменных.
входной канал. В большинстве расчетов вы будете предоставлять временные входные данные. В этом случае можно построить график с заполнителем для этих данных и ввести его при расчете. Не все расчеты или операции требуют ввода — для многих людей вся информация содержится в вычислительном графе.
# Import Tensorflow and Numpy
import Tensorflow as tf
import numpy as np
# ======================
# Define the Graph
# ======================
# Create Placeholders For X And Y (for feeding in data)
X = tf.placeholder("float",[10, 10],name="X") # Our input is 10x10
Y = tf.placeholder("float", [10, 1],name="Y") # Our output is 10x1
# Create a Trainable Variable, "W", our weights for the linear transformation
initial_W = np.zeros((10,1))
W = tf.Variable(initial_W, name="W", dtype="float32")
# Define Your Loss Function
Loss = tf.pow(tf.add(Y,-tf.matmul(X,W)),2,name="Loss")
with tf.Session() as sess: # set up the session
sess.run(tf.initialize_all_variables())
Model_Loss = sess.run(
Loss, # the first argument is the name of the Tensorflow variabl you want to return
{ # the second argument is the data for the placeholders
X: np.random.rand(10,10),
Y: np.random.rand(10).reshape(-1,1)
})
print(Model_Loss)
Как использовать вычислительные графы для многозадачного обучения
Когда мы создаем нейронную сеть, выполняющую многозадачное обучение, мы хотим, чтобы некоторые нейроны в сети были общими, а другие части сети были созданы индивидуально для разных задач в разное время. Когда мы тренируемся, мы хотим, чтобы каждая отдельная задача модифицировала общие нейроны.
Итак, во-первых, мы рисуем простую сетевую структуру из двух задач с общими слоями и определенными сетевыми слоями для каждой отдельной задачи. Мы передадим эти выходные данные нашей функции потерь с нашей целью. Я отметил на диаграмме, где нам нужно разработать заполнители.
# GRAPH CODE
# ============
# Import Tensorflow
import Tensorflow as tf
# ======================
# Define the Graph
# ======================
# Define the Placeholders
X = tf.placeholder("float", [10, 10], name="X")
Y1 = tf.placeholder("float", [10, 1], name="Y1")
Y2 = tf.placeholder("float", [10, 1], name="Y2")
# Define the weights for the layers
shared_layer_weights = tf.Variable([10,20], name="share_W")
Y1_layer_weights = tf.Variable([20,1], name="share_Y1")
Y2_layer_weights = tf.Variable([20,1], name="share_Y2")
# Construct the Layers with RELU Activations
shared_layer = tf.nn.relu(tf.matmul(X,shared_layer_weights))
Y1_layer = tf.nn.relu(tf.matmul(shared_layer,Y1_layer_weights))
Y2_layer_weights = tf.nn.relu(tf.matmul(shared_layer,Y2_layer_weights))
# Calculate Loss
Y1_Loss = tf.nn.l2_loss(Y1,Y1_layer)
Y2_Loss = tf.nn.l2_loss(Y2,Y2_layer)
Когда мы обучаем эту сеть, мы хотим обучить задачу 2, не изменяя параметры слоя задачи 1. Но при обучении любой задачи параметры общего слоя будут меняться. Это может показаться немного сложным — обычно у нас есть только один оптимизатор на графике, потому что вы оптимизируете только одну функцию потерь. К счастью, мы можем искусно использовать природу графов для обучения таких моделей двумя способами.
альтернативное обучение
Первое решение особенно полезно, когда вам нужен пакет данных задачи 1, а затем пакет данных задачи 2.
Помните, что TensorFlow автоматически определит, какие вычисления требуются для нужных вам операций, и выполнит только эти вычисления. Это означает, что если мы определим оптимизатор только для одной из задач, он будет обучать только те параметры, которые необходимы для вычисления этой задачи, а остальные оставят в покое. Поскольку задача 1 зависит только от слоя задачи 1 и общего слоя, параметры слоя задачи 2 не изменятся. Нарисуем нужный граф оптимизатора в конце каждой задачи.
# GRAPH CODE
# ============
# Import Tensorflow and Numpy
import Tensorflow as tf
import numpy as np
# ======================
# Define the Graph
# ======================
# Define the Placeholders
X = tf.placeholder("float", [10, 10], name="X")
Y1 = tf.placeholder("float", [10, 20], name="Y1")
Y2 = tf.placeholder("float", [10, 20], name="Y2")
# Define the weights for the layers
initial_shared_layer_weights = np.random.rand(10,20)
initial_Y1_layer_weights = np.random.rand(20,20)
initial_Y2_layer_weights = np.random.rand(20,20)
shared_layer_weights = tf.Variable(initial_shared_layer_weights, name="share_W", dtype="float32")
Y1_layer_weights = tf.Variable(initial_Y1_layer_weights, name="share_Y1", dtype="float32")
Y2_layer_weights = tf.Variable(initial_Y2_layer_weights, name="share_Y2", dtype="float32")
# Construct the Layers with RELU Activations
shared_layer = tf.nn.relu(tf.matmul(X,shared_layer_weights))
Y1_layer = tf.nn.relu(tf.matmul(shared_layer,Y1_layer_weights))
Y2_layer = tf.nn.relu(tf.matmul(shared_layer,Y2_layer_weights))
# Calculate Loss
Y1_Loss = tf.nn.l2_loss(Y1-Y1_layer)
Y2_Loss = tf.nn.l2_loss(Y2-Y2_layer)
# optimisers
Y1_op = tf.train.AdamOptimizer().minimize(Y1_Loss)
Y2_op = tf.train.AdamOptimizer().minimize(Y2_Loss)
Мы можем выполнять многозадачное обучение, поочередно вызывая оптимизатор для каждой задачи, что означает, что мы можем продолжать передавать некоторую информацию из каждой задачи в другую задачу, поскольку это делается через общие слои. Грубо говоря, мы обнаруживаем некую «общность» между задачами. Следующий код просто реализует этот процесс для нас. Если вы последуете моим идеям и реализуете их шаг за шагом, то можете скопировать следующий код:
# Calculation (Session) Code
# ==========================
# open the session
with tf.Session() as session:
session.run(tf.initialize_all_variables())
for iters in range(10):
if np.random.rand() < 0.5:
_, Y1_loss = session.run([Y1_op, Y1_Loss],
{
X: np.random.rand(10,10)*10,
Y1: np.random.rand(10,20)*10,
Y2: np.random.rand(10,20)*10
})
print(Y1_loss)
else:
_, Y2_loss = session.run([Y2_op, Y2_Loss],
{
X: np.random.rand(10,10)*10,
Y1: np.random.rand(10,20)*10,
Y2: np.random.rand(10,20)*10
})
print(Y2_loss)
Совет: когда лучше чередовать тренировки?
Чередование обучения — хорошая идея, когда у вас есть разные наборы данных для каждой отдельной задачи (например, перевод с английского на французский и с английского на немецкий). Спроектировав сеть таким образом, мы можем улучшить производительность каждой задачи, не находя дополнительных обучающих данных.
Попеременное обучение — один из самых распространенных случаев, потому что не так много наборов данных, которые могут удовлетворить обе ваши потребности. Возьмем пример.Например, в машинном зрении вам может потребоваться выполнить одну из задач, чтобы предсказать, повернулся ли объект, а другая задача может потребовать от вас изменить объект камеры. Эти две задачи явно связаны.
Совет: когда чередовать тренировки нецелесообразно?
Чередование тренировок легко можно сместить к конкретной задаче, первый подход очевиден. Если одна из ваших задач имеет больший набор данных, чем другие, то, если вы тренируетесь пропорционально размеру набора данных, ваш общий слой будет содержать информацию о задаче с большим количеством данных.
Второй случай не такой. Если обучение чередовать, итоговая задача в модели будет иметь смещения параметров. У вас нет очевидного способа преодолеть эту проблему, но это означает, что когда вам не нужно чередовать тренировки, попробуйте использовать второй метод обучения.
совместное обучение
Когда у вас есть набор данных с несколькими метками для каждого входа, вам действительно нужно обучать эти задачи вместе. Вопрос в том, как вы поддерживаете независимость между различными задачами? Ответ очень простой. Вам просто нужно добавить и оптимизировать функции потерь для отдельных задач. Ниже приведен значок, показывающий структуру сети, которая может быть совместно обучена, Конкретный код также выглядит следующим образом:
# GRAPH CODE
# ============
# Import Tensorflow and Numpy
import Tensorflow as tf
import numpy as np
# ======================
# Define the Graph
# ======================
# Define the Placeholders
X = tf.placeholder("float", [10, 10], name="X")
Y1 = tf.placeholder("float", [10, 20], name="Y1")
Y2 = tf.placeholder("float", [10, 20], name="Y2")
# Define the weights for the layers
initial_shared_layer_weights = np.random.rand(10,20)
initial_Y1_layer_weights = np.random.rand(20,20)
initial_Y2_layer_weights = np.random.rand(20,20)
shared_layer_weights = tf.Variable(initial_shared_layer_weights, name="share_W", dtype="float32")
Y1_layer_weights = tf.Variable(initial_Y1_layer_weights, name="share_Y1", dtype="float32")
Y2_layer_weights = tf.Variable(initial_Y2_layer_weights, name="share_Y2", dtype="float32")
# Construct the Layers with RELU Activations
shared_layer = tf.nn.relu(tf.matmul(X,shared_layer_weights))
Y1_layer = tf.nn.relu(tf.matmul(shared_layer,Y1_layer_weights))
Y2_layer = tf.nn.relu(tf.matmul(shared_layer,Y2_layer_weights))
# Calculate Loss
Y1_Loss = tf.nn.l2_loss(Y1-Y1_layer)
Y2_Loss = tf.nn.l2_loss(Y2-Y2_layer)
Joint_Loss = Y1_Loss + Y2_Loss
# optimisers
Optimiser = tf.train.AdamOptimizer().minimize(Joint_Loss)
Y1_op = tf.train.AdamOptimizer().minimize(Y1_Loss)
Y2_op = tf.train.AdamOptimizer().minimize(Y2_Loss)
# Joint Training
# Calculation (Session) Code
# ==========================
# open the session
with tf.Session() as session:
session.run(tf.initialize_all_variables())
_, Joint_Loss = session.run([Optimiser, Joint_Loss],
{
X: np.random.rand(10,10)*10,
Y1: np.random.rand(10,20)*10,
Y2: np.random.rand(10,20)*10
})
print(Joint_Loss)
Суммировать
В этом посте мы рассмотрели основы многозадачного обучения в глубоком обучении. Если вы использовали TensorFlow раньше и у вас есть собственные проекты, надеюсь, этого достаточно для начала.
Для тех, кто хочет больше контента и более подробных примеров того, как использовать эти примеры для повышения производительности при многозадачности, пожалуйста, обратитесь к соответствующим документам самостоятельно.
источник:github