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

动机

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

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

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

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

# -*- coding: utf-8 -*-
import numpy as np
from matplotlib import pyplot as plt

测试数据生成

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

输入:

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

输出:

X_train:n维二进制数据

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

#2维测试数据
#X_train=np.array([[0,0],[0,1],[1,0],[1,1]])
#y_train=np.array([0,1,1,0])
#生成用于奇偶校验的训练数据
def generate_data(n_dim):
X_train=[]
y_train=[]
for i in range(2**n_dim):
v=[0]*n_dim
x=i
for j in range(n_dim-1,-1,-1):
v[j]=x%2
x//=2
X_train.append(v)
y_train.append(sum(v)%2)
return np.array(X_train),np.array(y_train)

测试

X_train,y_train=generate_data(n_dim=3)
print(X_train)
print(y_train)
[[0 0 0]
[0 0 1]
[0 1 0]
[0 1 1]
[1 0 0]
[1 0 1]
[1 1 0]
[1 1 1]]
[0 1 1 0 1 0 0 1]

感知机模型实现

class MLP:
def __init__(self):
#使用列表保存所有的感知机层
self.layer=[]
#设置优化器
self.optimizator=None
#用于保存每一次迭代过程中的损失,最后可以用来对损失变化情况绘图
self.loss=[]
#设置损失函数
self.loss_func=None
#设置损失函数的梯度函数
self.loss_grad=None #可以用于给mlp加一个层
def add(self,layer):
self.layer.append(layer) #编译模型结构,初始化模型参数
def compile(self,loss='squared_loss',optimizator=None,epsilon=4):
#指定模型的优化方式,本文没有实现
self.optimizator=optimizator
#指定模型的损失函数
self.loss_func=loss_function[loss]
#设置损失函数的梯度函数
self.loss_grad=gradient_function[loss]
for i in range(len(self.layer)):
#初始化参数矩阵
if i==0:
row=self.layer[i].input_shape[0]
else:
row=self.layer[i-1].size
column=self.layer[i].size
#将参数设置为[-epsilon, epsilon]区间上均匀分布的随机数
self.layer[i].weight=np.random.rand(row,column)*2*epsilon-epsilon
self.layer[i].bias=np.random.rand(1,column)*2*epsilon-epsilon #对模型进行拟合训练
def fit(self,X,y,epochs=10000,lr=0.01):
epoch=0
y=y.reshape((-1,1))
while epoch < epochs:
#前向传播计算每层的输出
self.__forward__(X,y)
#将此次迭代的损失保存下来
self.loss.append(self.loss_func(model.layer[-1].output,y))
#反向传播计算每层参数的变化量
self.__backward__(X,y,lr)
#更新参数
for i in range(len(self.layer)):
self.layer[i].weight+=self.layer[i].weight_change
self.layer[i].bias+=self.layer[i].bias_change
epoch+=1 #预测样本类别
def predict(self,X_test):
self.__forward__(X_test)
y_pred=self.layer[-1].output
y_pred[np.less(y_pred,0.5)]=0
y_pred[np.greater_equal(y_pred,0.5)]=1
return y_pred.astype('int').ravel() #评估在测试集上的分类是否正确
def evaluate(self,X_test,y_test):
y_pred=self.predict(X_test)
return np.logical_not(np.logical_xor(y_pred,y_test.astype('bool'))) #评估在测试上进行分类的正确率
def evaluate_accuracy(self,X_test,y_test):
is_correct=self.evaluate(X_test,y_test)
return np.sum(is_correct)/is_correct.shape[0] #可视化模型训练过程中的损失变化
def print_loss(self):
plt.plot(self.loss)
plt.ylim(ymin=0)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.title('loss per epoch')
plt.show() #前向传播过程
def __forward__(self,X,y=None):
for i in range(len(self.layer)):
#获取每一层的输入数据
if i==0:
input_data=X
else:
input_data=self.layer[i-1].output
#更新每一层的输出
self.layer[i].net=np.dot(input_data,self.layer[i].weight)+self.layer[i].bias
self.layer[i].output=self.layer[i].activation(self.layer[i].net) #反向传播过程
def __backward__(self,X,y,lr):
for i in range(len(self.layer)-1,-1,-1):
if i==len(self.layer)-1:
temp=-1*self.loss_grad(y,self.layer[i].output)
else:
temp=np.dot(self.layer[i+1].sensitivity,np.transpose(self.layer[i+1].weight))
#计算每一层的敏感度,权重变化
self.layer[i].sensitivity=self.layer[i].gradient(self.layer[i].net)*temp
self.layer[i].weight_change=(lr)*np.dot(np.transpose(self.layer[i-1].output),self.layer[i].sensitivity)
self.layer[i].bias_change=(lr)*np.sum(self.layer[i].sensitivity,axis=0).reshape((1,-1))

感知机层类

