c++ तंत्रिका नेटवर्क सीख नहीं रहा-एमएनआईएसटी डेटा-हस्तलेख मान्यता



image-processing machine-learning (1)

मैंने एक तंत्रिका नेटवर्क कार्यक्रम लिखा है। यह लॉजिक गेट्स के लिए काम करता है, लेकिन जब मैं हस्तलिखित अंकों को पहचानने के लिए इसका उपयोग करने की कोशिश करता हूं - यह बस नहीं सीखता है।

कृपया नीचे दिया गया कोड पाएं:

// यह एक एकल न्यूरॉन है; शेष कोड को समझने के लिए यह आवश्यक हो सकता है

typedef struct SingleNeuron
{
    double                  outputValue;
    std::vector<double>     weight;
    std::vector<double>     deltaWeight;
    double                  gradient;
    double                  sum;
}SingleNeuron;

फिर मैं नेट शुरू करता हूं। मैंने भार को -0.5 से +0.5 के बीच यादृच्छिक मान के रूप में सेट किया है, 0 से 0, डेल्टा वेइट 0 तक

फिर FeedForward आता है:

for (unsigned i = 0; i < inputValues.size(); ++i)
{
    neuralNet[0][i].outputValue = inputValues[i];
    neuralNet[0][i].sum = 0.0;
    //  std::cout << "o/p Val = " << neuralNet[0][i].outputValue << std::endl;
}

for (unsigned i = 1; i < neuralNet.size(); ++i)
{
    std::vector<SingleNeuron> prevLayerNeurons = neuralNet[i - 1];
    unsigned j = 0;
    double thisNeuronOPVal = 0;
    //  std::cout << std::endl;
    for (j = 0; j < neuralNet[i].size() - 1; ++j)
    {
        double sum = 0;
        for (unsigned k = 0; k < prevLayerNeurons.size(); ++k)
        {
            sum += prevLayerNeurons[k].outputValue * prevLayerNeurons[k].weight[j];
        }
        neuralNet[i][j].sum = sum;
        neuralNet[i][j].outputValue = TransferFunction(sum);
        //      std::cout << neuralNet[i][j].outputValue << "\t";
    }
    //      std::cout << std::endl;
}

अंत में मेरा स्थानांतरण समारोह और इसके व्युत्पन्न का उल्लेख किया गया है।

इसके बाद मैं इसका उपयोग करके पीछे हटने की कोशिश करता हूं:

// calculate output layer gradients
for (unsigned i = 0; i < outputLayer.size() - 1; ++i)
{
    double delta = actualOutput[i] - outputLayer[i].outputValue;
    outputLayer[i].gradient = delta * TransferFunctionDerivative(outputLayer[i].sum);
}
//  std::cout << "Found Output gradients "<< std::endl;
// calculate hidden layer gradients
for (unsigned i = neuralNet.size() - 2; i > 0; --i)
{
    std::vector<SingleNeuron>& hiddenLayer = neuralNet[i];
    std::vector<SingleNeuron>& nextLayer = neuralNet[i + 1];

    for (unsigned j = 0; j < hiddenLayer.size(); ++j)
    {
        double dow = 0.0;
        for (unsigned k = 0; k < nextLayer.size() - 1; ++k)
        {
            dow += nextLayer[k].gradient * hiddenLayer[j].weight[k];
        }
        hiddenLayer[j].gradient = dow * TransferFunctionDerivative(hiddenLayer[j].sum);
    }
}
//  std::cout << "Found hidden layer gradients "<< std::endl;

// from output to 1st hidden layer, update all weights
for (unsigned i = neuralNet.size() - 1; i > 0; --i)
{
    std::vector <SingleNeuron>& currentLayer = neuralNet[i];
    std::vector <SingleNeuron>& prevLayer = neuralNet[i - 1];

    for (unsigned j = 0; j < currentLayer.size() - 1; ++j)
    {
        for (unsigned k = 0; k < prevLayer.size(); ++k)
        {
            SingleNeuron& thisNeueon = prevLayer[k];
            double oldDeltaWeight = thisNeueon.deltaWeight[j];
            double newDeltaWeight = ETA * thisNeueon.outputValue * currentLayer[j].gradient + (ALPHA * oldDeltaWeight);
            thisNeueon.deltaWeight[j] = newDeltaWeight;
            thisNeueon.weight[j] += newDeltaWeight;
        }
    }
}

