Keras是一套基于Tensorflow、Theano及CNTK后端的高层神经网络API,可以非常友好地支持快速实验,本文从零开始介绍了如何使用Keras搭建MLP并给出两个示例。

基于Ubuntu安装Keras

具体安装过程在官方中英文文档中有详细说明

中文 https://keras-cn.readthedocs.io/en/latest/for_beginners/keras_linux/

英文 https://keras.io/#installation

Keras基础知识

Sequential models

可以认为Keras中的所谓模型(models)就是某个具体的网络结构,如MLP、CNN、LSTM等,在Keras中它们被分为两种:序贯模型(Sequential)和函数式模型(Model)。

Sequential模型就是一个直接由若干网络层线性堆叠起来的网络,使用如下代码创建一个Sequential对象:

from keras.models import Sequential

model = Sequential()

Sequential的构造函数可以接收一个由layer组成的list,用以初始化该model

model = Sequential([
Dense(32, input_shape=(784,)),#一个Dense层
Activation('relu'),#为上一个Dense层附加激活函数
Dense(10),#再添加一个Dense层
Activation('softmax'),#为上一个Dense层附加激活函数
])

也可以使用.add()方法对该model初始化:

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

Dense layer

Dense layer即全连接层,构造方法如下:

keras.layers.core.Dense(
units,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None)

units:大于0的整数,表示该层输出维度。

activation:激活函数。

use_bias:是否使用偏置。

kernel_initializer:权值矩阵初始化方法。

bias_initializer:偏置的初始化方法。

regularizer与constraint:正则项与约束项。

我们可以使用前文提到的.add()方法为model添加全连接层,只有输入层需要指定输入数据维度,之后的层不需再指定前一层的维度。

compile & fit

model的结构设置好之后使用compile方法编译:

model.compile(
self,
optimizer,
loss,
metrics=None,
sample_weight_mode=None)

optimizer:预定义的优化器名称或自定义的优化器对象。

loss:预定义的损失函数名称或自定义的目标函数。

编译后使用fit方法训练模型:

model.fit(
self,
x,
y,
batch_size=32,
epochs=10,
verbose=1,
callbacks=None,
validation_split=0.0,
validation_data=None,
shuffle=True,
class_weight=None,
sample_weight=None,
initial_epoch=0)

x:作为输入数据的numpy array。

y:作为标签的numpy array。

batch_size:梯度下降时每个batch包含的样本数。

epochs:训练总轮数。

verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录。

训练一个线性回归模型

一个线性回归模型可以被认为是一个MLP的特例,即一个输入与输出只有1维且没有激活函数(或激活函数为线性函数a(x)=x)的MLP,我们首先生成一些离散的点,使这些点大致成线性关系,再构建一个Sequential model,最后在这些点上训练该model以得到它们的线性关系。

import numpy as np

from keras.models import Sequential
from keras.layers import Dense
from keras import optimizers data_size = 50 # 生成的数据集大小
batch_size = 40
learning_rate = 0.01
epochs = 300 # 在正负1之间均匀产生data_size个点
x_train = np.linspace(-1, 1, data_size)
# 使得数据点呈y=3x+5的关系,添加小范围正态随机数以获得数据的随机波动效果
y_train = 3 * x_train + 5 + np.random.rand(*x_train.shape)*0.3 # 创建一个Sequential模型
model = Sequential()
# 添加一个全连接层,输入数据维度为1,含一个输出单元,RandomUniform表示权值在正负0.05间均匀随机初始化
model.add(Dense(units=1, input_dim=1, kernel_initializer='RandomUniform')) # 打印查看当前的权重
print(model.layers[0].get_weights()) # 创建一个SGD对象以调整学习速率
sgd = optimizers.SGD(lr=learning_rate)
# 编译model,优化器使用刚创建的SGD对象,损失函数使用最小均方差mse
model.compile(optimizer=sgd, loss='mse')
# 使用之前生成的数据训练
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1) # 再次打印权重,可以看到其值在3与5附近
print(model.layers[0].get_weights())

结果:

...
Epoch 298/300
50/50 [==============================] - 0s 36us/step - loss: 0.0325
Epoch 299/300
50/50 [==============================] - 0s 45us/step - loss: 0.0264
Epoch 300/300
50/50 [==============================] - 0s 56us/step - loss: 0.0260
[array([[2.9937706]], dtype=float32), array([5.0084023], dtype=float32)]

