खोज…


वास्तव में एक अवधारणात्मक क्या है?

एक अवधारणात्मक का विज़ुअलाइज़ेशन

इसके मूल में एक बोधि वर्गीकरण के लिए एक अवधारणात्मक मॉडल सबसे सरल पर्यवेक्षणीय शिक्षण एल्गोरिदम में से एक है । यह एक प्रकार का रैखिक क्लासिफायरियर है , अर्थात एक वर्गीकरण एल्गोरिथ्म जो अपनी भविष्यवाणियों को रेखीय भविष्यवक्ता फ़ंक्शन के आधार पर फीचर वेक्टर के साथ भार के एक समूह के संयोजन के आधार पर बनाता है। सोचने का एक अधिक सहज तरीका केवल एक न्यूरॉन के साथ एक न्यूरल नेटवर्क की तरह है।

जिस तरह से यह काम करता है वह बहुत सरल है। इसमें इनपुट वैल्यू x का वेक्टर मिलता है जिसमें से प्रत्येक तत्व हमारे डेटा सेट की एक विशेषता है।

एक उदाहरण:

यह कहें कि हम वर्गीकृत करना चाहते हैं कि कोई वस्तु साइकिल है या कार। इस उदाहरण के लिए मान लीजिए कि हम 2 सुविधाओं का चयन करना चाहते हैं। वस्तु की ऊँचाई और चौड़ाई। उस स्थिति में x = [X1, x2] जहां X1 की ऊंचाई है और x2 की चौड़ाई है।

फिर एक बार हमारे पास हमारे इनपुट वेक्टर x हम एक वजन के साथ कि वेक्टर में प्रत्येक तत्व गुणा करने के लिए चाहते हैं। आमतौर पर वजन का मूल्य जितना अधिक होता है उतना ही महत्वपूर्ण है कि यह सुविधा है। यदि उदाहरण के लिए हमने फीचर x3 के रूप में रंग का उपयोग किया है और एक लाल रंग की बाइक है और एक लाल रंग की कार है तो परसेप्ट्रॉन इसे बहुत कम वजन देगा ताकि रंग अंतिम भविष्यवाणी को प्रभावित न करे।

ठीक है, इसलिए हमने 2 वैक्टर x और w को गुणा किया है और हम एक वेक्टर वापस पा गए हैं। अब हमें इस वेक्टर के तत्वों को योग करने की आवश्यकता है। ऐसा करने का एक स्मार्ट तरीका है w के द्वारा साधारण गुणा x के बजाय हम x को wT से गुणा कर सकते हैं जहाँ T का स्थानान्तरण है। हम वेक्टर के एक घुमाए गए संस्करण के रूप में एक वेक्टर के हस्तांतरण की कल्पना कर सकते हैं। अधिक जानकारी के लिए आप विकिपीडिया पृष्ठ पढ़ सकते हैं। अनिवार्य रूप से वेक्टर w के संक्रमण को लेने से हमें 1xN के बजाय Nx1 वेक्टर मिलता है। इस प्रकार अगर अब हम अपने इनपुट वेक्टर को आकार 1xN के साथ इस Nx1 भार वेक्टर से गुणा करते हैं तो हमें 1x1 वेक्टर (या केवल एक मान) मिलेगा जो कि X1 * w1 + x2 * w2 + ... + xn / wn के बराबर होगा। ऐसा करने के बाद, अब हमारी भविष्यवाणी है। लेकिन एक आखिरी बात है। यह भविष्यवाणी शायद एक नया नमूना वर्गीकृत करने में सक्षम होने के लिए एक साधारण 1 या -1 नहीं होगी। तो हम जो कर सकते हैं वह केवल निम्नलिखित कहना है: यदि हमारी भविष्यवाणी 0 से बड़ी है तो हम कहते हैं कि नमूना कक्षा 1 से संबंधित है, अन्यथा यदि भविष्यवाणी शून्य से छोटी है, तो हम कहते हैं कि नमूना कक्षा -1 से संबंधित है। इसे स्टेप फंक्शन कहा जाता है।

लेकिन हमें सही वज़न कैसे मिलता है ताकि हम सही भविष्यवाणियाँ करें? दूसरे शब्दों में, हम अपने अवधारणात्मक मॉडल को कैसे प्रशिक्षित करते हैं?

