【发布时间】:2021-08-26 07:37:55
【问题描述】:
简介:
我正在尝试让自动编码器在 32 个时间步长内学习 32 个特征,如位置、速度等 => 32x32“图像”。 为此,我只是制作了一个简单的线性模型,在每一层都使用 Tanh 函数以及对称的编码器和解码器。
在训练期间,我添加了自己的 dropout 版本,仅用于输入。 (以后我会使用nn.Dropout)
问题:
我的损失函数“sqrt(MSE)”以不规则的时间间隔出现大峰值。 (Batch_Size = 6000)
我尝试过的:(小测试,最大 1000 个 epoch)
-
clip_grad_norm_(model.parameters(), max_norm = 0.5)。 - 试过
ReLu和ELU。 - 激活函数
Batch = N / 2(我想做N但是我的gpu内存不够)。 - 不添加噪声或丢失(我认为噪声/丢失有助于但不能解决问题)。
- 去除 MSE 损失的平方根。
有人可以向我解释为什么会发生这种情况以及如何解决它吗?
def rand_bin_array(p_zeros, shape):
size = 1
for e in shape:
size *= e
arr = np.ones(size)
arr[:int(size * p_zeros)] = 0
np.random.shuffle(arr)
arr = arr.reshape(shape)
return arr
class Autoencoder_Liniar(nn.Module):
def __init__(self):
super().__init__()
self.encoder = nn.Sequential(
nn.Linear(1024, 921),
nn.Tanh(),
nn.Linear(921, 736),
nn.Tanh(),
nn.Linear(736, 515),
nn.Tanh(),
nn.Linear(515, 309),
nn.Tanh(),
nn.Linear(309, 128),
nn.Tanh(),
nn.Linear(128, 64),
nn.Tanh(),
)
self.decoder = nn.Sequential(
nn.Linear(64, 128),
nn.Tanh(),
nn.Linear(128, 309),
nn.Tanh(),
nn.Linear(309, 515),
nn.Tanh(),
nn.Linear(515, 736),
nn.Tanh(),
nn.Linear(736, 921),
nn.Tanh(),
nn.Linear(921, 1024),
nn.Tanh()
)
def forward(self, x):
enc = self.encoder(x)
dec = self.decoder(enc)
return dec
torch.manual_seed(0)
model = Autoencoder_Liniar().cuda()
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
random.seed(0)
epochs = 10000
batch_size = 6000
test_b_size = 5000
train_losses = []
test_losses = []
for i in range(epochs):
avg_loss = 0
random.shuffle(train_data)
for b in range(train_nr // batch_size):
start = b * batch_size
data = torch.FloatTensor(train_data[start : start + batch_size]).cuda()
noise_power = max(0.8 - i/epochs, 0.1)
noise = torch.FloatTensor(rand_bin_array(noise_power, data.shape)).cuda()
y_pred = model(data * noise)
loss = torch.sqrt(criterion(y_pred, data))
optimizer.zero_grad()
loss.backward()
#torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=0.5)
optimizer.step()
avg_loss += loss.item()
if b % 20 == 0:
print(f'EPOCH: {i} BATCH: {b} LOSS: {loss.item()}')
train_losses.append(avg_loss / (train_nr // batch_size))
with torch.no_grad():
avg_loss = 0
for b in range(test_nr // test_b_size):
start = b * test_b_size
data = np.array(test_data[start : start + test_b_size])
data = torch.FloatTensor(data).cuda()
y_pred = model(data)
loss = torch.sqrt(criterion(y_pred, data))
avg_loss += loss.item()
test_losses.append(avg_loss / (test_nr // test_b_size))
添加了获取gradient's norm over epochs graph 的代码(无噪音/丢失)
total_norm = 0
for p in model.parameters():
param_norm = p.grad.detach().data.norm(2)
total_norm += param_norm.item() ** 2
total_norm = total_norm ** 0.5
avg_grad += total_norm
optimizer.step()
【问题讨论】:
-
你为什么要解决你的损失?有可能是因为在你 sqrt 之后,你的损失在 y_pred = y_true 处变得不可微分,导致这个奇怪的尖峰。
-
刚才我试过不带sqrt,还是一样。
-
你能画出不同时期的梯度范数吗?通过这种方式,您将了解如何正确剪辑渐变。随意选择使用
max_norm=0.5没有意义... -
@Ivan 抱歉让您久等了(我的电脑很慢)。我已经添加了渐变图。
-
如果你看一下梯度图上的那些尖峰:我的想法是你可能应该尝试以较低的值进行剪辑(至少低于
0.5)。
标签: python pytorch autoencoder loss