ディープラーニングで出力される予想が常に一定の値
ディープラーニングはかなり駆け出しです。
機械学習については基礎の基礎を勉強した程度の無知です。
ディープラーニングで時系列の予想を行いたいのですが何をしても出力結果がほぼ一定の値になってしまします。
層の数を大きく変えても、活性化関数を見直して試行錯誤しても
学習後のモデルに何を渡してもほぼ一定の値を返すようになってしまいます。
下記のコードや説明を見て間違っている部分ありましたら指摘いただきたいです。
やりたいこと
- 時系列株の予想(上昇、変わらず、下落 の3パターン)
過去20日のデータを元に今後数日以内に上昇、変わらず、下落を予想 - deeplearning4jを使用(時系列は再帰型ニューラルネットワークを使用すると良い?)
入力と出力
入力データのshapeは、[numExamples,inputSize,timeSeriesLength]
- 現在学習はfitメソッドで1セットずつ行っているため
numExamples
は1
inputSize
は時系列の日数である20
timeSeriesLength
は時系列のパラメータで私の場合
始値
、終値
、独自のデータ
の3つ分なので3
独自データとは、アルゴリズム考えるのが得意なので機械学習ではない方法で発見したアルゴリズムで計算したデータです。
その日のとある変化を示し、将来の株価上下に明らかな関連性があるデータです。
(なので実際、機械学習しなくてもいいのですが誤差を除去したりしたいので)
出力データのshapeは、[numExamples,outputSize,timeSeriesLength]
timeSeriesLength
は上記入力で説明したとおり1
outputSize
は3
(上昇、変わらず、下落の3パターンを予測したいので)timeSeriesLength
は上記入力と合わせる必要があるみたいなので仕方なく20
本来はアウトプットは1次元3要素であればいいのですが、、、
定数(試行錯誤中で全体的にコード整ってなくてすいません)
// 【A】過去 解析データ
// 入力データの数(シグナルの点灯、解析自体はこの日数に関係しない あくまで入力データ数)
const val analyzeDays = 20
// 【B】未来 検知の有効期限
// シグナル検知後、何日後までの株価上下を当たりとするか
const val signalLimitDays = 10
const val numInputs = 3
//const val numHiddenNodes = 1000
const val numOutputs = 1
ネットワーク
fun createNeurarlNetwork(): MultiLayerNetwork {
val conf = NeuralNetConfiguration.Builder()
.seed(1992)
//.iterations(iterations)
.updater(RmsProp(0.01))
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.weightInit(WeightInit.XAVIER)
//.regularization(true)
.l2(1e-4)
.list()
.layer(0, GravesLSTM.Builder().nIn(numInputs).nOut(512).activation(Activation.TANH).gateActivationFunction(Activation.HARDSIGMOID).dropOut(0.1).build())
.layer(1, GravesLSTM.Builder().nIn(512).nOut(512).activation(Activation.TANH).gateActivationFunction(Activation.HARDSIGMOID).dropOut(0.1).build())
.layer(2, DenseLayer.Builder().nIn(512).nOut(128).activation(Activation.RELU).build())
.layer(3, RnnOutputLayer.Builder().nIn(128).nOut(numOutputs).activation(Activation.IDENTITY).lossFunction(LossFunctions.LossFunction.MSE).build())
.backpropType(BackpropType.TruncatedBPTT)
.tBPTTForwardLength(analyzeDays)
.tBPTTBackwardLength(analyzeDays)
.validateOutputLayerConfig(false)
//.pretrain(false)
//.backprop(true)
.build()
val net = MultiLayerNetwork(conf)
net.init()
return net
}
学習(学習データの 上昇、変わらず、下落 のデータパターンはおなじ数になるように用意しています)
// データ構成
var inIdx = 0
val inBuff = FloatArray(3*analyzeDays)
// 【A】過去を格納
for (i in 0 until analyzeDays) {
val r = res[i]
inBuff[inIdx++] = r.data.start
inBuff[inIdx++] = r.data.end
inBuff[inIdx++] = r.magnitude
//inBuff[inIdx++] = r.resistance
}
//
// B期間で株価の上下が見られるか解析
//--
省略
inBuffに格納したデータの正解(期待値)
val outBuff =
// 正解が上昇の場合
floatArrayOf(1F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F)
// 正解が変わらずの場合
floatArrayOf(0F, 1F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F)
// 正解が下落場合
floatArrayOf(0F, 0F, 1F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F, 0F)
//--
//
for (i in 0..5) {
neuralNetwork.fit(
Nd4j.create(
inBuff,
intArrayOf(1, 3, analyzeDays)
),
Nd4j.create(
outBuff,
intArrayOf(1, numOutputs, analyzeDays)
)
)
}
実用(予想)
// inputは上記「学習」と同じ形式
neuralNetwork.output(
Nd4j.create(
inBuff,
intArrayOf(1, 3, analyzeDays)
)
)
出力結果
[[[ 0.3230, 0.3230, 0.2329, 0.0089, -0.0144, -0.0179, -0.0185, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186]]]
↑入力に度のデータを渡しても上記とほぼ変わらない一定の値になってしまいます。
[[[ 0.3230, 0.3230, 0.2144, 0.0076, -0.0147, -0.0180, -0.0185, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186, -0.0186]]]
学習の様子を見ているとうまく進んでいるように見えますがこのような結果になってしまいます。
学習データは10年間の全銘柄分あるので十分なはずなのでなにか根本的に間違っているのでしょうが
いくら時間をかけても解決できないのでどうかお力を貸していただけるとうれしいです。