tensorflow入门之训练简单的神经网络方法


Posted in Python onFebruary 26, 2018

这几天开始学tensorflow,先来做一下学习记录

一.神经网络解决问题步骤:

1.提取问题中实体的特征向量作为神经网络的输入。也就是说要对数据集进行特征工程,然后知道每个样本的特征维度,以此来定义输入神经元的个数。

2.定义神经网络的结构,并定义如何从神经网络的输入得到输出。也就是说定义输入层,隐藏层以及输出层。

3.通过训练数据来调整神经网络中的参数取值,这是训练神经网络的过程。一般来说要定义模型的损失函数,以及参数优化的方法,如交叉熵损失函数和梯度下降法调优等。

4.利用训练好的模型预测未知的数据。也就是评估模型的好坏。

二.训练简单的向前传播神经网络

一下训练的神经模型是最简单的一类,而且是线性的(也就是说没有用激活函数去线性话),没有反向传播的过程,只是简单的说明神经网络工作的流程。

import tensorflow as tf

#定义隐藏层参数,每个w变量是一个tensor(可以当成是n*m的数组,n表示上一层结点个数,m表示本层结点个数)表示上一层与本层的连接权重,这里先随机定义权重
w1=tf.Variable(tf.random_normal([2,3],stddev=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1))

#定义存放输入数据的地方,也就是x向量,这里shape为前一个传入训练的样本个数,后面出入每个样本的维度大小
x=tf.placeholder(tf.float32,shape=(None,2),name="input")
#矩阵乘法
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

with tf.Session() as sess:
  #新版本好像不能用这个函数初始化所有变量了
  init_op=tf.initialize_all_variables()
  sess.run(init_op)
  #feed_dict用于向y中的x传入参数,这里传入3个,则y输出为一个3*1的tensor
  print(sess.run(y,feed_dict={x:[[0.7,0.9],[1.0,1.5],[2.1,2.3]]}))

至此,一个用x的每个维度乘以两层权重之后输出单个值得线性神经网络就定义好了。

三.定义损失函数以及反向传播算法

有了上面的基础,我们可以定义损失函数以及反向传播算法去拟合数据了,非线性数据我们可以定义激活函数去线性化。还有一些细节就是学习率的问题,这次使用的是动态学习率,首先把学习率设定为比较大的值,加速收敛,然后随着迭代次数的增加,学习率不断下降,防止错过局部最小值。还有一个问题,就是防止过拟合。一般神经网络防止过拟合的策略有两种,一种是正则化,一种是dropout,我们暂且不作讨论后者

损失函数:交叉熵

反向传播算法:梯度下降法

激活函数:relu

# -*- coding: utf-8 -*-
"""
Created on Fri Aug 18 14:02:19 2017

@author: osT
"""
import tensorflow as tf 
import numpy as np
#导入数据,这里的数据是每一行代表一个样本,每一行最后一列表示样本标签,0-32一共33个类
data=np.loadtxt('train_data.txt',dtype='float',delimiter=',')

#将样本标签转换成独热编码
def label_change(before_label):
  label_num=len(before_label)
  change_arr=np.zeros((label_num,33))
  for i in range(label_num):
    #该样本标签原本为0-32的,本人疏忽下32标记成33
    if before_label[i]==33.0:
      change_arr[i,int(before_label[i]-1)]=1
    else:
      change_arr[i,int(before_label[i])]=1
  return change_arr

#定义神经网络的输入输出结点,每个样本为1*315维,以及输出分类结果
INPUT_NODE=315
OUTPUT_NODE=33

#定义两层隐含层的神经网络,一层300个结点,一层100个结点
LAYER1_NODE=300
LAYER2_NODE=100

#定义学习率,学习率衰减速度,正则系数,训练调整参数的次数以及平滑衰减率
LEARNING_RATE_BASE=0.5
LEARNING_RATE_DECAY=0.99
REGULARIZATION_RATE=0.0001
TRAINING_STEPS=2000
MOVING_AVERAGE_DECAY=0.99

#定义整个神经网络的结构,也就是向前传播的过程,avg_class为平滑可训练量的类,不传入则不使用平滑
def inference(input_tensor,avg_class,w1,b1,w2,b2,w3,b3):
  if avg_class==None:
    #第一层隐含层,输入与权重矩阵乘后加上常数传入激活函数作为输出
    layer1=tf.nn.relu(tf.matmul(input_tensor,w1)+b1)
    #第二层隐含层,前一层的输出与权重矩阵乘后加上常数作为输出
    layer2=tf.nn.relu(tf.matmul(layer1,w2)+b2)
    #返回 第二层隐含层与权重矩阵乘加上常数作为输出
    return tf.matmul(layer2,w3)+b3
  else:
    #avg_class.average()平滑训练变量,也就是每一层与上一层的权重
    layer1=tf.nn.relu(tf.matmul(input_tensor,avg_class.average(w1))+avg_class.average(b1))
    layer2=tf.nn.relu(tf.matmul(layer1,avg_class.average(w2))+avg_class.average(b2))
    return tf.matmul(layer2,avg_class.average(w3))+avg_class.average(b3)

