博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于梯度下降的神经网络
阅读量:5896 次
发布时间:2019-06-19

本文共 18152 字,大约阅读时间需要 60 分钟。

一、特点:

0.无监督的神经网络1.基于梯度下降2.固定学习速率3.离线学习(批量学习) 4.隐藏层数目范围:[1, +∞)4.可以选择激活函数类型5.numpy的矩阵运算(黑科技) 6.友好的 API (高仿sklearn, 没办法,太好用了 ^_^!!!) 7.测试用到了sklearn库的datasets获取数据,未安装的朋友pip安装即可 8.神经网络学习过程的形象描述:正向传播、反向传播像海浪一样来回冲刷权值W与偏置b 9.用数组的形式实现各层的权值(矩阵)和偏置(向量),其好处是可以用循环来处理各个层。从而可以对隐藏层的数目没有了限制!!附图: 10.忍不住再补充一个想法:上面这个图可以泛化应用到各种循环流水作业的场景 二、效果: 未分类: 隐藏层:[6,4]效果:
隐藏层:[6,5,3]效果:
隐藏层:[6,8,5]效果:
隐藏层:[7,9,12,8,5]效果:(看来不是隐藏层越多,效果越好啊!)
三、代码:

 

import numpy as np'''无监督的神经网络1.基于梯度下降2.固定学习速率3.离线学习(批量学习)4.可以选择激活函数类型5.numpy强大的矩阵运算能力'''class NeuralNetworks(object):    '''    神经网络        用法:        >>> X = np.array([[0,0],[0,1],[1,0],[1,1]])        >>> y = np.array([0,1,2,3])                >>> hiden_layers = [4,6]        >>> active_type = ['sigmoid', 'sigmoid', 'sigmoid']        >>> nn = NeuralNetworks(hiden_layers, active_type)        >>> nn.fit(X, y)        >>> print(nn.predict(X))    '''    def __init__(self, hiden_layers=None, active_type=None, n_iter=10000, epsilon=0.01, lamda=0.01, only_hidens=True):        '''接收部分参数'''        self.epsilon = epsilon  # 学习速率        self.lamda = lamda      # 正则化强度        self.n_iter = n_iter    # 迭代次数        if hiden_layers is None:            hiden_layers = [5] # 默认:隐藏层数目1,节点数目5        self.hiden_layers = hiden_layers # 各隐藏层节点数 (list)        self.only_hidens = only_hidens # 接收的是否仅仅是隐藏层,默认True                # 激活函数类型        self.active_functions = {            'sigmoid': self._sigmoid,            'tanh': self._tanh, # 只有这个激活函数才有效果!!            'radb': self._radb,            #'line': self._line, #会出错!        }                # 激活函数的导函数类型        self.derivative_functions = {            'sigmoid': self._sigmoid_d,            'tanh': self._tanh_d,            'radb': self._radb_d,            #'line': self._line_d,        }                if active_type is not None:            self.active_type = active_type        else:            length = len(self.hiden_layers)            length = length + 1 if self.only_hidens else length - 1            self.active_type = ['tanh'] * length # 默认激活函数类型            print(length)            print(self.active_type)                def _sigmoid(self, z):        if np.max(z) > 600:            z[z.argmax()] = 600        return 1.0 / (1.0 + np.exp(-z))                def _tanh(self, z):        return (np.exp(z) - np.exp(-z)) / (np.exp(z) + np.exp(-z))                def _radb(self, z):        return np.exp(-z * z)                def _line(self, z):        return z                def _sigmoid_d(self, z):        return z * (1.0 - z)                def _tanh_d(self, z):        return 1.0 - z * z                def _radb_d(self, z):        return -2.0 * z * np.exp(-z * z)                def _line_d(self, z):        return np.ones(z.size) # 全一            def _build(self, X, y):        '''构建网络'''        self.X = X        self.y = y                # 变量        self.n_examples = y.size            # 样本集数目        self.n_features = X[0].size         # 样本特征数目        self.n_classes = np.unique(y).size  # 样本类别数目                all_layers = [] # 各层节点数目(输入、隐藏、输出) 其中隐藏层可多个!!        if self.only_hidens:            all_layers.append(self.n_features)            all_layers.extend(self.hiden_layers)            all_layers.append(self.n_classes)        else:            all_layers.extend(self.hiden_layers)                # 节点数目 (向量)        self.n = np.array(all_layers) # 如:[3, 4, 2]        self.size = self.n.size # 层的总数,如上:3                # 层 (向量)        self.a = np.empty(self.size, dtype=object)        self.delta_a = np.empty(self.size, dtype=object)                # 偏置 (向量)        self.b = np.empty(self.size - 1, dtype=object)# 先占位(置空),dtype=object !如下皆然        self.delta_b = np.empty(self.size - 1, dtype=object)        # 权 (矩阵)        self.W = np.empty(self.size - 1, dtype=object)        self.delta_W = np.empty(self.size - 1, dtype=object)        # 填充        mu, sigma = 0, 0.1 # 均值、方差        for i in range(self.size):            self.a[i] = np.ones(self.n[i])            self.delta_a[i] = np.zeros(self.n[i])            if i < self.size - 1:                self.b[i] = np.ones(self.n[i+1])   # 全一                self.W[i] = np.random.normal(mu, sigma, (self.n[i], self.n[i+1]))  # # 正态分布随机化                self.delta_b[i] = np.zeros(self.n[i+1])                 self.delta_W[i] = np.zeros((self.n[i], self.n[i+1]))    def _forward(self, X):        '''前向传播(批量)'''        self.a[0] = X # 便于使用循环        for i in range(self.size - 1):            nets = np.dot(self.a[i], self.W[i]) + self.b[i]            #self.a[i+1] = np.tanh(nets)            self.a[i+1] = self.active_functions[self.active_type[i]](nets) # 加了激活函数                exp_scores = np.exp(nets) # 注意这里还是 nets!!        probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)        return probs            def _backward(self, probs):        '''反向传播(批量)'''        last = self.size - 1                self.delta_a[last] = probs        self.delta_a[last][range(self.n_examples), self.y] -= 1        for i in range(last - 1, -1, -1):            # 注意:因为是全部样本,所以有些地方要转置,或者前后换位            self.delta_W[i] = np.dot(self.a[i].T, self.delta_a[i+1])            self.delta_b[i] = np.sum(self.delta_a[i+1], axis=0)            #self.delta_a[i] = np.dot(self.delta_a[i+1], self.W[i].T) * (1 - self.a[i]**2)            self.delta_a[i] = np.dot(self.delta_a[i+1], self.W[i].T) * self.derivative_functions[self.active_type[i]](self.a[i]) # 加了激活函数的导函数                        # 正则化            self.delta_W[i] += self.lamda * self.W[i]            #self.delta_b[i] += 0.0                        # 梯度下降            self.W[i] += -self.epsilon * self.delta_W[i]            self.b[i] += -self.epsilon * self.delta_b[i]    def _calculate_loss(self):        '''损失函数(批量)'''        probs = self._forward(self.X) # 批量: self.X                # 计算损失        corect_logprobs = -np.log(probs[range(self.n_examples), self.y])        data_loss = np.sum(corect_logprobs)                # 添加正则项损失(可选)        data_loss += self.lamda/2 * (sum([np.sum(np.square(w)) for w in self.W]))        return 1./self.n_examples * data_loss            def fit(self, X, y):        '''拟合'''        # 将神经网络搭建完整        self._build(X, y)                # 按迭代次数,依次:        for i in range(self.n_iter):            # 前向传播            probs = self._forward(self.X)            # 反向传播            self._backward(probs)            # 计算损失            if i % 1000 == 0:                loss = self._calculate_loss()                print("迭代次数:{}\t损失: {}".format(i, loss))    def predict(self, x):        '''预测(批量)'''        probs = self._forward(x)        return np.argmax(probs, axis=1)                # 以下皆为测试#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>def plot_decision_boundary(plt, xx, yy, Z, X, y, title):    '''作图函数'''    # 等高线图    plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)    # 散点图    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)        plt.xlabel('萼片长度')    plt.ylabel('萼片宽度')    plt.xlim(xx.min(), xx.max())    plt.ylim(yy.min(), yy.max())    plt.xticks(())    plt.yticks(())    plt.title(title)    plt.show()    def test2():    '''第二个测试函数'''    import matplotlib.pyplot as plt    from sklearn import datasets    # --------------------------------------------    # 解决matplotlib中文乱码    plt.rcParams['font.sans-serif'] = ['SimHei']    plt.rcParams['axes.unicode_minus'] = False    # --------------------------------------------        # ======================================================    # 生成数据    np.random.seed(0)    X, y = datasets.make_moons(200, noise=0.20)    h = .02    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),                         np.arange(y_min, y_max, h))    # ======================================================        # 先作散点图,看看数据特点    plt.scatter(X[:,0], X[:,1], s=40, c=y, cmap=plt.cm.Spectral)    plt.show()    # 定义神经网络    nn = NeuralNetworks([6,5,3])    # 拟合    nn.fit(X, y)    # 预测    Z = nn.predict(np.c_[xx.ravel(), yy.ravel()])    Z = Z.reshape(xx.shape)    # 作图    plot_decision_boundary(plt, xx, yy, Z, X, y, "预测效果图")def test1():    '''第一个测试函数'''    # 第一步:准备数据    # 说明:逻辑异或(XOR)    X = np.array([[-1,-1],[-1,1],[1,-1],[1,1]])    y = np.array([0,1,2,3])        # 第二步:创建神经网络    # 说明:1.两个隐藏层,节点数目分别为4、6有两个节点    #       2.输入层和输出层节点数目自动识别,默认不输入    #       3.若包含输入层与输出层,可以设置参数 only_hidens=True    #         如:nn = NeuralNetworks([2, 4, 6, 4], only_hidens=True)    #    #       4.完整例子:nn = NeuralNetworks(hiden_layers=[4, 6],    #                                       active_type = ['tanh', 'tanh', 'tanh'],     #                                       n_iter=10000,     #                                       epsilon=0.01,     #                                       lamda=0.01,     #                                       only_hidens=True)    nn = NeuralNetworks([2, 4, 6, 4], active_type = ['tanh', 'tanh', 'sigmoid'], only_hidens=False)        # 第三步:拟合    nn.fit(X, y)        # 第四步:预测    print(nn.predict(X))        if __name__ == '__main__':    test1()    test2()

 

