引言

  在上一篇博客中,介绍了各种Python的第三方库的安装,本周将要使用Tensorflow完成第一个神经网络,BP神经网络的编写。由于之前已经介绍过了BP神经网络的内部结构,本文将直接介绍Tensorflow编程常用的一些方法。

正文

神经网络的内容

  一般,一个神经网络程序包含以下几部分内容。

  1.数据表达和特征提取。对于一个非深度学习神经网络,主要影响其模型准确度的因素就是数据表达和特征提取。同样的一组数据,在欧式空间和非欧空间,就会有着不同的分布。有时候换一种思考问题的思路就会使得问题变得简单。所以选择合适的数据表达可以极大的降低解决问题的难度。同样,在机器学习中,特征的提取也不是一种简单的事。在一些复杂问题上,要通过人工的方式设计有效的特征集合,需要很多的时间和精力,有时甚至需要整个领域数十年的研究投入。例如,PCA独立成分分析就是特征提取中常用的手段之一。但是很多情况下,人为都很难提取出合适的特征。

  由于不同问题下,可以提取不同的特征向量,这里将不做具体介绍。事实上深度学习解决的核心问题之一就是自动地将简单的特征组合成更加复杂的特征,并使用这些组合特征解决问题。

  2.定义神经网络的结构。由神经网络发展的历史可知,不同结构的神经网络在不同的问题下得到的效果不同。因此分析问题,选择与问题合适的神经网络结构也同样重要。

  3.训练神经网络的参数。使用训练数据集训练神经网络。主要是利用神经网络输出误差反向传播修正神经网络中的参数,甚至结构。反向传播过程中,步长选择对神经网络的训练有着重要的影响,在此基础上产生了多种训练方法。将在后面介绍。

  4.使用训练好的神经网络预测未知数据。训练神经网络的目的就是对未知数据预测。

  具体过程可以由如下流程图表示:

BP神经网络

  这里将按照流程图,详细构造BP神经网络。

  1.数据预处理

  这里将使用自造的数据模拟实际数据,通过对自造的数据仿真,验证BP神经网络的拟合能力。模型将使用一个单输入单输出一阶惯性传递函数模型。模型结构如下所示:

  为了很好的激励出模型的特性,X将用随机数来表示。具体制造模型,例子:

  导入第三方库,后面将不再展示。

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

  导入完成后就需要生成输入与输出的数据了。由于现实中各种数据之间的单位不同,直接使用时,由于数量级的问题往往会导致神经网络建模出现一些奇怪的问题。所以建模数据是需要归一化的。而这里为了方便,将直接生成0~1的数据。例子:

#生成输入输出数据
input_size = 1#输入变量个数
output_size = 1#输出变量个数
data_size = 2000#样本个数
k,T,x_state = 0.5,200,0#比例增益,时间常数,初始状态 x_data = np.random.rand(data_size,input_size)#输入数据0~1之间
y_data = np.zeros((data_size,output_size))#初始化输出数据
t_conv = np.e**(-1/T)#零阶保持器,采样周期1s for i in range(data_size):
x_state = t_conv*x_state + k*(1-t_conv)*x_data[i]
y_data[i] = x_state

  这里使用零阶保持的方法,将传递函数离散化后生成了共2000点的数据。这样就完成了数据预处理。

  2.神经网络结构

  由于已经确定要使用BP神经网络为传递函数建模。所以直接按照一层隐含层的BP神经网络建立结构就可以了。而在建立前,需要学习Tensorflow中张量的相关操作。

  首先,在Tensorflow中定义张量的方法是。例子:

a = tf.constant([1,2,3])
print(a)

  从运行结果可以发现,Tensorflow中的张量与numpy中的向量不同,张量中包含着名字,维度,和类型三种属性。张量是建立在计算图上的,通过使用会话,就可以计算不同的数据。具体计算图将在之后Tensorflow可视化中介绍,这里暂时就可以理解为一个函数。Tensorflow中还含有不同的随机数常数生成函数,可以帮助建立神经网络中的权值和阈值。例子:

