【问题标题】:encoder/decoder ripping from autoencoder in encog编码器/解码器从编码器中的自动编码器翻录
【发布时间】:2023-08-16 10:40:01
【问题描述】:

我已经在 Encog 中创建并学习了自动编码器,并尝试将其拆分为几部分:编码器和解码器部分。不幸的是,我无法得到它,并且我不断收到奇怪的不正确数据(比较将一次网络应用于数据和两次数据的结果 -> enc -> dec)。

我尝试使用简单的 GetWeight 和 SetWeight 来实现,但结果不正确。在 encog 文档中找到的解决方案 - 初始化平面网络对我来说不清楚(我无法让它工作)。

        public static BasicNetwork getEncoder(BasicNetwork net)
        {
            var enc = new BasicNetwork();
            enc.AddLayer(new BasicLayer(null, true, net.GetLayerNeuronCount(0)));
            enc.AddLayer(new BasicLayer(new ActivationSigmoid(), true, net.GetLayerNeuronCount(1)));
            enc.AddLayer(new BasicLayer(new ActivationSigmoid(), false, net.GetLayerNeuronCount(2)));
            enc.Structure.FinalizeStructure ();

            var weights1 = net.Structure.Flat.Weights;
            var weights2 = enc.Structure.Flat.Weights;
            var idx1 = net.Structure.Flat.WeightIndex;
            var idx2 = enc.Structure.Flat.WeightIndex;

            for(var i = 0; i < 1; i++)
            {
                int n = net.GetLayerNeuronCount(i);
                int m = net.GetLayerNeuronCount(i + 1);

                Console.WriteLine("Decoder: {0} - {1}", n, m);

                for(var j = 0; j < n; j++)
                {
                    for(var k = 0; k < m; k++)
                    {
                        weights1 [idx1[i] + j * m + k] = weights2 [idx2[i] + j * m * k];
                    }
                }
            }


            return enc;
        }

AutoEncoder 的完整旧式(设置/获取权重)代码:

using System;
using Encog.Engine.Network.Activation;
using Encog.ML.Data;
using Encog.ML.Data.Basic;
using Encog.ML.Train;
using Encog.Neural.Networks;
using Encog.Neural.Networks.Layers;
using Encog.Neural.Networks.Training.Propagation.Resilient;

namespace engine
{
    public class AutoEncoder
    {
        private int k = 0;
        public IMLDataSet trainingSet
        {
            get;
            set;
        }

        public AutoEncoder(int k)
        {
            this.k = k;
        }

        public static BasicNetwork getDecoder(BasicNetwork net)
        {
            var dec = new BasicNetwork();
            dec.AddLayer(new BasicLayer(null, true, net.GetLayerNeuronCount(1)));
            dec.AddLayer(new BasicLayer(new ActivationSigmoid(), true, net.GetLayerNeuronCount(2)));

            dec.Structure.FinalizeStructure();

            for(var i = 1; i < 2; i++)
            {
                int n = net.GetLayerNeuronCount(i);
                int m = net.GetLayerNeuronCount(i + 1);

                Console.WriteLine("Decoder: {0} - {1}", n, m);

                for(var j = 0; j < n; j++)
                {
                    for(var k = 0; k < m; k++)
                    {
                        dec.SetWeight(i - 1, j, k, net.GetWeight(i, j, k));
                    }
                }
            }

            return dec;
        }

        public static BasicNetwork getEncoder(BasicNetwork net)
        {
            var enc = new BasicNetwork();
            enc.AddLayer(new BasicLayer(null, true, net.GetLayerNeuronCount(0)));
            enc.AddLayer(new BasicLayer(new ActivationSigmoid(), true, net.GetLayerNeuronCount(1)));

            enc.Structure.FinalizeStructure();

            for(var i = 0; i < 1; i++)
            {
                int n = net.GetLayerNeuronCount(i);
                int m = net.GetLayerNeuronCount(i + 1);

                Console.WriteLine("Encoder: {0} - {1}", n, m);

                for(var j = 0; j < n; j++)
                {
                    for(var k = 0; k < m; k++)
                    {
                        enc.SetWeight(i, j, k, net.GetWeight(i, j, k));
                    }
                }
            }

            return enc;
        }

        public BasicNetwork learn(double[][] data,
            double eps = 1e-6,
            long trainMaxIter = 10000)
        {
            int n = data.Length;
            int m = data[0].Length;
            double[][] output = new double[n][];
            for(var i = 0; i < n; i++)
            {
                output[i] = new double[m];
                data[i].CopyTo(output[i], 0);
            }

            var network = new BasicNetwork();
            network.AddLayer(new BasicLayer(null, true, m));
            network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, k));
            network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, m));
            network.Structure.FinalizeStructure();
            network.Reset();

            trainingSet = new BasicMLDataSet(data, output);
            IMLTrain train = new ResilientPropagation(network, trainingSet);

            int epoch = 1;
            do
            {
                train.Iteration();
                Console.WriteLine(@"Epoch #" + epoch + @" Error:" + train.Error);
                epoch++;
            } while(train.Error > eps && epoch < trainMaxIter);

            train.FinishTraining();

            return network;
        }
    }
}

我怎样才能正确地从自动编码器中只提取两个第一层用于编码器,然后从一个用于解码器的最后两个层?

【问题讨论】:

    标签: encog autoencoder


    【解决方案1】:

    如果您需要直接访问权重,最好的方法是使用 BasicNetwork.GetWeight()。这是一个示例,展示了如何使用 GetWeight 获取神经网络中的所有权重。它来自一个单元测试,以证明 GetWeight 确实有效,它使用 BasicNetwork.Compute 计算简单神经网络的输出,也可以通过对加权输入求和并应用 TanH 来手动计算。两者都产生相同的输出。

    如果你想直接访问权重数组,这里也有更多信息:http://www.heatonresearch.com/wiki/Weight

            var network = new BasicNetwork();
            network.AddLayer(new BasicLayer(null, true, 2));
            network.AddLayer(new BasicLayer(new ActivationTANH(), true, 2));
            network.AddLayer(new BasicLayer(new ActivationTANH(), false, 1));
            network.Structure.FinalizeStructure();
            network.Reset(100);
    
            BasicMLData input = new BasicMLData(2);
            input[0] = 0.1;
            input[1] = 0.2;
    
            Console.WriteLine("Using network: " + network.Compute(input));
    
            // now manually
            double sum1 = (input[0]*network.GetWeight(0, 0, 0))
                          + (input[1]*network.GetWeight(0, 1, 0))
                          + (1.0*network.GetWeight(0,2,0));
    
            double sum2 = (input[0]*network.GetWeight(0, 0, 1))
                          + (input[1]*network.GetWeight(0, 1, 1))
                          + (1.0*network.GetWeight(0,2,1));
    
            double hidden1 = Math.Tanh(sum1);
            double hidden2 = Math.Tanh(sum2);
    
            double sum3 = (hidden1 * network.GetWeight(1, 0, 0))
                          + (hidden2 * network.GetWeight(1, 1, 0))
                          + (1.0 * network.GetWeight(1, 2, 0));
    
            double output = Math.Tanh(sum3);
    
            Console.WriteLine("Using manual: " + network.Compute(input));
    

    【讨论】:

      最近更新 更多