Coder Social home page Coder Social logo

对抗训练 about unif HOT 28 OPEN

geyingli avatar geyingli commented on June 12, 2024
对抗训练

from unif.

Comments (28)

geyingli avatar geyingli commented on June 12, 2024 2

时而相同,时而不同。我猜这个取决于�tensorflow递归调用节点,keep_mask和x1_mask哪个更先触及random_tensor,后者先触及,就会先触发random_tensor的重新初始化,导致最终两者的mask相同;前者先触及,那么最终mask不同。我想我们可以先不纠结这个点,按规范写代码就行,正确写dropout mask,不会面临这个随机性的问题。你说呢�

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024 1

是滴,哈哈,多向您学习
祝您也顺利~

from unif.

geyingli avatar geyingli commented on June 12, 2024 1

在验证的时候是有把dropout_rate设为0的,那看来就是底层可能有不一样的实现,谢谢您的解答啦~

tensorflow源码我没怎么读,过去以研究上层网络为主,不能解决你的问题很抱歉哈

哈哈没事没事,能够大致知道问题出在哪也就很有收获啦

👍🏻👍🏻

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024 1

您好~
我在进行一项有这1000多个label的文本分类任务,在这个特定任务上,对代码做了点修改,解决了一些可能存在的问题~想和您分享一下,哈哈

  1. 我在使用smart时,在如下代码中,由于我的类别数特别多,可能会导致tf.log()内的值可能非常接近于0或者等于0,从而使得在求log以后,该值为负无穷,导致了loss为无穷值,从而在后面计算梯度的时候,梯度值为NAN,出现梯度爆炸的情况,loss也会一直为NAN;
        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg) - tf.log(probs)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs) - tf.log(probs_breg)), axis=-1)

以及

                per_example_loss = tf.reduce_sum(
                    probs_prtb * (tf.log(probs_prtb) - tf.log(probs)), axis=-1)
                per_example_loss_prtb = tf.reduce_sum(
                    probs * (tf.log(probs) - tf.log(probs_prtb)), axis=-1)

因此我改为了如下代码,为probs_breg、probs两个概率分布,在求log时,加上了一个极小数,解决了梯度爆炸的问题;不知道有没有别的解决办法了,因为这样会让概率分布的总和大于1,感觉会引入噪声;

        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg + 1e-9) - tf.log(probs + 1e-9)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs + 1e-9) - tf.log(probs_breg + 1e-9)), axis=-1)

我猜这在label个数较少时,或者别的任务上不会出现该问题;

  1. 另一个疑惑的地方是,我在smart的实现中没找到restore_op,即恢复embedding矩阵的操作,这样不会使loss朝着上升的方向在走吗
  2. 之前的这行FreeLB中的代码,如果不加的话,在我的1000多个label的文本分类任务上会导致loss不收敛的问题;
    cur_r = tf.cond(norm > ARGS.epsilon, lambda: (acc_r + tmp_r) * tf.divide(ARGS.epsilon, norm), lambda: (acc_r + tmp_r))

回复:

  1. 这个做法是正确的,写SMART的时候的确没有考虑到太多分类维度的问题。实际上,SMART和其他对抗式训练算法是对抗过拟合的,分类维度越多,过拟合越难。我在我自己的项目里面用的时候,只有简单容易过拟合的任务SMART才有提升,在其他的,比如语义匹配和MRC任务上,SMART是负增益的,徒增训练时长。所以这一类算法也不是万金油,处处见效,见实际场景使用,以实际效果为准。
  2. 这个问题我没太关注,我是照着论文的伪代码写的,实现以后的确比其他一众对抗式算法FreeLB等要好,也就没有关注这个点。正所谓实践科学,效果好就行~当然你可以试着改一下代码,看看加了restore以后能不能再提升一些
  3. 既然有效,可以commit到我们的代码里,提交pull request,成为contributors之一~
  1. 是的~在我的分类任务里,使用SMART方式时,将几个超参数都设置为0.001的情况下,效果才能与不加SMART时打平,其他超参组合,随着增大各种超参数,负增益也越来越明显;看原理也确实是解决使用BERT微调时的过拟合问题时使用,不太适合分类维度多且数据量大的情况。

  2. 我用的时候直接加上了restore_op,等我再去掉做个实验和您同步下结果~

  3. 哈哈非常乐意!

from unif.

geyingli avatar geyingli commented on June 12, 2024

你好~

有快一年没有碰这段代码了。我看了一下,应该是当时写的时候上面那段忘了删了,不过因为下面的r会覆盖上面的r,所以删不删其实表现上没有影响。具体来说,上下两段的区别是,一个用shape进行固定取值的缩放,一个直接使全局除以最大值进行归一化,都是为了避免随机扰动过于极端�,给训练带来噪声,实际使用中效果其实差不多。删掉上面那段就可以了。

对于dropout mask,之前有所了解,是使用额外的随机参数记录dropout,叠加扰动的时候dropout不变。实现起来不难,但需要时间。最近比较忙,可能要过段时间才能考虑了。谢谢你的建议

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

谢谢您的解答~

另外关于FreeLB里的这段代码,我做了点修改,加了一个判断,当扰动的范数超过epsilon ball的范围时,再进行缩放。
似乎论文里是这么说的,您看下是否正确~
cur_r = (acc_r + tmp_r) * tf.divide(ARGS.epsilon, norm)
->
cur_r = tf.cond(norm > ARGS.epsilon, lambda: (acc_r + tmp_r) * tf.divide(ARGS.epsilon, norm), lambda: (acc_r + tmp_r))

from unif.

geyingli avatar geyingli commented on June 12, 2024