वैसे अवधारणात्मक के मामले में हमें अपने मॉडल को प्रशिक्षित करने के लिए फैंसी गणित समीकरणों की आवश्यकता नहीं है। हमारे वजन को निम्नलिखित समीकरण द्वारा समायोजित किया जा सकता है:

Δw = एटा * (y - भविष्यवाणी) * x (i)

जहां x (i) हमारी विशेषता है (उदाहरण के लिए वजन 1 के लिए X1, w2 के लिए x2 और इसी तरह ...)।

यह भी देखा कि ईटीए नामक एक चर है जो सीखने की दर है। आप सीखने की दर की कल्पना कर सकते हैं कि हम कितना बड़ा बदलाव चाहते हैं। एक तेजी से सीखने के एल्गोरिथ्म में एक अच्छा सीखने की दर परिणाम है। ईटा का बहुत अधिक मूल्य प्रत्येक युग में त्रुटियों की बढ़ती मात्रा में परिणाम कर सकता है और मॉडल में वास्तव में खराब भविष्यवाणियां करता है और कभी नहीं बदलता है। सीखने की दर का बहुत कम होने के परिणामस्वरूप मॉडल को अभिसरण में बहुत अधिक समय लग सकता है। (आमतौर पर अवधारणात्मक मॉडल के लिए एटा को सेट करने का एक अच्छा मूल्य 0.1 है लेकिन यह केस से अलग हो सकता है)।

अंत में आप में से कुछ ने देखा होगा कि पहला इनपुट एक स्थिर (1) है और w0 से गुणा किया जाता है। तो वास्तव में क्या है? एक अच्छी भविष्यवाणी प्राप्त करने के लिए हमें पूर्वाग्रह जोड़ने की जरूरत है। और यही वास्तव में है।

पूर्वाग्रह शब्द के वजन को संशोधित करने के लिए हम उसी समीकरण का उपयोग करते हैं जैसा हमने दूसरे भार के लिए किया था, लेकिन इस मामले में हम इसे इनपुट से गुणा नहीं करते हैं (क्योंकि इनपुट एक स्थिर 1 है और इसलिए हमें इसकी आवश्यकता नहीं है):

Δw = एटा * (y - भविष्यवाणी)

तो यह मूल रूप से एक सरल अवधारणात्मक मॉडल कैसे काम करता है! एक बार जब हम अपने वजन को प्रशिक्षित करते हैं तो हम इसे नया डेटा दे सकते हैं और हमारी भविष्यवाणियां कर सकते हैं।

ध्यान दें:

परसेप्ट्रॉन मॉडल का एक महत्वपूर्ण नुकसान है! यदि डेटा रेखीय रूप से वियोज्य नहीं है , तो इसका अर्थ यह नहीं होगा कि ईआई (परफेक्ट वेट का पता लगाएगा), जिसका अर्थ है 2 फ़ीचर को एक सीधी रेखा से अलग करना। तो इससे बचने के लिए एक निश्चित संख्या में पुनरावृत्तियों को जोड़ना एक अच्छा अभ्यास है ताकि मॉडल वजन को समायोजित करने में अटक न जाए, जो कभी भी पूरी तरह से ट्यून नहीं किया जाएगा।

C ++ में एक Perceptron मॉडल को लागू करना

इस उदाहरण में मैं C ++ में पेसेप्ट्रॉन मॉडल के कार्यान्वयन के माध्यम से जाऊंगा, ताकि आप यह जान सकें कि यह कैसे काम करता है।

पहली चीजें सबसे पहले यह एक अच्छा तरीका है कि हम जो करना चाहते हैं उसका एक सरल एल्गोरिथ्म लिखें।

कलन विधि:

  1. वजन के लिए एक सदिश बनाएं और इसे 0 से शुरू करें (पूर्वाग्रह शब्द जोड़ना न भूलें)
  2. 0 त्रुटि या कम त्रुटि गणना प्राप्त होने तक वजन को समायोजित करते रहें।
  3. अनदेखी डेटा पर भविष्यवाणियां करें।

एक सुपर सरल एल्गोरिथ्म लिखा है चलो अब कुछ कार्यों को लिखें जिन्हें हमें आवश्यकता होगी।

  • हमें नेट के इनपुट की गणना करने के लिए एक फ़ंक्शन की आवश्यकता होगी (ei x * wT इनपुट्स को वज़न को गुणा करते हुए)
  • एक कदम समारोह ताकि हमें 1 या -1 की भविष्यवाणी मिल जाए
  • और एक फ़ंक्शन जो वजन के लिए आदर्श मूल्यों को पाता है।

