首先提醒一下, 第 7 讲的最后滑动平均的代码已经更新了, 代码要比理论重要
今天是过拟合, 和正则化, 本篇后面可能或更有兴趣, 因为涉及到可视化图形了, 而不是纯数据
过拟合: 神经网络模型在训练集上的准确率比较高在新的数据进行预测或分类时准确率较低, 说明模型泛华能力差
正则化: 在损失函数中给每个参数 w 加上权重, 引入模型辅助度指标, 从而抑制模型噪声, 减小过拟合
使用正则化后, 损失函数 loss 变为两项之和:
loss = loss(y 与 y_) + REGULARIZER*loss(w)
其中, 第一项是预测结果与标准答案之间的差距, 如之前讲过的交叉熵, 均方误差等; 第二项是正则化计算结果
看过我爬虫教程的可能了解这个正则 re,re 就是这个 regularize
正则化计算方法:
(1)L1 正则化: lossL1 = Σi |wi|
用 Tensorflow 函数表示: loss(w) = tf.contrib.layers.11_regularizer(REGULARIZER)(w)
(2)L2 正则化: lossL2 = Σi |wi|2
用 Tensorflow 函数表示: loss(w) = tf.contrib.layers.12_regularizer(REGULARIZER)(w)
用 Tensorflow 函数实现正则化:
- tf.add_to_collection('losses', tf.contrib.layers.12_regularizer(regularizer)(w)
- losss = cem + tf.add_n(tf.get_collection('losses'))
例如:
用 300 个符合正态分布的点 X[x0, x1]作为数据集, 根据点 X[x0, x1] 计算生成标注 Y_, 将数据集标注为红色点和蓝色点.
标注规则: 当 x02 + x12>= 2 时, y_=0, 标注为蓝色
我们分别用无正则化和正则化两种方法, 拟合曲线, 把红色点和蓝色点. 在实际分类时, 如果前向传播输出的预测值 y 接近 1 则为红色点概率越大, 接近 0 则为蓝色点概率越大, 输出的预测值 y 为 0.5 是红蓝点概率分界线
在本例子中, 我们使用了之前未用过的模块与函数
matplotlib 模块: Python 中可视化工具模块, 实现函数可视化
matplotlib 的安装
1. 在 PyCharm 设置中添加就可以:
2. 终端安装指令:
pip install matplotlib
函数 plt.scatter (): 利用指定颜色实现点 (x,y) 的可视化
- plt.scatter (x 坐标, y 坐标, c="颜色")
- plt.show()
收集规定区域内所有的网格坐标点:
# 找到规定区域以步长为分辨率的行列网格坐标点
xx,yy = np.mgrid[起: 止: 步长, 起: 止: 步长]
- # 收集规定区域内所有的网格坐标点
- grid = np.c_[xx.ravel(), yy.ravel()]
plt.contour() 函数: 告知 x,y 坐标和各点高度, 用 levels 指定高度的点瞄上颜色
- plt.contour (x 轴坐标值, y 轴坐标值, 该点的高度, levels=[等高线高度])
- plt.show()
本例代码如下:
- #coding:utf-8
- # 导入模块, 生成模拟数据集
- import tensorflow as tf
- import numpy as np
- import matplotlib.pyplot as plt
- BATCH_SIZE = 30
- seed = 2
- # 基于 seed 产生随机数
- rdm = np.random.RandomState(seed)
- # 随机数返回行列的矩阵, 表示组坐标点 (x0, x1) 作为输入数据集
- X = rdm.randn(300,2)
- # 从 X 这个 300 行 2 列的矩阵中取出一行, 判断如果两个坐标的平方和小于 2, 给 Y 赋值 1, 其余值 0
- # 作为输入数据集的标签(正确答案)
- Y_ = [int(x0*x0 + x1*x1<2) for (x0,x1) in X]
- # 遍历 Y 中的每个元素, 1 赋值'red' 其余赋值为'blue', 这样可视化显示时人可以直观区分
- Y_c = [['red' if y else 'blue'] for y in Y_]
- # 对数据集 X 和标签 Y 进行 shap 整理, 第一个元素为 - 1 表示, 随第二个参数计算得到
- # 第二个元素表示多少列, 把 X 郑磊为 n 行 2 列, 把 Y 整理为 n 行 1 列
- X = np.vstack(X).reshape(-1,2)
- Y_ = np.vstack(Y_).reshape(-1,1)
- print(X)
- print(Y_)
- print(Y_c)
- # 用 plt.scatter 画出数据集 X 各行中第 0 列元素和第 1 列元素的点即各行的(x0,x1),
- # 用各行 Y_c 对应的值表示颜色(c 是 color 的缩写)
- plt.scatter(X[:,0], X[:,1],c=np.squeeze(Y_c))
- plt.show()
- # 定义神经网络的输入, 参数和输出, 定义前向传播过程
- def get_weight(shape, regularizer):
- w = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
- tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
- return w
- def get_bias(shape):
- b = tf.Variable(tf.constant(0.01, shape=shape))
- return b
- x = tf.placeholder(tf.float32, shape=(None, 2))
- y_ = tf.placeholder(tf.float32, shape=(None, 1))
- w1 = get_weight([2,11], 0.01)
- b1 = get_bias([11])
- y1 = tf.nn.relu(tf.matmul(x, w1)+b1)
- w2 = get_weight([11,1], 0.01)
- b2 = get_bias([1])
- y = tf.matmul(y1, w2)+b2 #输出层不过激活
- # 定义损失函数
- loss_mse = tf.reduce_mean(tf.square(y-y_))
- loss_total = loss_mse + tf.add_n(tf.get_collection('losses'))
- # 定义反向传播方法: 不含正则化
- train_step = tf.train.AdadeltaOptimizer(0.0001).minimize(loss_mse)
- with tf.Session() as sess:
- init_op = tf.global_variables_initializer()
- sess.run(init_op)
- STEPS = 40000
- for i in range(STEPS):
- start = (i*BATCH_SIZE)%300
- end = start + BATCH_SIZE
- sess.run(train_step,feed_dict={x:X[start:end],y_:Y_[start:end]})
- if i % 2000 == 0:
- loss_mse_v = sess.run(loss_mse,feed_dict={x:X,y_:Y_})
- print("Atfer %d steps, loss is:%f" %(i, loss_mse_v))
- #xx 在 - 3 到 3 之间以步长为 0.01,yy 在 - 3 到 3 之间以步长 0.01, 生成二维码网格坐标点
- xx,yy = np.mgrid[-3:3:.01, -3:3:.01]
- #将 xx,yy 拉直, 并合成一个 2 列的矩阵, 得到一个网格的集合
- grid = np.c_[xx.ravel(),yy.ravel()]
- #将网格坐标点喂入神经网络, probs 为输出
- probs = sess.run(y, feed_dict={x:grid})
- # probs 的 shape 调整成 xx 的样子
- probs = probs.reshape(xx.shape)
- print("w1:\n",sess.run(w1))
- print("b1:\n", sess.run(b1))
- print("w2:\n", sess.run(w2))
- print("b2:\n", sess.run(b2))
- plt.scatter(X[:,0],X[:,1], c=np.squeeze(Y_c))
- plt.contour(xx,yy,probs,levels=[.5])
- plt.show()
- # 定义反向传播方法: 包含正则化
- train_step = tf.train.AdamOptimizer(0.0001).minimize(loss_total)
- with tf.Session() as sess:
- init_op = tf.global_variables_initializer()
- sess.run(init_op)
- STEPS = 40000
- for i in range(STEPS):
- start = (i*BATCH_SIZE)%300
- end = start + BATCH_SIZE
- sess.run(train_step, feed_dict={x:X[start:end],y_:Y_[start:end]})
- if i %2000 ==0:
- loss_v = sess.run(loss_total, feed_dict={x:X,y_:Y_})
- print("Atfer %d steps, loss is:%f" % (i, loss_v))
- # xx 在 - 3 到 3 之间以步长为 0.01,yy 在 - 3 到 3 之间以步长 0.01, 生成二维码网格坐标点
- xx, yy = np.mgrid[-3:3:.01, -3:3:.01]
- # 将 xx,yy 拉直, 并合成一个 2 列的矩阵, 得到一个网格的集合
- grid = np.c_[xx.ravel(), yy.ravel()]
- # 将网格坐标点喂入神经网络, probs 为输出
- probs = sess.run(y, feed_dict={x: grid})
- # probs 的 shape 调整成 xx 的样子
- probs = probs.reshape(xx.shape)
- print("w1:\n", sess.run(w1))
- print("b1:\n", sess.run(b1))
- print("w2:\n", sess.run(w2))
- print("b2:\n", sess.run(b2))
- plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))
- plt.contour(xx, yy, probs, levels=[.5])
- plt.show()
运行过程可能较慢, 请耐心等待
注意: 红字提示不是报错, 只是提示, 现在可以不管
运行结果
主要看输出的三张图:
下面再说一篇每张图的意思:
第一张图:
只有红蓝点, 对随机的点进行数据集可视化, 标注规则: 当 x02 + x12>= 2 时, y_=0, 标注为蓝色
第二张图:
代码的注释中说明已经很详细了, 就是执行没有正则化训练过程, 将红蓝点分开的效果
显然我这个有点失败, 但主要就是为了突出第三张图片的效果
第三张图:
执行包含正则化训练过程, 将红蓝点分开的效果
更多文章链接: Tensorflow 笔记
本笔记不允许任何个人和组织转载
来源: https://www.cnblogs.com/xpwi/p/9885139.html