博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
tensorflow框架学习(三)—— 两个简单的神经网络示例,回归与分类
阅读量:5093 次
发布时间:2019-06-13

本文共 8533 字,大约阅读时间需要 28 分钟。

一、回归神经网络

1、神经网络结构

定义一个简单的回归神经网络结构:

  • 数据集为(xi,yi),数据的特征数为1,所以x的维度为1。
  • 输入层1个神经元。
  • 隐藏层数为1,4个神经元。
  • 输出层1个神经元。
  • 隐藏层的激活函数为f(x)=x,输出层的激活函数为ReLU

结构图如下:

 

 

2、代码示例

相关函数说明:

  • tf.random_normal :用于生成正太分布随机数矩阵的tensor,tensorFlow有很多随机数函数,可以查找官方文档获得。
  • tf.zeros :用于生成0矩阵的tensor,tf.ones可以用来获得单位矩阵。
  • tf.nn.relu :tensorflow定义的用来实现ReLU激活函数的方法。
  • tf.reduce_sum :求和函数,通过axis来控制在哪个方向上求和,axis=[0]表示按行求和,axis=[1]表示按列求和。
  • tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) :梯度下降优化函数,learning_rate表示学习率,minimize表示最小化,loss是优化的损失函数。tensorFlow有很多优化函数,可以查找官方文档获得。

 

代码:

import tensorflow as tfimport numpy as npimport matplotlib.pyplot as plt# 创建数据训练数据集,x_data = np.linspace(-1, 1, 500).reshape(500, 1)noise = np.random.normal(0, 0.05, [500, 1])  # 制作噪音y_data = np.square(x_data) + 0.5 + noise# 创建占位符用于minibatch的梯度下降训练,建议数据类型使用tf.float32、tf.float64等浮点型数据x_in = tf.placeholder(tf.float32, [None, 1])y_in = tf.placeholder(tf.float32, [None, 1])# 定义一个添加层的函数def add_layer(input_, in_size, out_size, activation_funtion=None):    '''    :param input_: 输入的tensor    :param in_size: 输入的维度,即上一层的神经元个数    :param out_size: 输出的维度,即当前层的神经元个数即当前层的    :param activation_funtion: 激活函数    :return: 返回一个tensor    '''    weight = tf.Variable(tf.random_normal([in_size, out_size]))  # 权重,随机的in_size*out_size大小的权重矩阵    biase = tf.Variable(tf.zeros([1, out_size]) + 0.01)  # 偏置,1*out_size大小的0.01矩阵,不用0矩阵避免计算出错    if not activation_funtion:  # 根据是否有激活函数决定输出        output = tf.matmul(input_, weight) + biase    else:        output = activation_funtion(tf.matmul(input_, weight) + biase)    return output# 定义隐藏层,输入为原始数据,特征为1,所以输入为1个神经元,输出为4个神经元layer1 = add_layer(x_in, 1, 4, tf.nn.relu)# 定义输出层,输入为layer1返回的tensor,输入为4个神经元,输出为1个神经元,激活函数为ReLUpredict = add_layer(layer1, 4, 1)# 定义损失函数loss = tf.reduce_mean(tf.reduce_sum(tf.square(y_in - predict), axis=[1]))  # tf.reduce_sum的axis=[1]表示按列求和# 定义训练的优化方式为梯度下降train = tf.train.GradientDescentOptimizer(0.1).minimize(loss)  # 学习率为0.1init = tf.global_variables_initializer()with tf.Session() as sess:    sess.run(init)    # 训练1000次    for step in range(1000):        # 执行训练,因为有占位符所以要传入字典,占位符的好处是可以用来做minibatch训练,这里数据量小,直接传入全部数据来训练        sess.run(train, feed_dict={x_in: x_data, y_in: y_data})        # 每50步输出一次loss        if step % 49 == 0:            print(sess.run(loss, feed_dict={x_in: x_data, y_in: y_data}))    # 最后画出实际的散点图与拟合的折线图进行对比    predict_value = sess.run(predict, feed_dict={x_in: x_data})  # 先要获得预测值    plt.figure()    plt.scatter(x_data, y_data, c='r', marker='o')    plt.plot(x_data, predict_value, '--', lw=2, c='b')    plt.show()

 

 

二、分类神经网络——mnist手写字数据

1、网络结构与数据来源

数据的详细说明请查看:。

结构说明:

  • 数据集(xi,yi):数据共有60000张图。其中xi是表示的是每一个图片的数据,长度为28x28 = 784,即一张图片特征为784列;yi有0-9共10种结果,由于是分类,所以使用softmax函数,则yi最后对应的输出层需要有10个神经元对应,有几个类就有几个神经元。
  • 隐藏层:个数为0,定义隐藏层拟合效果较差,所以这里不定义。
  • 输出层:为10个神经元,激活函数为softmax。
  • 损失函数loss:交叉熵损失函数。(交叉熵损失请查阅:)
  • 迭代方法:由于数据集过大,使用minbtach方法。
  • 准确度的计算 :中有详细说明。

 