ये ट्रांसफरफनशन और इसके व्युत्पन्न हैं;

double TransferFunction(double x)
{
    double val;
    //val = tanh(x);
    val = 1 / (1 + exp(x * -1));
    return val;
}

double TransferFunctionDerivative(double x)
{
    //return 1 - x * x;
    double val = exp(x * -1) / pow((exp(x * -1) + 1), 2);
    return val;
}

एक बात मैंने देखी है यदि मैं मानक हस्तांतरण समारोह के लिए मानक सिग्मोइड फ़ंक्शन का उपयोग करता हूं और यदि मैं फ़ंक्शन स्थानांतरित करने के लिए न्यूरॉन का आउटपुट पास करता हूं - परिणाम इन्फिनिटी है। लेकिन tanh (x) इस मान के साथ ठीक काम करता है

इसलिए यदि मैं ट्रांसफर फ़ंक्शन के रूप में 1/1 + ई ^ (- x) का उपयोग कर रहा हूं तो मुझे Sum of Net Inputs पास करना होगा और tanh को मेरे ट्रांसफर फ़ंक्शन के साथ पास करना होगा, मुझे वर्तमान न्यूरॉन का output पास करना होगा।

मैं पूरी तरह समझ नहीं पा रहा हूं कि यह वही तरीका क्यों है, यह एक अलग सवाल के लिए कह सकता है।

लेकिन यह सवाल वास्तव में कुछ और है: नेटवर्क लॉजिक गेट्स के लिए काम कर रहा है लेकिन चरित्र पहचान के लिए नहीं

मैंने Learning Rate और Acceleration और # hidden layers और their sizes कई बदलाव / संयोजनों की कोशिश की है। कृपया नीचे दिए गए परिणाम पाएं:

AvgErr: 0.299399          #Pass799
AvgErr : 0.305071         #Pass809
AvgErr : 0.303046         #Pass819
AvgErr : 0.299569         #Pass829
AvgErr : 0.30413          #Pass839
AvgErr : 0.304165         #Pass849
AvgErr : 0.300529         #Pass859
AvgErr : 0.302973         #Pass869
AvgErr : 0.299238         #Pass879
AvgErr : 0.304708         #Pass889
AvgErr : 0.30068          #Pass899
AvgErr : 0.302582         #Pass909
AvgErr : 0.301767         #Pass919
AvgErr : 0.303167         #Pass929
AvgErr : 0.299551         #Pass939
AvgErr : 0.301295         #Pass949
AvgErr : 0.300651         #Pass959
AvgErr : 0.297867         #Pass969
AvgErr : 0.304221         #Pass979
AvgErr : 0.303702         #Pass989

परिणामों को देखने के बाद आपको लगता है कि यह आदमी बस स्थानीय मिनीमा में फंस गया है, लेकिन कृपया प्रतीक्षा करें और पढ़ें:

Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]          
Output = 0.0910903, 0.105674, 0.064575, 0.0864824, 0.128682, 0.0878434, 0.0946296, 0.154405, 0.0678767, 0.0666924

Input = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Output = 0.0916106, 0.105958, 0.0655508, 0.086579, 0.126461, 0.0884082, 0.110953, 0.163343, 0.0689315, 0.0675822

Input = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]          
Output = 0.105344, 0.105021, 0.0659517, 0.0858077, 0.123104, 0.0884107, 0.116917, 0.161911, 0.0693426, 0.0675156

Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]          
Output = , 0.107113, 0.101838, 0.0641632, 0.0967766, 0.117149, 0.085271, 0.11469, 0.153649, 0.0672772, 0.0652416

उपरोक्त # 996, # 997, # 998 और # 999 का उत्पादन ऊपर है

