PaddlePaddle / Paddle

PArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice (『飞桨』核心框架,深度学习&机器学习高性能单机、分布式训练和跨平台部署)
http://www.paddlepaddle.org/
Apache License 2.0
21.66k stars 5.44k forks source link

CycleGAN-VC模型复现,模型无法收敛 #19799

Closed LinAurora closed 3 years ago

LinAurora commented 4 years ago

通过修改官方的cycleGAN模型,来复现tensorflow版本的cycleGAN-Voice conversion模型时,训练过程中判别器损失不稳定,生成器损失无法正常收敛,而相同的tensorflow版本,收敛正常。 复现时,基本上所有参数都相同,损失函数也修改的和TF版本相同,对于不同的部分如conv1d的实现或某些卷积核参数等等都已经通过修改tensorflow版本验证了不影响训练,但在paddle框架下模型的生成损失总是无法正常收敛,判别损失也不稳定。 其中,paddle的sequence_conv的stride只能为1,所以选择用conv2d实现conv1d来复现TF版本的conv1d,padding=“same”通过单独计算复现,instance_norm层用了官方代码。pixel_shuffle层重写,效果等同TF,训练器框架分别用了官方CycleGAN的和自己写的,在项目中分别是目录是paddle_GAN和paddle_GAN1,二者不同之处仅在trainer.py,最终训练过程大致相同,都无法像TF中一样正常收敛。

到底是框架本身的问题还是代码的问题?

下面是项目公开在AIstudio上的代码,因为无法在AIstudio平台安装pyworld库,只能将数据预处理部分放在本地然后上传,经过pyworld处理后的VCC数据集分为f0,sp,ap部分,已上传训练需要的sp部分。 https://aistudio.baidu.com/aistudio/projectdetail/116174

ceci3 commented 4 years ago

您好,建议您可以对paddle和tf使用相同的初始化和参数,然后看输出是否相同,判断实现的op是否有问题,模型库中的CycleGAN(https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/PaddleGAN/trainer/CycleGAN.py)是和pytorch版本的对齐过生成效果和loss。可以看下是否使用上修改了什么,导致跟tf不同

LinAurora commented 4 years ago

您好,建议您可以对paddle和tf使用相同的初始化和参数,然后看输出是否相同,判断实现的op是否有问题,模型库中的CycleGAN(https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/PaddleGAN/trainer/CycleGAN.py)是和pytorch版本的对齐过生成效果和loss。可以看下是否使用上修改了什么,导致跟tf不同

您好,我尝试了对paddle和tf使用完全相同的参数,但输出数据仍旧无法对齐,最后只留下一个用conv2d实现的conv1d卷积层,仍旧无法对齐,当彻底删除此生成器中的最后一个卷积层后,paddle数据才与TF版本相等。。。。 下面是paddle中对卷积层的调用,输入数据格式为[1,24,128,1] o1 = conv1d(input=inputs, num_filters=24, filter_size=[1,1], stride=[1,1], name=name+'o1_conv') 下面是paddle中的定义。其实就是把conv2d的[N,C,H,W]中的W设为了1。 def conv1d(input, # The input with [N, C, H, W] format. num_filters=128, filter_size=[15,1], stride=[1,1], padding="same", name="conv1d", ): conv_1d=fluid.layers.conv2d(input,num_filters=num_filters,filter_size=filter_size,stride=stride,padding=padding,name=name+"conv1d") return conv_1d 下面是TF版本中的卷积层调用,输入格式为[1,128,1,24] o1 = conv1d_layer(inputs = inputs, filters = 24, kernel_size = 1, strides = 1, activation = None, name = 'o1_conv') 下面是TF版本中的conv1d的实现,为了与paddle相同,我同样用的是conv2d def conv1d_layer(#inputs = inputs, filters = 128, kernel_size = 15, strides = 1, activation = None, name = 'h1_conv' inputs, filters, kernel_size, strides = 1, padding = 'same', activation = None, kernel_initializer = None, name = None):

[1,128,1,24]

                                #TF中conv2d的input shape 为[N, H, W, C]
conv_layer=tf.layers.conv2d(
    inputs=inputs,
    filters=filters,
    kernel_size=[kernel_size,1],
    strides=[strides,1],
    padding=padding,
    activation=activation,
    kernel_initializer=kernel_initializer,
    name=name

)
return conv_layer

两边的优化器都是相同的 TF版本: self.generator_optimizer = tf.train.AdamOptimizer(learning_rate = self.generator_learning_rate, beta1 = 0.5).minimize(self.generator_loss, var_list = self.generator_vars) Paddle版本: optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.0002,beta1 = 0.5) optimizer.minimize(self.generator_loss, parameter_list=g_vars)

