Keras 初探

数字先锋说
• 阅读 5504

Keras 初探

最近在接触些深度学习的东西,也对一些深度学习的框架进行了大致的了解。Python的科学计算包主要是TheanoTensorFlow,特点就是很强大,但对于初学者不太友好、有点难用。但Keras可以基于这两种包之一方便地建立神经网络。

什么是Keras

Keras是一个高层神经网络API,Keras由纯Python编写而成并基TensorflowTheano以及CNTK后端。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果。

Keras可在Python 2.7或3.5运行,无缝调用后端的CPU或GPU网络。Keras由Google的Francois Chollet开发,并遵循以下原则:

  • 模块化:每个模块都是单独的流程或图,深度学习的所有问题都可以通过组装模块解决
  • 简单化:提供解决问题的最简单办法,不加装饰,最大化可读性
  • 扩展性:新模块的添加特别容易,方便试验新想法
  • Python:不使用任何自创格式,只使用原生Python

    如下图所示,在终端调用keras,后面会输出下面的提示,说明keras默认的后端为tensorflow

    Using TensorFlow backend.

Keras 初探

如果说默认的后端不是tensorflow,而是theano,我们可以配置后端文件进行修改:

~/.keras/keras.json

里面是:

{"epsilon": 1e-07, "floatx": "float32", "backend": "theano"}

我们把backend参数改为tensorflow即可。

序贯模型

Keras的目标就是搭建模型。最主要的模型是Sequential:不同层的叠加。模型创建后可以编译,调用后端进行优化,可以指定损失函数和优化算法。

编译后的模型需要导入数据:可以一批批加入数据,也可以一次性全加入。训练后的模型就可以做预测或分类了。大体上的步骤是:

  1. 定义模型:创建Sequential模型,加入每一层
  2. 编译模型:指定损失函数和优化算法,使用模型的compile()方法
  3. 拟合数据:使用模型的fit()方法拟合数据
  4. 进行预测:使用模型的evaluate()predict()方法进行预测
Sequential(序贯模型)是多个网络层的线性堆叠,说人话就是“一条路走到黑”。

我们一般通过.add()方法一个个的将layer加入模型:

from keras.models import Sequential
from keras.layers import Dense, Activation

model = Sequential()
model.add(Dense(32, input_shape=(784,)))
model.add(Activation('relu'))

输入数据

Sequential的第一层需要接受一个关于输入数据shape的参数,后面的各个层则可以自动的推导出中间数据的shape,因此不需要为每个层都指定这个参数。

有几种方法来为第一层指定输入数据的shape

  • 传递一个input_shape的关键字参数给第一层,input_shape是一个tuple类型的数据,其中也可以填入None,如果填入None则表示此位置可能是任何正整数。数据的batch大小不应包含在其中。
  • 有些2D层,如Dense,支持通过指定其输入维度input_dim来隐含的指定输入数据shape,是一个Int类型的数据。一些3D的时域层支持通过参数input_diminput_length来指定输入shape。
  • 如果你需要为输入指定一个固定大小的batch_size,可以传递batch_size参数到一个层中,例如你想指定输入张量的batch大小是32,数据shape是(6,8),则你需要传递batch_size=32input_shape=(6,8)
model = Sequential()
model.add(Dense(32, input_shape=(784,)))

一些重要概念:

batch:

我们经常用到的优化算法——梯度下降,在该算法中参数更新的方式主要有2种。

第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这种方法每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习,这称为Batch gradient descent,批梯度下降。

第二种,每看一个数据就算一下损失函数,然后求梯度更新参数,这个称为随机梯度下降,stochastic gradient descent。这个方法速度比较快,但是收敛性能不太好,可能在最优点附近晃来晃去,hit不到最优点。两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。

为了克服两种方法的缺点,现在一般采用的是一种折中手段,mini-batch gradient decent,小批的梯度下降,这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,计算量也不是很大。

基本上现在的梯度下降都是基于mini-batch的,所以Keras的模块中经常会出现batch_size,指的就是这个。

epochs:

指的就是训练过程中数据将被“轮”多少次。

编译模型和训练

在训练模型之前,我们需要通过compile来对学习过程进行配置。compile接收三个参数:

  • 优化器optimizer:该参数可指定为已预定义的优化器名,如rmspropadagrad,或一个Optimizer类的对象。
  • 损失函数loss:该参数为模型试图最小化的目标函数,它可为预定义的损失函数名,如categorical_crossentropymse,也可以为一个损失函数。
  • 指标列表metrics:对分类问题,我们一般将该列表设置为metrics=['accuracy']。指标可以是一个预定义指标的名字,也可以是一个用户定制的函数.指标函数应该返回单个张量,或一个完成metric_name - > metric_value映射的字典。

比如对于多分类问题:

model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

训练模型一般使用fit函数。

model.fit(data, labels, epochs=10, batch_size=32)

Keras实战

