"New Neural" es un proyecto de motor de red neuronal de código abierto para la plataforma MetaTrader 5. - página 16

 

No tengo forma de entender la esencia del proyecto. Por ejemplo, ¿qué es un motor de red neuronal? ¿Y por qué tiene que ser igual para los distintos tipos de redes? Algunas redes se "mueven" efectivamente de una manera, otras de otra. La descripción de la estructura de las redes también puede ser diferente en consecuencia. Un ejemplo sencillo es la resolución de ecuaciones lineales. Por supuesto, es posible resolver todos los tipos de sistemas lineales con un solo método: el de Gauss. Pero si conocemos la estructura de la matriz de coeficientes, hay métodos más eficientes de solución. Lo mismo ocurre con el problema del entrenamiento de las redes. Las redes de propagación hacia delante se entrenan por el método de propagación de errores hacia atrás, las redes de eco se entrenan por MNC, etc. ¿Por qué en lugar de un motor, crear varios motores? ¿Por qué necesitamos un equipo de programadores que trabajen en lo mismo mientras intentan llegar a un consenso? La unanimidad en este caso impide la creatividad. Deje que los diferentes programadores escriban los códigos de las diferentes redes en forma de una biblioteca que pueda ser llamada desde los indicadores y asesores. En este caso, el proyecto no difiere del sistema existente de envío por parte de los programadores de sus códigos a la base de código de la biblioteca, acompañado del artículo con una descripción detallada de la red, su funcionamiento y ejemplos de su uso. No hay nada malo si varios programadores crean códigos de la misma red de forma independiente. Existen decenas de variantes para el entrenamiento de redes de propagación directa. Con este enfoque, en lugar de perder mucho tiempo discutiendo cómo describir correctamente una red, la gente ya empezaría a crear los códigos de estas redes. Me interesa mucho leer el artículo de TheXpert sobre las redes de eco, por ejemplo. Pero aparentemente no ocurrirá en mucho tiempo.

 
gpwr:

No puedo entender la esencia del proyecto. Por ejemplo, ¿qué es el motor de la red neuronal? ¿Y por qué debería ser igual para los distintos tipos de redes?

Queremos versatilidad. La tripa y el montaje serán, por supuesto, diferentes. La unificación es necesaria para una posible visualización y combinación en comisiones.

gpwr:

Por ejemplo, me interesa mucho leer el artículo de TheXpert sobre las redes de eco. Pero probablemente tardará mucho tiempo.

Bueno, puede leerlo como parte de un opsorce :) .

Representación de escalas:


 

Eso es todo :)

Presentación de la red:


 

Ejemplo de plantilla de capas:

class LayerFunctional
{
        typedef boost::shared_ptr<Synapse> SynapsePtr;
        typedef std::vector<SynapsePtr> SynapseVector;
        typedef SynapseVector::iterator SynapseIterator;

public:
        typedef boost::shared_ptr<Vector> VectorPtr;
        typedef boost::shared_ptr<IPatternCollection> PatternsPtr;

public:
        LayerFunctional
                (         bool bAdaptiveStep
                        , double step
                        , size_t newSize
                        , bool bTUsed
                );

        void Init(const Initializer& initializer);

        void AddInputSynapse(boost::shared_ptr<Synapse> pSynapse);
        void RemoveInputSynapse(boost::shared_ptr<Synapse> pSynapse);

        void AddOutputSynapse(boost::shared_ptr<Synapse> pSynapse);
        void RemoveOutputSynapse(boost::shared_ptr<Synapse> pSynapse);

        void FwdPropagate();
        void BackPropagate();

        void ClearInputs();
        void ClearErrors();

        const size_t Size() const;

        void SetSize(size_t newSize);

        const bool ThresholdsUsed() const;
        void SetThresholdsUsed(bool used = false);

        const bool AdaptiveStepUsed() const;
        void SetAdaptiveStepUsed(bool used = false);
        const double GetStep() const;