怎么只一个卷积操作就会导致不同?

ceci3 commented 4 years ago

您好,可能是您构造conv1d的时候有些问题,使用以下方式我这里验证得到的tf和paddle的结果相同: paddle:

def conv1d(input,  # The input  with [N, C, H, W] format.
           num_filters=128,
           filter_size=[1, 15],
           stride=[1,1],
           padding="same",
           name="conv1d",
           ):
    param_attr = fluid.ParamAttr(name=name + '_w', initializer=fluid.initializer.Constant(1.0))
    bias_attr = fluid.ParamAttr(name=name + '_b', initializer=fluid.initializer.Constant(value=0.0))
    conv_1d=fluid.layers.conv2d(input,num_filters=num_filters,filter_size=filter_size,stride=stride,padding=padding,name=name+"conv1d", param_attr=param_attr, bias_attr=bias_attr)
    return conv_1d

if __name__ == '__main__':

    x = fluid.layers.data(name='x', shape=[1, 128, 1, 24], dtype='float32', append_batch_size=False)

tf:

def conv1d_layer(#inputs = inputs, filters = 128, kernel_size = 15, strides = 1, activation = None, name = 'h1_conv'
    inputs,
    filters,
    kernel_size,
    strides = 1,
    padding = 'same',
    activation = None,
    kernel_initializer = None,
    name = None):

    conv_layer=tf.layers.conv2d(
        inputs=inputs,
        filters=filters,
        data_format = 'channels_first',
        kernel_size=[1, kernel_size],
        strides=[1, strides],
        padding=padding,
        activation=activation,
        kernel_initializer = tf.ones_initializer(),
        bias_initializer=tf.zeros_initializer(),
        name=name
    )
    return conv_layer

x = tf.placeholder(tf.float32, shape=[1, 128, 1, 24])
y = conv1d_layer(x, filters = 128, kernel_size=15, strides=1)

optimizer = tf.train.AdamOptimizer(learning_rate=0.002, beta1=0.5, beta2=0.999, name='Adam')

np.random.seed(10)
train_data = np.random.randn(1, 128, 1, 24).astype('float32')
LinAurora commented 4 years ago
   您好,首先感谢您百忙之中解答我的问题,我尝试了您说的卷积实现方式后,发现卷积其实没有问题,

之所以不同时因为在模型开始训练时的参数随机初始化不同,但按理说结果的最大值和最小值的大致范围 也相同才对,可二者明显相差巨大。 问题似乎是出在初始化参数上,可Tensorflow版本的cycleGAN-VC模型中,除了这一句self.sess.run(tf.global_variables_initializer())全 局变量初始化以外,并没有其他的初始化操作了,而在paddle中,这种初始化似乎是自动完成的?在训练时,二者的初次生成loss都在30左右, 然后TF迅速下降,Paddle则停滞或缓慢下降到一定值后不变 然后我查看TF版本第一次运行时生成器返回的输出值,与输入值的最小最大值是很接近的。但是paddle版本, 生成器运行一次后与原始值的最大最小值差距巨大,但是由于是循环网络,再将第一个生成器的输出作为另一个生成器输入后, 得到的值却又与原值的最大最小值接近了,这是巧合还是有什么原因呢?问题究竟出在哪里?

   为了您能更好的理解问题,下面是Tensorflow版本和Paddle版本的的cycleGAN-VC模型的核心源码以及一些重要

层的实现。模型架构很清晰,我写了详细的注释

ceci3 commented 4 years ago

而在paddle中,这种初始化似乎是自动完成的?先回答您这个问题吧,exe.run(fluid.default_startup_program) 就是初始化参数的。 每层的初始化都是可以指定的,可以参考https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/PaddleGAN/network/base_network.py#L103 GAN模型库里的这种方式。

ceci3 commented 4 years ago

然后我查看TF版本第一次运行时生成器返回的输出值,与输入值的最小最大值是很接近的。但是paddle版本, 生成器运行一次后与原始值的最大最小值差距巨大 这个我不太明白您的具体意思是什么,如果网络确实相同,而且使用相同的初始化参数和相同的输入的话,得到的结果是一样的,可以排查一下网络结构或者其他op使用不一致的问题。