当然是可以的,对抗式训练是实践科学,改了代码以后可以试试表现如何。表现的好自然是不错的,表现的不好也是十分正常的事情。可以多尝试做做变通,没必要一定和论文保持一致,毕竟换一个数据集可能就是另一番景象。代码没问题~

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

感谢您的解答~
还有这几天在自己尝试实现dropout mask,阅读了一下tf.nn.Dropout的源码,发现其mask是由如下两行代码(来源于贴出的tensorflow中的Dropout实现)实现的;
random_tensor = random_ops.random_uniform( noise_shape, seed=seed, dtype=x.dtype)
keep_mask = random_tensor >= rate
但是其只是返回了ret结果,如果我想要获得mask,可能需要修改tensorflow的源码,在dropout_v2参数中增加keep_mask参数,并在返回值中增加keep_mask,请问这个思路正确吗?
ret = x * scale * math_ops.cast(keep_mask, x.dtype)
我还发现dropout_v2()函数有一个参数是seed,但是查阅API后发现他只是让多次会话时,可以生成的keep mask可以保持一致,但是对于某一次会话,不同step之间生成的keep mask还是会不同。
想请问您说的使用额外的随机参数记录dropout,具体该怎么做呢~

tensorflow中的Dropout实现:
Dropout

from unif.

geyingli avatar geyingli commented on June 12, 2024

小意思~

实现mask固定其实就是设置一个和tensor X=[batch_size, seq_length, hidden_size] 一模一样大小的随机变量mask=tf.get_variable('mask', shape=X.shape, initializer=tf.random_uniform_initializer(0, 1))
然后通过tf.greater(mask, 0.1)*X实现手动dropout,取代tf.nn.dropout。
那么如何保证每次叠加扰动的时候mask不变呢,那么就是用tf.control_dependencies([init_op]),其中init_op就是随机初始化一次mask,更具体怎么写,相信你明白~我就不多说了,没有那么复杂

另外为了保证项目代码的可迁移性,比如换了新设备能迅速跑起来,不太建议修改tensorflow源码。修改源码还有可能会造成不可预知的错误,你需要保证tensorflow内部所有引用了tf.nn.dropout的代码不会因为这一项修改而出错

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

您好~谢谢您的回复

按照您的思路,我尝试写了如下代码,x1、x2想模拟正常样本和对抗样本,但是发现对x1、x2,mask以后只有x1_mask和keep_mask保持一致,而x2_mask则没有。不知道问题出在了哪里~
也许是因为我对
init_op = tf.variables_initializer([random_tensor])
with tf.control_dependencies([init_op]):
这两行的操作理解的还不够深。

在您的freelb的代码中的init_r于此类似,我仔细调试您的代码后了解到,init_r会在sess.run(self._train_op)前被初始化一次,利用
local_init_op = tf.variables_initializer(variables)
module.sess.run(local_init_op)来实现,在https://github.com/geyingli/unif/blob/33280b5826a610427fdf62fa6185d5f3dfa03851/uf/processing.py#L71此处。

我感觉这行代码 init_op = tf.variables_initializer([random_tensor]) 是对random_tensor再次随机初始化一次,
然后通过with tf.control_dependencies([init_op]) 控制依赖,让之后的keep_mask依赖这次初始化的random_tensor。
但是我的结果中只有x1_mask依赖成功了,而x2_mask失败了,想请教您这是什么导致的呢~

`import tensorflow as tf

x1 = tf.constant([[[1., 2.], [3., 4.]], [[5., 6.], [7., 8.]]], dtype=tf.float32)
x2 = tf.constant([[[10., 20.], [30., 40.]], [[50., 60.], [70., 80.]]], dtype=tf.float32)
random_tensor = tf.get_variable('random_tensor', shape=[2, 2, 2], initializer=tf.random_uniform_initializer(minval=0, maxval=1))
keep_mask = tf.cast(tf.greater(random_tensor, 0.5), tf.float32)

init_op = tf.variables_initializer([random_tensor])

with tf.control_dependencies([init_op]):
x1_mask = x1 * keep_mask
x2_mask = x2 * keep_mask

global_variables = tf.get_default_graph()._collections.get('variables', [])
local_init_op = tf.variables_initializer(global_variables)

sess = tf.Session()

sess.run(local_init_op)
print("keep mask")
print(sess.run(keep_mask))
print("x1")
print(sess.run(x1))
print("x1 mask")
print(sess.run(x1_mask))
print("x2")
print(sess.run(x2))
print("x2 mask")
print(sess.run(x2_mask))

sess.close()`

