Я следую этому туто Прогнозирование временных рядов с помощью TensorFlow. js; Я новичок в науке о данных и Tensorflow JS.
Я думаю, что сделал ошибку, но не могу найти где. Я нахожусь на этапе обучения модели, и у меня очень большие потери, с 651878,125 до 411721. Я пытался увеличить количество эпох, оно продолжает уменьшаться, но все еще остается высоким (около 125000.000). Это нормально? Как мне нужно изменить, чтобы получить результат, ближайший к 0,0001?
Мои переменные: WINDOW_SIZE: число = 50, TRAINING_SIZE: число = 0,85; // = 70%, EPOCHS: число = 25, LEARNING_RATE: число = 0.01, N_LAYERS: число = 4.
Цены от 3800 $ до 9500 $, у меня от 1000 до 2000 записей в массиве объектов {date, value} с именем stockPrices = Array <{date, value}> ({date, value} - это класс с именем 'Data').
Спасибо за вашу помощь.
Моя функция SMA:
computeSMA(stockPrices:Array<Data>, window_size:number): Promise<Array<any>> {
let r_avgs = [], prices = [], avg_prev = 0;
//Get only prices, witout dates:
for (let i = 0; i < stockPrices.length; i++) {
prices.push(stockPrices[i].value);
}
//SMA calculation on window_size:
for (let i = 0; i <= prices.length - window_size; i++){
let curr_avg = 0, t = i + window_size;
for (let k = i; k < t && k <= prices.length; k++){
curr_avg = curr_avg + prices[k];
}
curr_avg = curr_avg / window_size;
r_avgs.push({
set: prices.slice(i, i + window_size),
avg: curr_avg
});
}
return new Promise((resolve, reject) => {
if (r_avgs.length > 0) {
resolve(r_avgs);
} else {
reject([]);
}
});
}
Вызов модели обучения:
//After calling computeSMA, I separate inputs (arrays of window_size values) from outputs (SMA) :
for (let i = 0; i < smaValues.length; i++) {
this.inputs.push(smaValues[i]['set']);
this.outputs.push(smaValues[i]['avg']);
console.log(smaValues[i]['avg']);
}
//inputsToTrain and outputsToTrain = this.WINDOW_SIZE % of data for training the model.
this.inputsToTrain = this.inputs.slice(0, Math.floor(this.TRAINING_SIZE * this.inputs.length));
this.outputsToTrain = this.outputs.slice(0, Math.floor(this.TRAINING_SIZE * this.outputs.length));
//inputsToValidate or outputsToValidate = (1 - this.WINDOW_SIZE) % of data for validating the model.
this.inputsToValidate = this.inputs.slice(Math.floor(this.TRAINING_SIZE * this.inputs.length), this.inputs.length);
this.outputsToValidate = this.outputs.slice(Math.floor(this.TRAINING_SIZE * this.outputs.length), this.outputs.length);
//Train the model.
this.trainModel(this.inputsToTrain, this.outputsToTrain, this.WINDOW_SIZE, this.EPOCHS, this.LEARNING_RATE, this.N_LAYERS, (epoch, log) => {
console.log(`${'EPOCH '}${epoch + 1}${' / '}${this.EPOCHS}${' ; Loss = '}${log.loss}`);
});
Функция модели обучения:
async trainModel(X, Y, window_size, n_epochs, learning_rate, n_layers, callback){
//Entraîne le modèle.
const input_layer_shape = window_size;
const input_layer_neurons = 100;
const rnn_input_layer_features = 10;
const rnn_input_layer_timesteps = input_layer_neurons / rnn_input_layer_features;
const rnn_input_shape = [rnn_input_layer_features, rnn_input_layer_timesteps];
const rnn_output_neurons = 20;
const rnn_batch_size = window_size;
const output_layer_shape = rnn_output_neurons;
const output_layer_neurons = 1;
const model = tf.sequential();
const xs = tf.tensor2d(X, [X.length, X[0].length]).div(tf.scalar(10));
const ys = tf.tensor2d(Y, [Y.length, 1]).reshape([Y.length, 1]).div(tf.scalar(10));
model.add(tf.layers.dense({units: input_layer_neurons, inputShape: [input_layer_shape]}));
model.add(tf.layers.reshape({targetShape: rnn_input_shape}));
let lstm_cells = [];
for (let index = 0; index < n_layers; index++) {
lstm_cells.push(tf.layers.lstmCell({units: rnn_output_neurons}));
}
model.add(tf.layers.rnn({
cell: lstm_cells,
inputShape: rnn_input_shape,
returnSequences: false
}));
model.add(tf.layers.dense({units: output_layer_neurons, inputShape: [output_layer_shape]}));
model.compile({
optimizer: tf.train.adam(learning_rate),
loss: 'meanSquaredError'
});
const hist = await model.fit(xs, ys,
{ batchSize: rnn_batch_size, epochs: n_epochs, callbacks: {
onEpochEnd: async (epoch, log) => {
callback(epoch, log);
}
}
});
return { model: model, stats: hist };
}