2、代码示例

相关函数说明:

  • input_data.read_data_sets(train_dir='MNIST_data',one_hot=True) :函数作用说明,读取数据,代码会自动下载数据(若网络原因可自行下载),下载的是数据文件夹,在当前工作目录下,里面包含训练集mnist.train(包含特征mnist.train.images与标签mnist.train.labels)与测试集mnist.test(包含特征mnist.test.images与标签mnist.test.labels)。参数说明,train_dir:数据相对路径,one_hot:是否为独热编码。mnist.train.next_batch。

  • tf.argmax(input,dimension) :返回input张量的最大值所在的位置,dimension=1为列最大。
  • tf.equal(x,y) :返回一个bool数组,当x==y则值为True。
  • mnist.train.next_batch(batch_size) :用来获取mnist每批次的数据,每次使用会自动获取下一批batch_size大小的数据集。

代码:

import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 读取数据,代码会自动下载数据,下载的是数据文件夹,在当前工作目录下,里面包含训练集与测试集,train_dir:数据路径,one_hot:是否为独热编码。 mnist = input_data.read_data_sets(train_dir='MNIST_data', one_hot=True) # 数据较大,因此用minbatch,batch_size每个批次的数据个数,batch_num为批次个数 batch_size = 1000 batch_num = mnist.train.num_examples // batch_size # 创建占位符用于minibatch的梯度下降训练,建议数据类型使用tf.float32、tf.float64等浮点型数据 x_in = tf.placeholder(tf.float32, [None, 784]) y_in = tf.placeholder(tf.float32, [None, 10]) # 定义一个添加层的函数 def add_layer(input_, in_size, out_size, activation_funtion=None):     '''     :param input_: 输入的tensor     :param in_size: 输入的维度,即上一层的神经元个数     :param out_size: 输出的维度,即当前层的神经元个数即当前层的     :param activation_funtion: 激活函数     :return: 返回一个tensor     '''     weight = tf.Variable(tf.random_normal([in_size, out_size]))  # 权重,随机的in_size*out_size大小的权重矩阵     biase = tf.Variable(tf.zeros([1, out_size]) + 0.01)  # 偏置,1*out_size大小的0.01矩阵,不用0矩阵避免计算出错     if not activation_funtion:  # 根据是否有激活函数决定输出         output = tf.matmul(input_, weight) + biase     else:         output = activation_funtion(tf.matmul(input_, weight) + biase)     return output # 定义输出层,输入为layer1返回的tensor,输入为784个神经元,输出为10个神经元,激活函数为softmax。 prediction = add_layer(x_in, 784, 10)  # 这个对应下一步定义交叉熵损失函数的method1,不需要激活函数softmax # 定义交叉熵损失函数,这里用method1 # method1:用自带的函数,这个函数会自动对prediction进行softmax操作所以不需要前面定义prediction不需要激活函数 cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(labels=y_in, logits=prediction)) # #method2:手动计算,这里tf.clip_by_value函数的作用是为了避免输入为负数或者0,log函数的定义域是大于0的,不这么做会出现LOSS=NAN且模型准确度不变的情况,这个坑会在代码示例后面说明。 # cross_entropy = -tf.reduce_sum(y_in * tf.log(tf.clip_by_value(prediction,1e-8,1.0))) # 定义训练的优化方式为梯度下降 train = tf.train.GradientDescentOptimizer(0.1).minimize(cross_entropy)  # 学习率为0.1 # 准确度,先得到bool型的数组correct_prediction ,再计算值为True的平均值即为准确率 correct_prediction = tf.equal(tf.argmax(y_in, 1), tf.argmax(prediction, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) init = tf.global_variables_initializer() with tf.Session() as sess:     sess.run(init)     # 训练20代     for epoch in range(20):         # 每代对数据进行一轮minibatch         for batch in range(batch_num):             batch_x, batch_y = mnist.train.next_batch(batch_size)  # 每个循环读取batch_size大小批次的数据             sess.run(train, feed_dict={x_in: batch_x, y_in: batch_y})             acc = sess.run(accuracy, feed_dict={x_in: mnist.test.images, y_in: mnist.test.labels})  # 用测试数据计算准确度             print('第%d代%d批次,准确率为%.6f' % (epoch + 1, batch + 1, acc))

 

3、 使用交叉商的坑

第一个坑:

使用method1计算较差熵时,定义prediction不能有激活函数tf.nn.softmax,因为tf.nn.softmax_cross_entropy_with_logits函数会自动对prediction进行softmax处理,所以正确的代码如下:

#定义输出层prediction = add_layer(x_in, 784, 10)  #定义交叉熵cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(labels=y_in, logits=prediction))