output:
keep mask
[[[1. 1.]
[1. 1.]]

[[0. 0.]
[0. 1.]]]
x1
[[[1. 2.]
[3. 4.]]

[[5. 6.]
[7. 8.]]]
x1 mask
[[[1. 2.]
[3. 4.]]

[[0. 0.]
[0. 8.]]]
x2
[[[10. 20.]
[30. 40.]]

[[50. 60.]
[70. 80.]]]
x2 mask
[[[10. 0.]
[30. 40.]]

from unif.

geyingli avatar geyingli commented on June 12, 2024

是这样的,按照上面的代码:
print(sess.run(keep_mask)) 调用的时候,random_tensor随机初始化了一次
print(sess.run(x1_mask))调用的时候,random_tensor又初始化了一次
随后调用print(sess.run(x2_mask))的时候,再一次初始化
细心观察一下,你会发现再跑一次,你用上面的代码跑的,keep_mask和x1_mask也不一样

因此正确的写法是:
a, b, c = sess.run([keey_mask, x1_mask, x2_mask])
print(a)
print(b)
print(c)

试一试~

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

谢谢您的指点,目前已经跑通了dropout mask的这种方式~

通过您的讲解,我了解到我出错的原因应该是因为每次sess.run(op)的时候,都会重新对计算图执行一遍,所以每次都会执行一次init_op,因此random_tensor初始化了多次,加深了理解,感恩~

另我又多跑了几遍,结果keep_mask和x1_mask,在mask位置上的结果是一致的
比如我的keep_mask是上面的
[[[1. 1.]
[1. 1.]]

[[0. 0.]
[0. 1.]]]
其x1_mask,在对应位置上是按keep_mask进行mask的(我想表达的是,比如mask矩阵(2 * 2 * 2)的第一个2*2矩阵中,四个元素均为1,而x1_mask,在第一个矩阵上的结果也都和原先的值相同,说明其对应元素是和mask中的四个1对应相乘了,即有按keep_mask进行mask)
[[[1. 2.]
[3. 4.]]

[[0. 0.]
[0. 8.]]]

对此我感到疑惑,当我sess.run(keep_mask)时,它的值依赖于random_tensor,而random_tensor的值又依赖于sess.run(local_init_op),第一次初始化全部变量值时所赋予的;
当我sess.run(x1_mask)时,random_tensor的值理应会因为init_op的初始化而发生变化,从而使得keep_mask发生变化,但结果却没有,这是为什么呢,还请您指点一下~

如下代码表达了我的想法:
`import tensorflow as tf

x1 = tf.constant([[[1., 2., 2.], [3., 4., 2.]], [[5., 6., 2.], [7., 8., 2.]]], dtype=tf.float32)
random_tensor = tf.get_variable('random_tensor', shape=[2, 2, 3], initializer=tf.random_uniform_initializer(minval=0, maxval=1))
keep_mask = tf.cast(tf.greater(random_tensor, 0.5), tf.float32)

init_op = tf.variables_initializer([random_tensor])

with tf.control_dependencies([init_op]):
x1_mask = x1 * keep_mask

global_variables = tf.get_default_graph()._collections.get('variables', [])
local_init_op = tf.variables_initializer(global_variables)

sess = tf.Session()

sess.run(local_init_op)
print("keep mask")
print(sess.run(keep_mask))

keep_mas, X1_mask = sess.run([keep_mask, x1_mask])
print("x1 mask's keep mask")
print(keep_mas)

sess.close()`

output:可见两个keep mask相同
keep mask
[[[0. 1. 1.]
[0. 1. 0.]]

[[1. 1. 1.]
[1. 0. 0.]]]
x1 mask's keep mask
[[[0. 1. 1.]
[0. 1. 0.]]

[[1. 1. 1.]
[1. 0. 0.]]]

from unif.

geyingli avatar geyingli commented on June 12, 2024

好的,太客气了~

上面的代码我跑了几次,两个keep mask都是不一样的,可否再确认一下呢

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

确认了~ 我分别使用1.12(windows)和1.13(Linux)版本进行了测试,结果是一样的
难道是版本问题吗

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

那看来是我测试的次数还是太少了~
您分析的很有道理,不纠结啦~

from unif.

geyingli avatar geyingli commented on June 12, 2024

哈哈,恩。其实就是把keep_mask,和x1_mask一样,给同样写到tf.control_depencies下面,这样两个变量的mask就完全一致了

最近忙别的项目,没有再更新UNIF了,�感谢你的支持,祝你顺利~

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

还想向您请教一下,我自己实现dropout以后,虽然代码可以跑,但是loss下降却有问题,使用tf.nn.dropout()在200个step时,我的loss可以下降到9左右,而用自己实现的dropout却为30左右。

以下是我代码中关于dropout的这部分,关键代码用(##关键代码)表示。其中version 1. 版本为使用tf.nn.dropout()进行dropout,此方式测试过loss是正常的,我尝试用此方式测试其余代码的正确性。

使用version 2. 进行dropout时,就出现了loss问题,
我进行了如下步骤(分类任务):

  1. 定义了变量random_tensor
  2. 对其进行初始化,得到init_dp_op
  3. 依赖init_dp_op,model.build()进行前向传播,得到文章最后的向量表示actual_h_pool_flat
  4. 把dropout_keep转换为tensor
  5. 计算scale,用于dropout后的非零元素的放大
  6. 计算keep_mask
  7. 将scale、keep_mask与文章表示向量actual_h_pool_flat相乘,得到dropout后的文章表示向量actual_h_dropout
  8. 过最后一层全连接层,得到用于分类的scores向量
  9. 计算loss
  10. 计算梯度,得到扰动
  11. 生成对抗样本
  12. 对抗样本进行前向传播,model.build()后得到对抗样本最后的向量表示attack_h_pool_flat
  13. 对attack_h_pool_flat进行dropout,使用前面得到的keep_mask与scale,对应元素相乘后得到最后的对抗样本表示attack_h_dropout
  14. 计算对抗样本的梯度
  15. 正常样本 + 对抗样本的梯度进行平均后更新参数

似乎没有问题,但是却出现了loss不正常下降的问题,百思不得其解,您有空的时候可以帮我看下吗~
(使用tensorflow1.12 Linux)

    dropout_keep = tf.placeholder(tf.float32)
    model = TextCNN(DATA_HELPER_OBJ.embedding_dim,
                                  vocab_size,
                                  ARGS.sentence_len,
                                  label_list,
                                  pretrained_embedding,
                                 ARGS.filter_num,
                                 ARGS.max_save_model,
                                 SUMMARIES_DIR,
                                 init_lr=ARGS.init_lr,
                                 lr_decay_step=ARGS.lr_decay_step,
                                 lr_decay_rate=ARGS.lr_decay_rate)

    with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE):
        learning_rate = tf.get_variable(initializer=tf.constant(1e-3), trainable=False, name='lr')
        global_step = tf.get_variable(initializer=tf.constant(0), dtype=tf.int32, name='global_step', trainable=False)
        lr = tf.train.exponential_decay(learning_rate, global_step, ARGS.lr_decay_step, ARGS.lr_decay_rate, staircase=True)
        optimizer = tf.train.AdamOptimizer(lr)

        # [batch_size, hidden_size] 最后的文章向量表示
        actual_h_pool_flat = model.build(x_batch, y_batch)

        # version 1. 使用tf.nn.dropout(), 对actual_h_pool_flat进行dropout
        # actual_h_dropout = tf.nn.dropout(actual_h_pool_flat, dropout_keep)  ##关键代码

        # version 2. 自己实现dropout, 对actual_h_pool_flat进行dropout
        random_tensor = tf.get_variable('random_tensor', shape=actual_h_pool_flat.shape[1:], initializer=tf.random_uniform_initializer(minval=0, maxval=1), trainable=False)  ##关键代码
        init_dp_op = tf.variables_initializer([random_tensor])  ##关键代码
        with tf.control_dependencies([init_dp_op]):  ##关键代码
            dropout_keep = tf.convert_to_tensor(dropout_keep, dtype=actual_h_pool_flat.dtype)  ##关键代码
            scale = 1 / dropout_keep  ##关键代码
            keep_mask = tf.cast(tf.greater(random_tensor, 1 - dropout_keep), tf.float32)  ##关键代码
            # dropout
            actual_h_dropout = actual_h_pool_flat * scale * keep_mask  ##关键代码

            # 计算scores: actual_h_dropout * weight = scores [batch_size, label_num]
            model.add_prediction_op(actual_h_dropout)  ##关键代码
            # 计算loss: losses = tf.nn.softmax_cross_entropy_with_logits_v2(logits=scores, labels=input_y)
            model.add_loss_op()  ##关键代码

            # attack
            actual_loss, actual_accuracy, actual_predictions, actual_input_y = model.loss, model.accuracy, model.predictions, model.input_y
            trainable_variables = tf.get_default_graph()._collections.get('trainable_variables', [])
            actual_grads = tf.gradients(actual_loss, trainable_variables)
            grad, param = get_grad_and_param(trainable_variables, actual_grads, 'embeddings_table:0')
            r = tf.multiply(ARGS.epsilon, grad / (tf.norm(grad) + 1e-9))
            attack_op = param.assign(param + r)

            # restore
            with tf.control_dependencies([attack_op]):
                attack_h_pool_flat = model.build(x_batch, y_batch)

                # version 1. 使用tf.nn.dropout(), 对attack_h_dropout进行dropout
                # attack_h_dropout = tf.nn.dropout(attack_h_pool_flat, dropout_keep)  ##关键代码

                # version 2. 自己实现dropout, 对actual_h_pool_flat进行dropout
                attack_h_dropout = attack_h_pool_flat * scale * keep_mask  ##关键代码
                model.add_prediction_op(attack_h_dropout)  ##关键代码
                model.add_loss_op()  ##关键代码
                attack_loss = model.loss
                attack_grads = tf.gradients(attack_loss, trainable_variables)
                restore_op = param.assign(param - r)

            # sum up
            with tf.control_dependencies([restore_op]):
                grads = [average_n_grads([actual_grad, attack_grad])
                        for (actual_grad, attack_grad) in zip(actual_grads, attack_grads)]

            update_params_op = update_global_params(trainable_variables, global_step, optimizer, grads)
            # update_step_op = global_step.assign(global_step + 1)
            train_op = tf.group([update_params_op, global_step])

model部分

   def add_prediction_op(self, h_dropout):
       with tf.name_scope('output'):
           weight = tf.get_variable('W_projection',
                                    shape=[self.num_filters_total, self.classes_num],
                                    initializer=self.norm_initializer, trainable=True)
           bias = tf.get_variable(initializer=tf.constant_initializer(0.1), shape=[self.classes_num], name='b', trainable=True)
           self.l2_loss = tf.add_n([tf.nn.l2_loss(weight), tf.nn.l2_loss(bias)])
           self.scores = tf.nn.xw_plus_b(h_dropout, weight, bias, name='scores')  ##关键代码
           self.predictions = tf.nn.softmax(self.scores)
           self.labels_all = tf.tile(self.labels, [tf.shape(self.predictions)[0], 1])

   def add_loss_op(self):
       with tf.name_scope('loss'):
           losses = tf.nn.softmax_cross_entropy_with_logits_v2(
               logits=self.scores, labels=self.input_y)
           self.loss = tf.reduce_mean(losses) + 0.001 * self.l2_loss
           tf.summary.scalar('loss', self.loss)

       with tf.name_scope('accuracy'):
           self.truth = tf.argmax(self.input_y, 1)
           self.pred = tf.argmax(self.predictions, 1)
           correct_preds = tf.cast(tf.equal(self.pred, self.truth), 'float')
           self.accuracy = tf.reduce_mean(correct_preds, name='accuracy')
           tf.summary.scalar('accuracy', self.accuracy)

from unif.

geyingli avatar geyingli commented on June 12, 2024

单从代码看,有一个地方不太可取:random_tensor = tf.get_variable('random_tensor', shape=actual_h_pool_flat.shape[1:]...这里,random_tensor的形状不应该忽视第一维的batch_size,因为tf.nn.dropout是所有维度都包括在内。建议可以把这里修改了以后再尝试一下效果。

如果成绩还是不好,可以试试把with tf.control_dependencies([init_dp_op]):注释掉,让�random_tensor每次跌价扰动时都重新初始化,对比tf.nn.dropout,排查一下问题根源。

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

以下结果均注释了with tf.control_dependencies([init_dp_op])(加上后经测试,结论也和以下实验一样)

如下为使用tf.nn.dropout()的正常结果(每1000个batch进行一次验证,如下为第一次验证):
[INFO] [20210327 20:22:56]: epoch:0, gstep:995, b-loss:6.2543, b-acc:0.1484, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:996, b-loss:6.1792, b-acc:0.2188, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:997, b-loss:6.0566, b-acc:0.2266, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:998, b-loss:5.9870, b-acc:0.2188, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:999, b-loss:6.0397, b-acc:0.1719, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:1000, b-loss:6.2203, b-acc:0.1797, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:23:23]: Evaluate on "test" data, loss: 5.6079, acc: 0.2745
[INFO] [20210327 20:23:39]: Evaluate on "dev" data, loss: 5.8003, acc: 0.2473
...

我尝试将random_tensor改为如下代码,使用actual_h_pool_flat的形状作为random_tensor的形状
random_tensor = tf.get_variable('random_tensor', shape=actual_h_pool_flat.shape...
random_tensor = tf.get_variable('random_tensor', shape=actual_h_pool_flat.get_shape().as_list()...,两者都会报错
错误信息:ValueError: You can only pass an initializer function that expects no arguments to its callable when the shape is not fully defined. The given initializer function expects the following args ['self', 'shape', 'dtype', 'partition_info']

我感觉是无法获取batch_size的维度导致的错误,因为feed数据之前,这一维是未知的,然后又尝试改为,使用tf.shape()来获取形状
random_tensor = tf.get_variable('random_tensor', shape=tf.shape(actual_h_pool_flat)...,但仍会报错,错误信息有点看不懂
错误信息:TypeError: Tensor objects are only iterable when eager execution is enabled. To iterate over this tensor use tf.map_fn.

最后我把shape的形状写死,768即最后的文章表示向量actual_h_pool_flat的维度
random_tensor = tf.get_variable('random_tensor', shape=[batch_size, 768]...

loss相比之前不取batch_size,下降许多,但仍比不上正常结果
[INFO] [20210330 19:55:17]: epoch:0, gstep:995, b-loss:6.5370, b-acc:0.1641, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:996, b-loss:6.8437, b-acc:0.1719, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:997, b-loss:6.4046, b-acc:0.2188, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:998, b-loss:6.6196, b-acc:0.1406, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:999, b-loss:6.5291, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:1000, b-loss:6.7619, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:44]: Evaluate on "test" data, loss: 6.0914, acc: 0.2483
[INFO] [20210330 19:55:59]: Evaluate on "dev" data, loss: 6.2881, acc: 0.2230

因为我使用的版本是tensorflow1.12,因此我又修改了dropout的代码和1.12版本中的实现对齐,将dropout部分的代码改为

        actual_h_pool_flat = model.build(x_batch, y_batch)
        # actual_h_dropout = tf.nn.dropout(actual_h_pool_flat, dropout_keep)
        random_tensor = tf.get_variable('random_tensor', shape=[ARGS.batch_size, 768], initializer=tf.random_uniform_initializer(minval=0, maxval=1), trainable=False)
        # init_dp_op = tf.variables_initializer([random_tensor])
        # with tf.control_dependencies([init_dp_op]):
        dropout_keep = tf.convert_to_tensor(dropout_keep, dtype=actual_h_pool_flat.dtype)

        # uniform [keep_prob, 1.0 + keep_prob)
        random_tensor += dropout_keep  ## 修改部分代码
        # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
        binary_tensor = tf.floor(random_tensor)  ## 修改部分代码
        actual_h_dropout = tf.div(actual_h_pool_flat, dropout_keep) * binary_tensor  ## 修改部分代码

        model.add_prediction_op(actual_h_dropout)
        model.add_loss_op()

        # attack
        actual_loss, actual_accuracy, actual_predictions, actual_input_y = model.loss, model.accuracy, model.predictions, model.input_y
        trainable_variables = tf.get_default_graph()._collections.get('trainable_variables', [])
        actual_grads = tf.gradients(actual_loss, trainable_variables)
        grad, param = get_grad_and_param(trainable_variables, actual_grads, 'embeddings_table:0')
        r = tf.multiply(ARGS.epsilon, grad / (tf.norm(grad) + 1e-9))
        attack_op = param.assign(param + r)

        # restore
        with tf.control_dependencies([attack_op]):
            attack_h_pool_flat = model.build(x_batch, y_batch)
            # attack_h_dropout = tf.nn.dropout(attack_h_pool_flat, dropout_keep)
            # 此行加不加,不影响结果,加的原因是dropout实现中对传入的x都做了转为tensor的操作
            # 不影响的原因,我感觉是因为attack_h_pool_flat 本身就是一个tensor了,属于重复操作,所以去掉了
            # attack_h_pool_flat = tf.convert_to_tensor(attack_h_pool_flat, name="attack_h_pool_flat") 
            attack_h_dropout = tf.div(attack_h_pool_flat, dropout_keep) * binary_tensor  ## 修改部分代码

            model.add_prediction_op(attack_h_dropout)
            model.add_loss_op()
            attack_loss = model.loss
            attack_grads = tf.gradients(attack_loss, trainable_variables)
            restore_op = param.assign(param - r)

acc相比上一版本差不太多,以上实验均跑了5次,使用自己写的dropout的第一次在测试集上的验证,基本都在24%左右
且之后几次的验证相比使用tf.nn.dropout()在相同的step时,也有所降低
[INFO] [20210330 19:41:30]: epoch:0, gstep:995, b-loss:6.6033, b-acc:0.1484, lr:0.001000, step_time:0.13s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:996, b-loss:6.6954, b-acc:0.1641, lr:0.001000, step_time:0.12s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:997, b-loss:6.5559, b-acc:0.1797, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:998, b-loss:6.3113, b-acc:0.1797, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:999, b-loss:6.3899, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:1000, b-loss:6.7224, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:57]: Evaluate on "test" data, loss: 6.1011, acc: 0.2438
[INFO] [20210330 19:42:13]: Evaluate on "dev" data, loss: 6.2961, acc: 0.2202

如下为1.12版本dropout的实现:https://github.com/tensorflow/tensorflow/blob/v1.12.0/tensorflow/python/ops/nn_ops.py#L2321
在其中我省略了实现中的noise_shape = _get_noise_shape(x, noise_shape),有点没看懂这行代码的作用,似乎在获取x的形状,之后再作为random_tensor的形状,但具体返回的结果是似乎又不是x的形状,感觉在写死random_tensor的形状之后,也用不上它,就没管这行

不知该从哪再进行排查了,还请您有空时指点一下~

from unif.

geyingli avatar geyingli commented on June 12, 2024

看到Github邮件过来回一下。过两天要放假,这几天太忙,不一定什么时候有时间可以帮你看,尽量先尝试着自己解决哈~

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

好滴~您先忙,我肯定先自己看着啦

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

您好~
我在进行一项有这1000多个label的文本分类任务,在这个特定任务上,对代码做了点修改,解决了一些可能存在的问题~想和您分享一下,哈哈

  1. 我在使用smart时,在如下代码中,由于我的类别数特别多,可能会导致tf.log()内的值可能非常接近于0或者等于0,从而使得在求log以后,该值为负无穷,导致了loss为无穷值,从而在后面计算梯度的时候,梯度值为NAN,出现梯度爆炸的情况,loss也会一直为NAN;
        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg) - tf.log(probs)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs) - tf.log(probs_breg)), axis=-1)

