一个可扩展的深度学习框架的Python实现(仿keras接口)

动机

keras是一种非常优秀的深度学习框架,其具有较好的易用性,可扩展性。keras的接口设计非常优雅,使用起来非常方便。在这里,我将仿照keras的接口,设计出可扩展的多层感知机模型,并在多维奇偶校验数据上进行测试。

本文实现的mlp的可扩展性在于:可以灵活指定神经网络的层数,每层神经元的个数,每层神经元的激活函数,以及指定神经网络的损失函数

本文将尽量使用numpy的矩阵运算用于训练网络,公式的推导过程可以参考此篇博客,细节上可能有所不同。

本文将只实现批量梯度下降用于训练网络,对于规模较大的数据集可扩展性不强;本文只实现了固定步长的学习率算法,将来可能会拓展到动态学习率算法;本文只实现了二分类问题的平方损失函数,对于多分类问题,用户可以自定义损失函数;

  1. # -*- coding: utf-8 -*-
  2. import numpy as np
  3. from matplotlib import pyplot as plt

测试数据生成

此函数将生成n维二进制数据及其奇偶校验码

输入:

n_dim:需要生成的二进制数据的维度

输出:

X_train:n维二进制数据

y_train:以上二进制数据的奇偶校验码

  1. #2维测试数据
  2. #X_train=np.array([[0,0],[0,1],[1,0],[1,1]])
  3. #y_train=np.array([0,1,1,0])
  4. #生成用于奇偶校验的训练数据
  5. def generate_data(n_dim):
  6. X_train=[]
  7. y_train=[]
  8. for i in range(2**n_dim):
  9. v=[0]*n_dim
  10. x=i
  11. for j in range(n_dim-1,-1,-1):
  12. v[j]=x%2
  13. x//=2
  14. X_train.append(v)
  15. y_train.append(sum(v)%2)
  16. return np.array(X_train),np.array(y_train)

测试

  1. X_train,y_train=generate_data(n_dim=3)
  2. print(X_train)
  3. print(y_train)
  1. [[0 0 0]
  2. [0 0 1]
  3. [0 1 0]
  4. [0 1 1]
  5. [1 0 0]
  6. [1 0 1]
  7. [1 1 0]
  8. [1 1 1]]
  9. [0 1 1 0 1 0 0 1]

感知机模型实现

  1. class MLP:
  2. def __init__(self):
  3. #使用列表保存所有的感知机层
  4. self.layer=[]
  5. #设置优化器
  6. self.optimizator=None
  7. #用于保存每一次迭代过程中的损失,最后可以用来对损失变化情况绘图
  8. self.loss=[]
  9. #设置损失函数
  10. self.loss_func=None
  11. #设置损失函数的梯度函数
  12. self.loss_grad=None
  13. #可以用于给mlp加一个层
  14. def add(self,layer):
  15. self.layer.append(layer)
  16. #编译模型结构,初始化模型参数
  17. def compile(self,loss='squared_loss',optimizator=None,epsilon=4):
  18. #指定模型的优化方式,本文没有实现
  19. self.optimizator=optimizator
  20. #指定模型的损失函数
  21. self.loss_func=loss_function[loss]
  22. #设置损失函数的梯度函数
  23. self.loss_grad=gradient_function[loss]
  24. for i in range(len(self.layer)):
  25. #初始化参数矩阵
  26. if i==0:
  27. row=self.layer[i].input_shape[0]
  28. else:
  29. row=self.layer[i-1].size
  30. column=self.layer[i].size
  31. #将参数设置为[-epsilon, epsilon]区间上均匀分布的随机数
  32. self.layer[i].weight=np.random.rand(row,column)*2*epsilon-epsilon
  33. self.layer[i].bias=np.random.rand(1,column)*2*epsilon-epsilon
  34. #对模型进行拟合训练
  35. def fit(self,X,y,epochs=10000,lr=0.01):
  36. epoch=0
  37. y=y.reshape((-1,1))
  38. while epoch < epochs:
  39. #前向传播计算每层的输出
  40. self.__forward__(X,y)
  41. #将此次迭代的损失保存下来
  42. self.loss.append(self.loss_func(model.layer[-1].output,y))
  43. #反向传播计算每层参数的变化量
  44. self.__backward__(X,y,lr)
  45. #更新参数
  46. for i in range(len(self.layer)):
  47. self.layer[i].weight+=self.layer[i].weight_change
  48. self.layer[i].bias+=self.layer[i].bias_change
  49. epoch+=1
  50. #预测样本类别
  51. def predict(self,X_test):
  52. self.__forward__(X_test)
  53. y_pred=self.layer[-1].output
  54. y_pred[np.less(y_pred,0.5)]=0
  55. y_pred[np.greater_equal(y_pred,0.5)]=1
  56. return y_pred.astype('int').ravel()
  57. #评估在测试集上的分类是否正确
  58. def evaluate(self,X_test,y_test):
  59. y_pred=self.predict(X_test)
  60. return np.logical_not(np.logical_xor(y_pred,y_test.astype('bool')))
  61. #评估在测试上进行分类的正确率
  62. def evaluate_accuracy(self,X_test,y_test):
  63. is_correct=self.evaluate(X_test,y_test)
  64. return np.sum(is_correct)/is_correct.shape[0]
  65. #可视化模型训练过程中的损失变化
  66. def print_loss(self):
  67. plt.plot(self.loss)
  68. plt.ylim(ymin=0)
  69. plt.xlabel('epoch')
  70. plt.ylabel('loss')
  71. plt.title('loss per epoch')
  72. plt.show()
  73. #前向传播过程
  74. def __forward__(self,X,y=None):
  75. for i in range(len(self.layer)):
  76. #获取每一层的输入数据
  77. if i==0:
  78. input_data=X
  79. else:
  80. input_data=self.layer[i-1].output
  81. #更新每一层的输出
  82. self.layer[i].net=np.dot(input_data,self.layer[i].weight)+self.layer[i].bias
  83. self.layer[i].output=self.layer[i].activation(self.layer[i].net)
  84. #反向传播过程
  85. def __backward__(self,X,y,lr):
  86. for i in range(len(self.layer)-1,-1,-1):
  87. if i==len(self.layer)-1:
  88. temp=-1*self.loss_grad(y,self.layer[i].output)
  89. else:
  90. temp=np.dot(self.layer[i+1].sensitivity,np.transpose(self.layer[i+1].weight))
  91. #计算每一层的敏感度,权重变化
  92. self.layer[i].sensitivity=self.layer[i].gradient(self.layer[i].net)*temp
  93. self.layer[i].weight_change=(lr)*np.dot(np.transpose(self.layer[i-1].output),self.layer[i].sensitivity)
  94. self.layer[i].bias_change=(lr)*np.sum(self.layer[i].sensitivity,axis=0).reshape((1,-1))