LinAurora commented 4 years ago

好的我再看下

LinAurora commented 4 years ago

然后我查看TF版本第一次运行时生成器返回的输出值,与输入值的最小最大值是很接近的。但是paddle版本, 生成器运行一次后与原始值的最大最小值差距巨大 这个我不太明白您的具体意思是什么,如果网络确实相同,而且使用相同的初始化参数和相同的输入的话,得到的结果是一样的,可以排查一下网络结构或者其他op使用不一致的问题。

您好,通过您的指导,我测试发现问题确实如您所说在于tensorflow的参数初始化, 于是我修改了两个版本的卷积函数的参数初始化方式分别为ones_initializer和constant(1),得到的输出确实是相同的,这说明conv1d的实现是没有问题的。 但是,Tensorflow模型的默认初始化方式并不是ones_initializer,而是glorot_uniform(),这个函数对应于paddle中的Xavier()初始化方式函数,于是我又修改了paddle参数的初始化方式为Xavier(),而得到的结果却不同,我分别看了两个初始化方式的源码,其中tensorflow版本只有两个参数,如下所示 def init(self, seed=None, dtype=dtypes.float32): super(GlorotUniform, self).init( scale=1.0, mode="fan_avg", distribution="uniform", seed=seed, dtype=dtype) 而Paddle版本是这样的, def init(self, uniform=True, fan_in=None, fan_out=None, seed=0): assert uniform is not None assert seed is not None super(XavierInitializer, self).init() self._uniform = uniform self._fan_in = fan_in self._fan_out = fan_out self._seed = seed 可以看到,paddle版本的seed为0,于是我把TF版本的seed也设为了0,但是得到的输出仍不相同。 图片 您能看下该如何使用glorot_uniform()和Xavier()初始化来保证二者完全相同吗?

ceci3 commented 4 years ago

paddle版本的seed为0的话会随机给一个seed的。就算seed相同,不同框架我也不确定是否随机得出的所有参数都相同。您现在是为了保证相同参数然后看整个网络的输出吗?如果是的话建议使用比较简单的方式,比如固定的常数来初始化所有的tf和paddle的参数,然后对比网络的输出。

LinAurora commented 4 years ago

和您想的一样,我也打算先用简单的常数初始化对齐整个网络后,再换成Xavier初始化方式查看效果。接下来几天我会尝试完全对齐整个网络。感谢您的指导。

LinAurora commented 4 years ago

paddle版本的seed为0的话会随机给一个seed的。就算seed相同,不同框架我也不确定是否随机得出的所有参数都相同。您现在是为了保证相同参数然后看整个网络的输出吗?如果是的话建议使用比较简单的方式,比如固定的常数来初始化所有的tf和paddle的参数,然后对比网络的输出。

您好,我先取消了神经网络的随机性,又重写了各种层的代码,并使用了相同的参数初始化,实现了输入输入的完全对齐后,进行训练时发现,tf版本可以正常运行,paddle仍旧无法正常训练,只有第一次训练的结果是相同的,包括各种层的输出和损失函数,这说明代码是没有问题的,所以我将问题重新定位在优化器上或者训练器的架构上,但是优化器都是相同的,而且无论是我使用自己写的和tf版本完全相同的训练器,还是使用对官方源码进行修改后的训练器,都无法正常收敛。 下面是生成器和训练器的源代码,和TF版本基本相同,运行也正常,可是无法像TF一样训练。

