Я пытаюсь создать и обучить автоэнкодер LSTM последовательностям символов (строкам). Это сделано просто для уменьшения размерности, т. е. для того, чтобы иметь возможность представлять строки до T = 1000 символов в виде векторов фиксированной длины размера N. Ради этого примера пусть N = 10. Каждый символ закодирован горячим способом массивы размера validChars (в моем случае validChars = 77).
Я использую ComputationalGraph, чтобы позже удалить слои декодера и использовать оставшиеся для кодирования. Глядя на dl4j-примеры, я пришел к следующему:
ComputationGraphConfiguration conf = new NeuralNetConfiguration.Builder()
.seed(12345)
.l2(0.0001)
.weightInit(WeightInit.XAVIER)
.updater(new Adam(0.005))
.graphBuilder()
.addInputs("input")
.addLayer("encoder1", new LSTM.Builder().nIn(dictSize).nOut(250)
.activation(Activation.TANH).build(), "input")
.addLayer("encoder2", new LSTM.Builder().nIn(250).nOut(10)
.activation(Activation.TANH).build(), "encoder1")
.addVertex("fixed", new PreprocessorVertex(new RnnToFeedForwardPreProcessor()), "encoder2")
.addVertex("sequenced", new PreprocessorVertex(new FeedForwardToRnnPreProcessor()), "fixed")
.addLayer("decoder1", new LSTM.Builder().nIn(10).nOut(250)
.activation(Activation.TANH).build(), "sequenced")
.addLayer("decoder2", new LSTM.Builder().nIn(250).nOut(dictSize)
.activation(Activation.TANH).build(), "decoder1")
.addLayer("output", new RnnOutputLayer.Builder()
.lossFunction(LossFunctions.LossFunction.MCXENT)
.activation(Activation.SOFTMAX).nIn(dictSize).nOut(dictSize).build(), "decoder2")
.setOutputs("output")
.backpropType(BackpropType.TruncatedBPTT).tBPTTForwardLength(tbpttLength).tBPTTBackwardLength(tbpttLength)
.build();
При этом я ожидал, что количество признаков будет следовать по пути: [77,T] -> [250,T] -> [10,T] -> [10] -> [10,T] -> [250, Т] -> [77, Т]
Я обучил эту сеть и удалил часть декодера следующим образом:
ComputationGraph encoder = new TransferLearning.GraphBuilder(net)
.setFeatureExtractor("fixed")
.removeVertexAndConnections("sequenced")
.removeVertexAndConnections("decoder1")
.removeVertexAndConnections("decoder2")
.removeVertexAndConnections("output")
.addLayer("output", new ActivationLayer.Builder().activation(Activation.IDENTITY).build(), "fixed")
.setOutputs("output")
.setInputs("input")
.build();
Но когда я кодирую строку длиной 1000 с помощью этого кодировщика, он выводит NDArray формы [1000, 10] вместо одномерного вектора длины 10. Моя цель — представить всю последовательность из 1000 символов одним вектором длина 10. Что мне не хватает?