假设我有两个集合,X 和 Y,以及一些已知的系数“a”。
设置 Y 取决于 X 和“a”,如下所示: Y = aX
import numpy as np
a = 2
X = np.random.randint(1, 10, 10)
Y = a * X
print(f"{X = }")
print(f"{Y = }")
>>> X = array([9, 2, 7, 8, 8, 9, 5, 8, 4, 1])
>>> Y = array([18, 4, 14, 16, 16, 18, 10, 16, 8, 2])
任务: 使用 PyTorch 工具包仅使用 X 和 Y 找到系数“a”
我尝试做什么以及问题是什么:
我正在尝试将 X[i] 传递给模型并期望从中获得系数 a_pred。然后我找到 y_pred = a_pred * X[i]。最后我比较 y[i] 和 y_pred。 显然,模型没有“看到”a_pred、“a”、y_pred 和 Y[i] 之间的关系。因此问题是:模型的架构应该是什么,才能找到正确的“a”系数?
我刚刚开始学习 PyTorch,不幸的是,到目前为止,我还没有找到这个问题的明确答案。到目前为止,在我看来,这个问题的解决方案一定与 GAN 有关,但不幸的是我不知道到底是如何相关的
我当前的代码:
import numpy as np
from torch.nn import Module, Linear, ReLU, Sequential, CrossEntropyLoss
from torch.optim import Adam
from torch import from_numpy
from random import randint
class FindParameter(Module):
def __init__(self):
super(FindParameter, self).__init__()
self.layers = Sequential(
Linear(1, 10),
ReLU(),
Linear(10, 100),
ReLU(),
Linear(100, 10),
ReLU(),
Linear(10, 1),
)
def forward(self, input):
return self.layers(input)
a = 5.0
x = []
y = []
train_dataset_size = 10000
for i in range(train_dataset_size):
x.append(randint(0, 10000))
y.append(x[i] * a)
X = [from_numpy(np.array([c], dtype=np.float32)) for c in x]
Y = [from_numpy(np.array([c], dtype=np.float32)) for c in y]
A = from_numpy(np.array([a], dtype=np.float32))
epochs = range(100)
model = FindParameter()
loss_f = CrossEntropyLoss()
optimizer = Adam(model.parameters(), lr=1e-3)
for epoch in epochs:
for x, y in zip(X, Y):
optimizer.zero_grad()
a_pred = model(x)
y_pred = a_pred * x
loss = loss_f(y_pred, y)
loss.backward()
optimizer.step()
我们在 R 包“cito”(简化了神经网络的训练)中展示了如何使用神经网络来优化任意函数(唯一的要求是它们必须是可微分的并用 Torch 编写)。您的问题与我们的示例类似:
模拟线性模型的一些数据(真实斜率 = 2,真实西格玛 = 0.4)
library torch
library(cito)
X = runif(200)
Y = 2*X + rnorm(200, sd = 0.4)
df = data.frame(X = X, Y = Y)
我们要优化的函数(线性模型):
Xt = torch_tensor(matrix(X))
Yt = torch_tensor(matrix(Y))
model_lm = function(par) {
pred = Xt$matmul(par[,1,drop=FALSE])
loss = -torch::distr_normal(pred, scale = torch::torch_exp(par[,2,drop=FALSE]))$log_prob(Yt)
return(loss$mean())
}
实际损失函数:
custom_loss = function(pred, true, ...) {
if(nrow(pred) > 1) return(torch_zeros(1L)) # disable loss calculation
loss = model_lm(pred)
return(loss)
}
X 和 Y 值并不重要,Y 中的列数必须与我们要优化的参数数量相匹配,这里有两列,一列用于斜率参数,一列用于 sigma 参数。我们向神经网络输入噪声,它会预测两个参数(类似于 GAN 中的生成器):
noise = matrix(runif(300*5), 300, 5)
noise_y = matrix(runif(300*2), 300, 2)
df = data.frame(y1 = noise_y[,1], y2 = noise_y[,2], noise)
拟合最终模型:
m = dnn(cbind(y1, y2)~., data = df, loss = custom_loss, batchsize = 1L, epochs = 20L, verbose = FALSE)
结果:
# Effect:
mean(predict(m)[,1])
#> [1] 2.02776
# SD
mean(exp(predict(m)[,2]))
#> [1] 0.3864421