有趣的是,当我们调整数据点的范围,将

x_train = np.linspace(-1, 1, data_size)

改为

x_train = np.linspace(-25, 25, data_size)

保持其他部分不变,再次运行程序训练,loss会振荡到无穷到导致训练失败,这是学习率过大造成的,将learning_rate由0.01改为0.003,再次训练,即可得到正确结果。

我们还可以加入一个隐层,调整学习率与epochs后也可以得到很好的训练结果:

import numpy as np

from keras.models import Sequential
from keras.layers import Dense
from keras import optimizers data_size = 50
batch_size = 40
learning_rate = 0.0003
epochs = 500 x_train = np.linspace(-25, 25, data_size)
y_train = 3 * x_train + 5 + np.random.rand(*x_train.shape)*0.3 model = Sequential()
#这里的units为4,即隐层单元个数为4
model.add(Dense(units=4, input_dim=1, kernel_initializer='RandomUniform'))
#再添加输出层,维度为1
model.add(Dense(units=1, kernel_initializer='RandomUniform')) print(model.layers[0].get_weights())
print(model.layers[1].get_weights()) sgd = optimizers.SGD(lr=learning_rate)
model.compile(optimizer=sgd, loss='mse')
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1) print(model.layers[0].get_weights())
print(model.layers[1].get_weights())

结果:

Epoch 498/500
50/50 [==============================] - 0s 119us/step - loss: 0.0169
Epoch 499/500
50/50 [==============================] - 0s 156us/step - loss: 0.0168
Epoch 500/500
50/50 [==============================] - 0s 85us/step - loss: 0.0182
[array([[ 0.8122992 , -0.08030439, -0.05526135, -1.0514123 ]],
dtype=float32), array([ 1.110988 , -0.11047827, -0.07585457, -1.4386528 ], dtype=float32)]
[array([[ 1.3721825 ],
[-0.13642032],
[-0.09367472],
[-1.7768502 ]], dtype=float32), array([0.968823], dtype=float32)]

结果中两个list中的第一个array是权值,第二个array是偏置。

训练一个用于识别MNIST的MLP

在Keras安装路径下的examples文件夹中可以找到mnist_mlp.py:

from __future__ import print_function

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop batch_size = 128
num_classes = 10
epochs = 20 #读取mnist的训练与测试数据
(x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
#整型转为浮点型
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
#归一到(0,1)区间内
x_train /= 255
x_test /= 255
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples') # convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes) #使用了两个隐层,每个隐层512个单元,激活函数选用relu,添加了Dropout防止过拟合,最后通过softmax输出
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax')) model.summary() #损失函数选用多分类对数损失函数,优化器选用RMSprop
model.compile(loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy']) history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

结果:

...
59392/60000 [============================>.] - ETA: 0s - loss: 0.0183 - acc: 0.99
59776/60000 [============================>.] - ETA: 0s - loss: 0.0182 - acc: 0.99
60000/60000 [==============================] - 15s 253us/step - loss: 0.0182 - acc: 0.9953 - val_loss: 0.1072 - val_acc: 0.9842
Test loss: 0.10721807914278024
Test accuracy: 0.9842

基于Keras搭建MLP的更多相关文章

  1. CNN实战篇-手把手教你利用开源数据进行图像识别(基于keras搭建)

    我一直强调做深度学习,最好是结合实际的数据上手,参照理论,对知识的掌握才会更加全面.先了解原理,然后找一匹数据来验证,这样会不断加深对理论的理解. 欢迎留言与交流! 数据来源: cifar10  (其 ...

  2. [AI开发]centOS7.5上基于keras/tensorflow深度学习环境搭建

    这篇文章详细介绍在centOS7.5上搭建基于keras/tensorflow的深度学习环境,该环境可用于实际生产.本人现在非常熟练linux(Ubuntu/centOS/openSUSE).wind ...

  3. 深度学习实践系列(3)- 使用Keras搭建notMNIST的神经网络

    前期回顾: 深度学习实践系列(1)- 从零搭建notMNIST逻辑回归模型 深度学习实践系列(2)- 搭建notMNIST的深度神经网络 在第二篇系列中,我们使用了TensorFlow搭建了第一个深度 ...

  4. [深度应用]·首届中国心电智能大赛初赛开源Baseline(基于Keras val_acc: 0.88)

    [深度应用]·首届中国心电智能大赛初赛开源Baseline(基于Keras val_acc: 0.88) 个人主页--> https://xiaosongshine.github.io/ 项目g ...

  5. [深度应用]·DC竞赛轴承故障检测开源Baseline(基于Keras 1D卷积 val_acc:0.99780)

    [深度应用]·DC竞赛轴承故障检测开源Baseline(基于Keras1D卷积 val_acc:0.99780) 个人网站--> http://www.yansongsong.cn/ Githu ...

  6. 不到 200 行代码,教你如何用 Keras 搭建生成对抗网络(GAN)【转】

    本文转载自:https://www.leiphone.com/news/201703/Y5vnDSV9uIJIQzQm.html 生成对抗网络(Generative Adversarial Netwo ...

  7. 基于Keras 的VGG16神经网络模型的Mnist数据集识别并使用GPU加速

    这段话放在前面:之前一种用的Pytorch,用着还挺爽,感觉挺方便的,但是在最近文献的时候,很多实验都是基于Google 的Keras的,所以抽空学了下Keras,学了之后才发现Keras相比Pyto ...

  8. 解析基于keras深度学习框架下yolov3的算法

    一.前言 由于前一段时间以及实现了基于keras深度学习框架下yolov3的算法,本来想趁着余热将自己的心得体会进行总结,但由于前几天有点事就没有完成计划,现在趁午休时间整理一下. 二.Keras框架 ...

  9. keras搭建神经网络快速入门笔记

    之前学习了tensorflow2.0的小伙伴可能会遇到一些问题,就是在读论文中的代码和一些实战项目往往使用keras+tensorflow1.0搭建, 所以本次和大家一起分享keras如何搭建神经网络 ...

随机推荐

  1. luogu_2831: 愤怒的小鸟

    洛谷2831:愤怒的小鸟(状压\(dp\)) 题意: 在二维平面上给定\(n\)个点\((1\leq n\leq18)\). 其中每个点用\((x_i,y_i)\)表示\((0<x_i,y_i& ...

  2. java的多线程之入门

    一.java多线程基本概念 调用run():在主线程调用子线程的run()方法会中断主线程等到子线程执行完毕之后再执行主线程. 调用start():在主线程中执行子线程的start()后会与主线程同步 ...

  3. 洛谷 p1968 美元汇率 题解

    传送门 美元由马克转化,马克由美元转化 求最大美元 每一天只有2种选择 ①:不转化另一货币 ②:转化另一货币 典型01背包 可以开一个二维数组f[100][3] F[i][1]表示前i天获得最大美元 ...

  4. 洛谷 P1621 集合

    目录 题目 思路 \(Code\) 题目 P1621 集合 思路 并查集+埃氏筛,一开始连通块的个数是\(b-a+1\)个,在筛素数的过程中只要当前素数大于\(p\)就对该素数筛出来的数进行判断,如果 ...

  5. 【JZOJ6214】【20190614】tetris

    题目 这是一道和俄罗斯方块有关的有趣题目 底面宽度为\(N\),高度无限,初始时方块高度为\(A_i\) 你可以决定每次会下落一个\(1 \times K\)或者\(K \times 1\)的方块 你 ...

  6. SQL进阶-数据类型转换

    一般有这几种转换: 一.数值型与字符型的转化 ### 数值型转为字符型: –> '65' select cast(65 as char); –> 'A' select char(65); ...

  7. 读RAM时的时序风险

    读RAM时的时序有两个风险:1.数据已经存储好,读所需的时间.2.数据同时更新,读所需的时间节点.对于前者,只要延时足够节拍就行.对于后者,还必须要考虑数据建立的时间,同样延时的准备可能会因为数据尚未 ...

  8. 第09组 Alpha事后诸葛亮

    组长博客链接 组长博客 参考邹欣老师的问题模板进行总结思考 设想和目标(2分) 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 解决的问题 我们软件初期旨在解决 ...

  9. File Browser文件资源服务器

    要是想一键启动的,这里有个封装版本的,上传到服务器,执行sh命令就能直接启动,也可以修改配置 链接:https://pan.baidu.com/s/1oVP5DrEQSV9hQmnF2bzM9A提取码 ...

  10. Http、Socket、WebSocket之间联系与区别

    WebSocket和Socket区别 可以把WebSocket想象成HTTP(应用层),HTTP和Socket什么关系,WebSocket和Socket就是什么关系. HTTP 协议有一个缺陷:通信只 ...