तो आगे की हलचल के बिना हम इसमें सही हो जाएँ।

चलो एक अवधारणात्मक वर्ग बनाकर सरल शुरू करते हैं:

class perceptron
{
public:
    
private:

};

अब हम उन कार्यों को जोड़ते हैं जिनकी हमें आवश्यकता होगी।

class perceptron
{
public:
    perceptron(float eta,int epochs);
    float netInput(vector<float> X);
    int predict(vector<float> X);
    void fit(vector< vector<float> > X, vector<float> y);
private:

};

ध्यान दें कि फ़ंक्शन फिट कैसे एक तर्क के रूप में वेक्टर के एक वेक्टर <फ्लोट> लेता है। ऐसा इसलिए है क्योंकि हमारा प्रशिक्षण डेटासेट मैट्रिक्स का एक इनपुट है। अनिवार्य रूप से हम चाहते हैं कि मैट्रिक्स कल्पना कर सकते हैं वैक्टर के एक जोड़े के रूप में एक और एक के ऊपर एक और की है कि मैट्रिक्स एक सुविधा की जा रही प्रत्येक स्तंभ खड़ी x।

अंत में चलिए उन मूल्यों को जोड़ते हैं जो हमारी कक्षा के लिए आवश्यक हैं। जैसे कि वी वेट को पकड़ने के लिए सदिश w , युगों की संख्या जो पास की संख्या को इंगित करता है जो हम प्रशिक्षण डेटासेट पर करेंगे। और निरंतर ईटीए जो सीखने की दर है, जिससे हम इस मूल्य को डायल करके प्रशिक्षण प्रक्रिया को तेज करने के लिए प्रत्येक वजन अपडेट को गुणा करेंगे या यदि ईटा बहुत अधिक है तो हम आदर्श परिणाम प्राप्त करने के लिए इसे नीचे डायल कर सकते हैं (अधिकांश अनुप्रयोगों के लिए) परसेप्ट्रोन मैं ०.१ के एटा मान का सुझाव दूंगा)।

class perceptron
{
public:
    perceptron(float eta,int epochs);
    float netInput(vector<float> X);
    int predict(vector<float> X);
    void fit(vector< vector<float> > X, vector<float> y);
private:
    float m_eta;
    int m_epochs;
    vector < float > m_w;
};

अब हमारे क्लास सेट के साथ। यह प्रत्येक कार्य को लिखने का समय है।

हम कंस्ट्रक्टर से शुरू करेंगे ( परसेप्ट्रॉन (फ्लोट एटा, इंट इपोक));

perceptron::perceptron(float eta, int epochs)
{
    m_epochs = epochs; // We set the private variable m_epochs to the user selected value
    m_eta = eta; // We do the same thing for eta
}

जैसा कि आप देख सकते हैं कि हम जो कर रहे हैं वह बहुत सरल सामान है। तो चलिए एक और सरल फंक्शन पर चलते हैं। भविष्यवाणी समारोह ( इंट भविष्यवाणी (वेक्टर एक्स); )। याद रखें कि सभी पूर्वानुमान फ़ंक्शन क्या करते हैं, नेट इनपुट ले रहे हैं और 1 का मान लौटा रहे हैं यदि नेटइंस्प्यूट 0 और -1 नंबर से बड़ा है।

int perceptron::predict(vector<float> X)
{
    return netInput(X) > 0 ? 1 : -1; //Step Function
}

ध्यान दें कि यदि हमने अपने जीवन को आसान बनाने के लिए एक इनलाइन का उपयोग किया है। यदि कथन काम करता है तो यहां इनलाइन कैसे है:

शर्त ? if_true: और

अब तक सब ठीक है। चलिए netInput फ़ंक्शन ( फ्लोट netInput (वेक्टर X); ) को लागू करने के लिए आगे बढ़ते हैं;

NetInput निम्नलिखित करता है; वेट वेक्टर के संक्रमण द्वारा इनपुट वेक्टर को गुणा करता है

x * wT

दूसरे शब्दों में, यह वेट w के वेक्टर के संबंधित तत्व द्वारा इनपुट वेक्टर x के प्रत्येक तत्व को गुणा करता है और फिर उनका योग लेता है और पूर्वाग्रह जोड़ता है।