        const VectorPtr GetInputs() const;
        const VectorPtr GetOutputs() const;
        const Vector& GetErrors() const;
        const Vector& GetThresholds() const;

        const PatternsPtr GetInputCollection() const;
        const PatternsPtr GetOutputCollection() const;


        void SetInputCollection(PatternsPtr patterns);
        void SetOutputCollection(PatternsPtr patterns);

        void FeedInputs(size_t patternIndex);
        void CompareOutputs(size_t patternIndex);

        void DoF(Vector& data);
        void DodF(Vector& data);

        void Learn();

        double CountAlpha();

        template<class Archive>
        void save(Archive & ar, const unsigned int version) const
        {
        }

        template<class Archive>
        void load(Archive & ar, const unsigned int version)
        {
        }

private:
        bool m_bAdaptiveStep;

        double m_Step;

        size_t m_Size;
        bool m_bTAreUsed;

        Vector m_vT;
        Vector m_vErrors;
        VectorPtr m_pInputs;
        VectorPtr m_pOutputs;

        SynapseVector m_vInSynapses;
        SynapseVector m_vOutSynapses;

        PatternsPtr m_pInputCollection;
        PatternsPtr m_pOutputCollection;
};

Esta es una aproximación para la implementación de la MLP, la mayor parte de ella se ajusta a la interfaz universal.

m_vInSynapses

Un vector de las sinapsis que componen la capa. Estas sinapsis y la propia capa están vinculadas a través de un

m_pInputs

tampón común. Por lo tanto, un cambio en el buffer será inmediatamente visible tanto para el objeto de capa como para las sinapsis.

Las sinapsis de salida también están vinculadas de la misma manera a través del buffer de salida.

 

Sinapsis:

class Synapse
{
        Synapse()
        {
        }

public:
        typedef boost::shared_ptr<Vector> VectorPtr;

public:
        Synapse(boost::shared_ptr<Vector> inputVector, boost::shared_ptr<Vector> outputVector);
        
        void AssignInput(boost::shared_ptr<Vector> inputVector);
        void AssignOutput(boost::shared_ptr<Vector> outputVector);

        void FwdPropagate();
        void BackPropagate(LayerFunctional* outLayer);

        double operator()(size_t inIdx, size_t outIdx) const;

        const Detail::Slice FromInput(size_t inIdx) const;
        const Detail::Slice ToOutput(size_t outIdx) const;

        size_t GetOutSize() const;
        size_t GetInSize() const;

        const Vector& GetErrors() const;
        void ZeroErrors();

        void Init(const Initializer& initializer);
        void Learn(LayerFunctional* outLayer, const double& step);

        const VectorPtr GetInputs() const;
        const VectorPtr GetOutputs() const;

        void SetValues(const Synapse& other);

private:
        size_t m_InSize;
        size_t m_OutSize;

        Matrix m_vSynapses;
        Vector m_vErrors;

        VectorPtr m_pInBuffer;
        VectorPtr m_pOutBuffer;
};

También hay errores en las sinapsis.

Los errores de las neuronas son para aprender los umbrales, los errores de las sinapsis son para aprender las sinapsis.

Y la matriz real de pesos (lo que falta aquí es una buena matriz de disponibilidad de pesos, que se puede establecer manualmente) y los buffers para la comunicación con las capas.

 

La red:

class Net
{
        typedef boost::shared_ptr<LayerFunctional> LayerPtr;
        typedef boost::shared_ptr<Synapse> SynapsePtr;
        
        typedef std::vector<LayerPtr> LayersVector;
        typedef std::vector<SynapsePtr> SynapsesVector;

public:
        Net();

        void AddLayer(size_t size, bool bTUsed)
        void AddLayer(const LayerPtr& pLayer);

        LayerPtr GetLayer(size_t index) const;
        SynapsePtr GetSynapse(size_t index) const;

        void ConnectLayers(LayerPtr& inLayer, LayerPtr& outLayer);
        size_t GetLayersCount() const;

