在机器学习中可能会存在过拟合的问题,表现为在训练集上表现很好,但在测试集中表现不如训练集中的那么好。

图中黑色曲线是正常模型,绿色曲线就是overfitting模型。尽管绿色曲线很精确的区分了所有的训练数据,但是并没有描述数据的整体特征,对新测试数据的适应性较差。

一般用于解决过拟合的方法有增加权重的惩罚机制,比如L2正规化,但在本处我们使用tensorflow提供的dropout方法,在训练的时候, 我们随机忽略掉一些神经元和神经联结 , 是这个神经网络变得”不完整”. 用一个不完整的神经网络训练一次.
到第二次再随机忽略另一些, 变成另一个不完整的神经网络. 有了这些随机 drop 掉的规则, 我们可以想象其实每次训练的时候, 我们都让每一次预测结果都不会依赖于其中某部分特定的神经元. 像l1, l2正规化一样, 过度依赖的 W , 也就是训练参数的数值会很大, l1, l2会惩罚这些大的 参数. Dropout 的做法是从根本上让神经网络没机会过度依赖.

本次我们使用之前sklearn中手写数字作为例子来进行。

加载数据

  1. from sklearn.datasets import load_digits
  2. from sklearn.preprocessing import LabelBinarizer
  3. digits = load_digits()
  4. X = digits.data
  5. y = digits.target
  6. # 把数值转换成one hot格式,例如:数字4就会被转换成:[0 0 0 0 1 0 0 0 0 0]
  7. y = LabelBinarizer().fit_transform(y)
  8. # 拆分数据集,以总量的30%作为测试集
  9. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

添加层

添加层函数如下:

  1. import tensorflow as tf
  2. def add_layer(inputs, in_size, out_size, activation_function=None):
  3. """
  4. 添加层
  5. :param inputs: 输入数据
  6. :param in_size: 输入数据的列数
  7. :param out_size: 输出数据的列数
  8. :param activation_function: 激励函数
  9. :return:
  10. """
  11. # 定义权重,初始时使用随机变量,可以简单理解为在进行梯度下降时的随机初始点,这个随机初始点要比0值好,因为如果是0值的话,反复计算就一直是固定在0中,导致可能下降不到其它位置去。
  12. Weights = tf.Variable(tf.random_normal([in_size, out_size]))
  13. # 偏置shape为1行out_size列
  14. biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
  15. # 建立神经网络线性公式:inputs * Weights + biases,我们大脑中的神经元的传递基本上也是类似这样的线性公式,这里的权重就是每个神经元传递某信号的强弱系数,偏置值是指这个神经元的原先所拥有的电位高低值
  16. Wx_plus_b = tf.matmul(inputs, Weights) + biases
  17. if activation_function is None:
  18. # 如果没有设置激活函数,则直接就把当前信号原封不动地传递出去
  19. outputs = Wx_plus_b
  20. else:
  21. # 如果设置了激活函数,则会由此激活函数来对信号进行传递或抑制
  22. outputs = activation_function(Wx_plus_b)
  23. return outputs

定义placehoder和创建实际的网络结构

  1. # 定义placeholder
  2. # 输入的手写数字大小为8*8单位的数据
  3. xs = tf.placeholder(tf.float32, [None, 8*8])
  4. # 输出值为one hot结构的数据
  5. ys = tf.placeholder(tf.float32, [None, 10])
  6. # 添加层
  7. # 第一层输入为8*8单位的手写输入数字图像,输出设定为100个神经元的层(为了能够看出是overfitting的问题),激活函数一般用tanh比较好
  8. l1 = add_layer(xs, 8*8, 100, activation_function=tf.nn.tanh)
  9. # 输出层因为最终是一个one hot的结构,因此输出的大小为10,激活函数用softmax
  10. prediction = add_layer(l1, 100, 10, activation_function=tf.nn.softmax)