tf.random_normal()#正太分布,可设置平均值、标准差、取值类型
tf.truncated_normal()#正态分布,但随机值偏离平均值2个标准差以内
tf.random_uniform()#平均分布,可设置最小值、最大值、取值类型
tf.random_gamma()#gamma分布,可设置形状参数,尺度参数,取值类型 tf.zeros()#产生全0数组
tf.ones()#产生全1数组
tf.fill()#产生全部为给定数字的数组

  特殊的,当不指导输入数据的长度时,可以用一个占位来定义。例子:

a = tf.placeholder(tf.float32,[None,1])

  定义好节点以后,就需要进行计算,常用的计算中加减乘除与之前相同,下面将介绍一些不同的。例子:

a = tf.Variable(tf.ones((1,3)))
b = tf.Variable(tf.ones((3,1))) c = tf.matmul(a,b)#向量乘法
d = tf.nn.relu(c)#激活函数ReLU
e = tf.nn.sigmoid(c)#激活函数sigmoid
f = tf.nn.tanh(c)#激活函数tanh

  依靠以上内容,就可以建立BP神经网络的结构。例子:

#神经网络结构
batch_size = 50#训练batch的大小
hide_size = 5#隐藏神经元个数 #预留每个batch中输入与输出的空间
x = tf.placeholder(tf.float32,shape = (None,input_size))#None随batch大小变化
y_pred = tf.placeholder(tf.float32,shape = (None,output_size)) w_hidden = tf.Variable(tf.random_normal([input_size,hide_size],stddev = 1,seed = 1))
b_hidden = tf.Variable(tf.zeros([1,hide_size],dtype = tf.float32))
w_output = tf.Variable(tf.random_normal([hide_size,output_size],stddev = 1,seed = 1)) #定义前向传播过程
h = tf.nn.tanh(tf.matmul(x,w_hidden)+b_hidden)
y = tf.nn.sigmoid(tf.matmul(h,w_output))

  之后反向传播Tensorflow可以自动进行,我们只需要定义损失函数和反向计算算法就可以了。神经网络模型的效果以及优化的目标是通过损失函数来定义的。这就是使用Tensorflow的优势。根据不同的用途,损失函数有着不同的定义方法。对于分类问题,可以使用交叉熵来定义。交叉熵的计算公式如下:

  编程例子:

cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-10,1.0)))#定义值与真实值间的交叉熵

  这里tf.clip_by_value可以将一个张量中的数值限制在一个范围内,避免运算错误。由于交叉熵经常与softmax回归一起使用,Tensorflow将它们进行了封装。例子:

cross_entropy = tf.nn.softmax_cross_entropy_with_logits(y,y_)

  与分类问题不同,本次例子解决的是回归问题。对于具体数值的预测,应该使用MSE均方误差作为损失函数。例子:

cross_entropy = tf.reduce_mean(tf.square(y_ - y))#定义损失函数

  并且,损失函数还可以自己定义,这里不再具体详述。

  3.训练神经网络

  训练神经网络时,要用到Tensorflow中另一个重要的内容,会话。会话拥有Tensorflow程序运行时的所有资源,并且可以对其进行管理。会话的打开与关闭与文件的读取类似。例子:

#方法1
sess=tf.Session()#创建会话
sess.run()#运行会话——类比打开文件
#具体会话执行内容
sess.close#关闭会话——类比关闭文件 #方法2
with tf.Session() as sess:
sess.run()
#通过缩进自动关闭

  在使用sess.run( )运行计算图时,我们可以传入fetches,用于取回某些操作或tensor的输出内容。fetches可以是list,tuple,namedtuple,dict中的任意一个。例子:

x = tf.constant([1])
y = tf.constant([2])
a = x+y with tf.Session() as sess:
z = sess.run(a)
print(z)

  同样在使用sess.run( )运行计算图时,我们可以传入feed,用于临时替代计算图中任意op操作的输入张量。例子:

x = numpy.array([2])
y = numpy.array([3]) input1 = tf.placeholder(tf.int32)
input2 = tf.placeholder(tf.int32)
output = input1+input2 with tf.Session() as sess:
print(sess.run(output, feed_dict = {input1:x, input2:y}))

  4.训练集,测试集。

  一般情况下需要将数据分为2类,一部分用来训练模型,一部分用来测试模型。这样就完成了最简单的BP神经网络的建立。

作业

使用普通BP神经网络拟合传递函数

#-*- coding:utf-8 -*-
#BP neural network
#Author:Kai Z import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt #生成输入输出数据
input_size = 1#输入变量个数
output_size = 1#输出变量个数
data_size = 2000#样本个数 x_data = np.random.rand(data_size,input_size)#输入数据0~1之间
y_data = np.zeros((data_size,output_size))#初始化输出数据 k,T,x_state = 0.5,200,0
t_conv = np.e**(-1/T)#零阶保持器,采样周期1s for i in range(data_size):
x_state = t_conv*x_state + k*(1-t_conv)*x_data[i]
y_data[i] = x_state #神经网络结构
batch_size = 50#训练batch的大小
hide_size = 5#隐藏神经元个数 #预留每个batch中输入与输出的空间
x = tf.placeholder(tf.float32,shape = (None,input_size))#None随batch大小变化
y = tf.placeholder(tf.float32,shape = (None,output_size)) w_hidden = tf.Variable(tf.random_normal([input_size,hide_size],stddev = 1,seed = 1))
b_hidden = tf.Variable(tf.zeros([1,hide_size],dtype = tf.float32))
w_output = tf.Variable(tf.random_normal([hide_size,output_size],stddev = 1,seed = 1)) #定义前向传播过程
h = tf.nn.tanh(tf.matmul(x,w_hidden)+b_hidden)
y_pred = tf.nn.sigmoid(tf.matmul(h,w_output)) #反向损失函数
learning_rate = 2e-3#学习速率
cross_entropy = tf.reduce_mean(tf.square(y_pred - y))#定义损失函数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)#定义反向传播优化方法 #创建会话
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)#初始化变量 #设定训练次数
STEPS = 10000#训练次数
for i in range(STEPS):
#选取训练batch
start = max((i * batch_size) % 1000,20)
end = min(start + batch_size,1000)#取前1000点训练 #计算
sess.run(train_step,feed_dict = {x:x_data[start:end],y:y_data[start:end]}) #显示误差
if i % 100 == 0:
total_cross_entropy = sess.run(cross_entropy,feed_dict = {x:x_data[1000:1500],y:y_data[1000:1500]})#1000~1500测试
print('训练%d次后,误差为%f'%(i,total_cross_entropy))
if total_cross_entropy <= 1e-3:
break
else:
print('未达到训练目标')
exit()
#保存结果
saver = tf.train.Saver()
file_path = 'D:/Study/Project/Hobby/Python/03 Study/02 Learn/test'
save_path = saver.save(sess,file_path)
predict = sess.run(y_pred,feed_dict={x:x_data})
predict = predict.ravel()#转换为向量
orange = y_data.ravel()
#建立时间轴
t = np.arange(2000)
plt.plot(t,predict)
plt.plot(t,orange)
plt.show()

后记

  可以看出,普通BP神经网络对动态传递函数的拟合效果并不是很好。这是由于神经网络是静态的,而传递函数是动态的。要想辨识动态系统,也得使用动态的神经网络。如最简单的NARX神经网络。或者更复杂的RNN。之后将进行RNN的实现。

  