(X1 * w1 + x2 * w2 + ... + xn * wn) + पूर्वाग्रह

पूर्वाग्रह = 1 * w0

float perceptron::netInput(vector<float> X)
{
    // Sum(Vector of weights * Input vector) + bias
    float probabilities = m_w[0]; // In this example I am adding the perceptron first
    for (int i = 0; i < X.size(); i++)
    {
        probabilities += X[i] * m_w[i + 1]; // Notice that for the weights I am counting
        // from the 2nd element since w0 is the bias and I already added it first.
    }
    return probabilities;
}

ठीक है, इसलिए हम अब बहुत काम कर रहे हैं आखिरी चीज जो हमें करने की ज़रूरत है वह है फिट फ़ंक्शन लिखना जो वजन को संशोधित करता है।

void perceptron::fit(vector< vector<float> > X, vector<float> y)
{
    for (int i = 0; i < X[0].size() + 1; i++) // X[0].size() + 1 -> I am using +1 to add the bias term
    {
        m_w.push_back(0); // Setting each weight to 0 and making the size of the vector
        // The same as the number of features (X[0].size()) + 1 for the bias term
    }
    for (int i = 0; i < m_epochs; i++) // Iterating through each epoch
    {
        for (int j = 0; j < X.size(); j++) // Iterating though each vector in our training Matrix
        {
            float update = m_eta * (y[j] - predict(X[j])); //we calculate the change for the weights
            for (int w = 1; w < m_w.size(); w++){ m_w[w] += update * X[j][w - 1]; } // we update each weight by the update * the training sample
            m_w[0] = update; // We update the Bias term and setting it equal to the update
        }
    }
}

तो यह अनिवार्य रूप से था। केवल 3 कार्यों के साथ अब हमारे पास एक कामकाजी अवधारणात्मक वर्ग है जिसका उपयोग हम भविष्यवाणियां करने के लिए कर सकते हैं!

मामले में आप कोड को कॉपी-पेस्ट करना चाहते हैं और इसे आज़माना चाहते हैं। यहां पूरी कक्षा है (मैंने कुछ अतिरिक्त कार्यक्षमता जोड़ी है जैसे कि वेट वेक्टर को प्रिंट करना और प्रत्येक कालखंड में त्रुटियां और साथ ही वजन को आयात / निर्यात करने का विकल्प जोड़ा है।)

यहाँ कोड है:

वर्ग शीर्षक:

class perceptron
{
public:
    perceptron(float eta,int epochs);
    float netInput(vector<float> X);
    int predict(vector<float> X);
    void fit(vector< vector<float> > X, vector<float> y);
    void printErrors();
    void exportWeights(string filename);
    void importWeights(string filename);
    void printWeights();
private:
    float m_eta;
    int m_epochs;
    vector < float > m_w;
    vector < float > m_errors;
};

कार्यों के साथ वर्ग .cpp फ़ाइल:

perceptron::perceptron(float eta, int epochs)
{
    m_epochs = epochs;
    m_eta = eta;
}

void perceptron::fit(vector< vector<float> > X, vector<float> y)
{
    for (int i = 0; i < X[0].size() + 1; i++) // X[0].size() + 1 -> I am using +1 to add the bias term
    {
        m_w.push_back(0);
    }
    for (int i = 0; i < m_epochs; i++)
    {
        int errors = 0;
        for (int j = 0; j < X.size(); j++)
        {
            float update = m_eta * (y[j] - predict(X[j]));
            for (int w = 1; w < m_w.size(); w++){ m_w[w] += update * X[j][w - 1]; }
            m_w[0] = update;
            errors += update != 0 ? 1 : 0;
        }
        m_errors.push_back(errors);
    }
}

float perceptron::netInput(vector<float> X)
{
    // Sum(Vector of weights * Input vector) + bias
    float probabilities = m_w[0];
    for (int i = 0; i < X.size(); i++)
    {
        probabilities += X[i] * m_w[i + 1];
    }
    return probabilities;
}

int perceptron::predict(vector<float> X)
{
    return netInput(X) > 0 ? 1 : -1; //Step Function
}

void perceptron::printErrors()
{
    printVector(m_errors);
}

void perceptron::exportWeights(string filename)
{
    ofstream outFile;
    outFile.open(filename);

    for (int i = 0; i < m_w.size(); i++)
    {
        outFile << m_w[i] << endl;
    }

    outFile.close();
}