class Layer:
def __init__(self,size,activation='sigmoid',input_shape=None):
#本层感知机的数量
self.size=size
#本层感知机的激活方式
self.activation=activation_function[activation]
#本层感知机的激活函数的求导函数
self.gradient=gradient_function[activation]
#mlp的输入维度,只对第一层的感知机有效。注意在这个模型中并没有定义输入层。
self.input_shape=input_shape
#此层感知机的输入
self.input=None
#此层感知机的权重矩阵
self.weight=None
#权重变更
self.weight_change=None
#偏置变更
self.bias_change=None
#此层感知机的偏置矩阵
self.bias=None
#记录神经元激活前的状态
self.net=None
#此层感知机的输出矩阵
self.output=None
#此层感知机的敏感度矩阵,误差逆传播的时候会用到
self.sensitivity=None

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

def squared_loss(y,y_pred):
return 0.5*np.sum(np.square(y-y_pred)) def squared_loss_gd(y,y_pred):
return y_pred-y def sigmoid(x):
return 1/(1+np.exp(-1*x)) def sigmoid_gd(x):
return sigmoid(x)*(1-sigmoid(x)) def relu(x):
y=x
y[np.less(y,0)]=0
return y def relu_gd(x):
g=x
g[np.less(x,0)]=0
g[np.equal(x,0)]=0.5
g[np.greater(x,0)]=1
return g def softmax():
pass def softmax_gd():
pass #使用字典保存函数,可以实现使用字符串查阅所需函数
loss_function={'squared_loss':squared_loss}
activation_function={'sigmoid':sigmoid,'softmax':softmax,'relu':relu}
gradient_function={'squared_loss':squared_loss_gd,'sigmoid':sigmoid_gd,'softmax':softmax_gd,'relu':relu_gd}

测试

#指定奇偶校验数据的维度
dim=5
#生成训练数据
X_train,y_train=generate_data(n_dim=dim)
#设置模型参数
model=MLP()
model.add(Layer(20,'sigmoid',input_shape=(dim,)))
model.add(Layer(10,'sigmoid'))
model.add(Layer(5,'sigmoid'))
model.add(Layer(1,'sigmoid'))
model.compile(loss='squared_loss')
model.fit(X_train,y_train,epochs=20000,lr=0.01)
#输出测试结果
print('-'*100)
print('accuracy:')
print(model.evaluate_accuracy(X_train,y_train))
model.print_loss()
----------------------------------------------------------------------------------------------
accuracy:
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. plsql经验之谈

    工具你用熟悉了,可以解决实际生活得问题,且是快速的.比如我们要需要表的字段,和注释的时候,直接右击,详情,可以复制. 我们讲个熟悉的场景或者案例,比如,我们需要把已经建立的源表,需要一定的加工和处理, ...

  2. 窗口迅速关闭的解决办法/scanf/if/for/break

    break if的格式 if(a>b) { printf("max=%d\n",a); } else printf("max=%d\n",b); scan ...

  3. IIS ApplicationPoolIdentity(配置IIS讀寫網站文件)

    原创地址:http://www.cnblogs.com/jfzhu/p/4067297.html 转载请注明出处 从IIS 7.5开始,Application Pool Identity的Built- ...

  4. Python学习笔记(十一)

    Python学习笔记(十一): 生成器,迭代器回顾 模块 作业-计算器 1. 生成器,迭代器回顾 1. 列表生成式:[x for x in range(10)] 2. 生成器 (generator o ...

  5. Xamarin.Forms 开发IOS、Android、UWP应用

    C#语言特点,简单.快速.高效.本次我们通过C#以及Xaml来做移动开发. 1.开发工具visual studio 2015或visual studio 2017.当然visual studio 20 ...

  6. NodeJs之数据库异常处理

    数据库异常 NodeJs版本:4.4.4 数据库链接错误 使用nodejs处理异常最麻烦不过,这里我抛开nodejs提供的domain和一些第三方库专门处理的东西.操作数据库是我们常用的功能.通过回调 ...

  7. Tracker-store

    升级后发现有个tracker-store占用cpu非常厉害,查了下,好像是GNOME 3使用 Documents 來整合 本机 以及 在线(Google / Twitter)账户的文件,这个功能会呼叫 ...

  8. Windows删除文件时找不到该项目

    当在Windows删除文件时出现找不到该项目或者显示该文件不在磁盘中,可以尝试以下方法: 在要删除文件的同级目录下 新建一文本文档,将下列代码复制到文档中,将文档保存为后缀名为.bat的文档(名字随意 ...

  9. python 模块的概念介绍

    模块 模块:本质就是一个.py文件分为三部分:内置模块.第三方模块,自定义模块 模块: 顶层文件 python模块python模块可以将代码量较大的程序分割成多个有组织的.彼此独立但又能互相交互的代码 ...

  10. 爱上朴实的CSS细节

    英文原文:Learning to Love the Boring Bits of CSS  未来的CSS太让人兴奋了:一方面,是全新的页面布局方式:另一方面,是酷炫的滤镜.颜色等视觉效果.这些CSS, ...