NO.2:自学tensorflow之路------BP神经网络编程的更多相关文章

  1. 自学Python之路-Python核心编程

    自学Python之路-Python核心编程 自学Python之路[第六回]:Python模块       6.1 自学Python6.1-模块简介    6.2 自学Python6.2-类.模块.包  ...

  2. 自学Python之路-Python并发编程+数据库+前端

    自学Python之路-Python并发编程+数据库+前端 自学Python之路[第一回]:1.11.2 1.3

  3. 自学Python之路-Python网络编程

    自学Python之路-Python网络编程 自学Python之路[第一回]:1.11.2 1.3

  4. NO.3:自学tensorflow之路------MNIST识别,神经网络拓展

    引言 最近自学GRU神经网络,感觉真的不简单.为了能够快速跑完程序,给我的渣渣笔记本(GT650M)也安装了一个GPU版的tensorflow.顺便也更新了版本到了tensorflow-gpu 1.7 ...

  5. NO.1:自学tensorflow之路------神经网络背景知识

    引言 从本周,我将开始tensorflow的学习.手头只有一本<tensorflow:实战Google深度学习框架>,这本书对于tensorflow的入门有一定帮助.tensorflow中 ...

  6. 菜鸟之路——机器学习之BP神经网络个人理解及Python实现

    关键词: 输入层(Input layer).隐藏层(Hidden layer).输出层(Output layer) 理论上如果有足够多的隐藏层和足够大的训练集,神经网络可以模拟出任何方程.隐藏层多的时 ...

  7. 【转】漫谈ANN(2):BP神经网络

    上一次我们讲了M-P模型,它实际上就是对单个神经元的一种建模,还不足以模拟人脑神经系统的功能.由这些人工神经元构建出来的网络,才能够具有学习.联想.记忆和模式识别的能力.BP网络就是一种简单的人工神经 ...

  8. 使用TenforFlow 搭建BP神经网络拟合二次函数

    使用简单BP神经网络拟合二次函数 当拥有两层神经元时候,拟合程度明显比一层好 并出现如下警告: C:\Program Files\Python36\lib\site-packages\matplotl ...

  9. TensorFlow初探之简单神经网络训练mnist数据集(TensorFlow2.0代码)

    from __future__ import print_function from tensorflow.examples.tutorials.mnist import input_data #加载 ...

随机推荐

  1. P3694 邦邦的大合唱站队

    题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一 ...

  2. linux centos 7.5下 源码编译安装 lua环境

    lua 5.3.5 下载安装时发现缺少库 readline 需要添加依赖 yum search readline 看有哪些包 安装带有 devel 字样的 安装无 devel 的非开发包,通常不会自动 ...

  3. virtualbox+vagrant学习-4-Vagrantfile-6-SSH Settings

    SSH Settings 配置命名空间:config.ssh config.ssh的设置涉及到将如何配置vagrant使其通过ssh访问你的计算机.与大多数vagrant设置一样,默认设置通常都很好, ...

  4. jQuery.fn.extend()

    jQuery.fn.extend() extend()方法是定义在jQuery构造函数的prototype对象上面的一个方法,这样做就能使得所有jQuery对象的实例都能共享这个方法.jQuery构造 ...

  5. spring-mybatis项目搭建(支持多数据源)

    一.目录结构图 2.配置文件内容 db.properties: #oracle public oracle.driverClass=oracle.jdbc.driver.OracleDriver or ...

  6. Google 地图切片URL地址解析

    一.Google地图切片的投影方式及瓦片索引机制 1.地图投影 Google地图采用的是Web墨卡托投影(如下图),为了方便忽略了两极变形较大的地区,把世界地图做成了一个边长等于赤道周长的正方形(赤道 ...

  7. launch edge 和 latch edge 延迟

    本文转自 http://www.cnblogs.com/inet2012/archive/2012/03/07/2384149.html launch edge和latch edge分别是指一条路径的 ...

  8. 【转】ios开发证书,描述文件,bundle ID的关系

    ios开发证书,描述文件,bundle ID的关系   苹果为了控制应用的开发与发布流程,制定了一套非常复杂的机制.这里面的关键词有:个人开发者账号,企业开发者账号,bundle ID,开发证书,发布 ...

  9. 学习笔记——线程 Thread

    Thread是.net1.0 1.1时出现的 主要了解线程等待.回调.前后台线程区别 1.实例: //定义:public delegate void ThreadStart(); ThreadStar ...

  10. iOS如何在一个包上切换正式环境和测试环境

    最近项目处于测试阶段,所以免不了每天都得打包给测试人员,由于我们公司规模比较大,项目环境也分为了三种:测试环境.预上线(预生产)环境.上线(生产)环境.所以每到了测试后期,每天打包的时间也占了不少,遇 ...