def train(data):
  #混洗数据
  np.random.shuffle(data)
  #取钱850个样本为训练样本,后面的全是测试样本,约250个
  data_train_x=data[:850,:315]
  data_train_y=label_change(data[:850,-1])
  data_test_x=data[850:,:315]
  data_test_y=label_change(data[850:,-1])

  #定义输出数据的地方,None表示无规定一次输入多少训练样本,y_是样本标签存放的地方
  x=tf.placeholder(tf.float32,shape=[None,INPUT_NODE],name='x-input')
  y_=tf.placeholder(tf.float32,shape=[None,OUTPUT_NODE],name='y-input')

  #依次定义每一层与上一层的权重,这里用随机数初始化,注意shape的对应关系
  w1=tf.Variable(tf.truncated_normal(shape=[INPUT_NODE,LAYER1_NODE],stddev=0.1))
  b1=tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE]))

  w2=tf.Variable(tf.truncated_normal(shape=[LAYER1_NODE,LAYER2_NODE],stddev=0.1))
  b2=tf.Variable(tf.constant(0.1,shape=[LAYER2_NODE]))

  w3=tf.Variable(tf.truncated_normal(shape=[LAYER2_NODE,OUTPUT_NODE],stddev=0.1))
  b3=tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE]))

  #输出向前传播的结果
  y=inference(x,None,w1,b1,w2,b2,w3,b3)

  #每训练完一次就会增加的变量
  global_step=tf.Variable(0,trainable=False)

  #定义平滑变量的类,输入为平滑衰减率和global_stop使得每训练完一次就会使用平滑过程
  variable_averages=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
  #将平滑应用到所有可训练的变量,即trainable=True的变量
  variable_averages_op=variable_averages.apply(tf.trainable_variables())

  #输出平滑后的预测值
  average_y=inference(x,variable_averages,w1,b1,w2,b2,w3,b3)

  #定义交叉熵和损失函数,但为什么传入的是label的arg_max(),就是对应分类的下标呢,我们迟点再说
  cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.arg_max(y_,1))
  #计算交叉熵的平均值,也就是本轮训练对所有训练样本的平均值
  cross_entrip_mean=tf.reduce_mean(cross_entropy)

  #定义正则化权重,并将其加上交叉熵作为损失函数
  regularizer=tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
  regularization=regularizer(w1)+regularizer(w2)+regularizer(w3)
  loss=cross_entrip_mean+regularization

  #定义动态学习率,随着训练的步骤增加不断递减
  learning_rate=tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,900,LEARNING_RATE_DECAY)
  #定义向后传播的算法,梯度下降发,注意后面的minimize要传入global_step
  train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
  #管理需要更新的变量,传入的参数是包含需要训练的变量的过程
  train_op=tf.group(train_step,variable_averages_op)

  #正确率预测
  correct_prediction=tf.equal(tf.arg_max(average_y,1),tf.arg_max(y_,1))
  accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

  with tf.Session() as sess:
    #初始所有变量
    tf.global_variables_initializer().run()
    #训练集输入字典
    validate_feed={x:data_train_x,y_:data_train_y}
    #测试集输入字典
    test_feed={x:data_test_x,y_:data_test_y}

    for i in range(TRAINING_STEPS):
      if i%1000==0:
        validate_acc=sess.run(accuracy,feed_dict=validate_feed)
        print("After %d training step(s),validation accuracy using average model is %g"%(i,validate_acc))
      #每一轮通过同一训练集训练,由于样本太少,没办法了
      sess.run(train_op,feed_dict=validate_feed)
    #用测试集查看模型的准确率
    test_acc=sess.run(accuracy,feed_dict=test_feed)
    print("After %d training step(s),test accuracy using average model is %g"%(TRAINING_STEPS,test_acc))
train(data)

然后我们来看一下为什么计算交叉熵时要传入样本的下标:

首先我们知道,输出结点有33个,通过与前面的权重相乘后,则每个结点都会有一个输出,每个输出我们暂且认为是对应每个类的概率,该值越大,我们就越认为该样本为对应的类。logits参数是神经网络的直接输出,也就是未经softmax函数处理的输出,labels传入的是单个值,也就是分类对应的下标,这是由于我们使用的计算交叉熵的函数 tf.nn.sparse_softmax_cross_entropy_with_logits()有关。这个函数对于在只有一个正确分类的模型计算起到加速作用,而这个labels的输入就是“这一个正确的分类”,对应到输出的结点,就是其下标了。我们还有一个没有加速的交叉熵函数:tf.nn.softmax_cross_entropy_with_logis(logis=,labels=)这个时候我们就应该传入本身的labels标签了。