class GeneratorAll():
    def __init__(self,input_A,input_B):
        self.program=fluid.default_main_program().clone()

        with fluid.program_guard(self.program):

            #A->B->A
            self.generation_B=build_generator_resnet_9blocks(input_A,name="G_A2B")
            self.cycle_A=build_generator_resnet_9blocks(self.generation_B,name="G_B2A")
            #B->A->B
            self.generation_A=build_generator_resnet_9blocks(input_B,name="G_B2A")
            self.cycle_B=build_generator_resnet_9blocks(self.generation_A,name="G_A2B")

            #A->A,B->B  保证提取到的特征为A或B的特征。
            self.generation_A_identity=build_generator_resnet_9blocks(input_A,name="G_B2A")
            self.generation_B_identity=build_generator_resnet_9blocks(input_B,name="G_A2B")
            #2判别器

            self.discrimination_A_fake=build_gen_discriminator(inputs=self.generation_A,name="D_A")
            self.discrimination_B_fake=build_gen_discriminator(inputs=self.generation_B,name="D_B")
            #循环损失

            self.cycle_loss=fluid.layers.elementwise_add(l1_loss(y=input_A,y_hat=self.cycle_A),l1_loss(y=input_B,y_hat=self.cycle_B))
            #验证损失
            self.identity_loss=fluid.layers.elementwise_add(l1_loss(y=input_A,y_hat=self.generation_A_identity),l1_loss(y=input_B,y_hat=self.generation_B_identity))
            #生成损失,生成器欺骗判别器
            self.generator_loss_A2B=l2_loss(y=self.discrimination_B_fake,y_hat=1)
            self.generator_loss_B2A=l2_loss(y=self.discrimination_A_fake,y_hat=1)
            #总损失-生成器
            self.generator_loss=self.generator_loss_A2B+self.generator_loss_B2A+lambda_cycle*self.cycle_loss+fluid.layers.piecewise_decay(boundaries=[15000],values=[5,0])*self.identity_loss #lambda改为可变量。
            g_vars = []
            for var in self.program.list_vars():
                if fluid.io.is_parameter(var) and (var.name.startswith("G") ):
                    g_vars.append(var.name)
            self.param_g = g_vars
            lr = 0.0002
            # 优化器
            optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.0002,beta1 = 0.5)
            optimizer.minimize(self.generator_loss, parameter_list=self.param_g)

class DiscriminatorAll():
    def __init__(self,input_A,input_B,fake_A,fake_B):
        self.program = fluid.default_main_program().clone()
        with fluid.program_guard(self.program):
            ###################################这里要分出去才行。不然不太好弄,建一个新的训练器。
            # 判别损失
            self.discrimination_input_A_real = build_gen_discriminator(inputs=input_A, name="D_A")
            self.discrimination_input_B_real = build_gen_discriminator(inputs=input_B, name="D_B")
            self.discrimination_input_A_fake = build_gen_discriminator(inputs=fake_A, name="D_A")
            self.discrimination_input_B_fake = build_gen_discriminator(inputs=fake_B, name="D_B")
            # 判别器分辨真假
            self.discriminator_loss_input_A_real = l2_loss(y=self.discrimination_input_A_real, y_hat=fluid.layers.ones([1],dtype="float32"))
            self.discriminator_loss_input_A_fake = l2_loss(y=self.discrimination_input_A_fake, y_hat=fluid.layers.zeros_like(self.discrimination_input_A_fake))
            self.discriminator_loss_A = (self.discriminator_loss_input_A_real + self.discriminator_loss_input_A_fake) / 2

            self.discriminator_loss_input_B_real = l2_loss(y=self.discrimination_input_B_real, y_hat=fluid.layers.ones([1],dtype="float32"))
            self.discriminator_loss_input_B_fake = l2_loss(y=self.discrimination_input_B_fake, y_hat=fluid.layers.zeros_like(self.discrimination_input_A_fake))
            self.discriminator_loss_B = (self.discriminator_loss_input_B_real + self.discriminator_loss_input_B_fake) / 2
            # 总损失-判别器
            self.discriminator_loss = self.discriminator_loss_A + self.discriminator_loss_B

            d_vars = []
            for var in self.program.list_vars():
                if fluid.io.is_parameter(var) and (var.name.startswith("D")):
                    d_vars.append(var.name)
            self.param_d = d_vars
            #优化器
            optimizer=fluid.optimizer.AdamOptimizer(learning_rate=0.0001,beta1 = 0.5)
            optimizer.minimize(self.discriminator_loss, parameter_list=self.param_d)
LinAurora commented 4 years ago

图片 图片 TF版本仅需300次迭代即可迅速下降到3000,并且是一直下降的,而PD版本的迭代过程一直高于第一次损失值且在剧烈波动

ceci3 commented 4 years ago

您好,方便给一份可以直接训练的两个版本的模型吗?我调试一下是不是反向有问题

LinAurora commented 4 years ago

您好,下面是两个版本的模型的链接。配置好环境后两个版本直接运行train.py即可。 https://pan.baidu.com/s/1w6i_U8wVagc6NFYn6O37qg

LinAurora commented 4 years ago

如果运行过程遇到什么bug或问题期待您及时回复。麻烦您了。

ceci3 commented 4 years ago

您好,请问下您的cuda版本和cudnn版本是?我看环境里没有写