一、特点:

0.无监督的神经网络1.基于梯度下降2.固定学习速率3.离线学习(批量学习) 4.隐藏层数目范围:[1, +∞)4.可以选择激活函数类型5.numpy的矩阵运算(黑科技) 6.友好的 API (高仿sklearn, 没办法,太好用了 ^_^!!!) 7.测试用到了sklearn库的datasets获取数据,未安装的朋友pip安装即可 8.神经网络学习过程的形象描述:正向传播、反向传播像海浪一样来回冲刷权值W与偏置b 9.用数组的形式实现各层的权值(矩阵)和偏置(向量),其好处是可以用循环来处理各个层。从而可以对隐藏层的数目没有了限制!!附图: 10.忍不住再补充一个想法:上面这个图可以泛化应用到各种循环流水作业的场景 二、效果: 未分类: 隐藏层:[6,4]效果:
隐藏层:[6,5,3]效果:
隐藏层:[6,8,5]效果:
隐藏层:[7,9,12,8,5]效果:(看来不是隐藏层越多,效果越好啊!)
三、代码:

 

import numpy as np'''无监督的神经网络1.基于梯度下降2.固定学习速率3.离线学习(批量学习)4.可以选择激活函数类型5.numpy强大的矩阵运算能力'''class NeuralNetworks(object):    '''    神经网络        用法:        >>> X = np.array([[0,0],[0,1],[1,0],[1,1]])        >>> y = np.array([0,1,2,3])                >>> hiden_layers = [4,6]        >>> active_type = ['sigmoid', 'sigmoid', 'sigmoid']        >>> nn = NeuralNetworks(hiden_layers, active_type)        >>> nn.fit(X, y)        >>> print(nn.predict(X))    '''    def __init__(self, hiden_layers=None, active_type=None, n_iter=10000, epsilon=0.01, lamda=0.01, only_hidens=True):        '''接收部分参数'''        self.epsilon = epsilon  # 学习速率        self.lamda = lamda      # 正则化强度        self.n_iter = n_iter    # 迭代次数        if hiden_layers is None:            hiden_layers = [5] # 默认:隐藏层数目1,节点数目5        self.hiden_layers = hiden_layers # 各隐藏层节点数 (list)        self.only_hidens = only_hidens # 接收的是否仅仅是隐藏层,默认True                # 激活函数类型        self.active_functions = {            'sigmoid': self._sigmoid,            'tanh': self._tanh, # 只有这个激活函数才有效果!!            'radb': self._radb,            #'line': self._line, #会出错!        }                # 激活函数的导函数类型        self.derivative_functions = {            'sigmoid': self._sigmoid_d,            'tanh': self._tanh_d,            'radb': self._radb_d,            #'line': self._line_d,        }                if active_type is not None:            self.active_type = active_type        else:            length = len(self.hiden_layers)            length = length + 1 if self.only_hidens else length - 1            self.active_type = ['tanh'] * length # 默认激活函数类型            print(length)            print(self.active_type)                def _sigmoid(self, z):        if np.max(z) > 600:            z[z.argmax()] = 600        return 1.0 / (1.0 + np.exp(-z))                def _tanh(self, z):        return (np.exp(z) - np.exp(-z)) / (np.exp(z) + np.exp(-z))                def _radb(self, z):        return np.exp(-z * z)                def _line(self, z):        return z                def _sigmoid_d(self, z):        return z * (1.0 - z)                def _tanh_d(self, z):        return 1.0 - z * z                def _radb_d(self, z):        return -2.0 * z * np.exp(-z * z)                def _line_d(self, z):        return np.ones(z.size) # 全一            def _build(self, X, y):        '''构建网络'''        self.X = X        self.y = y                # 变量        self.n_examples = y.size            # 样本集数目        self.n_features = X[0].size         # 样本特征数目        self.n_classes = np.unique(y).size  # 样本类别数目                all_layers = [] # 各层节点数目(输入、隐藏、输出) 其中隐藏层可多个!!        if self.only_hidens:            all_layers.append(self.n_features)            all_layers.extend(self.hiden_layers)            all_layers.append(self.n_classes)        else:            all_layers.extend(self.hiden_layers)                # 节点数目 (向量)        self.n = np.array(all_layers) # 如:[3, 4, 2]        self.size = self.n.size # 层的总数,如上:3                # 层 (向量)        self.a = np.empty(self.size, dtype=object)        self.delta_a = np.empty(self.size, dtype=object)                # 偏置 (向量)        self.b = np.empty(self.size - 1, dtype=object)# 先占位(置空),dtype=object !如下皆然        self.delta_b = np.empty(self.size - 1, dtype=object)        # 权 (矩阵)        self.W = np.empty(self.size - 1, dtype=object)        self.delta_W = np.empty(self.size - 1, dtype=object)        # 填充        mu, sigma = 0, 0.1 # 均值、方差        for i in range(self.size):            self.a[i] = np.ones(self.n[i])            self.delta_a[i] = np.zeros(self.n[i])            if i < self.size - 1:                self.b[i] = np.ones(self.n[i+1])   # 全一                self.W[i] = np.random.normal(mu, sigma, (self.n[i], self.n[i+1]))  # # 正态分布随机化                self.delta_b[i] = np.zeros(self.n[i+1])                 self.delta_W[i] = np.zeros((self.n[i], self.n[i+1]))    def _forward(self, X):        '''前向传播(批量)'''        self.a[0] = X # 便于使用循环        for i in range(self.size - 1):            nets = np.dot(self.a[i], self.W[i]) + self.b[i]            #self.a[i+1] = np.tanh(nets)            self.a[i+1] = self.active_functions[self.active_type[i]](nets) # 加了激活函数                exp_scores = np.exp(nets) # 注意这里还是 nets!!        probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)        return probs            def _backward(self, probs):        '''反向传播(批量)'''        last = self.size - 1                self.delta_a[last] = probs        self.delta_a[last][range(self.n_examples), self.y] -= 1        for i in range(last - 1, -1, -1):            # 注意:因为是全部样本,所以有些地方要转置,或者前后换位            self.delta_W[i] = np.dot(self.a[i].T, self.delta_a[i+1])            self.delta_b[i] = np.sum(self.delta_a[i+1], axis=0)            #self.delta_a[i] = np.dot(self.delta_a[i+1], self.W[i].T) * (1 - self.a[i]**2)            self.delta_a[i] = np.dot(self.delta_a[i+1], self.W[i].T) * self.derivative_functions[self.active_type[i]](self.a[i]) # 加了激活函数的导函数                        # 正则化            self.delta_W[i] += self.lamda * self.W[i]            #self.delta_b[i] += 0.0                        # 梯度下降            self.W[i] += -self.epsilon * self.delta_W[i]            self.b[i] += -self.epsilon * self.delta_b[i]    def _calculate_loss(self):        '''损失函数(批量)'''        probs = self._forward(self.X) # 批量: self.X                # 计算损失        corect_logprobs = -np.log(probs[range(self.n_examples), self.y])        data_loss = np.sum(corect_logprobs)                # 添加正则项损失(可选)        data_loss += self.lamda/2 * (sum([np.sum(np.square(w)) for w in self.W]))        return 1./self.n_examples * data_loss            def fit(self, X, y):        '''拟合'''        # 将神经网络搭建完整        self._build(X, y)                # 按迭代次数,依次:        for i in range(self.n_iter):            # 前向传播            probs = self._forward(self.X)            # 反向传播            self._backward(probs)            # 计算损失            if i % 1000 == 0:                loss = self._calculate_loss()                print("迭代次数:{}\t损失: {}".format(i, loss))    def predict(self, x):        '''预测(批量)'''        probs = self._forward(x)        return np.argmax(probs, axis=1)                # 以下皆为测试#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>def plot_decision_boundary(plt, xx, yy, Z, X, y, title):    '''作图函数'''    # 等高线图    plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)    # 散点图    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)        plt.xlabel('萼片长度')    plt.ylabel('萼片宽度')    plt.xlim(xx.min(), xx.max())    plt.ylim(yy.min(), yy.max())    plt.xticks(())    plt.yticks(())    plt.title(title)    plt.show()    def test2():    '''第二个测试函数'''    import matplotlib.pyplot as plt    from sklearn import datasets    # --------------------------------------------    # 解决matplotlib中文乱码    plt.rcParams['font.sans-serif'] = ['SimHei']    plt.rcParams['axes.unicode_minus'] = False    # --------------------------------------------        # ======================================================    # 生成数据    np.random.seed(0)    X, y = datasets.make_moons(200, noise=0.20)    h = .02    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),                         np.arange(y_min, y_max, h))    # ======================================================        # 先作散点图,看看数据特点    plt.scatter(X[:,0], X[:,1], s=40, c=y, cmap=plt.cm.Spectral)    plt.show()    # 定义神经网络    nn = NeuralNetworks([6,5,3])    # 拟合    nn.fit(X, y)    # 预测    Z = nn.predict(np.c_[xx.ravel(), yy.ravel()])    Z = Z.reshape(xx.shape)    # 作图    plot_decision_boundary(plt, xx, yy, Z, X, y, "预测效果图")def test1():    '''第一个测试函数'''    # 第一步:准备数据    # 说明:逻辑异或(XOR)    X = np.array([[-1,-1],[-1,1],[1,-1],[1,1]])    y = np.array([0,1,2,3])        # 第二步:创建神经网络    # 说明:1.两个隐藏层,节点数目分别为4、6有两个节点    #       2.输入层和输出层节点数目自动识别,默认不输入    #       3.若包含输入层与输出层,可以设置参数 only_hidens=True    #         如:nn = NeuralNetworks([2, 4, 6, 4], only_hidens=True)    #    #       4.完整例子:nn = NeuralNetworks(hiden_layers=[4, 6],    #                                       active_type = ['tanh', 'tanh', 'tanh'],     #                                       n_iter=10000,     #                                       epsilon=0.01,     #                                       lamda=0.01,     #                                       only_hidens=True)    nn = NeuralNetworks([2, 4, 6, 4], active_type = ['tanh', 'tanh', 'sigmoid'], only_hidens=False)        # 第三步:拟合    nn.fit(X, y)        # 第四步:预测    print(nn.predict(X))        if __name__ == '__main__':    test1()    test2()

 

