美文网首页
神经网络识别手写优化(四)

神经网络识别手写优化(四)

作者: skullfang | 来源:发表于2018-01-08 16:08 被阅读0次

    <h1>前言</h1>
    该 修改的都修改了看看效果吧。
    <h1>代码</h1>

    # -*- coding: utf-8 -*-
    # @Time    : 2017/11/27 上午10:23
    # @Author  : SkullFang
    # @Email   : yzhang.private@gmail.com
    # @File    : FiveDemo.py
    # @Software: PyCharm
    import random
    import json
    import sys
    import numpy as np
    class QuadraticCost(object):
        @staticmethod #静态函数注解
        def fn(a,y):
            return 0.5 * np.linalg.norm(a-y) **2
    
        @staticmethod
        def delta(z,a,y):
            return (a-y) * sigmoid_prime(z)
    
    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):
            """
            :param z:无用 
            :param a: 
            :param y: 
            :return: 
            """
            return a-y
    
    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_initialzer(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(sizes[:-1], self.sizes[1:])]
    
    
        def feedforward(self, a):
            for b, w in zip(self.biases, self.weights):
                a = sigmoid(np.dot(w, a) + b)
            return a
    
        # 随机梯度下降
        def SGD(self, training_data, epochs, mini_batch_size, eta,lmbda,
                test_data=None):
            if test_data: n_test = len(test_data)
            # 训练数据总个数
            n = len(training_data)
    
            # 开始训练 循环每一个epochs
            for j in xrange(epochs):
                # 洗牌 打乱训练数据
                random.shuffle(training_data)
    
                # mini_batch
                mini_batches = [training_data[k:k + mini_batch_size]
                                for k in range(0, n, mini_batch_size)]
    
    
                # 训练mini_batch
                for mini_batch in mini_batches:
                    self.update_mini_batch(mini_batch, eta,lmbda,n)
    
    
    
                # print "Epoch {0} complete".format(j)
                #
                #
                # if test_data:
                #     print "Epoch {0}: {1} / {2}".format(
                #
                #          j, self.evaluate(test_data), n_test)
                print "Epoch %s training complete" % j
    
                cost = self.total_cost(training_data, lmbda)
                print "Cost on training data: {}".format(cost)
                accuracy = self.accuracy(training_data, convert=True)
                print "Accuracy on training data: {} / {}".format(accuracy, n)
    
                if test_data:
                    cost = self.total_cost(test_data, lmbda, convert=True)
                    print "Cost on test data: {}".format(cost)
                    accuracy = self.accuracy(test_data)
                    print "Accuracy on test data: {} / {}".format(accuracy, len(test_data))
    
        # 更新mini_batch
        def update_mini_batch(self, mini_batch, eta,lmbda,n):
            # 保存每层偏倒
            nabla_b = [np.zeros(b.shape) for b in self.biases]
            nabla_w = [np.zeros(w.shape) for w in self.weights]
    
            # 训练每一个mini_batch
            for x, y in mini_batch:
                delta_nable_b, delta_nabla_w = self.update(x, y)
    
                # 保存一次训练网络中每层的偏倒
                nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nable_b)]
                nabla_w = [nw + dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
    
            # 更新权重和偏置 Wn+1 = wn - eta * nw
            self.weights = [w -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 update(self, x, y):
            # 保存每层偏倒
            nabla_b = [np.zeros(b.shape) for b in self.biases]
            nabla_w = [np.zeros(w.shape) for w in self.weights]
    
            activation = x
    
            # 保存每一层的激励值a=sigmoid(z)
            activations = [x]
    
            # 保存每一层的z=wx+b
            zs = []
            # 前向传播
            for b, w in zip(self.biases, self.weights):
                # 计算每层的z
                z = np.dot(w, activation) + b
    
                # 保存每层的z
                zs.append(z)
    
                # 计算每层的a
                activation = sigmoid(z)
    
                # 保存每一层的a
                activations.append(activation)
    
            # 反向更新了
            # 计算最后一层的误差
           # delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1])
            delta=(self.cost).delta(zs[-1],activations[-1],y)
            # 最后一层权重和偏置的倒数
            nabla_b[-1] = delta
            nabla_w[-1] = np.dot(delta, activations[-2].transpose())
    
            # 倒数第二层一直到第一层 权重和偏置的倒数
            for l in range(2, self.num_layers):
                z = zs[-l]
    
                sp = sigmoid_prime(z)
    
                # 当前层的误差
                delta = np.dot(self.weights[-l+1].transpose(), delta) * sp
    
                # 当前层偏置和权重的倒数
                nabla_b[-l] = delta
                nabla_w[-l] = np.dot(delta, activations[-l - 1].transpose())
    
            return (nabla_b, nabla_w)
    
        def evaluate(self, test_data):
            test_results = [(np.argmax(self.feedforward(x)), y)
                            for (x, y) in test_data]
            return sum(int(x == y) for (x, y) in test_results)
    
        def accuracy(self, data,convert=False):
            """
            计算准确率
            :param data: 
            :param convert: 看是不是测试集,因为训练集的标签是10维向量。测试集是数字
            :return: 
            """
            if convert:
                results = [(np.argmax(self.feedforward(x)), np.argmax(y))
                           for (x, y) in data]
            else:
                results = [(np.argmax(self.feedforward(x)), y)
                            for (x, y) in data]
            return sum(int(x == y) for (x, y) in results)
    
        def total_cost(self,data,lmbda,convert=False):
            """
            计算总损失
            :param data: 
            :param lmbda: 
            :param convert: 
            :return: 
            """
            cost=0.0
            for x,y in data:
                a=self.feedforward(x)
                if convert:
                    y= vectorized_result(y)
                cost+=self.cost.fn(a,y)/len(data)
    
            cost +=0.5*(lmbda/len(data))*sum(np.linalg.norm(w)**2 for w in self.weights)
            return cost
    
    
    
        def cost_derivative(self, output_activation, y):
            return (output_activation - y)
    
        def save(self,filename):
            """
            模型保存
            :param filename: 文件名 
            :return: 
            """
            data ={ "sizes": self.sizes, #模型结构
                    "weights": [w.tolist() for w in self.weights], #tolist转换为列表类型
                    "biases": [b.tolist() for b in self.biases],
                    "cost": str(self.cost.__name__) #保存一下损失函数
            }
            f=open(filename,"w")
            json.dump(data,f)
            f.close()
    def vectorized_result(j):
            """Return a 10-dimensional unit vector with a 1.0 in the j'th position
            and zeroes elsewhere.  This is used to convert a digit (0...9)
            into a corresponding desired output from the neural network.
    
            """
            e = np.zeros((10, 1))
            e[j] = 1.0
            return e
    
    def load(filename):
        """
        加载模型
        :param filename: 
        :return: 
        """
        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):
        return 1.0 / (1.0 + np.exp(-z))
    
    
    def sigmoid_prime(z):
        return sigmoid(z) * (1 - sigmoid(z))
    
    
    if __name__ == '__main__':
        from ProjectOne import mnist_loader
    
        traning_data, validation_data, test_data = mnist_loader.load_data_wrapper()
    
        net = Network([784, 60,10, 10])
        net.SGD(traning_data, 30, 10, 0.5, 5.0,test_data=test_data)
    

    相关文章

      网友评论

          本文标题:神经网络识别手写优化(四)

          本文链接:https://www.haomeiwen.com/subject/yfdwbxtx.html