19004


C++でOpenCVを用いてニューラルネットワークをトレーニングしたいです。

このエントリを参考にしました。 [参考サイト](http://kivantium.hateblo.jp/entry/2014/11/25/230658)

識別する画像は30*50の2値画像です。

訓練画像を読み込み、最後の列(INPUT+1)に教師信号(出力が1.0になってほしいニューロン)を付加して、1枚の画像を1行に出力し、csvファイルとしました。

* * *

グローバル定数は以下のように定義し、

[code]

    const int TRAINING_SAMPLES = 300; //訓練データ数
    const int INPUT = 30 * 50; // 入力次元
    const int CLASSES = 10; //出力次元
    
[/code]

学習データ、教師データは以下のように宣言しています。

[code]

    //---学習データ---
    cv::Mat trainingData(TRAINING_SAMPLES, INPUT, CV_32F);
    
    //---教師データ---
    cv::Mat trainingTeacher(TRAINING_SAMPLES, CLASSES, CV_32F);
    
    //---データセットの読み込み---
    readDataSet(filename, trainingData, trainingTeacher);
    
[/code]

csvファイルから訓練データを読み込む関数です。

[code]

    void readDataSet( char* filename, cv::Mat &data, cv::Mat &teacher)
    {
        ifstream ifs(filename);
        if (!ifs)
        {
            cerr << "Error:Input data file not found" << endl;
            exit(1);
        }
        string str;
        stringstream ss;
        float csvData[TEST_SAMPLES][INPUT + 1];
        for (int row = 0; row < TEST_SAMPLES; row++)
        {
            for (int col = 0; col < INPUT; col++)
            {
                getline(ifs.seekg(0, ios_base::cur), str, ',');
                ss.str(str);
                ss >> csvData[row][col];
                ss.str("");
                ss.clear(stringstream::goodbit);
            }
            getline(ifs.seekg(0, ios_base::cur), str, '\n');
            ss.str(str);
            ss >> csvData[row][INPUT];
            ss.str("");
            ss.clear(stringstream::goodbit);
        }
    
    //---学習データの読み込み---
        for (int row = 0; row < TRAINING_SAMPLES; row++)
        {
            for (int col = 0; col < INPUT; col++)
            {
                data.at<float>(row, col) = csvData[row][col];
            }
        }
    
    //---教師データの読み込み---
        for (int row = 0; row < TRAINING_SAMPLES; row++)
        {
            for (int col = 0; col < CLASSES; col++)
            {
                teacher.at<float>(row, col) = 0.0;
            }
            int label = (int)csvData[row][INPUT];
            teacher.at<float>(row, label) = 1.0;
        }
    }
    
[/code]

* * *

`TRAINING_SAMPLES`が小さいとき(10くらい)は問題なく動いてくれるのですが、  
`TRAINING_SAMPLES = 300`などとしたときはこの行で

[code]

    data.at<float>(row, col) = csvData[row][col];
    
[/code]

こんなエラーがでます。  
Unhandled exception at 0x00007FF7AB10D7F8 in NeuralNetwork.exe: 0xC0000005:
Access violation reading location 0x000000D306604000.

メモリーが足らないのかとも思いますが、x64で開発していますし(環境設定はこのサイトを参考にしました。[環境設定](http://www.buildinsider.net/small/opencv/03))  
Enable Large AddressesもYESにしましたが、直りませんでした。


CC BY-SA 3.0
2015-11-18T08:40:43.287
18980
2015-11-18T21:43:27.353
2015-11-18T21:20:08.490
4236
13075
question
c++ visual-studio opencv
C++, OpenCV ： 行列のサイズを大きくすると"Access violation reading location"エラーが出る


argusさんも指摘されていますが、その付近、

> float csvData[TEST_SAMPLES][INPUT + 1];

が大きすぎます。また`TEST_SAMPLES`を使用して変数宣言していながらループの際には`TRAINING_SAMPLES`を使用されている点も気になります。

宣言したサイズを超えて変数アクセスした場合は、`Stack overflow`にはならずに`Access violation`になります。  
Windows環境でVisual
Studioを使用されているようですが、その場合、[コード分析](https://msdn.microsoft.com/ja-
jp/library/hh419384.aspx)を使用することで検出可能です。

大きすぎる変数に対しては次のような警告が出ます。

> warning C6262: Function uses '180136' bytes of stack: exceeds
> /analyze:stacksize '16384'. Consider moving some data to heap.

また境界を越えてアクセスし得る場合は次のような警告が出ます。

> warning C6201: Index '299' is out of valid index range '0' to '9' for
> possibly stack allocated buffer 'csvData'.


CC BY-SA 3.0
2015-11-18T21:19:47.167
19004
2015-11-18T21:43:27.353
2015-11-18T21:43:27.353
4236
4236
18980
answer