我的模型在训练后预测完全相反的值。 (即将圆的内部值预测为外部,将外部值预测为内部)

问题描述 投票:0回答:1

制作数据集

from sklearn.datasets import make_circles
n_samples=1000
x, y = make_circles(n_samples, noise=0.03, random_state=42)
X = torch.from_numpy(x).type(torch.float)
Y = torch.from_numpy(y).type(torch.float)
from sklearn.model_selection import train_test_split
xtrain, xtest, ytrain, ytest = train_test_split(X, Y, test_size=0.2, random_state=42)

模型(预测圆)(我们知道圆的方程 s (

x**2 + y**2 = r**2
)

class cp(nn.Module):
    def __init__(self):
        super().__init__()
        self.r = nn.Parameter(torch.randn(1, requires_grad = True, dtype=torch.float))
    def forward(self, x):
        return x[:, 0]**2 + x[:, 1]**2 - self.r**2
torch.manual_seed(42)
m = cp()
loss_fn = nn.BCEWithLogitsLoss()
opt = torch.optim.SGD(params = m.parameters(), lr=0.1)

训练循环

e = 1000
for i in range(e+1):
    m.train()
    p = m(xtrain).squeeze()
    f = torch.round(torch.sigmoid(p))
    l = loss_fn(p, ytrain)
    acc = accuracy_fn(f, ytrain)
    opt.zero_grad()
    l.backward()
    opt.step()
    if(i%10==0):
        with torch.inference_mode():
            tp = m(xtest).squeeze()
            tf= torch.round(torch.sigmoid(tp))
            tl = loss_fn(tp, ytest)
            tacc = accuracy_fn(tf, ytest)
            print(f"epoch: {i} | train loss: {l:.4f} | train acc: {acc} | test loss: {tl:.4f} | test acc: {tacc}")
            if(i%100==0): print(m.state_dict())

如果我按照上述方式训练模型,它会预测 1 为 0,O 为 1。 IE。 ytrain[:10] =

tensor([1., 0., 0., 0., 1., 0., 1., 1., 0., 0.])
。预测值为: torch.round(torch.sigmoid(m(xtrain[:10]))) =
tensor([0., 1., 1., 1., 0., 1., 0., 0., 1., 1.])
但是,当我绘制圆时,它的预测正确(圆的半径预测正确) predicted circle

我试图预测一个圆。里面都是0,外面都是1。但训练后,它以相反的顺序进行预测(即外部 0 和内部 1)。请检查一次。我已经提供了完整的代码。

machine-learning deep-learning pytorch
1个回答
0
投票

模型返回此 logit:

x0 ** 2 + x1 ** 2 - r_optimal ** 2

上面的返回值使得样本insider_optimal返回负值,而r_optimal之外的样本返回正值。

我们可以按照这个进行预测类别:

  • r_optimal 内的样本 -> 模型返回负值
  • sigmoid(负)是 <0.5, so yhat = round(<0.5) = 0

同样,对于 r_optimal 之外的样本:

  • r_optimal 之外的样本 -> 模型返回正值
  • sigmoid(正)>0.5,所以 yhat = round(>0.5) = 1

因此,r_optimal 内部/外部的样本将得到 yhat=0/yhat=1 - 但这与训练集相反,其中实际标签为 y=1/y=0。

解决此问题的一种方法是反转返回值的符号。这意味着圆圈内的样本返回一个positive值,并将获得预测类别 yhat = round(sigmoid(+ve))) = 1.

return -(x[:, 0]**2 + x[:, 1]**2 - self.r**2)

© www.soinside.com 2019 - 2024. All rights reserved.