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.