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中使用HTMLParser解析html实例
Feb 08 Python
Python中tell()方法的使用详解
May 24 Python
Python 数据结构之堆栈实例代码
Jan 22 Python
Python语言生成水仙花数代码示例
Dec 18 Python
python中scikit-learn机器代码实例
Aug 05 Python
3个用于数据科学的顶级Python库
Sep 29 Python
总结python中pass的作用
Feb 27 Python
Python3将数据保存为txt文件的方法
Sep 12 Python
Python可变参数会自动填充前面的默认同名参数实例
Nov 18 Python
从训练好的tensorflow模型中打印训练变量实例
Jan 20 Python
Python3爬虫中识别图形验证码的实例讲解
Jul 30 Python
Pycharm常用快捷键总结及配置方法
Nov 14 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
php下防止单引号,双引号在接受页面转义的设置方法
2008/09/25 PHP
Zend Framework教程之Zend_Controller_Plugin插件用法详解
2016/03/07 PHP
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
2016/12/14 PHP
PHP反射原理与用法深入分析
2019/09/28 PHP
浅析PHP中的 inet_pton 网络函数
2019/12/16 PHP
newxtree.js代码
2007/03/13 Javascript
js随机颜色代码的多种实现方式
2013/04/23 Javascript
jquery改变disabled的boolean状态的三种方法
2013/12/13 Javascript
jquery和javascript中如何将一元素的内容赋给另一元素
2014/01/09 Javascript
JavaScript代码复用模式详解
2014/11/07 Javascript
浅析AngularJs HTTP响应拦截器
2015/12/28 Javascript
VueJs与ReactJS和AngularJS的异同点
2016/12/12 Javascript
js原生代码实现轮播图的实例讲解
2017/07/28 Javascript
基于对象合并功能的实现示例
2017/10/10 Javascript
Vue数据绑定简析小结
2019/05/07 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
Vue实现点击导航栏当前标签后变色功能
2020/08/19 Javascript
解决VueCil代理本地proxytable无效报错404的问题
2020/11/07 Javascript
在Lighttpd服务器中运行Django应用的方法
2015/07/22 Python
Python使用迭代器打印螺旋矩阵的思路及代码示例
2016/07/02 Python
Python Paramiko模块的使用实际案例
2018/02/01 Python
对numpy中shape的深入理解
2018/06/15 Python
示例详解Python3 or Python2 两者之间的差异
2018/08/23 Python
python实现两张图片的像素融合
2019/02/23 Python
pygame实现俄罗斯方块游戏(基础篇3)
2019/10/29 Python
Python多线程获取返回值代码实例
2020/02/17 Python
Python使用tkinter制作在线翻译软件
2021/02/22 Python
css3截图_动力节点Java学院整理
2017/07/11 HTML / CSS
TripAdvisor台湾:全球最大旅游网站
2018/08/26 全球购物
全球独特生活方式产品和礼品购物网站:AHAlife
2018/09/18 全球购物
美国椅子和沙发制造商:La-Z-Boy
2020/10/25 全球购物
2015年电话客服工作总结
2015/05/18 职场文书
职业生涯规划书之大学四年
2019/08/07 职场文书
Python读取文件夹下的所有文件实例代码
2021/04/02 Python
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
Java 深入探究讲解简单工厂模式
2022/04/07 Java/Android