O "New Neural" é um projecto de motor de rede neural Open Source para a plataforma MetaTrader 5. - página 16

 

Não tenho como entender a essência do projeto. Por exemplo, o que é um motor de rede neural? E por que tem de ser o mesmo para diferentes tipos de redes? Algumas redes efetivamente "se movem" de uma forma, outras de outra. A descrição da estrutura das redes também pode ser diferente em conformidade. Para um exemplo simples, veja a resolução de equações lineares. É claro que é possível resolver todos os tipos de sistemas lineares através de um único método - Gauss. Mas se conhecemos a estrutura da matriz de coeficientes, existem métodos mais eficientes de solução. O mesmo é o problema das redes de formação. As redes de propagação para a frente são treinadas pelo método de propagação de erros para trás, as redes echo são treinadas pelo MNC, etc. Porquê, em vez de um motor, criar vários motores? Por que precisamos de uma equipe de programadores trabalhando na mesma coisa enquanto tentamos chegar a um consenso? A unanimidade, neste caso, impede a criatividade. Deixe diferentes programadores escreverem os códigos de diferentes redes sob a forma de uma biblioteca que pode ser chamada a partir dos indicadores e conselheiros. Neste caso, o projeto não é diferente do sistema existente de enviar pelos programadores seus códigos para a base de códigos da biblioteca, acompanhado do artigo com uma descrição detalhada da rede, como ela funciona e exemplos de seu uso. Não há nada de errado se vários programadores criarem códigos da mesma rede independentemente. Existem dezenas de variantes para o treinamento de redes de propagação direta. Com esta abordagem, em vez de perder muito tempo discutindo como descrever corretamente uma rede, as pessoas já começariam a criar os códigos destas redes. Estou muito interessado em ler o artigo de TheXpert sobre redes echo, por exemplo. Mas aparentemente isso não vai acontecer por muito tempo.

 
gpwr:

Não consigo entender a essência do projeto. Por exemplo, o que é o motor da rede neural? E por que deveria ser o mesmo para diferentes tipos de redes?

Nós queremos versatilidade. O instinto e a montagem serão, naturalmente, diferentes. A unificação é necessária para uma possível visualização e combinação em comités.

gpwr:

Por exemplo, estou muito interessado em ler o artigo de TheXpert sobre redes echo. Mas provavelmente vai demorar muito tempo.

Bem, você pode lê-lo como parte de uma opsorga :) .

Representação de balanças:


 

Isso é tudo :)

Apresentando a rede:


 

Modelo de camada deamostra:

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 é uma aproximação para a implementação do MLP, a maior parte cabe na interface universal.

m_vInSynapses

Um vector das sinapses que compõem a camada. Estas sinapses e a própria camada estão ligadas através de um

m_pInputs

amortecedor comum. Portanto, uma alteração no buffer será imediatamente visível tanto para o objeto da camada quanto para as sinapses.

As sinapses de saída também estão ligadas da mesma forma através do buffer de saída.

 

Sinapses:

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

Os erros nas sinapses também existem.

Erros de neurônios são para limiares de aprendizagem, erros de sinapses são para sinapses de aprendizagem.

E a matriz real de pesos (o que falta aqui é uma boa matriz de disponibilidade de pesos, que pode ser definida manualmente) e amortecedores para a comunicação com as camadas.

 

A rede:

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

Isto é mais ou menos como a rede se parece.

 

Construir e usar no teste mais simples:

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

Plus podem ser feitos modelos para configurações típicas.

 
TheXpert:

Isso não vai funcionar :) você tem que saber ao menos o que tomar, o que ensinar e como avaliar. E estas são as coisas que tens de organizar com as tuas mãos.

Exacto. E eu não sei. Não só isso, há conjuntos que são muito difíceis de combinar. Os neurónios são apenas uma ferramenta. Em mãos habilidosas (veja Leonid, por exemplo) é muito poderoso.

Será que ele estaria disposto a dar-lhe conselhos?

No final, você deve evitar o risco de criar um produto que atenda plenamente às suas necessidades em termos de funcionalidade, mas que seja completamente inutilizável para 99% dos usuários em potencial.

Se temos que oferecer uma nova ferramenta de negociação ao mercado, ela deve ser dirigida a todos, incluindo aqueles que acabam de abrir o terminal, aqueles que usam o volante há anos, aqueles que têm dois graus superiores e aqueles que têm um computador superior.

A interface e o próprio produto devem ser tão simples e compreensíveis como um conjunto Lego.

 
Mischek:

Se a tarefa é fornecer uma nova ferramenta ao público, o ideal seria que ela fosse dirigida a todos, bem, a quase todos, incluindo aqueles que abriram o terminal pela primeira vez e aqueles que ficaram viciados durante anos, e aqueles que têm dois diplomas universitários e aqueles que têm um Tspsh.

Penso que é desejável ter alguém competente, mas não um programador.
 
Papaklass:
Realizar uma pesquisa entre os comerciantes. Que tarefas de negociação eles resolvem? Conseguir o que a maioria das pessoas precisa.
É muito difícil para os próprios comerciantes virem aqui e escreverem algo?