"New Neural" est un projet de moteur de réseau neuronal Open Source pour la plateforme MetaTrader 5. - page 16

 

Je n'ai aucun moyen de comprendre l'essence du projet. Par exemple, qu'est-ce qu'un moteur de réseau neuronal ? Et pourquoi faut-il que ce soit le même pour les différents types de réseaux ? Certains réseaux "bougent" effectivement d'une certaine manière, d'autres d'une autre. La description de la structure des réseaux peut également être différente en conséquence. Pour un exemple simple, prenons la résolution d'équations linéaires. Il est bien sûr possible de résoudre tous les types de systèmes linéaires par une seule méthode - Gauss. Mais si nous connaissons la structure de la matrice des coefficients, il existe des méthodes de résolution plus efficaces. Le même problème se pose pour la formation des réseaux. Les réseaux à propagation directe sont formés par la méthode de propagation d'erreur inverse, les réseaux d'écho sont formés par MNC, etc. Pourquoi, au lieu d'un moteur, en créer plusieurs ? Pourquoi avons-nous besoin d'une équipe de programmeurs travaillant sur la même chose tout en essayant de parvenir à un consensus ? Dans ce cas, l'unanimité empêche la créativité. Laissez différents programmeurs écrire les codes des différents réseaux sous la forme d'une bibliothèque qui peut être appelée à partir des indicateurs et des conseillers. Dans ce cas, le projet n'est pas différent du système existant d'envoi par les programmeurs de leurs codes à la base de code de la bibliothèque, accompagné de l'article avec une description détaillée du réseau, de son fonctionnement et des exemples de son utilisation. Il n'y a rien de mal à ce que plusieurs programmeurs créent indépendamment les codes d'un même réseau. Il existe des dizaines de variantes pour la formation des réseaux à propagation directe. Avec cette approche, au lieu de perdre beaucoup de temps à discuter de la manière de décrire correctement un réseau, les gens commenceraient déjà à créer les codes de ces réseaux. Je suis très intéressé de lire l'article de TheXpert sur les réseaux d'écho, par exemple. Mais apparemment, cela n'arrivera pas avant longtemps.

 
gpwr:

Je n'arrive pas à comprendre l'essence du projet. Par exemple, qu'est-ce que le moteur de réseau neuronal ? Et pourquoi devrait-il être le même pour les différents types de réseaux ?

Nous voulons de la polyvalence. Le boyau et l'assemblage seront bien sûr différents. L'unification est nécessaire pour permettre une visualisation et un regroupement en comités.

gpwr:

Par exemple, je suis très intéressé de lire l'article de TheXpert sur les réseaux d'écho. Mais cela prendra probablement beaucoup de temps.

Vous pouvez peut-être le lire dans le cadre d'une opsorce :) .

Représentation des échelles :


 

C'est tout :)

Présentation du réseau :


 

Modèle de calque :

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;
};

Il s'agit d'une approximation pour la mise en œuvre de MLP, la plupart d'entre eux correspondent à l'interface universelle.

m_vInSynapses

Un vecteur des synapses qui composent la couche. Ces synapses et la couche elle-même sont reliées par une

m_pInputs

tampon commun. Par conséquent, un changement dans le tampon sera immédiatement visible à la fois pour l'objet couche et les synapses.

Les synapses de sortie sont également liées de la même manière via le tampon de sortie.

 

Les synapses :

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;
};

Les synapses ont aussi des erreurs.

Les erreurs des neurones servent à apprendre les seuils, les erreurs des synapses servent à apprendre les synapses.

Et la matrice réelle des poids (ce qui manque ici est une bonne disponibilité de la matrice des poids, qui peut être définie manuellement) et les tampons pour la communication avec les couches.

 

Le filet :

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;
};

Voici à peu près à quoi ressemble le réseau.

 

Construire et utiliser dans le test le plus 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);
}

De plus, des modèles peuvent être réalisés pour des configurations typiques.

 
LeXpert:

Cela ne marchera pas :) vous devez savoir au moins ce qu'il faut prendre, ce qu'il faut enseigner et comment évaluer. Et ce sont les choses que vous devez organiser avec vos mains.

Exactement. Et je ne sais pas. De plus, il y a des ensembles qui sont très difficiles à combiner. Les neurones ne sont qu'un outil. Dans des mains habiles (prenez Leonid par exemple), il est très puissant.

Je me demande s'il serait prêt à vous donner des conseils.

Au final, vous devez éviter le risque de créer un produit qui répondra parfaitement à vos besoins en termes de fonctionnalités, mais qui sera totalement inutilisable pour 99 % des utilisateurs potentiels.

Si nous devons proposer un nouvel outil de trading au marché, il doit s'adresser à tout le monde, y compris ceux qui viennent d'ouvrir le terminal, ceux qui utilisent la manivelle depuis des années, ceux qui ont deux diplômes supérieurs et ceux qui ont un ordinateur supérieur.

L'interface et le produit lui-même doivent être aussi simples et compréhensibles qu'un jeu de Lego.

 
Mischek:

Si la tâche consiste à fournir un nouvel outil au public, il devrait idéalement s'adresser à tout le monde, enfin, presque tout le monde, y compris ceux qui ont ouvert le terminal pour la première fois et ceux qui sont accrochés depuis des années, et ceux qui ont deux diplômes universitaires et ceux qui ont un Tspsh.

Je pense qu'il est souhaitable d'avoir quelqu'un de compétent, mais pas un programmeur.
 
papaklass:
Réaliser une enquête auprès des commerçants. Quelles tâches commerciales résolvent-ils ? Obtenez ce dont la plupart des gens ont besoin.
Est-il trop difficile pour les commerçants eux-mêmes de venir et d'écrire quelque chose ici ?