感知机层类

  1. class Layer:
  2. def __init__(self,size,activation='sigmoid',input_shape=None):
  3. #本层感知机的数量
  4. self.size=size
  5. #本层感知机的激活方式
  6. self.activation=activation_function[activation]
  7. #本层感知机的激活函数的求导函数
  8. self.gradient=gradient_function[activation]
  9. #mlp的输入维度,只对第一层的感知机有效。注意在这个模型中并没有定义输入层。
  10. self.input_shape=input_shape
  11. #此层感知机的输入
  12. self.input=None
  13. #此层感知机的权重矩阵
  14. self.weight=None
  15. #权重变更
  16. self.weight_change=None
  17. #偏置变更
  18. self.bias_change=None
  19. #此层感知机的偏置矩阵
  20. self.bias=None
  21. #记录神经元激活前的状态
  22. self.net=None
  23. #此层感知机的输出矩阵
  24. self.output=None
  25. #此层感知机的敏感度矩阵,误差逆传播的时候会用到
  26. self.sensitivity=None

定义需要用到的损失函数和激活函数,定义其梯度函数

  1. def squared_loss(y,y_pred):
  2. return 0.5*np.sum(np.square(y-y_pred))
  3. def squared_loss_gd(y,y_pred):
  4. return y_pred-y
  5. def sigmoid(x):
  6. return 1/(1+np.exp(-1*x))
  7. def sigmoid_gd(x):
  8. return sigmoid(x)*(1-sigmoid(x))
  9. def relu(x):
  10. y=x
  11. y[np.less(y,0)]=0
  12. return y
  13. def relu_gd(x):
  14. g=x
  15. g[np.less(x,0)]=0
  16. g[np.equal(x,0)]=0.5
  17. g[np.greater(x,0)]=1
  18. return g
  19. def softmax():
  20. pass
  21. def softmax_gd():
  22. pass
  23. #使用字典保存函数,可以实现使用字符串查阅所需函数
  24. loss_function={'squared_loss':squared_loss}
  25. activation_function={'sigmoid':sigmoid,'softmax':softmax,'relu':relu}
  26. gradient_function={'squared_loss':squared_loss_gd,'sigmoid':sigmoid_gd,'softmax':softmax_gd,'relu':relu_gd}

测试

  1. #指定奇偶校验数据的维度
  2. dim=5
  3. #生成训练数据
  4. X_train,y_train=generate_data(n_dim=dim)
  5. #设置模型参数
  6. model=MLP()
  7. model.add(Layer(20,'sigmoid',input_shape=(dim,)))
  8. model.add(Layer(10,'sigmoid'))
  9. model.add(Layer(5,'sigmoid'))
  10. model.add(Layer(1,'sigmoid'))
  11. model.compile(loss='squared_loss')
  12. model.fit(X_train,y_train,epochs=20000,lr=0.01)
  13. #输出测试结果
  14. print('-'*100)
  15. print('accuracy:')
  16. print(model.evaluate_accuracy(X_train,y_train))
  17. model.print_loss()
  1. ----------------------------------------------------------------------------------------------
  2. accuracy:
  3. 1.0

