2016-06-14 5 views
0

인공 신경망을 이용한 수질 예측 프로젝트를 진행하고 있습니다. 파이썬을 사용하여 구현했습니다. 내 예측 모델을 완료했지만 생성 된 예측이 정확하지 않습니다.신경망에서 정확한 예측을 얻으려면 어떻게해야합니까?

내가하고있는 일은 지난 4 년 반 동안 매일 강을 따라 데이터를 수집했으며 과거 기록에서 데이터를 입력하여 특정 매개 변수에 대한 패턴을 예측합니다. 제가해야 할 일은 2012 년부터 2014 년까지 탁도에 대한 데이터를 입력하여 2015 년 물의 탁도 수준을 예측하는 것입니다.

내가 만든 모델에서 내가 2015 년에 수집 한 실제 데이터와 비교하면 정확하지 않습니다.이 문제를 해결하도록 도와주세요. 숨겨진 레이어 크기와 람다 값을 변경하여이 작업을 시도했습니다. // 탁도

//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 실제 데이터를 의미하며, 예측 된 데이터는 코드 enter image description here

+1

시그 모이 드의 출력 범위는 '[0, 1]'입니다. 목표 값을 조절해야합니다. – jorgenkg

+0

입력 및 출력을 조정했습니다. S 자형 함수가 필요한 크기 조정이 있습니까? – Akisha

+0

그런 다음 이미지 예측에 대한 스케일링을 되 돌리십시오. 그렇지 않으면 공정한 비교 방법을 모릅니다. –

답변

1

주석의 일부가 정확한 데이터와 일치하는 출력 S 자형 층 스케일링 제안을 사용하여 예측을 의미한다. 당신이 당신의 예측을 보면, 어떤 스케일링으로는 꽤 정확하다는 것을 알 수 있습니다. 그러나 나는 S 자형 함수를 스케일링하지 말 것을 권한다.

시그 모이 output 출력은 확률로 해석되어야하기 때문에 (일정한 제약 조건이 주어지면) 확률이 높아지면 계약을 위반하게되고 정의되지 않은 결과가 발생할 수 있습니다. 0-100으로 확장 한 후 100보다 큰 학습 목표를 받기 시작하면 어떻게됩니까? (당신이 온라인 시스템을 배우고 있다고 가정한다면, 그렇지 않을 수도 있습니다.)

선형 출력 레이어를 사용하도록 코드를 변경합니다. 네트워크를 교육 한 후 데이터를 조작 할 필요가 없습니다. 또한 귀하의 비용 함수가 최소 제곱이므로, 선형 출력 레이어는 볼록 (알고리즘이 고착 될 수있는 로컬 최적 수의 수를 줄입니다)됩니다.

+0

귀하의 의견에 진심으로 감사드립니다. 나는 그것에 따라 변화 시키려고 노력할 것이다. – Akisha

관련 문제