Создание правильного Анн для прогнозирования
Это мой первый раз, когда я использую python, поэтому у меня есть много сомнений.
Я пытаюсь сделать простую Энн для прогнозирования в Pybrain. Это сеть 2 Вход-1 выход. Входные данные: в первом столбце указаны годы, а во втором столбце - месяцы года. Выходными данными являются нормальные осадки, связанные с каждым месяцем. Я не знаю, сколько вещей я делаю неправильно, но когда я строю график результатов, у меня возникают ошибки.Это мой код:
from pybrain.datasets import SupervisedDataSet
from pybrain.tools.shortcuts import buildNetwork
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.tools.validation import ModuleValidator
from pybrain.structure import SigmoidLayer, LinearLayer,TanhLayer
from pybrain.utilities import percentError
import matplotlib.pyplot as plt
import numpy as np
import math
#----------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
ds = SupervisedDataSet(2,1)
input = np.loadtxt('entradas.csv', delimiter=',')
output = np.loadtxt('salidas.csv', delimiter=',')
for x in range(0, len(input)):
ds.addSample(input[x], output[x])
print (ds['input'])
print ("Hay una serie de",len(ds['target']),"datos")
#print(ds)
# Definicion topologia de la Red Neuronal
n = buildNetwork(ds.indim,5,ds.outdim,recurrent=True,hiddenclass=SigmoidLayer)
#ENTRENAMIENTO DE LA RED NEURONAL
trndata,partdata=ds.splitWithProportion(0.60)
tstdata,validata=partdata.splitWithProportion(0.50)
print ("Datos para Validacion:",len(validata))
print("Datos para Test:", len(tstdata))
print("Datos para Entrenamiento:", len(trndata))
treinadorSupervisionado = BackpropTrainer(n, dataset=trndata,momentum=0.1,verbose=True,weightdecay=0.01)
numeroDeEpocasPorPunto = 100
trnerr,valerr=treinadorSupervisionado.trainUntilConvergence(dataset=trndata,maxEpochs=numeroDeEpocasPorPunto)
max_anno = input.max(axis=0)[0]
min_anno = input.min(axis=0)[0]
max_precip = output.max()
min_precip = output.min()
print("El primer año de la serie temporal disponible es:", min_anno)
print("El ultimo año de la serie temporal disponible es:", max_anno)
print("La máxima precipitación registrada en la serie temporal es:", max_precip)
print("La mínima precipitación registrada en la serie temporal es:", min_precip)
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
plt.xlabel('número de épocas')
plt.ylabel(u'Error')
plt.plot(trnerr,'b',valerr,'r')
plt.show()
treinadorSupervisionado.trainOnDataset(trndata,50)
print(treinadorSupervisionado.totalepochs)
out=n.activateOnDataset(tstdata).argmax(axis=1)
print(percentError(out,tstdata))
out=n.activateOnDataset(tstdata)
out=out.argmax(axis=1)
salida=n.activateOnDataset(validata)
salida=salida.argmax(axis=1)
print(percentError(salida,validata))
print ('Pesos finales:', n.params)
#Parametros de la RNA:
for mod in n.modules:
print("Module:", mod.name)
if mod.paramdim > 0:
print("--parameters:", mod.params)
for conn in n.connections[mod]:
print("-connection to", conn.outmod.name)
if conn.paramdim > 0:
print("- parameters", conn.params)
if hasattr(n, "recurrentConns"):
print("Recurrent connections")
for conn in n.recurrentConns:
print("-", conn.inmod.name, " to", conn.outmod.name)
if conn.paramdim > 0:
print("- parameters", conn.params)
И вот какой сюжет я получаю после запуска кода:
Где синяя линия-ошибка обучения,а красная - ошибка проверки.Это не имеет никакого смысла. Я искал другие вопросы, но до сих пор не знаю, почему у меня такой результат.
Мой желаемый результат-предсказать, например, количество осадков за каждый месяц в последующие годы , например за 2010 год (серия идет с 1851 по 2008 год).
1 ответ:
Проверив ваш набор данных, я заметил, что это данные временного ряда. Обычно использование времени (месяца и года) в качестве функций не работает хорошо в этом случае.
Наиболее распространенными архитектурами для предсказания временных рядов являются RNN и его модернизированная версия LSTM. Есть хороший учебник по LSTM с использованием Keras в http://machinelearningmastery.com/time-series-prediction-lstm-recurrent-neural-networks-python-keras/Я попытался обучить LSTM (на основе учебника), используя ваш dataset и получил более красивый тренд потери валидации:
Я обучил LSTM (100 epoch) предсказывать осадки на основе данных за предыдущие 12 месяцев:
import numpy import matplotlib.pyplot as plt import pandas import math from keras.models import Sequential from keras.layers import Dense, LSTM, Dropout from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_squared_error # convert an array of values into a dataset matrix def create_dataset(dataset, look_back=1): dataX, dataY = [], [] for i in range(len(dataset) - look_back - 1): a = dataset[i:(i + look_back), 0] dataX.append(a) dataY.append(dataset[i + look_back, 0]) return numpy.array(dataX), numpy.array(dataY) # load the dataset dataframe = pandas.read_csv('salidas.csv', usecols=[0], engine='python') dataset = dataframe.values dataset = dataset.astype('float32') # normalize the dataset scaler = MinMaxScaler(feature_range=(0, 1)) dataset = scaler.fit_transform(dataset) # split into train and test sets train_size = int(len(dataset) * 0.67) test_size = len(dataset) - train_size train, test = dataset[0:train_size, :], dataset[train_size:len(dataset), :] # reshape into X=t and Y=t+1 look_back = 12 trainX, trainY = create_dataset(train, look_back) testX, testY = create_dataset(test, look_back) # reshape input to be [samples, time steps, features] trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1])) testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1])) # create and fit the LSTM network model = Sequential() model.add(LSTM(4, input_dim=look_back)) model.add(Dropout(0.2)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') history = model.fit(trainX, trainY, validation_split=0.33, nb_epoch=100, batch_size=1) # summarize history for loss plt.plot(history.history['loss']) plt.plot(history.history['val_loss']) plt.title('model loss') plt.ylabel('loss') plt.xlabel('epoch') plt.legend(['train', 'validation'], loc='upper left') plt.show()