LinAurora commented 4 years ago

您好,请问下您的cuda版本和cudnn版本是?我看环境里没有写

抱歉疏忽了,TF版本是 cuda 9.0,cudnn7.6.0 paddle版本为方便同时与tensorflow调试我没有使用GPU,在GPU运行的话,与AIstudio平台的相同,cuda版本是9.2.148。

ceci3 commented 4 years ago

您好,请问下您的cuda版本和cudnn版本是?我看环境里没有写

抱歉疏忽了,TF版本是 cuda 9.0,cudnn7.6.0 paddle版本为方便同时与tensorflow调试我没有使用GPU,在GPU运行的话,与AIstudio平台的相同,cuda版本是9.2.148。

TF 1.13.1是源码编译的吗?我看pip install这种安装方式的话安装tf 1.13.1的是cuda10版本的tf。

LinAurora commented 4 years ago

您好,请问下您的cuda版本和cudnn版本是?我看环境里没有写

抱歉疏忽了,TF版本是 cuda 9.0,cudnn7.6.0 paddle版本为方便同时与tensorflow调试我没有使用GPU,在GPU运行的话,与AIstudio平台的相同,cuda版本是9.2.148。

TF 1.13.1是源码编译的吗?我看pip install这种安装方式的话安装tf 1.13.1的是cuda10版本的tf。

没有,我是在windows环境下,用Anaconoda3,使用pip install安装的。tensorflow1.8以及之后的版本应该都可以正常运行。

ceci3 commented 4 years ago

您好,请问下您的cuda版本和cudnn版本是?我看环境里没有写

抱歉疏忽了,TF版本是 cuda 9.0,cudnn7.6.0 paddle版本为方便同时与tensorflow调试我没有使用GPU,在GPU运行的话,与AIstudio平台的相同,cuda版本是9.2.148。

TF 1.13.1是源码编译的吗?我看pip install这种安装方式的话安装tf 1.13.1的是cuda10版本的tf。

没有,我是在windows环境下,用Anaconoda3,使用pip install安装的。tensorflow1.8以及之后的版本应该都可以正常运行。

pip list的话输出的是tensorflow 还是 tensorflow_gpu?

LinAurora commented 4 years ago

二者都有,都是1.13.1

ceci3 commented 4 years ago

二者都有,都是1.13.1

好的,我测试一下,有结果会尽快反馈的~

LinAurora commented 4 years ago

非常感谢。

ceci3 commented 4 years ago

您好,我先取消了神经网络的随机性,又重写了各种层的代码,并使用了相同的参数初始化,实现了输入输入的完全对齐后,进行训练时发现,tf版本可以正常运行,paddle仍旧无法正常训练,只有第一次训练的结果是相同的, 您好,我直接跑您发过来的两个版本的模型,发现第一轮输出的loss并没有完全对上,不知道是您提供的版本问题还是说还要进行别的改动?是否可以提供第一次结果完全一致的代码?这样调试起来回快一些

屏幕快照 2019-09-27 上午11 38 57 屏幕快照 2019-09-27 上午11 39 04
LinAurora commented 4 years ago

好的,我中午回去看一下

LinAurora commented 4 years ago

您好,我先取消了神经网络的随机性,又重写了各种层的代码,并使用了相同的参数初始化,实现了输入输入的完全对齐后,进行训练时发现,tf版本可以正常运行,paddle仍旧无法正常训练,只有第一次训练的结果是相同的, 您好,我直接跑您发过来的两个版本的模型,发现第一轮输出的loss并没有完全对上,不知道是您提供的版本问题还是说还要进行别的改动?是否可以提供第一次结果完全一致的代码?这样调试起来回快一些

屏幕快照 2019-09-27 上午11 38 57 屏幕快照 2019-09-27 上午11 39 04

您好,我刚又运行了一下,发现二者确实是相同的。 QQ图片20190927124301 上图之所以有误差,是因为两个网络每个层最后的输出在小数点5位之后会有精度的不同,多层累加之后会导致误差积累,而且这个G_loss中是由三个loss加起来的,其中两个loss分别乘了放大系数,这导致二者之间的误差扩大到小数点后3位。 而您之所以二者相差较大,可能是因为版本或其他原因?我是在win10,py3.7,tensorflow1.13.1,cuda9.0,cudnn7.6.0,librosa0.7.0,pyworld0.2.8环境下运行的,但其实这已经可以表明训练的收敛问题不是出在网络是否完全对齐的问题上,所以感觉无需再纠结输出对齐问题,或许是在其他方面出了问题?

