BP neural network regression prediction model (python implementation)

       Neural network models are generally used for classification, and regression prediction models are not common. Based on a BP neural network used for classification, this paper modifies it and implements a regression model for indoor positioning. The main change of the model is to remove the nonlinear transformation of the third layer, or to replace the nonlinear activation function Sigmoid with the f(x)=x function. The main reason for this is that the output range of the sigmoid function is too small, between 0-1, while the output range of the regression model is larger. The model is modified as follows:



code show as below:

#coding: utf8
''''
author: Huangyuliang
'''
import json
import random
import sys
import numpy as np

#### Define the quadratic and cross-entropy cost functions
class CrossEntropyCost(object):

    @staticmethod
    def fn(a, y):
        return np.sum (np.nan_to_num (-y * np.log (a) - (1-y) * np.log (1-a)))

    @staticmethod
    def delta(z, a, y):
        return (a-y)

#### Main Network class
class Network(object):

    def __init__(self, sizes, cost=CrossEntropyCost):

        self.num_layers = len(sizes)
        self.sizes = sizes
        self.default_weight_initializer()
        self.cost=cost

    def default_weight_initializer(self):

        self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
        self.weights = [np.random.randn(y, x)/np.sqrt(x)
                        for x, y in zip(self.sizes[:-1], self.sizes[1:])]
    def large_weight_initializer(self):

        self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(self.sizes[:-1], self.sizes[1:])]
    def feedforward(self, a):
        """Return the output of the network if ``a`` is input."""
        for b, w in zip(self.biases[:-1], self.weights[:-1]): # 前n-1层
            a = sigmoid(np.dot(w, a)+b)

        b = self.biases[-1] # last layer
        w = self.weights[-1]
        a = np.dot(w, a)+b
        return a

    def SGD(self, training_data, epochs, mini_batch_size, eta,
            lmbda = 0.0,
            evaluation_data=None,
            monitor_evaluation_accuracy=False): # Train with stochastic gradient descent

        n = len(training_data)

        for j in xrange(epochs):
            random.shuffle(training_data)
            mini_batches = [training_data[k:k+mini_batch_size] for k in xrange(0, n, mini_batch_size)]
            
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch, eta, lmbda, len(training_data))
            print ("Epoch %s training complete" % j)
            
            if monitor_evaluation_accuracy:
                print ("Accuracy on evaluation data: {} / {}".format(self.accuracy(evaluation_data), j))
         
    def update_mini_batch(self, mini_batch, eta, lmbda, n):
        """Update the network's weights and biases by applying gradient
        descent using backpropagation to a single mini batch.  The
        ``mini_batch`` is a list of tuples ``(x, y)``, ``eta`` is the
        learning rate, ``lmbda`` is the regularization parameter, and
        ``n`` is the total size of the training data set.
        """
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        for x, y in mini_batch:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
        self.weights = [(1-eta*(lmbda/n))*w-(eta/len(mini_batch))*nw
                        for w, nw in zip(self.weights, nabla_w)]
        self.biases = [b-(eta/len(mini_batch))*nb
                       for b, nb in zip(self.biases, nabla_b)]

    def backprop(self, x, y):
        """Return a tuple ``(nabla_b, nabla_w)`` representing the
        gradient for the cost function C_x.  ``nabla_b`` and
        ``nabla_w`` are layer-by-layer lists of numpy arrays, similar
        to ``self.biases`` and ``self.weights``."""
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # feedforward
        activation = x
        activations = [x] # list to store all the activations, layer by layer
        zs = [] # list to store all the z vectors, layer by layer
        for b, w in zip(self.biases[:-1], self.weights[:-1]): # Forward pass first n-1 layers

            z = np.dot(w, activation)+b
            zs.append(z)
            activation = sigmoid(z)
            activations.append(activation)