定义损失函数

  1. # 定义损失函数
  2. cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), axis=1))
  3. # 在tensorboard中记录损失函数值
  4. tf.summary.scalar(‘loss‘, cross_entropy)
  5. # 用梯度下降优化器进行训练
  6. train_step = tf.train.GradientDescentOptimizer(0.6).minimize(cross_entropy)

记录损失函数并运行

  1. sess = tf.Session()
  2. merged = tf.summary.merge_all()
  3. # 分别记录训练集的loss和测试集的loss值,目的是为了能够对比训练集和测试集中得拟合情况
  4. train_writer = tf.summary.FileWriter("D:/todel/data/tensorflow/train", sess.graph)
  5. test_writer = tf.summary.FileWriter("D:/todel/data/tensorflow/test", sess.graph)
  6. init = tf.global_variables_initializer()
  7. sess.run(init)
  8. for i in range(500):
  9. sess.run(train_step, feed_dict={xs:X_train, ys:y_train})
  10. if i % 50 == 0:
  11. # 分别用训练集和测试集数据获得损失函数值
  12. train_result = sess.run(merged, feed_dict={xs:X_train, ys: y_train})
  13. train_writer.add_summary(train_result, i)
  14. test_result = sess.run(merged, feed_dict={xs:X_test, ys: y_test})
  15. test_writer.add_summary(test_result, i)

完整代码

  1. from sklearn.datasets import load_digits
  2. from sklearn.preprocessing import LabelBinarizer
  3. from sklearn.model_selection import train_test_split
  4. digits = load_digits()
  5. X = digits.data
  6. y = digits.target
  7. # 把数值转换成one hot格式,例如:数字4就会被转换成:[0 0 0 0 1 0 0 0 0 0]
  8. y = LabelBinarizer().fit_transform(y)
  9. # 拆分数据集,以总量的30%作为测试集
  10. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
  11. import tensorflow as tf
  12. def add_layer(inputs, in_size, out_size, activation_function=None):
  13. """
  14. 添加层
  15. :param inputs: 输入数据
  16. :param in_size: 输入数据的列数
  17. :param out_size: 输出数据的列数
  18. :param activation_function: 激励函数
  19. :return:
  20. """
  21. # 定义权重,初始时使用随机变量,可以简单理解为在进行梯度下降时的随机初始点,这个随机初始点要比0值好,因为如果是0值的话,反复计算就一直是固定在0中,导致可能下降不到其它位置去。
  22. Weights = tf.Variable(tf.random_normal([in_size, out_size]))
  23. # 偏置shape为1行out_size列
  24. biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
  25. # 建立神经网络线性公式:inputs * Weights + biases,我们大脑中的神经元的传递基本上也是类似这样的线性公式,这里的权重就是每个神经元传递某信号的强弱系数,偏置值是指这个神经元的原先所拥有的电位高低值
  26. Wx_plus_b = tf.matmul(inputs, Weights) + biases
  27. if activation_function is None:
  28. # 如果没有设置激活函数,则直接就把当前信号原封不动地传递出去
  29. outputs = Wx_plus_b
  30. else:
  31. # 如果设置了激活函数,则会由此激活函数来对信号进行传递或抑制
  32. outputs = activation_function(Wx_plus_b)
  33. return outputs
  34. # 定义placeholder
  35. # 输入的手写数字大小为8*8单位的数据
  36. xs = tf.placeholder(tf.float32, [None, 8*8])
  37. # 输出值为one hot结构的数据
  38. ys = tf.placeholder(tf.float32, [None, 10])
  39. # 添加层
  40. # 第一层输入为8*8单位的手写输入数字图像,输出设定为100个神经元的层(为了能够看出是overfitting的问题),激活函数一般用tanh比较好
  41. l1 = add_layer(xs, 8*8, 100, activation_function=tf.nn.tanh)
  42. # 输出层因为最终是一个one hot的结构,因此输出的大小为10,激活函数用softmax
  43. prediction = add_layer(l1, 100, 10, activation_function=tf.nn.softmax)
  44. # 定义损失函数
  45. cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), axis=1))
  46. # 在tensorboard中记录损失函数值
  47. tf.summary.scalar(‘loss‘, cross_entropy)
  48. # 用梯度下降优化器进行训练
  49. train_step = tf.train.GradientDescentOptimizer(0.6).minimize(cross_entropy)
  50. sess = tf.Session()
  51. merged = tf.summary.merge_all()
  52. # 分别记录训练集的loss和测试集的loss值,目的是为了能够对比训练集和测试集中得拟合情况
  53. train_writer = tf.summary.FileWriter("D:/todel/data/tensorflow/train", sess.graph)
  54. test_writer = tf.summary.FileWriter("D:/todel/data/tensorflow/test", sess.graph)
  55. init = tf.global_variables_initializer()
  56. sess.run(init)
  57. for i in range(500):
  58. sess.run(train_step, feed_dict={xs:X_train, ys:y_train})
  59. if i % 50 == 0:
  60. # 分别用训练集和测试集数据获得损失函数值
  61. train_result = sess.run(merged, feed_dict={xs:X_train, ys: y_train})
  62. train_writer.add_summary(train_result, i)
  63. test_result = sess.run(merged, feed_dict={xs:X_test, ys: y_test})
  64. test_writer.add_summary(test_result, i)

