欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

tensorflow正则化案例

程序员文章站 2022-07-13 12:42:39
...

前言

文章总结自mooc北京大学曹健老师的课程并且有我自己的注释和理解,点击查看:tensorflow课程

定义介绍

过拟合
如果谈到正则化,首先我们应该说说过拟合,从明面意思上我们可以知道过拟合就是过度拟合的意思,简单来说就是训练的模型过度相似匹配于训练集,从而在模型泛化使用受到训练集特征的干扰,因为受到原来数据集很大的影响,所以遇到新的数据集不能很好的适应。原因以及解决办法这里粘一个大佬的文章:点击
正则化
正则化会保证每个特征有一定的效用,不会使某一特征特别重要。
在tensorflow中就是给每个参数w都加上权重,引入模型复杂度指标,从而抑制模型噪声,减小过拟合。

案例背景

这个案列是300个符合正态分布的点X[x0, x1] 作为数据集
标注规则为:当x + x2 <2时,y_ =1,标注为红色;当xo°+ x2≥2时,y. =0,标注为蓝色。我们分别用无正则化和有正则化两种方法,拟合曲线,把红色点和蓝色点分开。在实际分类时,如果前向传播输出的预测值y接近1则为红色点概率越大,接近0则为蓝色点概率越大,输出的预测值y为0.5是红蓝点概率分界线。

源码

#0导入模块,生成模拟数据集
import tensorflow as tf
import numpy as np
import matplotlib. pyplot as plt
BATCH_SIZE = 30
seed = 2
tf.set_random_seed(1)#tensorflow加一个随机种子,这样w的值就会固定
#基于seed产生随机数
rdm = np.random.RandomState(seed)
#随机数返回300行2列的矩阵,表示300组坐标点(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"其余赋值'buue',这样可视化显示时人可以直观区分	
Y_c = [['red' if y else 'blue'] for y in Y_]
#  对数据集X和标签Y_进行shape整理,第一个元素为-1表示,随第二个参数计算得到,  
#  第二个元素表示>多少列,把X整理为n行2列,把Y整理为n行1列
X  = np.vstack(X).reshape(-1, 2)#vstack:在竖直方向上堆叠
Y_ = np.vstack(Y_).reshape(-1, 1)#reshape:变量名.reshape(-1,n),返回一个n列的数组,行数自动给定
# print(X)
# print(Y_)
# print(Y_c)
#用pLt. scatter画出数据集X各行中第0列元素和第1列元素的点即各行的(x0,×1),用各行Y_c对应的值表示颜色(c是 color的缩写)
plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))#numpy.squeeze(a,axis = None)  若axis为空,则删除所有单维度的条目
#plt.show()
plt.savefig('/home/kai/opt/opt4_7/ori.png')#保存图片

# #定义神经络的输入、参数和输出,定义前向传播过程
def get_weight(shape, regularizer):#正则化给每个w加权重
	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)#非线性函数relu的输出

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'))#均方误差的损失+每一个正则化w的损失

#定义反向传播方法:不含正则化
train_step = tf.train.AdamOptimizer(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("After %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.savefig('/home/kai/opt/opt4_7/no_re.png')
plt.close()#防止两张图片叠加。可以直接观看:#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("After %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.savefig('/home/kai/opt/opt4_7/re.png')

源码分析

注释的很清楚了
N函数plt. scatter (): 利用指定颜色实现点(x, y)的可视化plt. scatter (x 坐标,y 坐标,c=” 颜色”) plt. show()
N收集规定区域内所有的网格坐标点:xx,yy=np.mgrid[起:止:步长,起:止:步长] #找到规定 区域以步长为分辨率的行列网格坐标点grid = np.c_ [xx. rave1),yy. rave10)] #收集规定区域内所有 的网格坐标点
N plt. contour()函数:告知x、y坐标和各点高度,用levels指定高度的点描上颜色plt. contour (x 轴坐标值,y轴坐标值,该点的高度,levels=[等 高线的高度])
plt. show()