本文主要是介绍Keras的基本用法,所以数据集采用经典数据集,中间的数据清洗过程便可以省略一些。数据集用的是UCI数据集中的 皮马人糖尿病数据集(pima-indians-diabetes),在UCI的机器学习网站(http://mlearn.ics.uci.edu/dat...)可以免费下载。

数据集的内容是皮马人的医疗记录,以及过去5年内是否有糖尿病。所有的数据都是数字,问题是(是否有糖尿病是1或0),是二分类问题。数据的数量级不同,有8个属性:

  1. 怀孕次数
  2. 2小时口服葡萄糖耐量试验中的血浆葡萄糖浓度
  3. 舒张压(毫米汞柱)
  4. 2小时血清胰岛素(mu U/ml)
  5. 体重指数(BMI)
  6. 糖尿病血系功能
  7. 年龄(年)
  8. 类别:过去5年内是否有糖尿病

所有的数据都是数字,可以直接导入Keras,数据前5行长下面这样。。

6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1

数据导入

因为数据全部为数字,这里我们用NumPy的loadtxt()函数可以直接导入数据,其实用pandas的read_csv也可以,随意啦。并将数据集分成特征和标签。

dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
X = dataset[:,0:8]
Y = dataset[:,8]
delimiter参数为指定数据的界定符

模型定义

Keras的模型由层构成:我们建立一个Sequential模型,一层层加入神经元。第一步是确定输入层的数目正确:在创建模型时用input_dim参数确定。

全连接层用Dense类定义:第一个参数是本层神经元个数,然后是初始化方式和激活函数。这里的初始化方法是0到0.05的连续型均匀分布(uniform),Keras的默认方法也是这个。也可以用高斯分布进行初始化(normal)。

前两层的激活函数是线性整流函数(relu),最后一层的激活函数是S型函数(sigmoid)。之前大家喜欢用S型和正切函数,但现在线性整流函数效果更好。

为了保证输出是0到1的概率数字,最后一层的激活函数是S型函数,这样映射到0.5的阈值函数也容易。前两个隐层分别有12和8个神经元,最后一层是1个神经元(是否有糖尿病)。

隐层设置:不太好设置吧,我的理解是,一般来说,如果网络够大,即使存在问题也不会有影响。这个例子里我们用3层全连接网络。
model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))

模型的编译

Keras会调用Theano或者TensorFlow编译模型。

我们需要定义损失函数和优化算法,以及需要收集的数据。我们使用binary_crossentropy,错误的对数作为损失函数;adam作为优化算法。基于本问题是分类问题,so我们收集每轮的准确率。

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

训练并测试模型

网络按轮训练,通过nb_epoch参数控制。每次送入的数据可以用batch_size参数控制。这里我们只跑150轮,每次10个数据。

model.fit(X, Y, nb_epoch=150, batch_size=10)

我们把测试数据拿出来检验一下模型的效果(注意这样不能测试在新数据的预测能力)我们应该将数据分成训练和测试集。调用模型的evaluation()方法,传入训练时的数据。输出是平均值,包括平均误差和其他的数据,例如准确度。

scores = model.evaluate(X, Y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

结果输出

...
Epoch 143/150
768/768 [==============================] - 0s - loss: 0.4614 - acc: 0.7878
Epoch 144/150
768/768 [==============================] - 0s - loss: 0.4508 - acc: 0.7969
Epoch 145/150
768/768 [==============================] - 0s - loss: 0.4580 - acc: 0.7747
Epoch 146/150
768/768 [==============================] - 0s - loss: 0.4627 - acc: 0.7812
Epoch 147/150
768/768 [==============================] - 0s - loss: 0.4531 - acc: 0.7943
Epoch 148/150
768/768 [==============================] - 0s - loss: 0.4656 - acc: 0.7734
Epoch 149/150
768/768 [==============================] - 0s - loss: 0.4566 - acc: 0.7839
Epoch 150/150
768/768 [==============================] - 0s - loss: 0.4593 - acc: 0.7839
768/768 [==============================] - 0s
acc: 79.56%

最后模型的准确率为79.56%,还不是特别高。本文的目的只是为了将keras的特点展示出来。对于该数据集,我们还可以进行很多优化,比如神经网络中的隐层的设计、引入交叉验证调参、dropout等。看客莫急,后面会慢慢写到的。


Keras 初探

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
4年前
PPDB:今晚老齐直播
【今晚老齐直播】今晚(本周三晚)20:0021:00小白开始“用”飞桨(https://www.oschina.net/action/visit/ad?id1185)由PPDE(飞桨(https://www.oschina.net/action/visit/ad?id1185)开发者专家计划)成员老齐,为深度学习小白指点迷津。
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
4年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
4年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
4年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
4年前
CPU推理性能提高数十倍,旷视天元计算图、MatMul优化深度解读
  机器之心发布  机器之心编辑部  !(http://dingyue.ws.126.net/2020/0806/6a6e4896j00qemtzy001ad000p000aop.jpg)本文针对旷视天元深度学习框架在推理优化过程中所涉及的计算图优化与MatMul优化进行深度解读。  背景及引言  在深度学
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
数字先锋说
数字先锋说
Lv1
独在异乡为异客,每逢佳节倍思亲。遥知兄弟登高处,遍插茱萸少一人。
文章
4
粉丝
0
获赞
0