一个可扩展的深度学习框架的Python实现(仿keras接口)的更多相关文章

  1. 关于深度学习框架 TensorFlow、Theano 和 Keras

    [TensorFlow] ——( https://morvanzhou.github.io/tutorials/machine-learning/tensorflow/) 1.TensorFlow是啥 ...

  2. 从TensorFlow 到 Caffe2:盘点深度学习框架

    机器之心报道 本文首先介绍GitHub中最受欢迎的开源深度学习框架排名,然后再对其进行系统地对比 下图总结了在GitHub中最受欢迎的开源深度学习框架排名,该排名是基于各大框架在GitHub里的收藏数 ...

  3. 开源脉冲神经网络深度学习框架——惊蛰(SpikingJelly)

    开源脉冲神经网络深度学习框架--惊蛰(SpikingJelly) 背景 近年来神经形态计算芯片发展迅速,大量高校企业团队跟进,这样的芯片运行SNN的能效比与速度都超越了传统的通用计算设备.相应的,神经 ...

  4. 人工智能深度学习框架MXNet实战:深度神经网络的交通标志识别训练

    人工智能深度学习框架MXNet实战:深度神经网络的交通标志识别训练 MXNet 是一个轻量级.可移植.灵活的分布式深度学习框架,2017 年 1 月 23 日,该项目进入 Apache 基金会,成为 ...

  5. [深度学习大讲堂]从NNVM看2016年深度学习框架发展趋势

    本文为微信公众号[深度学习大讲堂]特约稿,转载请注明出处 虚拟框架杀入 从发现问题到解决问题 半年前的这时候,暑假,我在SIAT MMLAB实习. 看着同事一会儿跑Torch,一会儿跑MXNet,一会 ...

  6. [转]Caffe 深度学习框架上手教程

    Caffe 深度学习框架上手教程 机器学习Caffe caffe 原文地址:http://suanfazu.com/t/caffe/281   blink 15年1月 6   Caffe448是一个清 ...

  7. Caffe 深度学习框架介绍

    转自:http://suanfazu.com/t/caffe/281 Caffe是一个清晰而高效的深度学习框架,其作者是博士毕业于UC Berkeley的贾扬清,目前在Google工作. Caffe是 ...

  8. 推荐GitHub上10 个开源深度学习框架

    推荐GitHub上10 个开源深度学习框架   日前,Google 开源了 TensorFlow(GitHub),此举在深度学习领域影响巨大,因为 Google 在人工智能领域的研发成绩斐然,有着雄厚 ...

  9. 学习笔记︱Nvidia DIGITS网页版深度学习框架——深度学习版SPSS

    DIGITS: Deep Learning GPU Training System1,是由英伟达(NVIDIA)公司开发的第一个交互式深度学习GPU训练系统.目的在于整合现有的Deep Learnin ...

随机推荐

  1. 【学习】如何用jQuery获取iframe中的元素

    (我的博客网站中的原文:http://www.xiaoxianworld.com/archives/292,欢迎遇到的小伙伴常来瞅瞅,给点评论和建议,有错误和不足,也请指出.) 说实在的,以前真的很少 ...

  2. web前端开发初学者必看的学习路线(附思维导图)

    很多同学想学习WEB前端开发,虽然互联网有很多的教程.网站.书籍,可是却又不知从何开始如何选取.看完网友高等游民白乌鸦无私分享的原标题为<写给同事的前端学习路线>这篇文章,相信你会有所收获 ...

  3. Android性能优化之启动速度优化

    Android性能优化之启动速度优化   Android app 启动速度优化,首先谈谈为什么会走到优化这一步,如果一开始创建 app 项目的时候就把这个启动速度考虑进去,那么肯定就不需要重新再来优化 ...

  4. angular.js基础

    内置指令 所有的内置指令的前缀都为ng,不建议自定义指令使用该前缀,以免冲突.首先从一些常见的内置指令开始.先列出一些关键的内置指令,顺便简单说说作用域的问题. ng-model 将表单控件和当前作用 ...

  5. sql里的null和空的区别

    null表示为未知,未定义: 空表示为空白,或者0: sql查询,排序时null在''的前面: 定义字段为not null,写为空可以写入: null不可以用来比较,只能用is null判断:

  6. NLog在asp.net中的使用

    一.关于安装 1.可以直接通过vs自带的Nuget包管理器来搜索下载,直接搜索"NLog": 注意,除了要安装第一个之外,一定要安装"NLog.Config", ...

  7. 五、在IDEA中使用GIt版本控制并将本地代码上传至Github

    一.安装git     Git工具下载:https://git-scm.com/downloads 从官网下载.安装很简单,基本都是下一步. 安装完的第一件事情就是创建一个Git用户: git con ...

  8. 探究Angular依赖注入对象$injector

    $injector其实是一个IOC容器,包含了很多我们通过.module()和$provide创建的模块和服务.$injector服务提供了对依赖注入器对象的访问,当然我们也可以调用angular.i ...

  9. linux GCC 编译多个.c/.h文件

    基本认识: #include <xxx>:首先去系统目录中找头文件,如果没有在到当前目录下找.像标准的头文件 stdio.h.stdlib.h等用这个方法. #include " ...

  10. MicroService.Core简易微服务框架《一、简介》

    MicroService.Core MicroService.Core 的初衷是为了方便的创建一个微服务, 可作为 Windows Service 或者控制台模式启动. 它底层使用了 OWin 自托管 ...