本文转自罗兵博客园博客,原文链接:http://www.cnblogs.com/hhh5460/p/5126268.html
,如需转载请自行联系原作者
你可能感兴趣的文章
C语言---数据结构(内建,数组,自定义)
查看>>
Ruby中使用patch HTTP方法
查看>>
c :函数指针具体解释
查看>>
hdu 4893Wow! Such Sequence!
查看>>
Java信号量 Semaphore 介绍
查看>>
【HttpClient4.5中文教程】【第一章 :基础】1.1运行请求(二)
查看>>
qsc oj 22 哗啦啦村的刁难(3)(随机数,神题)
查看>>
java上传图片剪切工具类
查看>>
UVA - 10622 Perfect P-th Powers
查看>>
angularjs之UI Grid 的刷新 本地数据源及HTTP数据源
查看>>
Php 通过curl提交post内容为 Json的请求
查看>>
HDU 1133 Buy the Ticket 卡特兰数
查看>>
如何卸载visualsvn for visual studio
查看>>
Golang开发环境搭建(Notepad++、LiteIDE两种方式以及martini框架使用)
查看>>
Linux中rz和sz命令用法详解
查看>>
Light OJ 1317 Throwing Balls into the Baskets 概率DP
查看>>
解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.-
查看>>
ubuntu系统里vi编辑器时,按方向箭头输入是乱码的ABCD字母?(图文详解)
查看>>
sklearn 模型选择和评估
查看>>
成为Java顶尖程序员 ,看这11本书就够了
查看>>