“ValueError:没有为任何变量提供梯度”层中的自定义函数

时间:2021-03-01 01:30:59

标签: python tensorflow tensorflow2.0

我的代码遇到了一些问题。我给出了 nn 2 个坐标,它必须将这些转换为 3 个变量(角度)。这些角度用于计算一些应该在给定点结束的向量的位置。当我尝试运行代码时,出现上述错误。

import tensorflow as tf
from tensorflow.keras import layers, losses
import numpy as np
from tensorflow.keras import Model
from main import robot_arm

r = robot_arm()
r.set_joints([1, 2, 2])

train_points = []
test_points = []

for i in range(1000000):
    element = []

    for i in range(2):
        element.append(np.random.uniform(-5, 5))

    train_points.append(element)

train_points = np.array(train_points)
print(train_points.shape)

for i in range(10000):
    element = []

    for i in range(2):
        element.append(np.random.uniform(-5, 5))

    test_points.append(element)

test_points = np.array(test_points)
print(test_points.shape)


class robot_arm_ai(Model):
    def __init__(self):
        super(robot_arm_ai, self).__init__()
        self.decoder = tf.keras.Sequential([
            layers.Dense(100, activation='linear'),
            layers.Dense(100, activation='linear'),
            layers.Dense(100, activation='linear'),
            layers.Dense(100, activation='linear'),
            layers.Dense(3),
        ])


    def call(self, x):
        x = self.decoder(x)

        return r.calculate_point(x)





model = robot_arm_ai()



model.compile(optimizer="adam", loss=losses.MeanSquaredError(), run_eagerly=True)

model.fit(train_points, train_points,
          epochs=10,
          shuffle=True,
          batch_size=256,
          validation_data=(test_points, test_points))

这是用来描述机械臂的代码

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf


class joint():

    def __init__(self, j_len=1, j_rot=0):
        self.rot = j_rot
        self.len = j_len
        self.x_component = 0
        self.y_component = 0
        self.set_vector()

    def print(self):
        print("Length: " + str(self.len))
        print("Rotation: " + str(self.rot))

    def set_vector(self):
        self.y_component = self.len * np.sin(self.rot * (2 * np.pi) )
        self.x_component = self.len * np.cos(self.rot * (2 * np.pi) )

    def random_rotation(self):
        self.rot = np.random.uniform(-360, 360)

    def set_rot(self, rot):
        self.rot = rot

    def random_rotation_set(self):
        self.random_rotation()

    def get_x(self):
        return self.x_component

    def get_y(self):
        return self.y_component


class robot_arm():

    def __init__(self):
        self.joints = []
        self.x = 0
        self.y = 0

    def print(self):
        depth = 0

        for i in self.joints:
            print("- " * 30)
            print("Element " + str(depth))
            i.print()
            depth = depth + 1

    def set_joints(self, lens):
        for i in lens:
            self.joints.append(joint(j_len=i))

    def random_rotation(self):
        for i in self.joints:
            i.random_rotation_set()
        self.set_endpoint()

    def get_point(self):
        return self.x, self.y

    def calculate_point(self, rot):
        res = []
        rot = rot.numpy().tolist()
        for i in rot:
            self.set_rot(i)
            self.set_endpoint()
            res.append(self.get_point())

        return tf.convert_to_tensor( res )

    def set_endpoint(self):
        self.x = 0
        self.y = 0

        for i in self.joints:
            i.set_vector()
            self.x = self.x + i.get_x()
            self.y = self.y + i.get_y()

    def set_rot(self, rots):

        if (len(rots) == len(self.joints)):
            for r, j in zip(rots, self.joints):
                j.set_rot(r)
            self.set_endpoint()

        else:

            print("Failure. Passed Rotations unequal to length of joint chain. Rotation not completed.")
            print(rots.shape)

    def draw_plot(self):

        last_x = 0
        last_y = 0

        for i in self.joints:
            x_val = i.get_x() + last_x
            y_val = i.get_y() + last_y

            plt.plot([last_x, x_val], [last_y, y_val])

            last_y = y_val
            last_x = x_val

        plt.show()



我认为这与通过函数传递图层有关,但不确定。 (返回 r.calculate_point(x))

2 个答案:

答案 0 :(得分:0)

自定义 LayerModel 应至少具有四种方法: __init__buildcallget_config 。 您的图层只有两个 .

答案 1 :(得分:0)

可能与 robot_arm.calculate_point 方法在 tensorflow 之外进行计算有关,因此无法进行反向传播,因为梯度磁带无法“跟踪”从 xr.calculate_point(x)。见https://www.tensorflow.org/guide/autodiff#getting_a_gradient_of_none

由于在 robot_arm.calculate_point 方法上没有任何可训练的内容,我将该操作移到 robot_arm_ai.call 方法之外。然后你应该能够训练你的模型。