Как создать автоэнкодер с зеркальным отображением (транспонированием) весов кодировщика / декодера

Я пытаюсь создать свою первую нейронную сеть Autoencoder, используя TensorFlow. Размеры слоев в кодировщике и декодере одинаковые, только наоборот. Автоэнкодер учится сжимать и восстанавливать данные изображения в соответствии с разумным стандартом, но я хотел бы попытаться улучшить его производительность, вместо этого используя декодер в качестве точного транспонирования кодировщика.

Я не понимаю, как это сделать в TensorFlow.

Вот фрагмент построения моей сети:

imgW, imgH = 28, 28
encoderDims = [
    imgW * imgH,
    (imgW // 2) * (imgH // 2),
    (imgW // 3) * (imgH // 3),
    (imgW // 4) * (imgH // 4)
]
decoderDims = list(reversed(encoderDims))

encoderWeights, encoderBiases = [], []
decoderWeights, decoderBiases = [], []
for layer in range(len(encoderDims) - 1):
    encoderWeights.append(
        tf.Variable(tf.random_normal([encoderDims[layer], encoderDims[layer + 1]]))
    )
    encoderBiases.append(
        tf.Variable(tf.random_normal([encoderDims[layer + 1]]))
    )
    decoderWeights.append(
        tf.Variable(tf.random_normal([decoderDims[layer], decoderDims[layer + 1]]))
    )
    decoderBiases.append(
        tf.Variable(tf.random_normal([decoderDims[layer + 1]]))
    )

input = tf.placeholder(tf.float32, [None, imgW * imgH])
encoded = input
for layer in range(len(encoderDims) - 1):
    encoded = tf.add(tf.matmul(encoded, encoderWeights[layer]), encoderBiases[layer])
    encoded = tf.nn.sigmoid(encoded)

decoded = encoded
for layer in range(len(decoderDims) - 1):
    decoded = tf.add(tf.matmul(decoded, decoderWeights[layer]), decoderBiases[layer])
    if layer != len(decoderDims) - 2:
        decoded = tf.nn.sigmoid(decoded)

loss = tf.losses.mean_squared_error(labels=input, predictions=decoded)
train = tf.train.AdamOptimizer(learningRate).minimize(loss)

Я не знаю, как преодолеть две проблемы:

  1. Как я могу отрегулировать только параметры кодировщика во время тренировки с учетом потерь?
  2. Как я могу создать веса и смещения декодера таким образом, чтобы после каждой итерации обучения параметров кодера они устанавливались как транспонирование вновь настроенных параметров кодера?
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
1 130
1

Ответы 1

Сомневаюсь, что это превзойдет обычные автоэнкодеры. Но если вы добьетесь удивительно хороших результатов, сообщите об этом сообществу. По поводу ваших вопросов:

1.) Поскольку вы должны использовать некоторую ошибку реконструкции между вводом и выводом, единственный вариант - тренироваться со всей сетью (например, кодировщиком и декодером в целом). Но вы можете установить флаг для переменных декодера, который предотвращает их изменение алгоритмом после инициализации. Установите их на trainable=False. После обучения для эпохи вы можете установить их вручную на транспонированные веса кодировщика.

2.) Здесь я не уверен, как вы интерпретируете «транспонировать». Если вы имеете в виду, что веса уровня 1 кодера должны совпадать с весами последнего уровня декодера, вы можете попробовать следующее:

for layer in range(len(encoderWeights)):
    decoderWeights[-layer-1] = tf.transpose(encoderWeights[layer])

Если вы хотите транспонировать матрицы слоев по отдельности, вы можете использовать упомянутый tf.tranpose(). С математической точки зрения правильной обратной операцией умножения матриц будет обратная матрица, если она определена. TensorFlow предоставляет для этого tf.matrix_inverse(). Однако будьте очень осторожны при использовании, поскольку разумный результат не гарантируется.

«Я сомневаюсь, что это превзойдет обычные автоэнкодеры». В этой статье (arxiv.org/pdf/1708.01715.pdf), в которой описываются успешные результаты использования модели глубокого автокодера для рекомендательной системы (что я тоже пытаюсь сделать), говорится, что это то, что они сделали в последнем параграфе страницы 1. Также в оригинальной статье Джеффри Хинтона В предложении автокодеров (cs.toronto.edu/~hinton/science.pdf) также использовалась эта перестановка весовых матриц из кодера в декодер с последующей тонкой настройкой весов кодера и декодера независимо друг от друга.

KOB 05.07.2018 12:32

Что касается вашего второго пункта: да, это просто простое математическое транспонирование матрицы, которое необходимо, поскольку первая матрица весов кодирования будет иметь размер, например, 728x400, и, следовательно, последняя матрица весов декодера теперь будет нужно транспонировать это, 400x728.

KOB 05.07.2018 12:36

И по вашему 1-му пункту, я думаю, что можно использовать подход, подобный этому. Прочитав вашу точку зрения, я думаю, что мог бы просто использовать кодировщик на каждой итерации, вычислить потери, затем перенести каждую матрицу весов кодирования и, следовательно, смоделировать процесс декодирования, из которого можно вычислить потери. Затем, из-за этой потери, я мог бы тренировать только веса кодировщика, как вы обрисовали. Это будет повторяться до тех пор, пока потери не станут достаточно низкими, и я смогу затем построить постоянный декодер, транспонировав веса обученного кодера, и сохранить всю модель.

KOB 05.07.2018 12:40

Что касается первого утверждения, это было основано исключительно на моей интуиции. Я еще не читал газет, но обязательно сделаю это. Спасибо, что сообщили мне об этом. Что касается вашего ответа на пункт 1.): это хорошее подробное описание того, как я подхожу к этому. Я просто не знаю, что вы имеете в виду под итерацией. Планируете ли вы копировать веса кодировщика после обучения с каждой партией или после окончания эпохи? Что касается пункта 2.): Я обновил свой ответ, поскольку вы указали желаемую операцию.

DocDriven 05.07.2018 13:09

Да, извините, под итерацией я просто имел в виду каждый прямой проход пакета. Текущий входной сигнал будет пропущен через кодер, а затем я умножу кодированный слой на транспозиции весовых матриц кодировщика (имитируя декодер), чтобы иметь возможность вычислить потери, а затем соответствующим образом скорректировать веса кодера перед обработкой следующего партия. У меня он работает, но, похоже, он не работает без предвзятости, и теперь я не думаю, что вообще возможно добиться такого «зеркального отображения» кодировщика на декодер, когда присутствуют смещения.

KOB 05.07.2018 14:31

Например, если весовые коэффициенты первого уровня кодера были матрицей 784x400, то смещение здесь было бы списком из 400 весовых значений. Однако в декодере последний уровень будет иметь веса 400x784, и поэтому это окончательное смещение должно быть размером 784, чего нет в кодере.

KOB 05.07.2018 14:31

Другие вопросы по теме