以及

                per_example_loss = tf.reduce_sum(
                    probs_prtb * (tf.log(probs_prtb) - tf.log(probs)), axis=-1)
                per_example_loss_prtb = tf.reduce_sum(
                    probs * (tf.log(probs) - tf.log(probs_prtb)), axis=-1)

因此我改为了如下代码,为probs_breg、probs两个概率分布,在求log时,加上了一个极小数,解决了梯度爆炸的问题;不知道有没有别的解决办法了,因为这样会让概率分布的总和大于1,感觉会引入噪声;

        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg + 1e-9) - tf.log(probs + 1e-9)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs + 1e-9) - tf.log(probs_breg + 1e-9)), axis=-1)

我猜这在label个数较少时,或者别的任务上不会出现该问题;

  1. 另一个疑惑的地方是,我在smart的实现中没找到restore_op,即恢复embedding矩阵的操作,这样不会使loss朝着上升的方向在走吗

  2. 之前的这行FreeLB中的代码,如果不加的话,在我的1000多个label的文本分类任务上会导致loss不收敛的问题;
    cur_r = tf.cond(norm > ARGS.epsilon, lambda: (acc_r + tmp_r) * tf.divide(ARGS.epsilon, norm), lambda: (acc_r + tmp_r))

from unif.

geyingli avatar geyingli commented on June 12, 2024