तो बस नेटवर्क सीख नहीं रहा है। इस के लिए मैंने ALPHA = 0.4, ETA = 0.7, 100 न्यूरॉन्स में से प्रत्येक छिपी हुई परतों का उपयोग किया है और औसत 10 युग से अधिक है। यदि आप सीखने की दर 0.4 या इतनी छुपी परतों के बारे में चिंतित हैं, तो मैंने पहले से ही अपनी विविधताओं का प्रयास किया है। उदाहरण के लिए सीखने की दर 0.1 और 4 छिपी हुई परतों के लिए - 16 में से प्रत्येक

Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]          
Output = 0.0883238, 0.0983253, 0.0613749, 0.0809751, 0.124972, 0.0897194, 0.0911235, 0.179984, 0.0681346, 0.0660039

Input = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]          
Output = 0.0868767, 0.0966924, 0.0612488, 0.0798343, 0.120353, 0.0882381, 0.111925, 0.169309, 0.0676711, 0.0656819

Input = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]          
Output = 0.105252, 0.0943837, 0.0604416, 0.0781779, 0.116231, 0.0858496, 0.108437, 0.1588, 0.0663156, 0.0645477

Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]          
Output = 0.102023, 0.0914957, 0.059178, 0.09339, 0.111851, 0.0842454, 0.104834, 0.149892, 0.0651799, 0.063558

मुझे इतना यकीन है कि मुझे कुछ याद आया है। मैं इसे समझने में सक्षम नहीं हूं। मैंने टॉम मिशेल के एल्गोरिदम को कई बार पढ़ा है, लेकिन मुझे नहीं पता कि क्या गलत है। मैं जो भी उदाहरण हाथ से हल करता हूं - काम करता है! (कृपया मुझे हाथ से एमएनआईएसटी डेटा छवियों को हल करने के लिए मत कहें;)) मुझे नहीं पता कि कोड कहां बदलना है, क्या करना है .. कृपया मदद करें ..

संपादित करें - टिप्पणियों में सुझावों के अनुसार अधिक डेटा अपलोड करना

32 की 1 छिपी हुई परत - अभी भी कोई सीख नहीं है।

अपेक्षित आउटपुट - इनपुट 0-9 के बीच छवियां है, इसलिए एक साधारण वेक्टर जो वर्तमान छवि है, का वर्णन करता है, वह बिट 1 अन्य सभी 0 है। तो मैं चाहता हूं कि आउटपुट उस विशेष बिट के लिए 1 के करीब हो और अन्य बंद हो जाएं 0 के लिए उदाहरण के लिए यदि इनपुट Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0] मैं Output = 0.002023, 0.0914957, 0.059178, 0.09339, 0.011851, 0.0842454, 0.924834, 0.049892, 0.0651799, 0.063558 जैसे कुछ होना चाहता Output = 0.002023, 0.0914957, 0.059178, 0.09339, 0.011851, 0.0842454, 0.924834, 0.049892, 0.0651799, 0.063558 (यह अस्पष्ट, हाथ से उत्पन्न) है

यहां अन्य शोधकर्ता के काम के लिंक दिए गए हैं।

Stanford

SourceForge - यह एक पुस्तकालय है

न केवल इन 2, डेमो दिखाने वाली कई साइटें हैं।

चीजें उनके लिए काफी ठीक काम कर रही हैं। अगर मैं उनके जैसे नेटवर्क पैरामीटर (अल्फा, ईटीए) सेट करता हूं तो मुझे उनके जैसे परिणाम नहीं मिल रहे हैं, इसलिए यह आश्वस्त है कि मेरे कोड में कुछ गड़बड़ है।

संपादित करें 2

अधिक विफलता मामलों को जोड़ना

Accelaration - 0.7, सीखने की दर 0.1

त्वरण - 0.7, सीखने की दर 0.6

उपरोक्त दोनों मामलों में छिपी परतें 3 थीं, 32 न्यूरॉन्स में से प्रत्येक।


इस उत्तर को प्रश्न पर ओपी की टिप्पणी से कॉपी किया गया है।

मैंने पहेली हल की। मैंने सबसे खराब गलती की थी। मैं गलत इनपुट दे रहा था। मैंने reshape का उपयोग करने के बजाय छवियों को स्कैन करने के लिए ओपनसीवी का उपयोग किया है, मैं resize रहा था और इसलिए इनपुट छवियों के रैखिक इंटरपोलेशन था। तो मेरा इनपुट गलत था। कोड के साथ कुछ भी गलत नहीं था। मेरा नेटवर्क 784 - 65 - 10 96.43% सटीकता देता है।





gradient