Извините, но ваш код беспорядок ... И если это просто для демонстрации идеи автоэнкодера (здесь у вас просто есть координаты X, Y, Z, а вы называете ее image
), то она выбрана довольно плохо.
Не в пути: Если это изображение, вы не сможете его закодировать как один пиксель, это требует немного большей сложности.
Исходный код
Вот простой автокодер для кодирования 3 векторов измерения 1x3: [1,2,3], [1,2,3], [100,200,500] до 1x1
true только в этом случае, поскольку у вас есть пакет 3
элементов (в то время как вы назвали batch
out_features
сети!). Их размеры не 1x3
, а просто 3
. Вот Минимальный воспроизводимый пример с комментарием:
import torch
# Rows are batches, there could be 3, there could be a thousand
data = torch.tensor([[1, 2, 3], [1, 2, 3], [100, 200, 500]]).float()
# 3 input features, columns of data
encoder = torch.nn.Sequential(torch.nn.Linear(3, 1), torch.nn.Sigmoid())
decoder = torch.nn.Sequential(torch.nn.Linear(1, 3), torch.nn.Sigmoid())
autoencoder = torch.nn.Sequential(encoder, decoder)
optimizer = torch.optim.Adam(params=autoencoder.parameters(), lr=0.001)
epochs = 10000
for i in range(epochs):
optimizer.zero_grad()
reconstructions = autoencoder(data)
loss = torch.dist(data, reconstructions)
loss.backward()
optimizer.step()
# Print loss every 100 epoochs
if i % 100 == 0:
print(loss)
Будет ли это работать?
Этот более интересный. В принципе, если ваша нейронная сеть обучена, вам не нужно переучивать ее, чтобы включить пример, который она ранее не видела (поскольку цель нейронной сети - выучить некоторые шаблоны для решения задачи).
В вашем случае это не будет.
Почему это не сработает?
Прежде всего, у вас есть сигмовидная активация в decoder
, которая ограничивает выходной диапазон [0, 1]
. Вы пытаетесь предсказать данные, которые находятся за пределами этого диапазона, поэтому это невозможно.
Без выполнения я могу сказать вам, к чему приведет потеря этого примера go по отношению к (со всеми весами, равными +inf
). Все прогнозы всегда будут [1, 1, 1]
(или как можно ближе к нему), так как это значение меньше всего портит сеть, поэтому вам просто нужно вычислить расстояние каждого vector
в данных до [1, 1, 1]
. Здесь потеря застряла в районе 546.2719
. Веса и уклоны составляют около 1041 * (что довольно много для сигмовидной кишки) после 100000 эпох. Ваши значения могут отличаться, но тренд ясен (хотя он остановится, поскольку 10
довольно близко к 1
, когда вы наберете sh с sigmoid
).
Удаление torch.nn.Sigmoid
из decoder
Что если мы удалим torch.nn.Sigmoid()
из decoder
? Он научится почти идеально восстанавливать только ваши 3 примера , с потерей 0.002
после "только" 500000
эпох:
Вот выученные веса decoder
:
tensor([[ 99.0000],
[198.0000],
[496.9999]], requires_grad=True)
А вот bias
:
tensor([1.0000, 2.0000, 2.9999])
А вот выход encoder
для каждого примера:
tensor([[2.2822e-13],
[2.2822e-13],
[1.0000e+00]])
Анализ результатов
Ваша сеть узнала только то, что вы сказали ей изучать, а это ... величина (+ умный bias
хакер).
[1, 2, 3 ] vector
Пример [1, 2, 3]
(повторяется дважды). его кодирование - 2e-13
и идет к нулю, поэтому мы предположим, что оно равно нулю.
Теперь, умножив 0
на все веса, вы все равно получите ноль. Добавьте bias
, что составляет [1.0, 2.0, 2.99999]
, и вы волшебным образом восстановите свой вход.
[100, 200, 500] vector
Вы, вероятно, можете видеть, куда он идет.
Кодированное значение равно 1.0
, при умножении на decoder
веса мы получаем [99.0, 198.0, 497.0]
. Добавьте bias
к нему и вуаля, мы получим наш [100.0, 200.0, 500.0]
.
[1, 1, 1] вектор
В вашем случае это, очевидно, не будет работать как величина [1, 1, 1]
действительно маленький, следовательно, он будет закодирован как zero
и реконструирован как [1, 2, 3]
.
Удаление torch.nn.Sigmoid
из encoder
Немного вне топики c, но когда вы удаляете сигмоид из кодировщика, он не сможет выучить этот шаблон так же легко. Причина в том, что сеть должна быть более консервативной с весами (поскольку они не будут раздавлены). Вам придется понизить скорость обучения (желательно постоянно снижать ее в процессе обучения), поскольку в какой-то момент она становится нестабильной (при попытке достичь «идеального места»).
Сходство обучения
Трудно (по крайней мере, для сети) определить «подобное» в этом случае. [1, 2, 3]
похоже на [3, 2, 1]
? Он не имеет понятия различных размеров и должен объединить эти три числа в единое значение (позднее использованное для реконструкции).
Как продемонстрировано, он, вероятно, изучит некоторые неявные шаблоны в ваших данных, которые будут хороши в восстановлении "хотя бы чего-то", но не найдет общий шаблон, который вы ищете. Тем не менее, это зависит от ваших данных и их свойств, но я бы вообще не стал спорить, и я думаю, что его возможности обобщения были бы плохими.
И, как вы видели в анализе выше, нейронная сеть довольно хорошо находит эти паттерны, даже когда вы их не видели (или, возможно, вы видели, и это то, что вы искали?), Или они не понимают вообще не существует.
Если вам нужно сходство измерений (и это не просто мысленный эксперимент), у вас есть много "созданных человеком" вещей, таких как p-norm
, некоторые кодировки (они также измеряют подобие, но по-другому), поэтому лучше для go для этого ИМО.