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

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

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

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

加载数据

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

添加层

添加层函数如下:

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

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

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

定义损失函数

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

记录损失函数并运行

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

完整代码

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

输出结果

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

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

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

消除过拟合

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

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

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

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

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

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

这样全部代码为:

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

    @import '~@/assets/scss/helpers/_mixin'; 原理:CSS loader 会把把非根路径的url解释为相对路径, 加~前缀才会解释成模块路径.

  2. Rabbit给单独的消息设置超时

    /** * 发送消息 * @param user */@RequestMapping(value = prefix+"/setRabbitMessage", method = Re ...

  3. python学习笔记(十一)处理json

    json串就是字符串,json串里必须是双引号 d={'car':{'color':'red','price':100,'count':50}, '爱分叉':{'color':'red','price ...

  4. [CSP-S模拟测试]:嘟嘟噜(约瑟夫问题)

    题目描述 由于众所周知的原因,冈部一直欠真由理一串香蕉.为了封上真由理的嘴,冈部承诺只要真由理回答出这个问题,就给她买一车的香蕉:一开始有$n$个人围成一个圈,从$1$开始顺时针报数,报出$m$的人被 ...

  5. webpack 常用配置

    webpack.config.js const path = require('path'); const webpack = require('webpack'); const htmlWebpac ...

  6. Vagrant 手册之 Provisioning - 概述

    原文地址 通过 Vagrant 中的 provisioner 配置程序,可以在使用 vagrant up 启动虚拟机时,在虚拟机上执行安装软件.更改配置等操作. box 通常是通用的,而每个项目总有自 ...

  7. Visual Studio Code配置技巧

    Visual Studio Code配置技巧 VS Code是啥 Visual Studio Code(以下简称 VS Code) 是一个免费.开源.跨平台的由微软开发的程序编辑器.它是用 TypeS ...

  8. Filter 和Listener

    Filter 和Listener Filter : 过滤器 1.概念 浏览器发出请求访问服务器的资源,过滤器将请求拦截,完成一些特殊的功能. 作用:一般用于完成通过的操作.如:登陆验证.统一编码处理. ...

  9. Netty之大名鼎鼎的EventLoop

    EventLoopGroup 与Reactor: 前面的章节中我们已经知道了,一个Netty 程序启动时,至少要指定一个EventLoopGroup(如果使用到的是NIO,通常是指NioEventLo ...

  10. Stream的排序

    1.list<Integer>的正序 List<Integer> list = new ArrayList<>();list.add(50);list.add(45 ...