ceci3 commented 4 years ago

因为按照您之前的意思,第一个epoch是可以对上的,第二个epoch是对不上的。现在是要对齐反向,查找是否是反向计算的问题,所以如果输出没有对齐的话,不太好排查反向计算是否有问题。

LinAurora commented 4 years ago

因为按照您之前的意思,第一个epoch是可以对上的,第二个epoch是对不上的。现在是要对齐反向,查找是否是反向计算的问题,所以如果输出没有对齐的话,不太好排查反向计算是否有问题。

额,非常抱歉。。。我刚看了下,发现您之所以得到的结果和我不同,是因为我把在对模型打包时把输入数据弄错了。。我刚修改了一下,下面是模型地址。 https://pan.baidu.com/s/1oQ_jv8u4cE_WTBtjnCNQDw 另外, 图片 这是用以上模型中生成函数只保留一个卷积层的输出结果,他们的参数初始化,输入的数据完全相同, 图片 但他们的输出却始终在小数最后几位有所不同

LinAurora commented 4 years ago

这似乎是没有办法彻底对齐?

ceci3 commented 4 years ago

因为按照您之前的意思,第一个epoch是可以对上的,第二个epoch是对不上的。现在是要对齐反向,查找是否是反向计算的问题,所以如果输出没有对齐的话,不太好排查反向计算是否有问题。

额,非常抱歉。。。我刚看了下,发现您之所以得到的结果和我不同,是因为我把在对模型打包时把输入数据弄错了。。我刚修改了一下,下面是模型地址。 https://pan.baidu.com/s/1oQ_jv8u4cE_WTBtjnCNQDw 另外, 图片 这是用以上模型中生成函数只保留一个卷积层的输出结果,他们的参数初始化,输入的数据完全相同, 图片 但他们的输出却始终在小数最后几位有所不同

好的,我先看下吧,这应该不至于影响收敛。

LinAurora commented 4 years ago

因为按照您之前的意思,第一个epoch是可以对上的,第二个epoch是对不上的。现在是要对齐反向,查找是否是反向计算的问题,所以如果输出没有对齐的话,不太好排查反向计算是否有问题。

额,非常抱歉。。。我刚看了下,发现您之所以得到的结果和我不同,是因为我把在对模型打包时把输入数据弄错了。。我刚修改了一下,下面是模型地址。 https://pan.baidu.com/s/1oQ_jv8u4cE_WTBtjnCNQDw 另外, 图片 这是用以上模型中生成函数只保留一个卷积层的输出结果,他们的参数初始化,输入的数据完全相同, 图片 但他们的输出却始终在小数最后几位有所不同

好的,我先看下吧,这应该不至于影响收敛。

好的麻烦您了

LinAurora commented 4 years ago

您好,请问这些天您有发现问题吗?我在这期间检查了许多次,也重新运行了许多次,也尝试更新过paddle使用最新版本,但还是没有找到问题所在。

LinAurora commented 4 years ago

如果您实在没有空,能不能简单说下您是如何调试反向传播过程的呢?我在网上寻找很久但没有找到相关资料,这个网络模型确实困扰我许久,真心希望能尽早解决。

ceci3 commented 4 years ago

抱歉抱歉,最近实在太忙.. 我简单讲下paddle怎么调试反向吧,通过print(str(train_program))打印出program,然后从打印出来的program里type: "*_grad"一般代表反向op,op的outputs里arguments就是反向输出的名字,把这个名字加入到exe.run 的fetch_list里就可以打出来经过反向op的值了

LinAurora commented 4 years ago

我这段时间也是被各种事情忙的没法专心弄这个,非常理解您,您能顺便说下TensorFlow该怎么调试反向呢?我也没找到这方面的资料。。麻烦您了

ceci3 commented 4 years ago

tf好像是需要利用tf.gradient来打印,具体的我也没有调试过

LinAurora commented 4 years ago

好的非常感谢您的指导。

paddle-bot-old[bot] commented 3 years ago

Since you haven\'t replied for more than a year, we have closed this issue/pr. If the problem is not solved or there is a follow-up one, please reopen it at any time and we will continue to follow up. 由于您超过一年未回复,我们将关闭这个issue/pr。 若问题未解决或有后续问题,请随时重新打开,我们会继续跟进。