开发者社区> 吞吞吐吐的> 正文

灵活定义神经网络结构

简介:
+关注继续查看

用numpy可以灵活定义神经网络结构,还可以应用numpy强大的矩阵运算功能!

 

一、用法

1). 定义一个三层神经网络:

'''示例一'''
nn = NeuralNetworks([3,4,2]) # 定义神经网络
nn.fit(X,y) # 拟合
print(nn.predict(X)) #预测

说明:

  输入层节点数目:3

  隐藏层节点数目:4

  输出层节点数目:2

 

2).定义一个五层神经网络:

'''示例二'''
nn = NeuralNetworks([3,5,7,4,2]) # 定义神经网络
nn.fit(X,y) # 拟合
print(nn.predict(X)) #预测

说明:

  输入层节点数目:3

  隐藏层1节点数目:5

  隐藏层2节点数目:7

  隐藏层3节点数目:4

  输出层节点数目:2

 

二、实现

如下实现方式为本人(@hhh5460)原创。 要点: dtype=object

复制代码
import numpy as np

class NeuralNetworks(object):
    ''''''
    def __init__(self, n_layers=None, active_type=None, n_iter=10000, error=0.05, alpha=0.5, lamda=0.4):
        '''搭建神经网络框架'''
        # 各层节点数目 (向量)
        self.n = np.array(n_layers) # 'n_layers必须为list类型,如:[3,4,2] 或 n_layers=[3,4,2]'
        self.size = self.n.size # 层的总数
            
        # 层 (向量)
        self.z = np.empty(self.size, dtype=object) # 先占位(置空),dtype=object !如下皆然
        self.a = np.empty(self.size, dtype=object)
        self.data_a = np.empty(self.size, dtype=object)
        
        # 偏置 (向量)
        self.b = np.empty(self.size, dtype=object)
        self.delta_b = np.empty(self.size, dtype=object)

        # 权 (矩阵)
        self.w = np.empty(self.size, dtype=object)
        self.delta_w = np.empty(self.size, dtype=object)
        
        # 填充
        for i in range(self.size):
            self.a[i] = np.zeros(self.n[i])  # 全零
            self.z[i] = np.zeros(self.n[i])  # 全零
            self.data_a[i] = np.zeros(self.n[i])  # 全零
            if i < self.size - 1:
                self.b[i] = np.ones(self.n[i+1])   # 全一
                self.delta_b[i] = np.zeros(self.n[i+1])  # 全零
                mu, sigma = 0, 0.1 # 均值、方差
                self.w[i] = np.random.normal(mu, sigma, (self.n[i], self.n[i+1]))  # # 正态分布随机化
                self.delta_w[i] = np.zeros((self.n[i], self.n[i+1]))  # 全零
复制代码

 

下面完整代码是我学习斯坦福机器学习教程,完全自己敲出来的:

 

复制代码
import numpy as np
'''
参考:http://ufldl.stanford.edu/wiki/index.php/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C
'''



