多任务学习简述
-
什么是多任务学习
- 多任务学习(Multi-Task Learning)顾名思义就是把多个任务放在一起学习,即对多个任务的目标一起联合建模并训练
- 我们的大脑工作机制也是如此,我们时刻都在进行着多任务学习,而且不同任务之间在相互影响着。比如学习英语和法语,你学习其中的一门语言是有助于另一门语言的学习的。
-
为什么要多任务学习
- 多任务学习可以将多个任务联合训练,只需一个流程就可以实现多个任务的学习
- 多任务学习可以挖掘不同任务间的联系,通过共享特征的方式实现迁移学习
- 多任务学习一定程度上对其中的任务进行泛化,使得模型不容易过拟合
Tensorflow实现
-
示例图
- 先来看一个在深度学习中的双任务学习示例图
- 如图所示,两个任务除了有各自的TaskLayer参数,还有个共享参数层SharedLayer,那么这样的网络如何来训练呢?下面介绍两种训练方法以及代码实现
-
交替训练 Alternative Trainning
- 如图所示,交替训练的意思就是在迭代训练中你来我往地交替进行各自的loss学习,阅读下面的代码就可以一目了然了。
- 代码
# 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) with tf.Session() as session: session.run(tf.initialize_all_variables()) for iters in range(10000): 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("iteration:{}, y1_loss:{}".format(iters, 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("iteration:{}, y2_loss:{}".format(iters, Y2_loss)) session.close()
- 什么时候选择交替训练呢?当不同任务有各自的训练数据时,就可以对不同的任务输入各自的数据,而无需去构造一份专门的数据。如果不同任务的数据集数量差距太大时,此时模型会偏向于数据量大的任务。
-
联合训练 Joint Training
- 当你有一份数据带有不同的标签时,就可以对多任务同时进行训练了,怎么做到呢,很简单,只需要把不同任务的loss做一个加权和即可。
- 代码
# 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 = 0.5*Y1_Loss + 0.5*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()) for iters in range(10000): _, 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("iteration:{}, joint_loss:{}".format(iters, Joint_loss)) session.close()