输出结果

当我们运行了上面的代码后,会在D:/todel/data/tensorflow/目录下生成tensorboard收集的日志文件,我们可以在那个目录下输入:

最终在tensorboard中显示的图形为:

我们发现,训练集(蓝色的那条曲线)损失值要比测试集(黄色的那条曲线)小,这样就存在过拟合的情况。

消除过拟合

为了消除过拟合,我们采用dropout方式来进行。
首先设置一个保留概率的placeholder,这样在运行时可以通过参数来进行设置

  1. # 设置保留概率,即我们要保留的结果所占比例,它作为一个placeholder,在run时传入, 当keep_prob=1的时候,相当于100%保留,也就是dropout没有起作用。
  2. keep_prob = tf.placeholder(tf.float32)

然后在add_layer函数中调用dropout功能:

  1. # 调用dropout功能
  2. Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)

最后在训练时设置保留的概率,但在获得损失值时用全部的数据来进行获取:

  1. for i in range(500):
  2. sess.run(train_step, feed_dict={xs:X_train, ys:y_train, keep_prob: 0.7})
  3. if i % 50 == 0:
  4. # 分别用训练集和测试集数据获得损失函数值
  5. train_result = sess.run(merged, feed_dict={xs:X_train, ys: y_train, keep_prob:1})
  6. train_writer.add_summary(train_result, i)
  7. test_result = sess.run(merged, feed_dict={xs:X_test, ys: y_test, keep_prob:1})
  8. test_writer.add_summary(test_result, i)

