【问题标题】:How to create my own loss function in Pytorch?如何在 Pytorch 中创建自己的损失函数?
【发布时间】:2020-04-06 18:24:29
【问题描述】:

我想创建一个模型来预测圆的参数(中心坐标、半径)。

输入是一个点数组(带噪声的圆弧):

def generate_circle(x0, y0, r, start_angle, phi, N, sigma):
    theta = np.linspace(start_angle*np.pi/180, (start_angle + phi)*np.pi/180, num=N)
    x = np.array([np.random.normal(r*np.cos(t) + x0 , sigma, 1)[0] for t in theta])
    y = np.array([np.random.normal(r*np.sin(t) + y0 , sigma, 1)[0] for t in theta])
    return x, y

n_x = 1000
start_angle = 0
phi = 90
N = 100
sigma = 0.005 
x_full = []
for i in range(n_x):
    x0 = np.random.normal(0 , 10, 1)[0]
    y0 = np.random.normal(0 , 10, 1)[0]
    r = np.random.normal(0 , 10, 1)[0]
    x, y = generate_circle(x0, y0, r, start_angle, phi, N, sigma)
    x_full.append(np.array([ [x[i], y[i]] for i in range(len(x))]))
X = torch.from_numpy(np.array(x_full))
print(X.size()) # torch.Size([1000, 100, 2])

输出:[x_c, y_c, r]

作为一个损失函数,我需要使用这个:

我尝试实现如下内容:

class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)
        self.predict = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        x = F.relu(self.hidden(x))
        x = self.predict(x)
        return x

# It doesn't work, it's just an idea
def my_loss(point, params):
    arr = ((point[:, 0] - params[:, 0])**2 + (point[:, 1] - params[:, 1])**2 - params[:, 2]**2)**2
    loss = torch.sum(arr)
    return loss

# For N pairs (x, y) model predicts parameters of circle
net = Net(n_feature=N*2, n_hidden=10, n_output=3)

optimizer = torch.optim.SGD(net.parameters(), lr=1e-4)

for t in range(1000):
    prediction = net(X.view(n_x, N*2).float())
    loss = my_loss(X, prediction)
    print(f"loss: {loss}")

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

那么,问题是在这种情况下,如何正确实现我自己的 Pytorch 损失函数?

或者如何改变模型的结构以获得预期的结果?

【问题讨论】:

    标签: python-3.x machine-learning deep-learning pytorch loss-function


    【解决方案1】:

    您试图在预测输出和输入之间而不是在预测输出和真实输出之间创建损失。为此,您需要在生成 x0y0r 时保存它们的真实值。

    n_x = 1000
    start_angle = 0
    phi = 90
    N = 100
    sigma = 0.005 
    x_full = []
    targets = [] # <-- Here
    for i in range(n_x):
        x0 = np.random.normal(0 , 10, 1)[0]
        y0 = np.random.normal(0 , 10, 1)[0]
        r = np.random.normal(0 , 10, 1)[0]
        targets.append(np.array([x0, y0, r])) # <-- Here
        x, y = generate_circle(x0, y0, r, start_angle, phi, N, sigma)
        x_full.append(np.array([ [x[i], y[i]] for i in range(len(x))]))
    X = torch.from_numpy(np.array(x_full))
    Y = torch.from_numpy(np.array(targets)) # <-- Here
    print(X.size()) # torch.Size([1000, 100, 2])
    print(Y.size()) # torch.Size([1000, 3])
    

    现在,当您致电 my_loss 时,您应该使用:

    loss = my_loss(Y, prediction)
    

    您在 for 循环的每次迭代中都传递了所有数据点,我会将您的数据分成更小的部分,这样您的模型就不会每次都学会输出相同的值。例如你已经生成了 1000 个点,所以在每次迭代中随机选择 100 个点,使用类似random.sample(...)

    您的输入数字非常大,这意味着您的损失会很大,因此生成介于 0 和 1 之间的输入,然后如果您需要介于 0 和 10 之间的值,您可以乘以 10。

    【讨论】:

      猜你喜欢
      • 2019-05-27
      • 2020-06-03
      • 2022-01-15
      • 1970-01-01
      • 2021-11-13
      • 2019-03-12
      • 2021-10-03
      • 2020-02-25
      • 2018-09-23
      相关资源
      最近更新 更多