制作正确的ANN用于预测

时间:2017-02-12 12:23:32

标签: python artificial-intelligence forecasting pybrain

这是我第一次使用python,所以我有很多疑问。

我正在尝试在Pybrain中制作一个简单的ANN进行预测。它是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)

这是我在运行代码后获得的情节:

Error vs Epochs

蓝线是训练错误,红线是验证错误。

这没有任何意义。我已经搜索了其他问题,但我仍然不知道为什么我会得到这个结果。

我希望的结果是预测,例如,接下来几年每个月的降雨量,例如2010年(该系列从1851年到2008年)。

1 个答案:

答案 0 :(得分:2)

检查数据集后,我注意到它是时间序列数据。通常使用时间(月份和年份)作为功能在这种情况下不能很好地工作。

预测时间序列的最常见架构是RNN及其升级版本LSTM。在http://machinelearningmastery.com/time-series-prediction-lstm-recurrent-neural-networks-python-keras/

中使用Keras有一个很好的LSTM教程

我尝试使用您的数据集训练LSTM(基于教程)并获得更好看的验证损失趋势:

loss chart

我训练LSTM(100个纪元)根据前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()