tensorflow入门之训练简单的神经网络方法
作者:py小菜鸟 发布时间:2021-07-16 14:21:51
这几天开始学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防止过拟合。
附上训练集
来源:http://blog.csdn.net/m0_37650263/article/details/77343220


猜你喜欢
- 本文实例讲述了python多重继承用法,分享给大家供大家参考。具体实现方法如下:1.mro.py文件如下:#!/usr/bin/python
- keras 深度学习框架中get_value函数运行越来越慢,内存消耗越来越大问题问题描述如上图所示,经过时间和内存消耗跟踪测试,发现是ke
- 更详细的信息可以去查msdn或者Navigator 2.0以后的说明文档,这里我们之做个简单的说明 包括一下几大属性: appCodeNam
- MSSQL SERVER 2005 数学函数 1.求绝对值 ABS() select FWeight-50,ABS(FWeight-50),
- 深度学习网络通常具有很深的层次结构,而且层与层之间通常会有并联、串联等连接方式。当使用PyTorch建立一个深度学习网络并输出文本向读者展示
- 一、random模块简介Python标准库中的random函数,可以生成随机浮点数、整数、字符串,甚至帮助你随机选择列表序列中的一个元素,打
- 花了两周时间,利用工作间隙时间,开发了一个基于Django的项目任务管理Web应用。项目计划的实时动态,可以方便地被项目成员查看(^_^又重
- 1.sonarqube是一款代码分析的工具,通过soanrScanner扫描后的数据传递给sonarqube进行分析2.sonarqube社
- 引言with 语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from __future__ im
- 本文实例为大家分享了python实现石头剪刀布的具体代码,供大家参考,具体内容如下老师布置了一个石头剪刀布的作业,要可视化,还是先用代码实现
- Azkaban是什么?Azkaban是由Linkedin公司推出的一个批量工作流任务调度器,主要用于在一个工作流内以一个特定的顺
- 概述在列表复制这个问题,看似简单的复制却有着许多的学问,尤其是对新手来说,理所当然的事情却并不如意,比如列表的赋值、复制、浅拷贝、深拷贝等绕
- Anaconda Jupyter安装拓展nbextensions先在终端pip两个包:Pip install jupyter_contrib
- javascript是种脚本语言,浏览器下载到哪儿就会执行到哪儿,这种特性会为编程提供方便,但也容易使程序过于凌乱,支离破碎。 js从功能上
- 本文实例讲述了Python导出DBF文件到Excel的方法。分享给大家供大家参考。具体如下:from dbfpy import dbffro
- 相对C/C++ 而言,我们所用的JavaScript 在内存这一方面的处理已经让我们在开发中更注重业务逻辑的编写。但是随着业务的不断复杂化,
- 起因事情是这样的,项目最近有个需求。服务器有个图片空间,说白了就是个文件夹。文件夹的结构大家都知道,一层一层的。然后需要在前端以树形展示。具
- 作用:可以清空此文件所在的web站点所有文件,将文件内容清零.运行完毕所有文件大小都变成0字节.此代码本人原创,转载请注明转自本站,谢谢合作
- 对于添加一个文件的路径我用的第一个方法就是sys.path.append()博主比较懒,就直接截图了啊对于上级文件路径和再上一级的路径可以直
- 1.数组上的迭代NumPy 包含一个迭代器对象numpy.nditer。它是一个有效的多维迭代器对象,可以用于在数组上进行迭代。数组的每个元