class NeuralNetworks(object):
    ''''''
    def __init__(self, n_layers=None, active_type=None, n_iter=10000, error=0.05, alpha=0.5, lamda=0.4):
        '''搭建神经网络框架'''
        self.n_iter = n_iter # 迭代次数
        self.error = error # 允许最大误差
        self.alpha = alpha # 学习速率
        self.lamda = lamda # 衰减因子 # 此处故意拼写错误!
        
        
        if n_layers is None:
            raise '各层的节点数目必须设置!'
        elif not isinstance(n_layers, list):
            raise 'n_layers必须为list类型,如:[3,4,2] 或 n_layers=[3,4,2]'
        # 节点数目 (向量)
        self.n = np.array(n_layers)
        self.size = self.n.size # 层的总数
            
        # 层 (向量)
        self.a = np.empty(self.size, dtype=object) # 先占位(置空),dtype=object !如下皆然
        self.z = np.empty(self.size, dtype=object)
        
        # 偏置 (向量)
        self.b = np.empty(self.size, dtype=object)
        self.delta_b = np.empty(self.size, dtype=object)

        # 权 (矩阵)
        self.w = np.empty(self.size, dtype=object)
        self.delta_w = np.empty(self.size, dtype=object)
        
        # 残差 (向量)
        self.data_a = np.empty(self.size, dtype=object)
        
        # 填充
        for i in range(self.size):
            self.a[i] = np.zeros(self.n[i])  # 全零
            self.z[i] = np.zeros(self.n[i])  # 全零
            self.data_a[i] = np.zeros(self.n[i])  # 全零
            if i < self.size - 1:
                self.b[i] = np.ones(self.n[i+1])   # 全一
                self.delta_b[i] = np.zeros(self.n[i+1])  # 全零
                mu, sigma = 0, 0.1 # 均值、方差
                self.w[i] = np.random.normal(mu, sigma, (self.n[i], self.n[i+1]))  # # 正态分布随机化
                self.delta_w[i] = np.zeros((self.n[i], self.n[i+1]))  # 全零

        # 激活函数
        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 None:
            self.active_type = ['sigmoid'] * (self.size - 1) # 默认激活函数类型
        else:
            self.active_type = 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 forward(self, x):
        '''正向传播(在线)''' 
        # 用样本 x 走一遍,刷新所有 z, a
        self.a[0] = x
        for i in range(self.size - 1):
            self.z[i+1] = np.dot(self.a[i], self.w[i]) + self.b[i] 
            self.a[i+1] = self.active_functions[self.active_type[i]](self.z[i+1]) # 加了激活函数

    def err(self, X, Y):
        '''误差'''
        last = self.size-1
        err = 0.0
        for x, y in zip(X, Y):
            self.forward(x)
            err += 0.5 * np.sum((self.a[last] - y)**2)
        err /= X.shape[0]
        err += sum([np.sum(w) for w in self.w[:last]**2])
        return err
    
    def backward(self, y):
        '''反向传播(在线)'''
        last = self.size - 1
        # 用样本 y 走一遍,刷新所有delta_w, delta_b
        self.data_a[last] = -(y - self.a[last]) * self.derivative_functions[self.active_type[last-1]](self.z[last]) # 加了激活函数的导函数
        for i in range(last-1, 1, -1):
            self.data_a[i] = np.dot(self.w[i], self.data_a[i+1]) * self.derivative_functions[self.active_type[i-1]](self.z[i]) # 加了激活函数的导函数
            # 计算偏导
            p_w = np.outer(self.a[i], self.data_a[i+1]) # 外积!感谢 numpy 的强大!
            p_b = self.data_a[i+1]
            # 更新 delta_w, delta_w
            self.delta_w[i] = self.delta_w[i] + p_w
            self.delta_b[i] = self.delta_b[i] + p_b
        
    def update(self, n_samples):
        '''更新权重参数'''
        last = self.size - 1
        for i in range(last):
            self.w[i] -= self.alpha * ((1/n_samples) * self.delta_w[i] + self.lamda * self.w[i])
            self.b[i] -= self.alpha * ((1/n_samples) * self.delta_b[i])
            
    def fit(self, X, Y):
        '''拟合'''
        for i in range(self.n_iter):
            # 用所有样本,依次
            for x, y in zip(X, Y):
                self.forward(x)  # 前向,更新 a, z;
                self.backward(y) # 后向,更新 delta_w, delta_b
                
            # 然后,更新 w, b
            self.update(len(X))
            
            # 计算误差
            err = self.err(X, Y)
            if err < self.error:
                break

            # 整千次显示误差(否则太无聊!)
            if i % 1000 == 0:
                print('iter: {}, error: {}'.format(i, err))

    def predict(self, X):
        '''预测'''
        last = self.size - 1
        res = []
        for x in X:
            self.forward(x)
            res.append(self.a[last])
        return np.array(res)
        

        
if __name__ == '__main__':
    nn = NeuralNetworks([2,3,4,3,1], n_iter=5000, alpha=0.4, lamda=0.3, error=0.06) # 定义神经网络

    X = np.array([[0.,0.], # 准备数据
                  [0.,1.],
                  [1.,0.],
                  [1.,1.]])
    y = np.array([0,1,1,0])
    
    nn.fit(X,y)          # 拟合
    print(nn.predict(X)) # 预测
    
    
复制代码

 

本文转自罗兵博客园博客,原文链接:http://www.cnblogs.com/hhh5460/p/5124132.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
再也不担心用不好二分法了,因为我找到了"作弊"的接口
导读:算法是程序的灵魂,而复杂度则是算法的核心指标之一。为了降低复杂度量级,可谓是令无数程序员绞尽脑汁、甚至是摧枯秀发。一般而言,若能实现对数阶的时间复杂度,算法效率往往就已经非常理想。而实现对数阶的常用思想莫过于二分。 二分常有,好用的二分并不常有。while条件是lo<hi还是lo<=hi?分支判断mid是+1还是-1还是仍然取值mid?最后return哪个值?如果目标序列不是严格递增又该怎么处理?想想都不禁让人敬而远之。幸运的是,在python语言中,已经内置了成熟的二分函数。
3 0
地图可视化不只是pyecharts.map
导读:地图可视化是一种非常直观的数据分析结果展现形式,python有很多可视化库可以实现,pyecharts就是很多python爱好者喜爱的实现地图可视化方法之一。不可否认,pyecharts绘制的地图实现方便、图形美观而且支持交互,但在面对不同需求时,其实我们还有很多其他手段实现地图可视化。
4 0
7. 给Lamb配置flask-sqlalchemy
由于之前已经有一篇介绍flask_sqlalchemy的文章了,这里大体内容就不介绍了。由于在公司的golang项目里有在使用gorm,个人觉得实在是方便,已经从sql奴隶变成了sql大哥,CRUD简直是得心应手。所以这里还是废话不多说,直接采用flask_sqlalchemy。
3 0
8. 为Lamb编写用户登录接口(带token)
上篇我们给Lamb引入了flask_sqlalchemy,接着我们就编写我们第一个接口---登录
3 0
452. 用最少数量的箭引爆气球
用最少数量的箭引爆气球
4 0
面试题57 - II. 和为s的连续正数序列
面试题57 - II. 和为s的连续正数序列
3 0
elasticsearch-head插件的使用
由于es服务启动之后,访问界面比较丑陋,为了更好的查看索引库当中的信息,我们可以通过安装elasticsearch-head这个插件来实现,这个插件可以更方便快捷的看到es的管理界面
7 0
4852
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载