这样全部代码为:

  1. from sklearn.datasets import load_digits
  2. from sklearn.preprocessing import LabelBinarizer
  3. from sklearn.model_selection import train_test_split
  4. digits = load_digits()
  5. X = digits.data
  6. y = digits.target
  7. # 把数值转换成one hot格式,例如:数字4就会被转换成:[0 0 0 0 1 0 0 0 0 0]
  8. y = LabelBinarizer().fit_transform(y)
  9. # 拆分数据集,以总量的30%作为测试集
  10. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
  11. import tensorflow as tf
  12. def add_layer(inputs, in_size, out_size, activation_function=None):
  13. """
  14. 添加层
  15. :param inputs: 输入数据
  16. :param in_size: 输入数据的列数
  17. :param out_size: 输出数据的列数
  18. :param activation_function: 激励函数
  19. :return:
  20. """
  21. # 定义权重,初始时使用随机变量,可以简单理解为在进行梯度下降时的随机初始点,这个随机初始点要比0值好,因为如果是0值的话,反复计算就一直是固定在0中,导致可能下降不到其它位置去。
  22. Weights = tf.Variable(tf.random_normal([in_size, out_size]))
  23. # 偏置shape为1行out_size列
  24. biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
  25. # 建立神经网络线性公式:inputs * Weights + biases,我们大脑中的神经元的传递基本上也是类似这样的线性公式,这里的权重就是每个神经元传递某信号的强弱系数,偏置值是指这个神经元的原先所拥有的电位高低值
  26. Wx_plus_b = tf.matmul(inputs, Weights) + biases
  27. # 调用dropout功能
  28. Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)
  29. if activation_function is None:
  30. # 如果没有设置激活函数,则直接就把当前信号原封不动地传递出去
  31. outputs = Wx_plus_b
  32. else:
  33. # 如果设置了激活函数,则会由此激活函数来对信号进行传递或抑制
  34. outputs = activation_function(Wx_plus_b)
  35. return outputs
  36. # 定义placeholder
  37. # 输入的手写数字大小为8*8单位的数据
  38. xs = tf.placeholder(tf.float32, [None, 8*8])
  39. # 输出值为one hot结构的数据
  40. ys = tf.placeholder(tf.float32, [None, 10])
  41. # 设置保留概率,即我们要保留的结果所占比例,它作为一个placeholder,在run时传入, 当keep_prob=1的时候,相当于100%保留,也就是dropout没有起作用。
  42. keep_prob = tf.placeholder(tf.float32)
  43. # 添加层
  44. # 第一层输入为8*8单位的手写输入数字图像,输出设定为100个神经元的层(为了能够看出是overfitting的问题),激活函数一般用tanh比较好
  45. l1 = add_layer(xs, 8*8, 100, activation_function=tf.nn.tanh)
  46. # 输出层因为最终是一个one hot的结构,因此输出的大小为10,激活函数用softmax
  47. prediction = add_layer(l1, 100, 10, activation_function=tf.nn.softmax)
  48. # 定义损失函数
  49. cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), axis=1))
  50. # 在tensorboard中记录损失函数值
  51. tf.summary.scalar(‘loss‘, cross_entropy)
  52. # 用梯度下降优化器进行训练
  53. train_step = tf.train.GradientDescentOptimizer(0.6).minimize(cross_entropy)
  54. sess = tf.Session()
  55. merged = tf.summary.merge_all()
  56. # 分别记录训练集的loss和测试集的loss值,目的是为了能够对比训练集和测试集中得拟合情况
  57. train_writer = tf.summary.FileWriter("D:/todel/data/tensorflow/train", sess.graph)
  58. test_writer = tf.summary.FileWriter("D:/todel/data/tensorflow/test", sess.graph)
  59. init = tf.global_variables_initializer()
  60. sess.run(init)
  61. for i in range(500):
  62. sess.run(train_step, feed_dict={xs:X_train, ys:y_train, keep_prob: 0.7})
  63. if i % 50 == 0:
  64. # 分别用训练集和测试集数据获得损失函数值
  65. train_result = sess.run(merged, feed_dict={xs:X_train, ys: y_train, keep_prob:1})
  66. train_writer.add_summary(train_result, i)
  67. test_result = sess.run(merged, feed_dict={xs:X_test, ys: y_test, keep_prob:1})
  68. test_writer.add_summary(test_result, i)

运行后输出tensorboard图形为(记得把之前的文件或目录进行删除并运行tensorboard进行显示图形):

这样训练集和测试集的损失值就比较接近了。

