【问题标题】:How to get accurate predictions from Neural Network?如何从神经网络中获得准确的预测?
【发布时间】:2016-06-14 17:35:28
【问题描述】:

我正在做一个使用人工神经网络进行水质预测的项目。我使用python实现了这个。我已经完成了我的预测模型,但生成的预测不太准确。

我正在做的是我每天从河流收集数据,过去 4 年半,我通过输入过去记录的数据来预测特定参数的模式。我需要做的只是通过提供 2012-2014 年的浊度数据来预测 2015 年水的“浊度水平”。

从我创建的模型来看,与我收集的 2015 年的真实数据相比,它不太准确。请帮我解决这个问题。我尝试通过更改隐藏层大小和 Lambda 值来实现这一点。

//This is my code

import xlrd
import numpy as np
from numpy import zeros
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy import optimize

#Neural Network

class Neural_Network(object):

    def __init__(self,Lambda):        
        #Define Hyperparameters
        self.inputLayerSize = 2
        self.outputLayerSize = 1
        self.hiddenLayerSize = 10
        #Weights (parameters)
        self.W1 = np.random.randn(self.inputLayerSize,self.hiddenLayerSize)
        self.W2 = np.random.randn(self.hiddenLayerSize,self.outputLayerSize)

        #Regularization Parameter:
        self.Lambda = Lambda

    def forward(self, arrayInput):
        #Propogate inputs though network
        self.z2 = np.dot(arrayInput, self.W1)
        self.a2 = self.sigmoid(self.z2)
        self.z3 = np.dot(self.a2, self.W2)
        yHat = self.sigmoid(self.z3) 
        return yHat

    def sigmoid(self, z):
        #Apply sigmoid activation function to scalar, vector, or matrix
        return 1/(1+np.exp(-z))

    def sigmoidPrime(self,z):
        #Gradient of sigmoid
        return np.exp(-z)/((1+np.exp(-z))**2)

    def costFunction(self, arrayInput, arrayOutput):
        #Compute cost for given input,output use weights already stored in class.       
        self.yHat = self.forward(arrayInput)
        #J = 0.5*sum((arrayOutput-self.yHat)**2)
        #J = 0.5*sum((arrayOutput-self.yHat)**2)/arrayInput.shape[0] + (self.Lambda/2)
        J = 0.5*sum((arrayOutput-self.yHat)**2)/arrayInput.shape[0] + (self.Lambda/2)*sum(sum(self.W1**2),sum(self.W2**2))
        #J = 0.5*sum((arrayOutput-self.yHat)**2)/arrayInput.shape[0] + (self.Lambda/2)*(sum(self.W1**2)+sum(self.W2**2))       
        return J

    def costFunctionPrime(self, arrayInput, arrayOutput):
        #Compute derivative with respect to W and W2 for a given X and y:
        self.yHat = self.forward(arrayInput)

        delta3 = np.multiply(-(arrayOutput-self.yHat), self.sigmoidPrime(self.z3))
        #Add gradient of regularization term:
        #dJdW2 = np.dot(self.a2.T, delta3) + self.Lambda*self.W2
        dJdW2 = np.dot(self.a2.T, delta3)

        delta2 = np.dot(delta3, self.W2.T)*self.sigmoidPrime(self.z2)
        #Add gradient of regularization term:
        #dJdW1 = np.dot(arrayInput.T, delta2)+ self.Lambda*self.W1
        dJdW1 = np.dot(arrayInput.T, delta2)  

        return dJdW1, dJdW2

    #Helper Functions for interacting with other classes:
    def getParams(self):
        #Get W1 and W2 unrolled into vector:
        params = np.concatenate((self.W1.ravel(), self.W2.ravel()))
        return params

    def setParams(self, params):
        #Set W1 and W2 using single paramater vector.
        W1_start = 0
        W1_end = self.hiddenLayerSize * self.inputLayerSize
        self.W1 = np.reshape(params[W1_start:W1_end], (self.inputLayerSize , self.hiddenLayerSize))
        W2_end = W1_end + self.hiddenLayerSize*self.outputLayerSize
        self.W2 = np.reshape(params[W1_end:W2_end], (self.hiddenLayerSize, self.outputLayerSize))

    def computeGradients(self, arrayInput, arrayOutput):
        dJdW1, dJdW2 = self.costFunctionPrime(arrayInput, arrayOutput)        
        return np.concatenate((dJdW1.ravel(), dJdW2.ravel()))

    def computeNumericalGradient(self,N, X, y):
        paramsInitial = N.getParams()        
        numgrad = np.zeros(paramsInitial.shape)
        perturb = np.zeros(paramsInitial.shape)
        e = 1e-4

        for p in range(len(paramsInitial)):
            #Set perturbation vector
            perturb[p] = e
            N.setParams(paramsInitial + perturb)
            loss2 = N.costFunction(X, y)

            N.setParams(paramsInitial - perturb)
            loss1 = N.costFunction(X, y)

            #Compute Numerical Gradient
            numgrad[p] = (loss2 - loss1) / (2*e)            

            #Return the value we changed to zero:
            perturb[p] = 0

        #Return Params to original value:
        N.setParams(paramsInitial)
        return numgrad

