如何利用Keras的扩展性

2024-06-16 17:38
文章标签 keras 扩展性

本文主要是介绍如何利用Keras的扩展性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://blog.csdn.net/hewb14/article/details/53414068

Keras是一个用于在Python上搭神经网络模型的框架,语法和torch比较相似。我个人认为Keras最大的特点是包装很好,一些在训练过程中要输出的方法和常用的优化函数、目标函数都已经内置了,非常适合用来写大作业。Keras和python的哲学有些相似,那就是尽量不自己造轮子。

但是最近逛知乎,看到有答案说,Keras只能用来搭一些世面上已经普及的网络,和其它框架相比比较小白。换句话说,就是Keras的扩展性不好。作为一个试用过theano、tensorflow、torch、caffe等框架,最后定居在Keras的人,我对此不太同意。事实上,Keras拥有不错的扩展性,这一方面是因为设计时就留好的接口,另一方面是因为清晰的代码结构,让你可以有很多自定义的空间。所以下面用几个例子介绍在Keras中如何自定义层和各种方法。


0、backend

如果想在Keras中自定义各种层和函数,一定会用到的就是backend。一般导入的方法是

[python]  view plain copy
  1. from keras import backend as K  
这是因为Keras可以有两种后台,即theano和tensorflow,所以一些操作张量的函数可能是随后台的不同而不同的,

通过引入这个backend,就可以让Keras来处理兼容性。

比如求x的平均,就是K.mean(x)。backend文件本身在keras/backend文件夹下,可以通过阅读代码来了解backend都支持哪些操作。backend里面函数很多,一般都够用了。


1、Lambda 层

如果你只是想对流经该层的数据做个变换,而这个变换本身没有什么需要学习的参数,那么直接用Lambda Layer是最合适的了。

导入的方法是 

[python]  view plain copy
  1. <span style="font-size:18px;">    from keras.layers.core import Lambda</span>  
    Lambda函数接受两个参数,第一个是输入张量对输出张量的映射函数,第二个是输入的shape对输出的shape的映射函数。比如想构建这样一个层,流经该层的数据会被减去平均值,那么可以这样定义:

[python]  view plain copy
  1. <span style="font-size:18px;">def sub_mean(x):  
  2.     x -= K.mean(x,axis=1,keepdims=True)  
  3.     return x  
  4. model.add( Lambda(sub_mean,output_shape=lambda input_shape:input_shape ))</span>  
 因为输出的shape和输入的shape是一样的,第二个参数就直接用了恒等映射。

把模型完整地建立出来:

[python]  view plain copy
  1. <span style="font-size:18px;">def get_submean_model():  
  2.     model = Sequential()  
  3.     model.add(Dense(5,input_dim=7))  
  4.     def sub_mean(x):  
  5.         x -= K.mean(x,axis=1,keepdims=True)  
  6.         return x  
  7.     model.add( Lambda(sub_mean,output_shape=lambda input_shape:input_shape))  
  8.     model.compile(optimizer='rmsprop',loss='mse')  
  9.     return model  
  10. model = get_submean_model()  
  11. res=model.predict(np.random.random((3,7)))</span>  
得到地res的平均值是[  5.96046448e-08  -5.96046448e-08   0.00000000e+00],可见确实实现了减去均值的作用。


2、自定义非递归层

如果自己想定义的层中有需要学习的变量,那么就不能用lambda层了,需要自己写一个出来。

比如说我想定义一个层,它的效果是对张量乘一个正对角阵(换句话说,输入向量与一个要学习的向量逐元素相乘),那么可以这样写:

首先要导入基类  from keras.engine.topology import Layer

然后对MyLaber定义如下:

[python]  view plain copy
  1. <span style="font-size:18px;">class MyLayer(Layer):  
  2.     def __init__(self,output_dim,**kw):  
  3.         self.output_dim = output_dim  
  4.         super(MyLayer,self).__init__(**kw)  
  5.     def build(self,input_shape):  
  6.         input_dim = input_shape[1]  
  7.         assert(input_dim == self.output_dim)  
  8.         inital_SCALER = np.ones((input_dim,))*1000  
  9.         self.SCALER = K.variable(inital_SCALER)  
  10.         self.trainable_weights = [self.SCALER]  
  11.         super(MyLayer,self).build(input_shape)  
  12.     def call(self,x,mask=None):  
  13.         #return x - K.mean(x,axis=1,keepdims=True)  
  14.         x *= self.SCALER  
  15.         return x  
  16.     def get_output_shape_for(self,input_shape):  
  17.         return input_shape</span>  
 主要参照Keras内置的层的写法,比如Dense在keras/layers/core.py中,要把能学习的参数放在self.trainable_weights中。这里把初始值设成了1000是为了让该层的效果更显著。然后把模型写全来测试一下

[python]  view plain copy
  1. <span style="font-size:18px;">def get_mylayer_model():  
  2.     model = Sequential()  
  3.     model.add(Dense(5,input_dim=7))  
  4.     model.add(MyLayer(5))  
  5.     model.compile(optimizer='rmsprop',loss='mse')  
  6.     return model  
  7. model = get_mylayer_model()  
  8. res=model.predict(np.random.random((3,7)))  
  9. print res</span>  
res如下:

[[  271.2746582  -1053.31506348   147.17185974 -1120.33740234  609.54876709]
 [ -263.69671631  -390.41921997   291.17721558  -594.58721924   615.97369385]
 [  -46.58752823  -733.11328125   -21.9815979   -570.79351807      649.44158936]]

都是很大的数,而不加MyLayer时每个值一般也不超过+-2,这个层确实起了作用。

在fit之前调用model.get_weights(),看到该层的权重都是1000,随便随机出来个测试集,fit几千个epoch只后,loss变得很小,MyLayer的权重变成了997左右,而前面一层Dense的权重都成10^-4量级,说明MyLayer中的参数也确实是可学习的。


3、自定义损失函数

Keras内置的损失函数都在keras/objectives.py中,比如mse的定义是:

[python]  view plain copy
  1. <span style="font-size:18px;">def mean_squared_error(y_true, y_pred):  
  2.     return K.mean(K.square(y_pred - y_true), axis=-1)</span>  
 按照相同的格式,可以定义自己的损失函数。比如我们想要差值的4次方的平均作为损失函数:
[python]  view plain copy
  1. <span style="font-size:18px;">def my_object(y_true,y_pred):  
  2.     return K.mean(K.square(K.square(y_pred-y_true)),axis=-1)</span>  
把模型写全:
[python]  view plain copy
  1. def get_myobj_model():  
  2.     model = Sequential()  
  3.     model.add(Dense(5,input_dim=7))  
  4.     model.add(Dense(3))  
  5.     def my_object(y_true,y_pred):  
  6.         return K.mean(K.square(K.square(y_pred-y_true)),axis=-1)  
  7.     model.compile(optimizer='sgd',loss=my_object)  
  8.     return model  
  9. model = get_myobj_model()  
能自定义损失函数是非常重要一环,它极大的扩展了网络的应用。例如希望用cnn训练出来一个前后景分割的滤波器,它的输出的像素在对应前景的位置是1,在对应后景的位置是0。不但希望网络输出的值的mse小,而且希望0和1分别都连在一起,不要出来雪花状的输出。那么自定义损失函数就能做到了,实际是把两个损失函数放到了一个损失函数中。

另外一些很有用的损失函数如warp-ctc,就可以在这里集成进模型。


4、自定义递归层

递归层的定义方法和非递归层不太一样。根据Keras内LSTM的写法,它还有一个reset_states函数和step函数,这是由递归的性质决定的。例子都在keras/layers/recurrent.py中。

之前看学长用lasagne写的LSTM的变体,看得我想哭,还不如在Keras中把LSTM得代码复制过来修修改改。不过LSTM也不能直接复制过来,还需要import几个依赖:

[python]  view plain copy
  1. rom keras.layers.recurrent import LSTM,Recurrent,time_distributed_dense  
  2. from keras import initializations,regularizers,activations  
  3. from keras.engine import InputSpec  


5、自定义优化函数

Keras的代码确实好,耦合度很低。Keras内置的优化函数在keras/optimizers.py中,基类Optimizer也在这个文件里。例如把它内置的SGD算法拷贝到自己的文件中,只要先from keras.optimizers import Optimizer就能编译通过。