以下结果均注释了with tf.control_dependencies([init_dp_op])(加上后经测试,结论也和以下实验一样)

如下为使用tf.nn.dropout()的正常结果(每1000个batch进行一次验证,如下为第一次验证):
[INFO] [20210327 20:22:56]: epoch:0, gstep:995, b-loss:6.2543, b-acc:0.1484, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:996, b-loss:6.1792, b-acc:0.2188, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:997, b-loss:6.0566, b-acc:0.2266, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:998, b-loss:5.9870, b-acc:0.2188, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:999, b-loss:6.0397, b-acc:0.1719, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:22:56]: epoch:0, gstep:1000, b-loss:6.2203, b-acc:0.1797, lr:0.001000, step_time:0.10s.
[INFO] [20210327 20:23:23]: Evaluate on "test" data, loss: 5.6079, acc: 0.2745
[INFO] [20210327 20:23:39]: Evaluate on "dev" data, loss: 5.8003, acc: 0.2473
...

我尝试将random_tensor改为如下代码,使用actual_h_pool_flat的形状作为random_tensor的形状
random_tensor = tf.get_variable('random_tensor', shape=actual_h_pool_flat.shape...
random_tensor = tf.get_variable('random_tensor', shape=actual_h_pool_flat.get_shape().as_list()...,两者都会报错
错误信息:ValueError: You can only pass an initializer function that expects no arguments to its callable when the shape is not fully defined. The given initializer function expects the following args ['self', 'shape', 'dtype', 'partition_info']

我感觉是无法获取batch_size的维度导致的错误,因为feed数据之前,这一维是未知的,然后又尝试改为,使用tf.shape()来获取形状
random_tensor = tf.get_variable('random_tensor', shape=tf.shape(actual_h_pool_flat)...,但仍会报错,错误信息有点看不懂
错误信息:TypeError: Tensor objects are only iterable when eager execution is enabled. To iterate over this tensor use tf.map_fn.

最后我把shape的形状写死,768即最后的文章表示向量actual_h_pool_flat的维度
random_tensor = tf.get_variable('random_tensor', shape=[batch_size, 768]...

loss相比之前不取batch_size,下降许多,但仍比不上正常结果
[INFO] [20210330 19:55:17]: epoch:0, gstep:995, b-loss:6.5370, b-acc:0.1641, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:996, b-loss:6.8437, b-acc:0.1719, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:997, b-loss:6.4046, b-acc:0.2188, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:998, b-loss:6.6196, b-acc:0.1406, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:999, b-loss:6.5291, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:17]: epoch:0, gstep:1000, b-loss:6.7619, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:55:44]: Evaluate on "test" data, loss: 6.0914, acc: 0.2483
[INFO] [20210330 19:55:59]: Evaluate on "dev" data, loss: 6.2881, acc: 0.2230

因为我使用的版本是tensorflow1.12,因此我又修改了dropout的代码和1.12版本中的实现对齐,将dropout部分的代码改为

        actual_h_pool_flat = model.build(x_batch, y_batch)
        # actual_h_dropout = tf.nn.dropout(actual_h_pool_flat, dropout_keep)
        random_tensor = tf.get_variable('random_tensor', shape=[ARGS.batch_size, 768], initializer=tf.random_uniform_initializer(minval=0, maxval=1), trainable=False)
        # init_dp_op = tf.variables_initializer([random_tensor])
        # with tf.control_dependencies([init_dp_op]):
        dropout_keep = tf.convert_to_tensor(dropout_keep, dtype=actual_h_pool_flat.dtype)

        # uniform [keep_prob, 1.0 + keep_prob)
        random_tensor += dropout_keep  ## 修改部分代码
        # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
        binary_tensor = tf.floor(random_tensor)  ## 修改部分代码
        actual_h_dropout = tf.div(actual_h_pool_flat, dropout_keep) * binary_tensor  ## 修改部分代码

        model.add_prediction_op(actual_h_dropout)
        model.add_loss_op()

        # attack
        actual_loss, actual_accuracy, actual_predictions, actual_input_y = model.loss, model.accuracy, model.predictions, model.input_y
        trainable_variables = tf.get_default_graph()._collections.get('trainable_variables', [])
        actual_grads = tf.gradients(actual_loss, trainable_variables)
        grad, param = get_grad_and_param(trainable_variables, actual_grads, 'embeddings_table:0')
        r = tf.multiply(ARGS.epsilon, grad / (tf.norm(grad) + 1e-9))
        attack_op = param.assign(param + r)

        # restore
        with tf.control_dependencies([attack_op]):
            attack_h_pool_flat = model.build(x_batch, y_batch)
            # attack_h_dropout = tf.nn.dropout(attack_h_pool_flat, dropout_keep)
            # 此行加不加,不影响结果,加的原因是dropout实现中对传入的x都做了转为tensor的操作
            # 不影响的原因,我感觉是因为attack_h_pool_flat 本身就是一个tensor了,属于重复操作,所以去掉了
            # attack_h_pool_flat = tf.convert_to_tensor(attack_h_pool_flat, name="attack_h_pool_flat") 
            attack_h_dropout = tf.div(attack_h_pool_flat, dropout_keep) * binary_tensor  ## 修改部分代码

            model.add_prediction_op(attack_h_dropout)
            model.add_loss_op()
            attack_loss = model.loss
            attack_grads = tf.gradients(attack_loss, trainable_variables)
            restore_op = param.assign(param - r)

acc相比上一版本差不太多,以上实验均跑了5次,使用自己写的dropout的第一次在测试集上的验证,基本都在24%左右
且之后几次的验证相比使用tf.nn.dropout()在相同的step时,也有所降低
[INFO] [20210330 19:41:30]: epoch:0, gstep:995, b-loss:6.6033, b-acc:0.1484, lr:0.001000, step_time:0.13s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:996, b-loss:6.6954, b-acc:0.1641, lr:0.001000, step_time:0.12s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:997, b-loss:6.5559, b-acc:0.1797, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:998, b-loss:6.3113, b-acc:0.1797, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:999, b-loss:6.3899, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:30]: epoch:0, gstep:1000, b-loss:6.7224, b-acc:0.1875, lr:0.001000, step_time:0.10s.
[INFO] [20210330 19:41:57]: Evaluate on "test" data, loss: 6.1011, acc: 0.2438
[INFO] [20210330 19:42:13]: Evaluate on "dev" data, loss: 6.2961, acc: 0.2202

如下为1.12版本dropout的实现:https://github.com/tensorflow/tensorflow/blob/v1.12.0/tensorflow/python/ops/nn_ops.py#L2321
在其中我省略了实现中的noise_shape = _get_noise_shape(x, noise_shape),有点没看懂这行代码的作用,似乎在获取x的形状,之后再作为random_tensor的形状,但具体返回的结果是似乎又不是x的形状,感觉在写死random_tensor的形状之后,也用不上它,就没管这行

不知该从哪再进行排查了,还请您有空时指点一下~

noise_shape那一行代码的确是没用的,看代码知道,它是在你指定了noise形状的时候才发挥作用,否则拿到的就是x的形状。验证集没有tf原生dropout成绩好,你看看,有没有可能是因为推理的时候,没有把dropout_rate设为0,如果是的话,原因可能就在这里。如果不是的话,可能是tensorflow底层对dropout有不一样的实现,比如它可能不是随机10%置为0,是置为负无穷大,等等

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

在验证的时候是有把dropout_rate设为0的,那看来就是底层可能有不一样的实现,谢谢您的解答啦~

from unif.

geyingli avatar geyingli commented on June 12, 2024

您好~
我在进行一项有这1000多个label的文本分类任务,在这个特定任务上,对代码做了点修改,解决了一些可能存在的问题~想和您分享一下,哈哈

  1. 我在使用smart时,在如下代码中,由于我的类别数特别多,可能会导致tf.log()内的值可能非常接近于0或者等于0,从而使得在求log以后,该值为负无穷,导致了loss为无穷值,从而在后面计算梯度的时候,梯度值为NAN,出现梯度爆炸的情况,loss也会一直为NAN;
        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg) - tf.log(probs)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs) - tf.log(probs_breg)), axis=-1)

