Alokacja tablicy <vector> – przekroczenie pamięci?

0

Piszę Adaline z użyciem wektorów. Kod jak poniżej:

    void Adaline::fillArrays()
    {
        for (int i = 0; i < numberOfNeurons; i++)
        {
                neuron[i].tabX.reserve(numberOfSignals);
            neuron[i].output = 0;
            neuron[i].z = 0;
            neuron[i].y = -1;
        }

        // przypisanie wartości do sieci
        for (int i = 0; i < numberOfNeurons; i++)
        {
            for (int j = 0; j < numberOfSignals; j++)
            {
                cout << "Enter signal [" << i << "," << j << "]: "; cin >> neuron[i].tabX[j];
                neuron[i].wX.push_back(0.2+ 0.1*(j+1) - 0.08*(i+1));
                neuron[i].dW.push_back(0);
            }
            cout << "Enter expected output: "; cin >> neuron[i].z;
        }
    }

Pojawiają się dziwne błędy pokroju:

+ message 0x01240288 L"vector subscript out of range" const wchar_t *

lub:

    _STD_BEGIN

    #ifdef _DEBUG
    _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Debug_message(const wchar_t *message, const wchar_t *file, unsigned int line)
        {   // report error and die
            if(::_CrtDbgReportW(_CRT_ASSERT, file, line, NULL, L"%ls", message)==1)
            {
                ::_CrtDbgBreak();
            }
        }
    _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Debug_message(const unsigned short *message, const unsigned short *file, unsigned int line)
        {   // report error and die
            _Debug_message((wchar_t *) message, (wchar_t *) file, line);
        }

    #endif

    _STD_END

Ma ktoś ideę, o co tutaj chodzi? Podejrzewam, że standardowo problem z pamięcią.

1

A czy na pewno nigdzie nie przekraczasz zakresu wektora? ;p

1

numberOfNeurons na pewno odpowiada neuron.size()? Wypisz sobie neuron.size() na początku tej metody, albo debuguj i zobacz co zwróci.

0

Oto kawałek kodu obrazujący alokację pamięci dla "neuron":

    iterations = 100;
    numberOfNeurons = 2; // important
    numberOfSignals = 3; // important
    eta = 0.6;

    neuron.reserve(numberOfNeurons);

    fillArrays();
    Delta();

Faktycznie wynosi zero jak sprawdzam rozmiar, chociaż nie wiem jakim cudem. Warto zwrócić uwagę, że neuron jest klasy "Neuron" i może tutaj gdzieś jest problem? Z drugiej strony, na chłopski rozum powinien zaalokować 2 obiekty klasy "Neuron".

2

Na chłopski rozum to właśnie nie powinien. Dokumentację poczytaj: http://en.cppreference.com/w/cpp/container/vector/reserve
I tu jeszcze: http://en.cppreference.com/w/cpp/container/vector/resize

0

Wracając więc z podróży. Aktualnie alokacja przestrzeni oraz wartości dla wektora neuronów wygląda tak:

void Adaline::fillVector(vector <Neuron>& neurons)
{
    for (int i = 0; i < numberOfNeurons; i++)
    {
        Neuron neurony;
        neurony.output = 0;
        neurony.z = 0;
        neurony.y = -1;

        for (int j = 0; j < numberOfSignals; j++)
        {
            neurony.tabX.push_back(0);
            cout << "Enter signal [" << i << "," << j << "]: "; cin >> neurony.tabX[j];
            neurony.wX.push_back(0.2 + 0.1*(j + 1) - 0.08*(i + 1));
            neurony.dW.push_back(0);
        }
        cout << "Enter expected output: "; cin >> neurony.z;
        neurons.push_back(neurony); // wpisujemy pierwszy (kolejny) wektor do naszej głównej tablicy neuronów
    }

    Delta(neurons);

}

Lokalnie tworzymy klasę Neurony neurony, wpisujemy wszystkie wartości do naszego głównego neurons (neurons.push_back(neurony);), którą to wartość zachowujemy. Następnie przekazujemy neurons do reguły delta, gdzie realizujemy całą sieć Madaline. Jak zachowuje się program: alokuje poprawnie rozmiary każdego z wektorów (także wektorów <float> i <int> klasy Neuron), wpisuje także poprawnie wejściowe sygnały tabX (najpierw alokujemy miejsce z wartością zero, a potem wpisujemy tam wartość), ale już niepoprawnie wpisuje wartości wagowe wX. Po prostu wpisuje tam same zera, nie wiedzieć czemu. Jakiś pomysł, co z tym zrobić?

0
        Neuron neurony;
        neurony.output = 0;
        neurony.z = 0;
        neurony.y = -1; 

Ile masz neuronów w jednym neuronie? ;P Jeden? To dlaczego nazwany "neurony"? :P (chyba, że to "neuron igrek"?) Co ważniejsze - rozejrzyj się za pojęciem "konstruktor". Za każdym razem tak ręcznie przypisujesz wartości początkowe neuronów?