#Trainer class    
class trainer(object):
    def __init__(self, N):
        self.N = N

    def costFunctionWrapper(self, params, arrayInput, arrayOutput):
        self.N.setParams(params)
        cost = self.N.costFunction(arrayInput, arrayOutput)
        #grad = self.N.computeGradients(arrayInput, arrayOutput)
        grad = self.N.computeNumericalGradient(self.N,arrayInput, arrayOutput)
        return cost, grad

    def callbackF(self, params):
        self.N.setParams(params)
        self.J.append(self.N.costFunction(self.arrayInput, self.arrayOutput))
        self.testJ.append(self.N.costFunction(self.TestInput, self.TestOutput))

    def train(self, arrayInput, arrayOutput,TestInput,TestOutput):
        #Make an internal variable for the callback function:
        self.arrayInput = arrayInput
        self.arrayOutput = arrayOutput

        self.TestInput = TestInput
        self.TestOutput = TestOutput

        #Make empty list to store costs:
        self.J = []
        self.testJ= []

        params0 = self.N.getParams()

        options = {'maxiter': 200, 'disp' : True}
        _res = optimize.minimize(self.costFunctionWrapper, params0, jac=True, method='BFGS', \
                                 args=(arrayInput, arrayOutput), options=options, callback=self.callbackF)

        self.N.setParams(_res.x)
        self.optimizationResults = _res



#Main Program   

path = "F:\prototype\\newdata\\tody\\turbidity\\c.xlsx"
book = xlrd.open_workbook(path)

input1=[]
output=[]
testinput=[]
testoutput=[]

#training data set
first_sheet = book.sheet_by_index(1)
for row in range(first_sheet.ncols-1):
    input1.append(first_sheet.col_values(row))

for row in range((first_sheet.ncols-1),first_sheet.ncols ):
    output.append(first_sheet.col_values(row))

arrayInput = np.asarray(input1)
arrayInput = arrayInput.T
arrayOutput = np.asarray(output)
arrayOutput = arrayOutput.T

#testing data set
first_sheet1 = book.sheet_by_index(0)
for row in range(first_sheet1.ncols-1):
    testinput.append(first_sheet1.col_values(row))

for row in range((first_sheet1.ncols-1),first_sheet1.ncols ):
    testoutput.append(first_sheet1.col_values(row))

TestInput = np.asarray(testinput)
TestInput = TestInput.T
TestOutput = np.asarray(testoutput)
TestOutput = TestOutput.T

#2016
input2016=[]
first_sheet2 = book.sheet_by_index(2)
for row in range(first_sheet2.ncols):
    input2016.append(first_sheet2.col_values(row))

Input = np.asarray(input2016)
Input = Input.T

# Scaling
arrayInput = arrayInput / np.amax(arrayInput, axis=0)
arrayOutput = arrayOutput / np.amax(arrayOutput, axis=0)

TestInput = TestInput / np.amax(TestInput, axis=0)
Input = Input / np.amax(Input, axis=0)
TestOutput = TestOutput / np.amax(TestOutput, axis=0)

NN=Neural_Network(Lambda=0.00000000000001)

T = trainer(NN)
T.train(arrayInput,arrayOutput,TestInput,TestOutput)


print NN.costFunctionPrime(arrayInput,arrayOutput)

Output =  NN.forward(Input)
print Output
print '----------'
#print TestOutput

#plt.plot(T.J)
plt.plot(Output)
plt.grid(1)
plt.xlabel('Iterations')
plt.ylabel('cost')
plt.show()

//浊度表示2015年真实数据,预测表示使用此代码预测的数据

【问题讨论】:

  • Sigmoid 的输出范围为 '[0, 1]'。您需要缩放目标值
  • 我已经扩展了我的输入和输出。 t sigmoid 函数是否需要任何缩放?
  • 然后恢复图像预测的缩放比例,否则我们不知道如何进行公平比较。

标签: python scikit-learn neural-network prediction


【解决方案1】:

一些 cmets 建议缩放输出 sigmoid 层以匹配正确的数据。如果您查看您的预测,您会发现通过一些缩放,它们非常准确。不过,我建议不要缩放 sigmoidal 函数。

一个 sigmoidal 输出被解释为一个概率(给定遵循某些约束),因此缩放它会破坏该合同并且可能会产生未定义的结果。如果从 0 到 100 进行缩放,但随后开始接受大于 100 的训练目标,会发生什么情况? (假设您正在训练一个在线系统,否则该示例可能不相关)

我会更改您的代码以使用线性输出层。这不需要在训练网络后对数据进行任何操作。此外,鉴于您的成本函数是最小二乘法,线性输出层将是凸的(这减少了您的算法可能陷入的局部最优值的数量)。

【讨论】:

  • 非常感谢您的反馈。我会尝试根据它来改变。
猜你喜欢
  • 2018-05-05
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
  • 1970-01-01
  • 2016-07-28
  • 2017-08-31
  • 2017-12-02
  • 1970-01-01
相关资源
最近更新 更多