以及

                per_example_loss = tf.reduce_sum(
                    probs_prtb * (tf.log(probs_prtb) - tf.log(probs)), axis=-1)
                per_example_loss_prtb = tf.reduce_sum(
                    probs * (tf.log(probs) - tf.log(probs_prtb)), axis=-1)

因此我改为了如下代码,为probs_breg、probs两个概率分布,在求log时,加上了一个极小数,解决了梯度爆炸的问题;不知道有没有别的解决办法了,因为这样会让概率分布的总和大于1,感觉会引入噪声;

        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg + 1e-9) - tf.log(probs + 1e-9)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs + 1e-9) - tf.log(probs_breg + 1e-9)), axis=-1)

我猜这在label个数较少时,或者别的任务上不会出现该问题;

  1. 另一个疑惑的地方是,我在smart的实现中没找到restore_op,即恢复embedding矩阵的操作,这样不会使loss朝着上升的方向在走吗
  2. 之前的这行FreeLB中的代码,如果不加的话,在我的1000多个label的文本分类任务上会导致loss不收敛的问题;
    cur_r = tf.cond(norm > ARGS.epsilon, lambda: (acc_r + tmp_r) * tf.divide(ARGS.epsilon, norm), lambda: (acc_r + tmp_r))

回复:

  1. 这个做法是正确的,写SMART的时候的确没有考虑到太多分类维度的问题。实际上,SMART和其他对抗式训练算法是对抗过拟合的,分类维度越多,过拟合越难。我在我自己的项目里面用的时候,只有简单容易过拟合的任务SMART才有提升,在其他的,比如语义匹配和MRC任务上,SMART是负增益的,徒增训练时长。所以这一类算法也不是万金油,处处见效,见实际场景使用,以实际效果为准。
  2. 这个问题我没太关注,我是照着论文的伪代码写的,实现以后的确比其他一众对抗式算法FreeLB等要好,也就没有关注这个点。正所谓实践科学,效果好就行~当然你可以试着改一下代码,看看加了restore以后能不能再提升一些
  3. 既然有效,可以commit到我们的代码里,提交pull request,成为contributors之一~