        size_t GetSynapsesCount() const;

        void Init(const Initializer& initializer);

        void FeedInputs(size_t patternIndex);
        void FwdPropagate();
        void BackPropagate();
        void CountErrors(size_t patternIndex);
        void Learn();

        size_t GetLayerID(const LayerPtr& pLayer) const;

        void save(Archive & ar, const unsigned int version) const
        void load(Archive & ar, const unsigned int version)

private:
        struct Link;

        typedef std::vector<Link> LinksVector;

private:
        size_t m_LayersCount;
        size_t m_SynapsesCount;

        LayersVector m_vLayers;
        SynapsesVector m_vSynapses;
        LinksVector m_vLinks;
};

Este es el aspecto aproximado de la red.

 

Construir y utilizar en la prueba más simple:

void XORTest()
{
        Net net;

        LayerPtr inLayer(new Layer<Functions::LinearFunction>(false, 0.2, 2, false));
        LayerPtr hiddenLayer(new Layer<Functions::BiSigmoidFunction>(false, 0.2, 3, false));
        LayerPtr outLayer(new Layer<Functions::LinearFunction>(false, 0.2, 1, false));

        net.AddLayer(inLayer);
        net.AddLayer(hiddenLayer);
        net.AddLayer(outLayer);

        net.ConnectLayers(inLayer, hiddenLayer);
        net.ConnectLayers(hiddenLayer, outLayer);

        PatternsPtr inPattern(new PatternCollection<>(2));
        // filling patterns

        PatternsPtr outPattern(new PatternCollection<>(1));
        // filling patterns

        inLayer->SetInputCollection(inPattern);
        outLayer->SetOutputCollection(outPattern);

        Initializer initer(0.1);
        net.Init(initer);

        size_t count = 0;
        double Es = 0.0;

        do 
        {
                Es = 0.0;
                for (size_t i = 0; i < 4; ++i)
                {
                        net.FeedInputs(i);
                        net.FwdPropagate();
                        net.CountErrors(i);
                        net.BackPropagate();
                        net.Learn();

                        Vector v(outLayer->Size());
                        v = outLayer->GetErrors();
                        v *= v;

                        Es += v.sum()/2.0;
                }

                ++count;
        } while(Es > 0.0001 && count < 10000);
}

Además, se pueden hacer plantillas para configuraciones típicas.

 
TheXpert:

Eso no funcionará :) hay que saber al menos qué tomar, qué enseñar y cómo evaluar. Y estas son las cosas que tienes que organizar con tus manos.

Exacto. Y no lo sé. No sólo eso, hay conjuntos que son muy difíciles de combinar en absoluto. Las neuronas son sólo una herramienta. En manos hábiles (por ejemplo, Leonid) es muy potente.

Me pregunto si estaría dispuesto a aconsejarte.

Al final, hay que evitar el riesgo de crear un producto que satisfaga plenamente sus necesidades en términos de funcionalidad, pero que sea completamente inutilizable para el 99% de los usuarios potenciales.

Si tenemos que ofrecer una nueva herramienta de negociación al mercado, debe estar dirigida a todo el mundo, incluidos los que acaban de abrir el terminal, los que llevan años utilizando el volante, los que tienen dos títulos superiores y los que tienen un ordenador superior.

La interfaz y el producto en sí deben ser tan sencillos y comprensibles como un juego de Lego.

 
Mischek:

Si la tarea es proporcionar una nueva herramienta al público, lo ideal es que se dirija a todos, bueno, a casi todos, incluyendo a los que abrieron el terminal por primera vez y a los que estuvieron enganchados durante años, y a los que tienen dos carreras universitarias y a los que tienen un Tspsh.

Creo que es deseable que haya alguien competente, pero no un programador.
 
papaklass:
Realice una encuesta entre los comerciantes. ¿Qué tareas comerciales resuelven? Consigue lo que la mayoría de la gente necesita.
¿Es demasiado problema que los propios comerciantes suban y escriban algo aquí?