有时候要得到state-of-the-art的结果,需要用sgd加动量法充分收敛。比如学习率0.01学习上100epoch,再把学习率减半,再学100epoch,依次类推。如果不自定义优化函数的话,就要分阶段调用fit函数,修改学习率,可能还要重新compile。这就不是很优美了。其它一些奇葩的学习策略,也可以通过自定义优化函数来得到。


6、后记

Keras确实非常强大,不但能用来写大作业,做一些研究也够用了。Yeah


这篇关于如何利用Keras的扩展性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067102

相关文章

Kaggle刷比赛的利器,LR,LGBM,XGBoost,Keras

刷比赛利器,感谢分享的人。 摘要 最近打各种比赛,在这里分享一些General Model,稍微改改就能用的 环境: python 3.5.2 XGBoost调参大全: http://blog.csdn.net/han_xiaoyang/article/details/52665396 XGBoost 官方API: http://xgboost.readthedocs.io/en

深度学习 之 keras

注意使用keras 首先压迫安装theano 或者tensorflow,keras默认使用tensorflow   首先创建一个moel from keras.models import Sequentialmodel = Sequential()   然后添加神经层及激活函数 from keras.layers import Dense, Activationmodel.ad

图像识别之目标检测keras-tensorflow 实现yolo3

关于windows gpu环境请参考https://liuhuiyao.blog.csdn.net/article/details/109271898  keras-yolo3 地址  https://github.com/qqwweee/keras-yolo3 本人真实实现的情况是: windows 10 tensorboard             1.8.0 tensorflow-

windows 机器学习 tensorflow-gpu +keras gpu环境的 相关驱动安装-CUDA,cuDNN。

本人真实实现的情况是: windows 10 tensorboard             1.8.0 tensorflow-gpu          1.8.0 pip install -i https://pypi.mirrors.ustc.edu.cn/simple/ tensorflow-gpu==1.8.0 Keras                   2.2.4 pip

多态、多态的好处(扩展性)

文章目录 多态多态中成员访问特点提醒:理解这些的时候要记得继承啊方法重写它们存在的意义所在。就好理解啦。 多态的好处c++中多态(理论结合实践的理解) 多态 1、多态:同一个对象,在不同时刻体现出来的不同状态。 2、多态的前提:   1)要有继承关系或实现关系(接口);   2)要有方法重写;   3)要有父类或者父接口引用指向子类`Fu f= new Zi();     注

在keras中使用tensorflow自带的评估标准

在keras中使用tensorflow自带的标准     Metrics是衡量一个神经网络性能的重要指标,然而在keras环境下,仅有有限个评估标准可以使用。Tensorflow自带了很多的评估标准,因此就产生了一个问题,能否在keras中使用tensorflow自带的评估标准?     多的不说,直接上代码! // 首先将tensorflow的函数封装成为keras下的函数def as_k

深度学习-TensorFlow2 :构建DNN神经网络模型【构建方式:自定义函数、keras.Sequential、CompileFit、自定义Layer、自定义Model】

1、手工创建参数、函数–>利用tf.GradientTape()进行梯度优化(手写数字识别) import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'import tensorflow as tffrom tensorflow.keras import datasets# 一、获取手写数字辨识训练数据集(X_train, Y_train), (X_

keras missing label unlabeled 未标注类 如何训练 如何自定义损失函数 去除未标注类 缺少标签

我从这里找到的答案: def ignore_unknown_xentropy(ytrue, ypred):return (1-ytrue[:, :, :, 0])*categorical_crossentropy(ytrue, ypred) 然后下面是我的代码: 我感觉看到这个帖子的应该都看得懂吧(其实就是懒得解释了,请看注释)  from __future__ import print_

keras 实现dense prediction 逐像素标注 语义分割 像素级语义标注 pixelwise segmention labeling classification 3D数据

主要是keras的示例都是图片分类。而真正的论文代码,又太大了,不适合初学者(比如我)来学习。 所以我查找了一些资料。我在google 上捞的。 其中有个教程让人感觉很好.更完整的教程。另一个教程。 大概就是说,你的输入ground truth label需要是(width*height,class number),然后网络最后需要加个sigmoid,后面用binary_crossentro