最后,我们来总结一下提高模型准确率的方法:

1.使用激活函数。也就是去线性化,这步几乎是必须的。
2.增加隐含层。就本例而言,单隐含层300个结点,准确率在89%左右;单隐含层400个结点,准确率在93%左右;而双隐含层300结点和100结点,准确率在94%左右。但增加隐含层意味着增加训练时间。
3.使用动态学习率。这不但可以加快训练的速度,还可以增加神经网络收敛到较低的极小值处的概率,从而增加准确率。
4.使用平滑模型。主要可以增加模型的健壮性,使其泛化能力更强。
5.加入正则化或者使用dropout防止过拟合。

附上训练集

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现ip查询示例
Mar 26 Python
Python中解析JSON并同时进行自定义编码处理实例
Feb 08 Python
python插入数据到列表的方法
Apr 30 Python
Python异常的检测和处理方法
Oct 26 Python
深入理解Python异常处理的哲学
Feb 01 Python
python创建学生成绩管理系统
Nov 22 Python
Python 面向对象静态方法、类方法、属性方法知识点小结
Mar 09 Python
基于python爬取有道翻译过程图解
Mar 31 Python
python MultipartEncoder传输zip文件实例
Apr 07 Python
python新手学习使用库
Jun 11 Python
python用tkinter实现一个简易能进行随机点名的界面
Sep 27 Python
scrapy redis配置文件setting参数详解
Nov 18 Python
基于Python实现的微信好友数据分析
Feb 26 #Python
TensorFlow 实战之实现卷积神经网络的实例讲解
Feb 26 #Python
使用django-crontab实现定时任务的示例
Feb 26 #Python
Django中的CBV和FBV示例介绍
Feb 25 #Python
python中正则表达式的使用方法
Feb 25 #Python
python爬虫爬取淘宝商品信息(selenum+phontomjs)
Feb 24 #Python
python正则表达式爬取猫眼电影top100
Feb 24 #Python
You might like
收音机怀古---春雷3P7图片欣赏
2021/03/02 无线电
PHP支持多种格式图片上传(支持jpg、png、gif)
2011/11/03 PHP
解析PHP汉字转换拼音的类
2013/06/18 PHP
ThinkPHP中ajax使用实例教程
2014/08/22 PHP
基于php(Thinkphp)+jquery 实现ajax多选反选不选删除数据功能
2017/02/24 PHP
聊聊 PHP 8 新特性 Attributes
2020/08/19 PHP
JS.getTextContent(element,preformatted)使用介绍
2013/09/21 Javascript
location.href用法总结(最主要的)
2013/12/27 Javascript
node.js中的fs.stat方法使用说明
2014/12/16 Javascript
JavaScript中检查对象property的存在性方法介绍
2014/12/30 Javascript
javascript每日必学之循环
2016/02/19 Javascript
原生JS实现的放大镜效果实例代码
2016/10/15 Javascript
基于vue的fullpage.js单页滚动插件
2017/03/20 Javascript
整理关于Bootstrap过渡动画的慕课笔记
2017/03/29 Javascript
详解Angular 4.x Injector
2017/05/04 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
2017/06/14 Javascript
layui加载表格,绑定新增,编辑删除,查看按钮事件的例子
2019/09/06 Javascript
javascript二维数组和对象的深拷贝与浅拷贝实例分析
2019/10/26 Javascript
微信小程序实现下滑到底部自动翻页功能
2020/03/07 Javascript
JS如何定义用字符串拼接的变量
2020/07/11 Javascript
学习python处理python编码问题
2011/03/13 Python
python模拟登陆Tom邮箱示例分享
2014/01/13 Python
python3 线性回归验证方法
2019/07/09 Python
使用虚拟环境打包python为exe 文件的方法
2019/08/29 Python
Pytorch 实现计算分类器准确率(总分类及子分类)
2020/01/18 Python
python安装cx_Oracle和wxPython的方法
2020/09/14 Python
微信小程序实现可实时改变转速的css3旋转动画实例代码
2018/09/11 HTML / CSS
CSS3+HTML5+JS 实现一个块的收缩与展开动画效果
2020/11/17 HTML / CSS
五分钟学会HTML5的WebSocket协议
2019/11/22 HTML / CSS
欧姆龙医疗欧洲有限公司:Omron Healthcare Europe B.V
2020/06/13 全球购物
电子商务专业学生的自我鉴定
2013/11/28 职场文书
毕业典礼主持词大全
2014/03/26 职场文书
法定代表人授权委托书范文
2014/08/02 职场文书
2016圣诞节贺卡寄语
2015/12/07 职场文书
婚礼必备主持词范本!
2019/07/23 职场文书
Python并发编程实例教程之线程的玩法
2021/06/20 Python