私はdeeplearning4jライブラリを初めて使いましたが、一般的にニューラルネットワークの経験があります。
私はリアルタイムで音楽のビートを検出するはずのリカレントニューラルネットワーク(特にLSTM)を訓練しようとしています。私が今までに見つけたdeeplearning4jでリカレントニューラルネットを使用する例はすべて、ファイルからトレーニングデータを読み取るリーダーを使用しています。マイクを使ってリアルタイムで音楽を録音したいので、あらかじめ生成されたファイルを読み取ることができないため、ニューラルネットワークに入力されたデータはアプリケーションによってリアルタイムで生成されます。実行時に生成されるデータを持つdeeplearning4jのリカレントニューラルネットワーク
これは私が自分のネットワークを生成するために使用しているコードである:
NeuralNetConfiguration.ListBuilder builder = new NeuralNetConfiguration.Builder()
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT).iterations(1)
.learningRate(0.1)
.rmsDecay(0.95)
.regularization(true)
.l2(0.001)
.weightInit(WeightInit.XAVIER)
.updater(Updater.RMSPROP)
.list();
int nextIn = hiddenLayers.length > 0 ? hiddenLayers[0] : numOutputs;
builder = builder.layer(0, new GravesLSTM.Builder().nIn(numInputs).nOut(nextIn).activation("softsign").build());
for(int i = 0; i < hiddenLayers.length - 1; i++){
nextIn = hiddenLayers[i + 1];
builder = builder.layer(i + 1, new GravesLSTM.Builder().nIn(hiddenLayers[i]).nOut(nextIn).activation("softsign").build());
}
builder = builder.layer(hiddenLayers.length, new RnnOutputLayer.Builder(LossFunctions.LossFunction.MCXENT).nIn(nextIn).nOut(numOutputs).activation("softsign").build());
MultiLayerConfiguration conf = builder.backpropType(BackpropType.TruncatedBPTT).tBPTTForwardLength(DEFAULT_RECURRENCE_DEPTH).tBPTTBackwardLength(DEFAULT_RECURRENCE_DEPTH)
.pretrain(false).backprop(true)
.build();
net = new MultiLayerNetwork(conf);
net.init();
この場合、私は(主に録音したオーディオのFFTデータである)約700の入力、1つの出力を使用してい(0 [拍動なし]と1 [拍]の間の数値を出力すると仮定されています)、私のhiddenLayers配列はints {50,25,10}で構成されています。私はこのコードを使用しているネットワークの出力を取得するための
:netInputData私は、一次元、二重配列としてネットワークに入力したいデータである
double[] output = new double[]{net.rnnTimeStep(Nd4j.create(netInputData)).getDouble(0)};
。
私はそれをプロットするときsomething like thisのように見える訓練されていないネットワークのためのいくつかの出力を得るので、このコードがうまくいきます。
しかし、一度ネットワークをトレーニングしようとすると(短時間だけトレーニングしてもネットワークの重みが少し変わっても、出力は訓練されていないネットワークと非常に似ているはずです)私はlooks like a constantの出力を得る。
これは私がネットワークを訓練するために使用しているコードです:
for(int timestep = 0; timestep < trainingData.length - DEFAULT_RECURRENCE_DEPTH; timestep++){
INDArray inputDataArray = Nd4j.create(new int[]{1, numInputs, DEFAULT_RECURRENCE_DEPTH},'f');
for(int inputPos = 0; inputPos < trainingData[timestep].length; inputPos++)
for(int inputTimeWindowPos = 0; inputTimeWindowPos < DEFAULT_RECURRENCE_DEPTH; inputTimeWindowPos++)
inputDataArray.putScalar(new int[]{0, inputPos, inputTimeWindowPos}, trainingData[timestep + inputTimeWindowPos][inputPos]);
INDArray desiredOutputDataArray = Nd4j.create(new int[]{1, numOutputs, DEFAULT_RECURRENCE_DEPTH},'f');
for(int outputPos = 0; outputPos < desiredOutputData[timestep].length; outputPos++)
for(int inputTimeWindowPos = 0; inputTimeWindowPos < DEFAULT_RECURRENCE_DEPTH; inputTimeWindowPos++)
desiredOutputDataArray.putScalar(new int[]{0, outputPos, inputTimeWindowPos}, desiredOutputData[timestep + inputTimeWindowPos][outputPos]);
net.fit(new DataSet(inputDataArray, desiredOutputDataArray));
}
はもう一度、私は入力のために、ダブル配列として所望の出力のための私のデータを持っています。今回は、2つの配列が2次元です。第1のインデックスは時間(インデックス0は記録されたオーディオの最初のオーディオデータである)を表し、第2のインデックスはこのタイムステップの入力(またはそれぞれの所望の出力)を表す。
ネットワークのトレーニング後に表示された出力を考えれば、自分のデータからINDArraysを作成するために使用されたコードに問題があるはずです。私はこれらの配列を初期化するためのいくつかの重要なステップがないか、データをこれらの配列に配置するために必要な順序を乱しましたか?
ありがとうございました。
優秀な質問です。コミュニティに参加してください。チャンネルのhttps://gitter.im/deeplearning4j/deeplearning4jコミッターがあなたを助けることができます! – tremstat