void perceptron::importWeights(string filename)
{
    ifstream inFile;
    inFile.open(filename);

    for (int i = 0; i < m_w.size(); i++)
    {
        inFile >> m_w[i];
    }
}

void perceptron::printWeights()
{
    cout << "weights: ";
    for (int i = 0; i < m_w.size(); i++)
    {
        cout << m_w[i] << " ";
    }
    cout << endl;
}

यदि आप एक उदाहरण यहाँ आज़माना चाहते हैं तो एक उदाहरण मैंने बनाया है:

main.cpp:

#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <string>
#include <math.h> 

#include "MachineLearning.h"

using namespace std;
using namespace MachineLearning;

vector< vector<float> > getIrisX();
vector<float> getIrisy();

int main()
{
    vector< vector<float> > X = getIrisX();
    vector<float> y = getIrisy();
    vector<float> test1;
    test1.push_back(5.0);
    test1.push_back(3.3);
    test1.push_back(1.4);
    test1.push_back(0.2);

    vector<float> test2;
    test2.push_back(6.0);
    test2.push_back(2.2);
    test2.push_back(5.0);
    test2.push_back(1.5);
    //printVector(X);
    //for (int i = 0; i < y.size(); i++){ cout << y[i] << " "; }cout << endl;

    perceptron clf(0.1, 14);
    clf.fit(X, y);
    clf.printErrors();
    cout << "Now Predicting: 5.0,3.3,1.4,0.2(CorrectClass=-1,Iris-setosa) -> " << clf.predict(test1) << endl;
    cout << "Now Predicting: 6.0,2.2,5.0,1.5(CorrectClass=1,Iris-virginica) -> " << clf.predict(test2) << endl;

    system("PAUSE");
    return 0;
}

vector<float> getIrisy()
{
    vector<float> y;

    ifstream inFile;
    inFile.open("y.data");
    string sampleClass;
    for (int i = 0; i < 100; i++)
    {
        inFile >> sampleClass;
        if (sampleClass == "Iris-setosa")
        {
            y.push_back(-1);
        }
        else
        {
            y.push_back(1);
        }
    }

    return y;
}

vector< vector<float> > getIrisX()
{
    ifstream af;
    ifstream bf;
    ifstream cf;
    ifstream df;
    af.open("a.data");
    bf.open("b.data");
    cf.open("c.data");
    df.open("d.data");

    vector< vector<float> > X;

    for (int i = 0; i < 100; i++)
    {
        char scrap;
        int scrapN;
        af >> scrapN;
        bf >> scrapN;
        cf >> scrapN;
        df >> scrapN;

        af >> scrap;
        bf >> scrap;
        cf >> scrap;
        df >> scrap;
        float a, b, c, d;
        af >> a;
        bf >> b;
        cf >> c;
        df >> d;
        X.push_back(vector < float > {a, b, c, d});
    }

    af.close();
    bf.close();
    cf.close();
    df.close();

    return X;
}

जिस तरह से मैंने आईरिस डेटासेट आयात किया है वह वास्तव में आदर्श नहीं है, लेकिन मुझे बस कुछ ऐसा चाहिए था जो काम करे।

डेटा फ़ाइलों को यहाँ पाया जा सकता है।

मुझे आशा है कि आपको यह मददगार लगा!

पूर्वाग्रह क्या है


पूर्वाग्रह क्या है

एक परसेप्ट्रॉन को एक फ़ंक्शन के रूप में देखा जा सकता है जो एक इनपुट (वास्तविक-मूल्यवान) वेक्टर x को आउटपुट मान f (x) (बाइनरी ) पर मैप करता है:

यहाँ छवि विवरण दर्ज करें

जहां w वास्तविक-मूल्य भार का एक वेक्टर है और बी हमारे पूर्वाग्रह मूल्य है। पूर्वाग्रह एक मूल्य है जो निर्णय सीमा को मूल (0,0) से दूर स्थानांतरित करता है और यह किसी भी इनपुट मूल्य पर निर्भर नहीं करता है।

पूर्वाग्रह पर एक स्थानिक तरीके से सोचकर, पूर्वाग्रह निर्णय सीमा की स्थिति (हालांकि अभिविन्यास नहीं) को बदल देता है। हम पूर्वाग्रह द्वारा स्थानांतरित किए गए उसी वक्र के एक उदाहरण के नीचे देख सकते हैं:

यहाँ छवि विवरण दर्ज करें



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow