質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.86%

  • Java

    12467questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • NullPointerException

    25questions

    null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

javaでの多数パーセプトロン

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 43

riririra

score 2

質問内容

javaでのニューラルネットワーク、多数パーセプトロンを実装しようとしていますがlearnメソッド内の出力計算でNullPointerExceptionを吐いてしまいます、一体何が間違っているのでしょうか
入力と中間層の数が一致していれば問題なく作動します

    public void learn( double[][] x , double[] answer )
    {
        // 変数初期化
        double[]    in      = null;                           // i回目の試行で利用する教師入力データ
        double      ans     = 0;                              // i回目の試行で利用する教師出力データ
        double[]    h       = new double[ middleNumber ];     // 中間層の出力
        double[]    o       = new double[ outputNumber ];     // 出力層の出力
        int i = 0;
        double[][] seikai = new double  [MAX_TRIAL][1];
        double seigo = 0;

        // 学習
        int succeed = 0;        // 連続正解回数を初期化
        for(  i=0 ; i<MAX_TRIAL ; i++ )
        {
            // 行間を空ける
            if(i % 1000  == 0){
            System.out.println();
            System.out.println( String.format( "Trial:%d" , i ) );
            }
            // 使用する教師データを選択
            in  = x[ i % answer.length ];
            ans = answer[ i % answer.length ];

            // 出力値を推定:中間層の出力計算
            for( int j=0 ; j<middleNumber ; j++ )
            {
                h[j] = middleNeurons[j].output( in );
            }

            // 出力値を推定:出力層の出力計算
            for( int j=0 ; j<outputNumber ; j++ )
            {
//ここでNullPointerException
                o[j] = outputNeurons[j].output( h );
            }
            if(i % 1000  == 0){
            System.out.println( String.format( "[input] %f , %f , %f" , in[0] , in[1] , in[2] ) );
            System.out.println( String.format( "[answer] %f" , ans ) );
            System.out.println( String.format( "[output] %f" , o[0] ) );
            System.out.println( String.format( "[middle] %f , %f" , h[0] , h[1] ) );
            System.out.println(Math.abs(ans - o[0]));
            }
            if(Math.abs(ans - o[0]) < 0.01470588235){
                seikai[i][0] = 1;
            }
            // 評価・判定
            boolean successFlg  = true;
            for( int j=0 ; j<outputNumber ; j++ )
            {
                // 出力層ニューロンの学習定数δを計算
                double delta = ( ans - o[j] ) * o[j] * ( 1.0d - o[j] );

                // 教師データとの誤差が十分小さい場合は次の処理へ
                // そうでなければ正解フラグを初期化
                if( Math.abs( ans - o[j] ) < MAX_GAP ){ continue; }
                                                  else{ successFlg = false; }

                // 学習
                //if(i % 1000 == 0){
                //System.out.println( "[learn] before o :" + outputNeurons[j] );
                //}
                outputNeurons[j].learn( delta , h );
                //if(i % 10000 == 0){
                //System.out.println( "[learn] after o  :" + outputNeurons[j] );
                //}

            }

            // 連続成功回数による終了判定
            if( successFlg )
            {
                // 連続成功回数をインクリメントして、
                // 終了条件を満たすか確認
                succeed++;
                if( succeed >= x.length ){ break; }else{ continue; }
            }else{
                succeed = 0;
            }

            // 中間層の更新
            for( int j=0 ; j<middleNumber ; j++ )
            {   
                // 中間層ニューロンの学習定数δを計算
                double sumDelta = 0;
                for( int k=0 ; k<outputNumber ; k++ )
                {
                    Neuron  n    = outputNeurons[k];
                    sumDelta    += n.getInputWeightIndexOf(j) * n.getDelta(); 
                }
                double delta = h[j] * ( 1.0d - h[j] ) * sumDelta;

                // 学習
                //if(i % 1000 == 0){
                //System.out.println( "[learn] before m :" + middleNeurons[j] );
                //}
                middleNeurons[j].learn( delta , in );
                //if(i % 1000 == 0){
                //System.out.println( "[learn] after m  :" + middleNeurons[j] );
                //}
            }


            // 再度出力
            // 出力値を推定:中間層の出力計算
            for( int j=0 ; j<middleNumber ; j++ )
            {
                h[j] = middleNeurons[j].output( in );
            }

            // 出力値を推定:出力層の出力計算
            for( int j=0 ; j<outputNumber ; j++ )
            {
                o[j] = outputNeurons[j].output( h );
            }
            if(i % 1000  == 0){
            System.out.println( String.format( "[input] %f , %f" , in[0] , in[1] ) );
            System.out.println( String.format( "[output] %f" , o[0] ) );
            System.out.println( String.format( "[middle] %f , %f" , h[0] , h[1] ) );
            }

        }

        // すべての教師データで正解を出すか
        // 収束限度回数を超えた場合に終了
        System.out.println( "[finish] " + this );
        System.out.println( String.format( "Trial:%d" , i ) );
        //正誤判定
        for(int j = 500; j >= 1; j--){
            System.out.println(seikai[i-1][0]);
            seigo += seikai[i-1][0];
            i--;
        }
        System.out.println( String.format("正解回数は %f" , seigo ));
    }

    @Override
    public String toString()
    {
        // 戻り値変数
        String str  = "";

        // 中間層ニューロン出力
        str += " middle neurons ( ";
        for( Neuron n : middleNeurons ){ str += n; }
        str += ") ";

        // 出力層ニューロン出力
        str += " output neurons ( ";
        for( Neuron n : outputNeurons ){ str += n; }
        str += ") ";

        return str;
    }



    /**
     * 多層パーセプトロン内部で利用するニューロン 
     * @author karura
     */
    class Neuron
    {

        // 内部変数
        protected int         inputNeuronNum  = 0;         // 入力の数
        protected double[]    inputWeights    = null;      // 入力ごとの結合加重
        protected double      delta           = 0;         // 学習定数δ
        protected double      threshold       = 0;         // 閾値θ
        protected double      eater           = 1.0d;      // 学習係数η

        /**
         * 初期化
         * @param inputNeuronNum 入力ニューロン数
         */
        public Neuron( int inputNeuronNum )
        {
            // 変数初期化
            Random r = new Random();
            this.inputNeuronNum = inputNeuronNum;
            this.inputWeights   = new double[ inputNeuronNum ];
            this.threshold      = r.nextDouble();               // 閾値をランダムに生成

            // 結合加重を乱数で初期化
            for( int i=0 ; i<inputWeights.length ; i++ )
            { this.inputWeights[i] = r.nextDouble();}
        }

        /**
         * 学習(バックプロパゲーション学習)
         * @param inputValues 入力データ
         * @param delta       δ
         */
        public void learn( double delta , double[] inputValues  )
        {
            // 内部変数の更新
            this.delta  = delta;

            // 結合加重の更新
            for( int i=0 ; i<inputWeights.length ; i++ )
            {
                // バックプロパゲーション学習
                inputWeights[i] += eater * delta * inputValues[i];
            }

            // 閾値の更新
            threshold -= eater * delta; 
        }

        /**
         * 計算
         * @param  inputValues 入力ニューロンからの入力値
         * @return 推定値
         */
        public double output( double[] inputValues )
        {
            // 入力値の総和を計算
            double  sum = -threshold;
            //System.out.println(inputNeuronNum);
            for( int i=0 ; i<inputNeuronNum ; i++ ){ sum += inputValues[i] * inputWeights[i]; }

            // 活性化関数を適用して、出力値を計算
            double  out = activation( sum );

            return out;
        }

        /**
         * 活性化関数(シグモイド関数)
         * @param x
         * @return
         */
        protected double activation( double x )
        {
            return 1 / ( 1 + Math.pow( Math.E , -x ) );
        }

        /**
         * 
         * 入力iに対する結合加重を取得
         * @param i
         * @return
         */
        public double getInputWeightIndexOf( int i )
        {
            if( i>=inputNumber ){ new RuntimeException("outbound of index"); }
            return inputWeights[i];
        }

        /**
         * 学習定数δの取得
         * @return 学習定数δ
         */
        public double getDelta()
        {
            return delta;
        }

        /**
         * クラス内部確認用の文字列出力
         */
        @Override
        public String toString()
        {
            // 出力文字列の作成
            String output = "weight : ";
            for( int i=0 ; i<inputNeuronNum ; i++ ){ output += inputWeights[i] + " , "; }

            return output;

        }

    }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

