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

这几天开始学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防止过拟合。

附上训练集

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

您可能感兴趣的文章:

  • TensorFlow 实战之实现卷积神经网络的实例讲解
  • tensorflow建立一个简单的神经网络的方法
(0)

相关推荐

  • tensorflow建立一个简单的神经网络的方法

    本笔记目的是通过tensorflow实现一个两层的神经网络.目的是实现一个二次函数的拟合. 如何添加一层网络 代码如下: def add_layer(inputs, in_size, out_size, activation_function=None): # add one more layer and return the output of this layer Weights = tf.Variable(tf.random_normal([in_size, out_size])) bia

  • TensorFlow 实战之实现卷积神经网络的实例讲解

    本文根据最近学习TensorFlow书籍网络文章的情况,特将一些学习心得做了总结,详情如下.如有不当之处,请各位大拿多多指点,在此谢过. 一.相关性概念 1.卷积神经网络(ConvolutionNeural Network,CNN) 19世纪60年代科学家最早提出感受野(ReceptiveField).当时通过对猫视觉皮层细胞研究,科学家发现每一个视觉神经元只会处理一小块区域的视觉图像,即感受野.20世纪80年代,日本科学家提出神经认知机(Neocognitron)的概念,被视为卷积神经网络最初

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

    这几天开始学tensorflow,先来做一下学习记录 一.神经网络解决问题步骤: 1.提取问题中实体的特征向量作为神经网络的输入.也就是说要对数据集进行特征工程,然后知道每个样本的特征维度,以此来定义输入神经元的个数. 2.定义神经网络的结构,并定义如何从神经网络的输入得到输出.也就是说定义输入层,隐藏层以及输出层. 3.通过训练数据来调整神经网络中的参数取值,这是训练神经网络的过程.一般来说要定义模型的损失函数,以及参数优化的方法,如交叉熵损失函数和梯度下降法调优等. 4.利用训练好的模型预测

  • tensorflow学习笔记之简单的神经网络训练和测试

    本文实例为大家分享了用简单的神经网络来训练和测试的具体代码,供大家参考,具体内容如下 刚开始学习tf时,我们从简单的地方开始.卷积神经网络(CNN)是由简单的神经网络(NN)发展而来的,因此,我们的第一个例子,就从神经网络开始. 神经网络没有卷积功能,只有简单的三层:输入层,隐藏层和输出层. 数据从输入层输入,在隐藏层进行加权变换,最后在输出层进行输出.输出的时候,我们可以使用softmax回归,输出属于每个类别的概率值.借用极客学院的图表示如下: 其中,x1,x2,x3为输入数据,经过运算后,

  • Python通过TensorFLow进行线性模型训练原理与实现方法详解

    本文实例讲述了Python通过TensorFLow进行线性模型训练原理与实现方法.分享给大家供大家参考,具体如下: 1.相关概念 例如要从一个线性分布的途中抽象出其y=kx+b的分布规律 特征是输入变量,即简单线性回归中的 x 变量.简单的机器学习项目可能会使用单个特征,而比较复杂的机器学习项目可能会使用数百万个特征. 标签是我们要预测的事物,即简单线性回归中的 y 变量. 样本是指具体的数据实例.有标签样本是指具有{特征,标签}的数据,用于训练模型,总结规律.无标签样本只具有特征的数据x,通过

  • 利用TensorFlow训练简单的二分类神经网络模型的方法

    利用TensorFlow实现<神经网络与机器学习>一书中4.7模式分类练习 具体问题是将如下图所示双月牙数据集分类. 使用到的工具: python3.5    tensorflow1.2.1   numpy   matplotlib 1.产生双月环数据集 def produceData(r,w,d,num): r1 = r-w/2 r2 = r+w/2 #上半圆 theta1 = np.random.uniform(0, np.pi ,num) X_Col1 = np.random.unifo

  • TensorFlow实现随机训练和批量训练的方法

    TensorFlow更新模型变量.它能一次操作一个数据点,也可以一次操作大量数据.一个训练例子上的操作可能导致比较"古怪"的学习过程,但使用大批量的训练会造成计算成本昂贵.到底选用哪种训练类型对机器学习算法的收敛非常关键. 为了TensorFlow计算变量梯度来让反向传播工作,我们必须度量一个或者多个样本的损失. 随机训练会一次随机抽样训练数据和目标数据对完成训练.另外一个可选项是,一次大批量训练取平均损失来进行梯度计算,批量训练大小可以一次上扩到整个数据集.这里将显示如何扩展前面的回

  • TensorFlow入门使用 tf.train.Saver()保存模型

    关于模型保存的一点心得 saver = tf.train.Saver(max_to_keep=3) 在定义 saver 的时候一般会定义最多保存模型的数量,一般来说,如果模型本身很大,我们需要考虑到硬盘大小.如果你需要在当前训练好的模型的基础上进行 fine-tune,那么尽可能多的保存模型,后继 fine-tune 不一定从最好的 ckpt 进行,因为有可能一下子就过拟合了.但是如果保存太多,硬盘也有压力呀.如果只想保留最好的模型,方法就是每次迭代到一定步数就在验证集上计算一次 accurac

  • 利用Tensorflow构建和训练自己的CNN来做简单的验证码识别方式

    Tensorflow是目前最流行的深度学习框架,我们可以用它来搭建自己的卷积神经网络并训练自己的分类器,本文介绍怎样使用Tensorflow构建自己的CNN,怎样训练用于简单的验证码识别的分类器.本文假设你已经安装好了Tensorflow,了解过CNN的一些知识. 下面将分步介绍怎样获得训练数据,怎样使用tensorflow构建卷积神经网络,怎样训练,以及怎样测试训练出来的分类器 1. 准备训练样本 使用Python的库captcha来生成我们需要的训练样本,代码如下: import sys i

  • tensorflow保持每次训练结果一致的简单实现

    在用tensorflow构建神经网络的时候,有很多随机的因素,比如参数的随机初始化: 正态分布随机变量tf.random_normal([m,n]),均匀分布的随机变量tf.random_uniform([m,n]),还有在从tfrecord读取数据时,也会随机打乱数据. 那么由于这些随机的操作,即使是在输入数据完全一样的情况下,每次训练的结果也不一样,那么如果想要使得每次训练的结果一致,应该怎么做呢? 可以在最开始时,固定随机数种子,如下 tf.set_random_seed(1) 以上这篇t

  • Tensorflow实现在训练好的模型上进行测试

    Tensorflow可以使用训练好的模型对新的数据进行测试,有两种方法:第一种方法是调用模型和训练在同一个py文件中,中情况比较简单:第二种是训练过程和调用模型过程分别在两个py文件中.本文将讲解第二种方法. 模型的保存 tensorflow提供可保存训练模型的接口,使用起来也不是很难,直接上代码讲解: #网络结构 w1 = tf.Variable(tf.truncated_normal([in_units, h1_units], stddev=0.1)) b1 = tf.Variable(tf

随机推荐