void Adaline::fillVector(vector <Neuron>& neurons) 

Czyyyyli z zewnątrz przyjmujesz ten vector? Coś mi się zdaje, że niepotrzebny ten parametr, bo Ci tylko nazwą przesłania this->neurons. Zadziałałoby jeszcze, jeśli wołałbyś to z "wewnętrznym" vectorem w parametrze, ale zawołania nam nie wkleiłeś, to nic na ten temat nie wiemy.

"Lokalnie tworzymy klasę " - nie klasę, a instancję, obiekt klasy.
"najpierw alokujemy miejsce z wartością zero, a potem wpisujemy tam wartość" - oj... ech. :P Nie. neurony.output już sobie szczęśliwie istnieje, bo obiekt neurony został już skonstruowany. Przypisujesz tam wartość, owszem, ale żadna alokacja pamięci nie ma już miejsca.

Jakiego typu jest Neuron::wX?

0

W porządku. Odnośnie konstruktorów i zabierania parametrów z zewnątrz – póki co chcę przetestować działanie tych wektorów, potem się zająć całym upiększaniem (to raczej zgodne z taksonomią Blooma, że najpierw nabiera się wiedzy o sadzeniu kwiatów, a potem dba się o stylistykę ogrodu, niemniej staram się zrozumieć nieodpartą pokusę wykazania niewiedzy skądinąd początkującego programisty).

Xupicor napisał(a):

"najpierw alokujemy miejsce z wartością zero, a potem wpisujemy tam wartość" - oj... ech. :P Nie. neurony.output już sobie szczęśliwie istnieje, bo obiekt neurony został już skonstruowany. Przypisujesz tam wartość, owszem, ale żadna alokacja pamięci nie ma już miejsca.

Tu akurat odnosiłem się do tabX.:)

class Neuron {
public:
    vector <int> tabX;
    vector <float>  wX;
    vector <float>  dW;
    float output;
    float z;
    int y;
};

Klasa Neuron wygląda tak. Wszystkie rozmiary wektorowe alokowane są poprawne – nie wpisują się jednak poprawnie wartości do wX (jedynie same zera).

1

Sure, najpierw się naucz używać, a potem dobrze używać - ale może warto by było zacząć od dobrze używać, żeby się nie "oduczać" potem? Szczególnie, jeśli sam się uczysz, bo nie będzie komu Cię potem skorygować. ;) To w ogóle temat rzeka, nie miejsce i nie czas.

Tu akurat odnosiłem się do tabX.:)
Wszystko jedno. Pamięć używana przez tabX to część pamięci obiektu, więc w momencie gdy kontrola wchodzi w ciało konstruktora obiektu - cała ta pamięć jest już zaalokowana. Pamięć pod elementy tabX to inna sprawa.

Po prostu miej świadomość, że rzucasz na lewo i prawo słowami, które mają pewne ścisłe znaczenia, a składasz je do kupy w taki sposób, że nie tylko nie da się ukryć, żeś pan początkującym, ale po prostu ciężko to zignorować. Jeśli wszyscy to zignorują, jeszcześ gotów pomyśleć, że wszystko jest w porządku. My na tym nie stracimy - ale Ty nie zyskasz. :P

No ale wracając... Hmmm, jak wywołujesz tę metodę?

0

Masz rację – lepiej się uczyć na "czystym" kodzie niż zasyfionym jak u mnie, ale powiem szczerze, że najpierw chcę "skumać" do końca ten vector i sposób implementacji, a potem zrekonstruować wszystkie powiązania między klasami i metodami. Odnośnie poprawiania mnie co do nazewnictwa – jak najbardziej, i dobrze, że to podkreślasz, bo przy okazji ciągle się uczę:).

Odnośnie wywołania metody, wygląda to tak:

Adaline::Adaline()
{
    iterations = 100;
    numberOfNeurons = 2;
    numberOfSignals = 3; 
    eta = 0.6;

    fillVector(neurony);
}

Więc, po stworzeniu w main obiektu Adaline adaline konstruktor domyślny automatycznie stworzy wektor dla naszej sieci vector <neuron> neurony (tak zapis wygląda w definicji klasy). neurony od razu przekazujemy do funkcji fillVector (zapisana powyżej), która następnie wywołuje funkcję z regułą delta, a funkcja z regułą delta wywołuje wyświetlanie (trochę pozagnieżdżałem, każda następna funkcja jest w funkcji poprzedzającej, ale kod całkiem sprawnie się czyta). Problem w tym, że neurony.wX.push_back(0.2 + 0.1(j + 1) - 0.08(i + 1)); nie przypisuje żadnej wartości poza zerem. A według wikibooks:

vector<int> tab;
cin >> n;
for( int i=0; i<n; ++i )
{
   int element;
   cin >> element;
   tab.push_back(element);
}

podobna składnia powinna ładniutko wpisywać element na końcu naszego wektora. Niestety u mnie wpisuje same zera.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0