# The last layer, no non-linear
        b = self.biases[-1]
        w = self.weights[-1]
        z = np.dot(w, activation)+b
        zs.append(z)
        activation = z
        activations.append(activation)
        # backward pass back propagation
        delta = (self.cost).delta(zs[-1], activations[-1], y) # error Tj - Oj
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())  #  (Tj - Oj) * O(j-1)

        for l in xrange(2, self.num_layers):
            z = zs [-l] # w*a + b
            sp = sigmoid_prime (z) # z * (1-z)
            delta = np.dot(self.weights[-l+1].transpose(), delta) * sp # z*(1-z)*(Err*w) hidden layer error
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())  # Errj * Oi
        return (nabla_b, nabla_w)

    def accuracy(self, data):

        results = [(self.feedforward(x), y) for (x, y) in data]  
        alist=[np.sqrt((x[0][0]-y[0])**2+(x[1][0]-y[1])**2) for (x,y) in results]

        return np.mean(alist)

    def save(self, filename):
        """Save the neural network to the file ``filename``."""
        data = {"sizes": self.sizes,
                "weights": [w.tolist() for w in self.weights],
                "biases": [b.tolist() for b in self.biases],
                "cost": str(self.cost.__name__)}
        f = open(filename, "w")
        json.dump(data, f)
        f.close()

#### Loading a Network
def load(filename):
    """Load a neural network from the file ``filename``.  Returns an
    instance of Network.
    """
    f = open(filename, "r")
    data = json.load(f)
    f.close()
    cost = getattr(sys.modules[__name__], data["cost"])
    net = Network(data["sizes"], cost=cost)
    net.weights = [np.array(w) for w in data["weights"]]
    net.biases = [np.array(b) for b in data["biases"]]
    return net

def sigmoid(z):
    """The sigmoid function."""
    return 1.0/(1.0+np.exp(-z))
  
def sigmoid_prime(z):
    """Derivative of the sigmoid function."""
    return sigmoid(z)*(1-sigmoid(z))


Call the neural network for training and save the parameters:

#coding: utf8
import my_datas_loader_1
import network_0

training_data,test_data = my_datas_loader_1.load_data_wrapper()
#### Train the network and save the trained parameters
net = network_0.Network([14,100,2],cost = network_0.CrossEntropyCost)
net.large_weight_initializer()
net.SGD(training_data,1000,316,0.005,lmbda =0.1,evaluation_data=test_data,monitor_evaluation_accuracy=True)
filename=r'C:\Users\hyl\Desktop\Second_158\Regression_Model\parameters.txt'
net.save(filename)
 
 
The results of training rounds 190-199 are as follows:

Call the saved parameters for positioning prediction:
#coding: utf8
import my_datas_loader_1
import network_0
import matplotlib.pyplot as plt

test_data = my_datas_loader_1.load_test_data()
#### Call the trained network for prediction
filename=r'D:\Workspase\Nerual_networks\parameters.txt' ## The file saves the trained parameters
net = network_0.load(filename) ## call parameters to form a network
fig=plt.figure(1)
ax=fig.add_subplot(1,1,1)
ax.axis("equal")
# plt.grid(color='b' , linewidth='0.5' ,linestyle='-') # Add grid
x=[-0.3,-0.3,-17.1,-17.1,-0.3] ## This is the outline of the terrain on the ninth floor
y=[-0.3,26.4,26.4,-0.3,-0.3]
m=[1.5,1.5,-18.9,-18.9,1.5]
n=[-2.1,28.2,28.2,-2.1,-2.1]
ax.plot(x,y,m,n,c='k')

for i in range(len(test_data)):   
    pre = net.feedforward(test_data[i][0]) # pre is the predicted coordinate        
    bx = for [0]
    by=pre[1]                    
    ax.scatter(bx,by,s=4,lw=2,marker='.',alpha=1) #scatterplot   
    plt.pause (0.001)
plt.show()
 
 
The positioning accuracy is about 1.5 meters. The positioning effect is shown in the following figure:


The real path is for pedestrians to circle the circular corridor from the origin.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325548177&siteId=291194637