tensorflow用dropout解决over fitting的更多相关文章

  1. tensorflow用dropout解决over fitting-【老鱼学tensorflow】

    在机器学习中可能会存在过拟合的问题,表现为在训练集上表现很好,但在测试集中表现不如训练集中的那么好. 图中黑色曲线是正常模型,绿色曲线就是overfitting模型.尽管绿色曲线很精确的区分了所有的训 ...

  2. tensorflow学习之(八)使用dropout解决overfitting(过拟合)问题

    #使用dropout解决overfitting(过拟合)问题 #如果有dropout,在feed_dict的参数中一定要加入dropout的值 import tensorflow as tf from ...

  3. 4 TensorFlow入门之dropout解决overfitting问题

    ------------------------------------ 写在开头:此文参照莫烦python教程(墙裂推荐!!!) ---------------------------------- ...

  4. TensorFlow实战第七课(dropout解决overfitting)

    Dropout 解决 overfitting overfitting也被称为过度学习,过度拟合.他是机器学习中常见的问题. 图中的黑色曲线是正常模型,绿色曲线就是overfitting模型.尽管绿色曲 ...

  5. 【转载】 深度学习总结:用pytorch做dropout和Batch Normalization时需要注意的地方,用tensorflow做dropout和BN时需要注意的地方,

    原文地址: https://blog.csdn.net/weixin_40759186/article/details/87547795 ------------------------------- ...

  6. Tensorflow调试Bug解决办法记录

    1.ascii' codec can't encode characters in position 0-4: ordinal not in range(128) 原因是python2.X默认的编码是 ...

  7. TF:利用sklearn自带数据集使用dropout解决学习中overfitting的问题+Tensorboard显示变化曲线—Jason niu

    import tensorflow as tf from sklearn.datasets import load_digits #from sklearn.cross_validation impo ...

  8. 【TensorFlow】:解决TensorFlow的ImportError: DLL load failed: 动态链接库(DLL)初始化例程失败

    [背景] 在scikit-learn基础上系统结合数学和编程的角度学习了机器学习后(我的github:https://github.com/wwcom614/machine-learning),意犹未 ...

  9. TensorFlow 用神经网络解决非线性问题

    本节涉及点: 激活函数 sigmoid 产生随机训练数据 使用随机训练数据训练 加入偏移量b加快训练过程 进阶:批量生产随机训练数据 在前面的三好学生问题中,学校改变了评三好的标准 —— 总分> ...

随机推荐

  1. 一、ARM

    1.1 ARM 分类 1.1.1 版本号分类 以前分类的是 ARM7,ARM9... ARM11,在 ARM11 之后,就是以 Cortex 系列分类了: Cortex-R:应用在实时系统上的系列 C ...

  2. DOM 操作表格

    操作表格<table>标签是 HTML 中结构最为复杂的一个,我们可以通过 DOM 来创建生成它,或者 HTML DOM 来操作它.(PS:HTML DOM 提供了更加方便快捷的方式来操作 ...

  3. Android App渗透测试工具汇总

    网上搜集了一些App安全学习教程及工具,项目地址:https://github.com/Brucetg/App_Security 一. drozer简介 drozer(以前称为Mercury)是一款A ...

  4. phpstorm 生产php pojo类

    一. 修改Generate POJO.groovy文件 改为 import com.intellij.database.model.DasTable import com.intellij.datab ...

  5. Orabbix无法获取Oracle DB Size和DB Files Size的解决方法

    Orabbix无法获取Oracle DB Size和DB Files Size的解决方法 这几天在研究Orabbix时发现在Zabbix中无法获取DB Size和DB Files Size的大小,后来 ...

  6. Oracle12c创建及删除PDB

    在12C R1版本中只支持Global Shared Undo模式,所有container共享一个UNDO表空间:在12C R2引入了PDB Local Undo模式,每个container都有自己的 ...

  7. Linux内核设计与实现 总结笔记(第二章)

    一.Linux内核中的一些基本概念 内核空间:内核可独立于普通应用程序,它一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限.这种系统态和被保护起来的内存空间,称为内核空间. 进程上下文:当 ...

  8. JS自定义随机数字键盘

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 关于Reporting Services网站

    1.http://www.c-sharpcorner.com/search/sql%20server%20reporting%20services 2.https://msdn.microsoft.c ...

  10. codeforces_D. Treasure Hunting_[DP+Binary Search]

    http://codeforces.com/contest/1201/problem/D 题意:n行m列的矩阵中,有k个targets,从[1, 1]出发,每次只能向上下左右四个方向移动一步,且只有在 ...