第一部分.正则化函数及其应用
通常使用的正则化方法包含L1正则化和L2正则化,介绍如下:
| L1 正则化 | L2 正则化 |
说明 | 直接在原来的损失函数基础上加上权重参数的绝对值和: | 直接在原来的损失函数基础上加上权重参数的平方和: |
函数 | tf.contrib.layers.l1_regularizer(lamda) lamda:正则化参数λ | tf.contrib.layers.l2_regularizer(lamda) lamda:正则化参数λ |
使用方式:
一般将正则化函数与需要正则化的变量联合起来,并将结果存入到一个有名称的集合中:
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(0.5)(weight))
其中:
tf.add_to_collection 向集合’losses’中添加元素
‘losses’ 名称为losses的集合
weight 需要被正则化的变量
介绍:
简单的说,正则函数l2_regularizer只是将weight中元素进行平方加和求均值,再乘以系数λ(如上0.5) ,将求出的结果返回。
使用示例:
import tensorflow as tf import tensorflow.contrib as contrib
weight = tf.constant([[1.0, -2.0], [-3.0, 4.0]]) # 初始化一个常量weight tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(0.5)(weight)) # 将常量weight进行正则化生成的新tensor存储到losses集中,即向losses中存入1/2*(1^2+(-2)^2+(-3)^2+4^2)*0.5=7.5 a=weight+1 # 建立a,a为[[2,-1],[-2,5]] tf.add_to_collection('losses',tf.reduce_sum(a)) # 对a进行reduce_sum运算,将结果存入losses中,即存入2-1-2+5=4 b=tf.get_collection('losses') # 取出losses中存储的数据集赋值给b c=tf.add_n(b) # 对b进行add_n操作,赋值给c with tf.Session() as sess: # 输出结果 print(sess.run(weight)) print(sess.run(a)) print(sess.run(b)) print(sess.run(c)) |
输出结果: [[ 1. -2.] [-3. 4.]] [[ 2. -1.] [-2. 5.]] [7.5, 4.0] 11.5 |
注: 可以通过调整weight的结构和值、正则系数来观察正则化对结果的影响,从而更好的了解正则化。 |
参考:
https://blog.csdn.net/red_stone1/article/details/80755144 https://blog.csdn.net/lilong117194/article/details/79130032 讲的很详细 |
第二部分.在逻辑回归中应用正则化
以3.1中的程序为例,步骤如下:
步骤1. 建立数据源(样本库)——使用随机初始化的方式。由于需要进行逻辑分类,需要建立2个数据类,并合并在一起。如下:
num_points=1000 # 样本数目 vectors_set=[] x1_PlotData=[] # 用于后期绘图的数据 y1_PlotData=[] x2_PlotData=[] y2_PlotData=[] for i in range(int(num_points/2)): x1=np.random.normal(0.0,0.55) #横坐标,进行随机高斯处理化,以0为均值,以0.55为标准差 y1=x1*0.1+0.3+np.random.normal(-0.03,0.03) #纵坐标,数据点在y1=x1*0.1+0.3上小范围浮动 vectors_set.append([x1,y1,0]) x2 = np.random.normal(0.0, 0.55) y2 = x2 * 0.1 + 0.5 + np.random.normal(-0.03, 0.03) vectors_set.append([x2, y2,1]) x1_PlotData.append(x1) y1_PlotData.append(y1) x2_PlotData.append(x2) y2_PlotData.append(y2) x1_data=[v[0] for v in vectors_set] # 使用np.mat将list转化为numpy中的矩阵格式 x2_data=[v[1] for v in vectors_set] y_data=[v[2] for v in vectors_set] |
步骤2.建立数据流图:新建变量theta(同时建立正则项),假设函数 ,代价函数(同时添加正则项),优化算法选择梯度下降法,并设置步长:
theta=tf.Variable(np.zeros([3,1]),dtype=tf.float32) # 新建变量和占位符 tf.add_to_collection('cost',tf.contrib.layers.l2_regularizer(0.02)(theta)) # 将theta的正则项存储到'cost'中,正则系数为0.01 x_input=tf.placeholder(tf.float32,shape=[num_points,3]) y_input=tf.placeholder(tf.float32)
h_theta=1/(1+tf.exp(-tf.matmul(x_input,theta))) # 构建假设函数
cost_=-tf.reduce_mean(y_input*tf.log(h_theta)+(1-y_input)*tf.log(1-h_theta)) # 构建代价(损失)函数 tf.add_to_collection('cost',cost_) # 将损失存储到'cost'集合中 cost=tf.add_n(tf.get_collection('cost')) # 将'cost'集合内的元素进行加和运算,输出添加正则项的损失函数cost optimizer = tf.train.GradientDescentOptimizer(0.99) # 选择梯度下降法,并设置步长。 train_step = optimizer.minimize(cost) |
步骤3.初始化流图:
sess = tf.Session() init = tf.global_variables_initializer() sess.run(init) |
步骤4.开始训练,同时记录训练过程:
x_plot=[] y_plot=[] steps = 2000 # 训练次数 for i in range(steps): xs=np.column_stack((np.ones([num_points]), np.mat(x1_data).T,np.mat(x2_data).T)) ys = np.mat(y_data).T feed = { x_input: xs, y_input: ys } sess.run(train_step, feed_dict=feed) if i % 100 == 0 : # 每训练100次,记录训练结果 print("After %d iteration:" % i) print("Theta:" ,sess.run(theta)) print("Cost: %f" % sess.run(cost, feed_dict=feed)) x_plot.append(i) y_plot.append(sess.run(cost, feed_dict=feed)) |
步骤5.输出训练结果,主要为训练参数theta和损失值(代价值):
print("Finnally Result") print("Theta:" ,sess.run(theta)) print("Cost: %f" % sess.run(cost, feed_dict=feed)) |
步骤6.在样本集中绘制训练后的直线,和“训练次数-损失”曲线,一边观察训练结果:
x_result=[-2,2] Theta_result=sess.run(theta) y_result=[] for x_temp in x_result: # 如果直接赋值y_result=x_result*W+b,则y_result类型为Tensor,不能直接打印 y_result.append((-Theta_result[0]-x_temp*Theta_result[1])/Theta_result[2]) plt.subplot(1,2,1) plt.scatter(x1_PlotData,y1_PlotData,c='g') plt.scatter(x2_PlotData,y2_PlotData,c='r') plt.plot(x_result,y_result,'-y') plt.subplot(1,2,2) plt.plot(x_plot,y_plot,'-') plt.show() |
输出结果(通过更改步骤2中的,观察不同的正则系数对结果的影响):
正则系数为0.02: |
正则系数为0.001: |
注:
- 由以上两图可知,正则系数越大,拟合的阻力越大(即防止过拟合),容易发生欠拟合。
- 这个例子只是作为拟合函数的应用而展示的,由于是线性分类问题,正则化的作用不是很大。当分类的边界有多个弯曲时,正则化发挥的作用就会显现出来。