可以尝试使用method1计算交叉熵,并定义prediction的时候传入激活函数,会发现拟合效果变差,代码如下

#定义输出层prediction = add_layer(x_in, 784, 10, tf.nn.softmax)  #定义交叉熵cross_entropy = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(labels=y_in, logits=prediction))

 

第二个坑:

先来看一下,当使用method2手动计算交叉熵时,不使用tf.clip_by_value时候的代码的时候运行是什么样子的,代码修改如下:

#method2:手动计算,这里tf.clip_by_value函数的作用是为了避免输入为负数或者0,log函数的定义域是大于0的,不这么做会出现LOSS=NAN且模型准确度不变的情况,这个坑会在代码示例后面说明。cross_entropy = -tf.reduce_sum(y_in * tf.log(prediction))

运行结果为:

C:\Users\EDZ\PycharmProjects\DY\Scripts\python.exe C:/Users/EDZ/.PyCharm2019.1/config/scratches/tf.pyExtracting MNIST_data\train-images-idx3-ubyte.gzExtracting MNIST_data\train-labels-idx1-ubyte.gzExtracting MNIST_data\t10k-images-idx3-ubyte.gzExtracting MNIST_data\t10k-labels-idx1-ubyte.gz第1代1批次,准确率为0.098000第1代2批次,准确率为0.098000第1代3批次,准确率为0.098000第1代4批次,准确率为0.098000第1代5批次,准确率为0.098000第1代6批次,准确率为0.098000第1代7批次,准确率为0.098000

可以看出准确率完全没有变化,准确率没有变化说明cross_entropy没有变,没有进行训练,于是输出每次迭代cross_entropy的值,代码修改如下:

# print('第%d代%d批次,准确率为%.6f' % (epoch + 1, batch + 1, acc))            loss = sess.run(cross_entropy, feed_dict={x_in: mnist.test.images, y_in: mnist.test.labels})            print('第%d代%d批次,loss为%.6f' % (epoch + 1, batch + 1, loss))

运行结果为:

C:\Users\EDZ\PycharmProjects\DY\Scripts\python.exe C:/Users/EDZ/.PyCharm2019.1/config/scratches/tf.pyExtracting MNIST_data\train-images-idx3-ubyte.gzExtracting MNIST_data\train-labels-idx1-ubyte.gzExtracting MNIST_data\t10k-images-idx3-ubyte.gzExtracting MNIST_data\t10k-labels-idx1-ubyte.gz第1代1批次,loss为nan第1代2批次,loss为nan第1代3批次,loss为nan第1代4批次,loss为nan第1代5批次,loss为nan第1代6批次,loss为nan第1代7批次,loss为nan

出现这样的结果是因为,log函数的定义域是x>0,但是传入的数据predicttion可能含有0或者负数,此时就会出现计算结果为NAN的情况,为了避免这个情况就需要用到tf.clip_by_value函数将数据限制在0-1之间,下面是这个函数的介绍:

tf.clip_by_value(t,clip_value_min,clip_value_max,name=None)

  • t: Tensor or IndexedSlices.
  • clip_value_min: A 0-D (scalar) Tensor, or a Tensor with the same shape as t. The minimum value to clip by.
  • clip_value_max: A 0-D (scalar) Tensor, or a Tensor with the same shape as t. The maximum value to clip by.
  • name: A name for the operation (optional).

作用:截断tensor数据的值,让数据的值在区间 [clip_value_min , clip_value_max] 内。若tensor的值value<clip_value_min,则返回value=clip_value_min;若clip_value_min<=value<=clip_value_max,则返回value;若clip_value_max<value,则返回clip_value_max。

 

转载于:https://www.cnblogs.com/dwithy/p/11263424.html

你可能感兴趣的文章
内存管理 浅析 内存管理/内存优化技巧
查看>>
【BZOJ 5222】[Lydsy2017省队十连测]怪题
查看>>
Java跟Javac,package与import
查看>>
Json格式的字符串转换为正常显示的日期格式
查看>>
[转]使用 Razor 进行递归操作
查看>>
[转]Android xxx is not translated in yyy, zzz 的解决方法
查看>>
docker入门
查看>>
Android系统--输入系统(十一)Reader线程_简单处理
查看>>
监督学习模型分类 生成模型vs判别模型 概率模型vs非概率模型 参数模型vs非参数模型...
查看>>
Mobiscroll脚本破解,去除Trial和注册时间限制【转】
查看>>
32位与64位 兼容编程
查看>>
iframe父子页面通信
查看>>
map基本用法
查看>>
Redis快速入门
查看>>
BootStrap---2.表格和按钮
查看>>
Linear Algebra lecture 2 note
查看>>
CRC计算模型
查看>>
Ajax之404,200等查询
查看>>
Aizu - 1378 Secret of Chocolate Poles (DP)
查看>>
csv HTTP简单表服务器
查看>>