エラーメッセージがないのと、クラスの定義がないのとで答えづらいですが……

o[j] = outputNeurons[j].output( h );

ここで例外が発生するとのことですので、outputNeurons か outputNeurons[j] が null になっているんじゃないでしょうか。
その場合、初期化で何かミスしているのだと思います。
outputNeurons はクラスのメンバですよね? ローカル変数を定義し忘れているとかでなく。

あと、これは質問とは無関係ですが、outputNumber を outputNeurons.Length と別で管理しているのはなぜでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.86%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    このコードをスマートにしてください

    aをb乗するプログラムを作成しております。 前回の質問で回答していただいた方々のおかげでとりあえずやりたかった動作をしてくれるプログラムは完成しました。 しかしこのプログラムを

  • 受付中

    オブ

    下記うお願いします。本質問に関係ない処理が記載されていますが気にしないでください。よ         Donut d1 = new Dc2);          Syste

  • 解決済

    会員情報システム(Java)での作り方

    javaで会員情報システムのようなものを作りたいです。 下記の実行結果(コマンドプロンプトで実行)になるような、登録プログラムを作成したいのですが、作成方法が分かりませんので、教

  • 解決済

    javaについて

    javaについて質問です。情報処理検定第53回のプログラミング部門1級のjavaの問題をやっているんですけど、そのjavaに平均値を追加したいです。どのように追加すれば良いのでしょ

  • 解決済

    double型の範囲について

    前提・実現したいこと 毎度お世話になっております。グラフで曲線を描きたいと思っております。 結果を格納する変数にdouble型を用いているのですが、途中から値がおかしくなります

  • 受付中

    Javaを使った性格診断プログラムを作りたいです。

    簡単な性格診断プログラムを作りたいです。 Java初心者です。 Javaを使って、簡単な性格診断プログラムを作ろうと思っています。 1~4の数字で入力して回答してもらう質

同じタグがついた質問を見る

  • Java

    12467questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • NullPointerException

    25questions

    null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。