57764


売上個数予想のプログラムを作っていますが、  
学習させた後`MultiLayerNetwork.output(xxx)`させた結果が常に同じ値になり困っています。

事前に学習データを`AI.MaxInputStringLength`（20）のパラメータに変換済みでそのサンプルが数万個あります。  
つまり、入力は20のパラメータがあります。  
今回は売上個数の予想なので出力は1つです。  
（ディープラーニングは初めてなのでまずはそれっぽい結果が出るだけでよく、モデル構築は勘に近いです）

下記コードは処理を **読める程度** に **必要な部分だけを抜粋** しています。  
`AI.MaxInputStringLength` は 入力パラメータ数なので`20`です。
（Stringとついてますが入力は事前処理しているので文字列ではありません）

# ニューラルネットワークモデル

[code]

    val modelConfig = NeuralNetConfiguration.Builder()
            .seed(1142)
            .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
            .iterations(1000)
            .learningRate(0.001)
            //.updater(Updater.NESTEROVS).momentum(0.9)
            //.regularization(true).l2(1e-4)
            .list()
            .layer(0, DenseLayer.Builder()
                .nIn(MaxInputStringLength)
                .nOut(500)
                .activation(Activation.SIGMOID)
                .weightInit(WeightInit.XAVIER)
                .build())
    
        var layer = 1   //  ↑inputが0だから1から始まる
        var beforeOutputCount = 500   //  ↑inputのアウトプットの数
        val middleLayerLength = 100
        for (i in 0 until middleLayerLength) {
            val outputCount = 500
    
            modelConfig.layer(
                layer++, DenseLayer.Builder()
                    .nIn(beforeOutputCount)
                    .nOut(outputCount)
                    .activation(Activation.RELU)
                    .weightInit(WeightInit.XAVIER)
                    .build()
            )
    
            beforeOutputCount = outputCount
        }
    
        modelConfig.layer(layer, OutputLayer.Builder()
            .nIn(beforeOutputCount)
            .nOut(1)
            .activation(Activation.SIGMOID)
            .weightInit(WeightInit.XAVIER)
            .build())
    
        val model = MultiLayerNetwork(modelConfig.build())
        model.init()
    
[/code]

# データセットの作成（20インプット1アウトプット * サンプルの数 を一つのDataSetに）

[code]

    fun loadDataSet(apps: LinkedList<App>): DataSet {
        //  省略解説　dataCount　は学習データの数（数万）
        //  省略解説　AI.MaxInputStringLength　はinputの数（今回は常に20）
    
        //  データ領域を用意する
        val inputBuff = FloatArray(AI.MaxInputStringLength * dataCount)
        val answerBuff = FloatArray(dataCount)
    
        //  データを格納する
        var inputOffset = 0
        var answerOffset = 0
    
        for ({省略解説　学習データの数だけ繰り返す　dataCount}) {            
            //  入力
            //  省略解説　`putInputメソッド`はforで回されてきた`学習データ`を`inputBuff`に格納して新しいオフセットを返す
            //  メソッド内部で`学習データ`の`inputの数`だけ格納されるのでこのメソッドは`inputOffset+AI.MaxInputStringLength`の値を常に返すことになる
            inputOffset = putInput(inputBuff, inputOffset, AI.MaxInputStringLength)
    
           //  回答
           answerBuff[answerOffset++] = meta.salesCount.toFloat()
        }
    
    
        return DataSet(
            Nd4j.create(
                inputBuff,
                intArrayOf(dataCount, MaxInputStringLength)
            ),
            Nd4j.create(
                answerBuff,
                intArrayOf(dataCount, 1)
            )
        )
    }
    
[/code]

# 学習部分

[code]

    model.fit(loadDataSet(xxx))
    
[/code]

# 運用部分

[code]

    val out = model.output(Nd4j.create(/*省略解説　インプット配列　AI.MaxInputStringLength文の長さを持つ*/))
    
[/code]

この運用部分のoutの値が`model.output`に何を渡しても常に一定の値になってしまします。（だいたい 0.99997754 みたいな）

渡すデータの次元を指定しないといけないのかなと思い

[code]

    val out = model.output(Nd4j.create(inputBuff, intArrayOf(1, AI.MaxInputStringLength)))
    
[/code]

にしてもやはり同じ値が返ってきました。

# 学習の推移

[![画像の説明をここに入力](https://i.stack.imgur.com/92iBy.png)](https://i.stack.imgur.com/92iBy.png)


CC BY-SA 4.0
2019-09-02T04:16:28.840
57759
2019-09-02T06:43:53.080
10346
question
機械学習 深層学習 deeplearning4j
ディープラーニングの解析結果が常に同じ値になります

[code]

    modelConfig.layer(layer, OutputLayer.Builder()
        .nIn(beforeOutputCount)
        .nOut(1)
        .activation(Activation.SIGMOID)
        .weightInit(WeightInit.XAVIER)
        .build())
    
[/code]

最後の層の出力にSIGMOID関数がかかるので、必ず0～1になります。  
データセットの具体例がないので正確にはわかりませんが、売り上げ個数ということで実際は自然数になるはずですが、0～1の範囲で最も近い0.999…になっているのではないでしょうか。

[code]

    val middleLayerLength = 100
    
[/code]

また直接関係はなく条件次第ではありますが全結合102層で上手く学習させるのは難しいので一旦3～10層程度で実験するのはどうでしょうか？


CC BY-SA 4.0
2019-09-02T06:43:53.080
57764
2019-09-02T06:43:53.080
241
57759
answer