from unif.

geyingli avatar geyingli commented on June 12, 2024

在验证的时候是有把dropout_rate设为0的,那看来就是底层可能有不一样的实现,谢谢您的解答啦~

tensorflow源码我没怎么读,过去以研究上层网络为主,不能解决你的问题很抱歉哈

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

在验证的时候是有把dropout_rate设为0的,那看来就是底层可能有不一样的实现,谢谢您的解答啦~

tensorflow源码我没怎么读,过去以研究上层网络为主,不能解决你的问题很抱歉哈

哈哈没事没事,能够大致知道问题出在哪也就很有收获啦

from unif.

yupeijei1997 avatar yupeijei1997 commented on June 12, 2024

您好~
我在进行一项有这1000多个label的文本分类任务,在这个特定任务上,对代码做了点修改,解决了一些可能存在的问题~想和您分享一下,哈哈

  1. 我在使用smart时,在如下代码中,由于我的类别数特别多,可能会导致tf.log()内的值可能非常接近于0或者等于0,从而使得在求log以后,该值为负无穷,导致了loss为无穷值,从而在后面计算梯度的时候,梯度值为NAN,出现梯度爆炸的情况,loss也会一直为NAN;
        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg) - tf.log(probs)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs) - tf.log(probs_breg)), axis=-1)

以及

                per_example_loss = tf.reduce_sum(
                    probs_prtb * (tf.log(probs_prtb) - tf.log(probs)), axis=-1)
                per_example_loss_prtb = tf.reduce_sum(
                    probs * (tf.log(probs) - tf.log(probs_prtb)), axis=-1)

因此我改为了如下代码,为probs_breg、probs两个概率分布,在求log时,加上了一个极小数,解决了梯度爆炸的问题;不知道有没有别的解决办法了,因为这样会让概率分布的总和大于1,感觉会引入噪声;

        per_example_loss = tf.reduce_sum(
            probs_breg * (tf.log(probs_breg + 1e-9) - tf.log(probs + 1e-9)), axis=-1)
        per_example_loss_breg = tf.reduce_sum(
            probs * (tf.log(probs + 1e-9) - tf.log(probs_breg + 1e-9)), axis=-1)

我猜这在label个数较少时,或者别的任务上不会出现该问题;

  1. 另一个疑惑的地方是,我在smart的实现中没找到restore_op,即恢复embedding矩阵的操作,这样不会使loss朝着上升的方向在走吗
  2. 之前的这行FreeLB中的代码,如果不加的话,在我的1000多个label的文本分类任务上会导致loss不收敛的问题;
    cur_r = tf.cond(norm > ARGS.epsilon, lambda: (acc_r + tmp_r) * tf.divide(ARGS.epsilon, norm), lambda: (acc_r + tmp_r))

回复:

  1. 这个做法是正确的,写SMART的时候的确没有考虑到太多分类维度的问题。实际上,SMART和其他对抗式训练算法是对抗过拟合的,分类维度越多,过拟合越难。我在我自己的项目里面用的时候,只有简单容易过拟合的任务SMART才有提升,在其他的,比如语义匹配和MRC任务上,SMART是负增益的,徒增训练时长。所以这一类算法也不是万金油,处处见效,见实际场景使用,以实际效果为准。
  2. 这个问题我没太关注,我是照着论文的伪代码写的,实现以后的确比其他一众对抗式算法FreeLB等要好,也就没有关注这个点。正所谓实践科学,效果好就行~当然你可以试着改一下代码,看看加了restore以后能不能再提升一些
  3. 既然有效,可以commit到我们的代码里,提交pull request,成为contributors之一~

同步~
已测试SMART去掉restore_op后的结果了,去掉后会导致无法收敛。

from unif.

Related Issues (10)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.