程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

第十一节,全连接网络中的优化技巧-过拟合、正则化,dropout、退化学习率等

 随着科研人员在使用神经网络训练时不断的尝试,为我们留下了很多有用的技巧,合理的运用这些技巧可以使自己的模型得到更好的拟合效果。

一 利用异或数据集演示过拟合

全连接网络虽然在拟合问题上比较强大,但太强大的拟合效果也带来了其它的麻烦,这就是过拟合问题。

首先我们看一个例子,这次将原有的4个异或带护具扩充成了上百个具有异或特征的数据集,然后通过全连接网络将它们进行分类。

实例描述:构建异或数据集模拟样本,在构建一个简单的多层神经网络来拟合其样本特征,观察其出现前泥河的现象,接着通过增大网络复杂性的方式来优化欠拟合问题,使其出现过拟合现象。

1. 构建异或数据集

复制代码
'''
    生成随机数据
    '''
    np.random.seed(10)
    #特征个数
    num_features = 2
    #样本个数
    num_samples = 320
    #n返回长度为特征的数组 正太分布
    mean = np.random.randn(num_features)
    print('mean',mean)
    cov = np.eye(num_features)
    print('cov',cov)
    X,Y = generate(num_samples,mean,cov,[[3.0,0.0],[3.0,3.0],[0.0,3.0]],num_classes=4)
    #转换为二种类别
    Y = Y % 2        
    
    xr = []
    xb = []
    
    for (l,k) in zip(Y[:],X[:]):
        if l == 0.0:
            xr.append([k[0],k[1]])
        else:
            xb.append([k[0],k[1]])
        
    xr = np.array(xr)
    xb = np.array(xb)
    plt.scatter(xr[:,0],xr[:,1],c='r',marker='+')
    plt.scatter(xb[:,0],xb[:,1],c='b',marker='o')
复制代码

可以看到图上数据分为两类,左上和左下是一类,右上和右下是一类。

2 定义网络模型

复制代码
'''
    定义变量
    '''
    #学习率
    learning_rate = 1e-4
    #输入层节点个数
    n_input = 2
    #隐藏层节点个数
    n_hidden = 2
    #输出节点数
    n_label = 1
    
    input_x = tf.placeholder(tf.float32,[None,n_input])
    input_y = tf.placeholder(tf.float32,[None,n_label])
    
    '''
    定义学习参数
    
    h1 代表隐藏层
    h2 代表输出层
    '''
    weights = {
            'h1':tf.Variable(tf.truncated_normal(shape=[n_input,n_hidden],stddev = 0.01)),     #方差0.1
            'h2':tf.Variable(tf.truncated_normal(shape=[n_hidden,n_label],stddev=0.01))
            }
    
    
    biases = {
            'h1':tf.Variable(tf.zeros([n_hidden])),    
            'h2':tf.Variable(tf.zeros([n_label]))
            }
    
    
    '''
    定义网络模型
    '''
    #隐藏层
    layer_1 = tf.nn.relu(tf.add(tf.matmul(input_x,weights['h1']),biases['h1']))
    
    
    #代价函数
    y_pred = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['h2']),biases['h2'])) 
    loss = tf.reduce_mean(tf.square(y_pred - input_y))
    
        
    train = tf.train.AdamOptimizer(learning_rate).minimize(loss)
复制代码

3. 训练网络并可视化显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
'''
  开始训练
  '''
  training_epochs = 30000
  sess = tf.InteractiveSession()
   
  #初始化
  sess.run(tf.global_variables_initializer())
   
  for epoch in range(training_epochs):
      _,lo = sess.run([train,loss],feed_dict={input_x:X,input_y:np.reshape(Y,[-1,1])})
      if epoch % 1000 == 0:
          print('Epoch {0}  loss {1}'.format(epoch,lo))
       
       
  '''
  数据可视化
  '''     
  nb_of_xs = 200
  xs1 = np.linspace(-1,8,num = nb_of_xs)
  xs2 = np.linspace(-1,8,num = nb_of_xs)
   
  #创建网格
  xx,yy = np.meshgrid(xs1,xs2)
   
  #初始化和填充 classfication plane
  classfication_plane = np.zeros([nb_of_xs,nb_of_xs])
   
  for i in range(nb_of_xs):
      for j in range(nb_of_xs):
          #计算每个输入样本对应的分类标签
          classfication_plane[i,j] = sess.run(y_pred,feed_dict={input_x:[[xx[i,j],yy[i,j]]]})
           
  #创建 color map用于显示
  cmap = ListedColormap([
              colorConverter.to_rgba('r',alpha = 0.30),
              colorConverter.to_rgba('b',alpha = 0.30),     
          ])
  #显示各个样本边界
  plt.contourf(xx,yy,classfication_plane,cmap = cmap)
  plt.show()

  

可以看到,模型在迭代训练20000次之后梯度更新就放缓了,而且loss值约等于16%并且准确率不高,所可视化的图片也没有将数据完全分开。

图上这种现象就叫做欠拟合,即没有完全拟合到想要得到的真实数据情况。

4 修正模型提高拟合度

欠拟合的原因并不是模型不行,而是我们的学习方法无法更精准地学习到适合的模型参数。模型越薄弱,对训练的要求就越高。但是可以采用增加节点或者增加层的方式,让模型具有更高的拟合性,从而降低模型的训练难度。

将隐藏层的节点个数改为200,代码如下:

1
2
#隐藏层节点个数
n_hidden = 200

从图中可以看到强大的全连接网络,仅仅通过一个隐藏层,使用200个神经元就可以把数据划分的那么细致。而loss值也在逐渐变小,30000次之后已经变成了0.056.

5 验证过拟合

那么对于上面的模型好不好呢?我们再取少量的数据放到模型中验证一下,然后用同样的方式在坐标系中可视化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
'''
    测试  可以看到测试集loss值和训练集loss差距较大 这是因为模型过拟合了
    '''
    test_x,test_y = generate(12,mean,cov,[[3.0,0.0],[3.0,3.0],[0.0,3.0]],num_classes=4)
    #转换为二种类别
    test_y = test_y % 2     
 
 
     
    xr = []
    xb = []
     
    for (l,k) in zip(test_y[:],test_x[:]):
        if l == 0.0:
            xr.append([k[0],k[1]])
        else:
            xb.append([k[0],k[1]])
         
    xr = np.array(xr)
    xb = np.array(xb)
    plt.figure()
    plt.scatter(xr[:,0],xr[:,1],c='r',marker='+')
    plt.scatter(xb[:,0],xb[:,1],c='b',marker='o')
     
    lo = sess.run(loss,feed_dict={input_x:test_x,input_y:np.reshape(test_y,[-1,1])})
    print('Test data  loss {0}'.format(lo))
         
    nb_of_xs = 200
    xs1 = np.linspace(-1,8,num = nb_of_xs)
    xs2 = np.linspace(-1,8,num = nb_of_xs)
     
    #创建网格
    xx,yy = np.meshgrid(xs1,xs2)
     
    #初始化和填充 classfication plane
    classfication_plane = np.zeros([nb_of_xs,nb_of_xs])
     
    for i in range(nb_of_xs):
        for j in range(nb_of_xs):
            #计算每个输入样本对应的分类标签
            classfication_plane[i,j] = sess.run(y_pred,feed_dict={input_x:[[xx[i,j],yy[i,j]]]})
             
    #创建 color map用于显示
    cmap = ListedColormap([
                colorConverter.to_rgba('r',alpha = 0.30),
                colorConverter.to_rgba('b',alpha = 0.30),     
            ])
    #显示各个样本边界
    plt.contourf(xx,yy,classfication_plane,cmap = cmap)
    plt.show()

从这次运行结果,我们可以看到测试集的loss增加到了0.21,并没有原来训练时候的那么好0.056,模型还是原来的模型,但是这次却只框住了少量的样本。这种现象就是过拟合,它和欠拟合都是我们在训练模型中不愿意看到的现象,我们要的是真正的拟合在测试情况下能够变现出训练时的良好效果。

避免过拟合的方法有很多:常用的有early stopping、数据集扩展、正则化、弃权等,下面会使用这些方法来对该案例来进行优化。

6 通过正则化改善过拟合情况

 Tensorflow中封装了L2正则化的函数可以直接使用:

1
tf.nn.l2_loss(t,name=None)

函数原型如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def l2_loss(t, name=None):
  r"""L2 Loss.
 
  Computes half the L2 norm of a tensor without the `sqrt`:
 
      output = sum(t ** 2) / 2
 
  Args:
    t: A `Tensor`. Must be one of the following types: `half`, `float32`, `float64`.
      Typically 2-D, but may have any dimensions.
    name: A name for the operation (optional).
 
  Returns:
    A `Tensor`. Has the same type as `t`. 0-D.
  """
  result = _op_def_lib.apply_op("L2Loss", t=t, name=name)
  return result

但是并没有提供L1正则化函数,但是可以自己组合:

1
tf.reduce_sum(tf.abs(w))

我们在代码中加入L2正则化:并设置返回参数lamda=1.6,修改代价函数如下:

1
loss = tf.reduce_mean(tf.square(y_pred - input_y)) + lamda * tf.nn.l2_loss(weights['h1'])/ num_samples + tf.nn.l2_loss(weights['h2']) *lamda/ num_samples

  

训练集的代价值从0.056增加到了0.106,但是测试集的代价值仅仅从0.21降到了0.0197,其效果并不是太明显。

7 通过增大数据集改善过拟合情况

下面再试试通过增大数据集的方法来改善过度拟合的情况,这里不再生产一个随机样本,而是每次从循环生成1000个数据。部分代码如下:

1
2
3
4
5
6
7
for epoch in range(training_epochs):
       train_x,train_y = generate(num_samples,mean,cov,[[3.0,0.0],[3.0,3.0],[0.0,3.0]],num_classes=4)
       #转换为二种类别
       train_y = train_y % 2     
       _,lo = sess.run([train,loss],feed_dict={input_x:train_x,input_y:np.reshape(train_y,[-1,1])})
       if epoch % 1000 == 0:
           print('Epoch {0}  loss {1}'.format(epoch,lo))

亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。

日期姓名金额
2023-09-06*源19
2023-09-11*朝科88
2023-09-21*号5
2023-09-16*真60
2023-10-26*通9.9
2023-11-04*慎0.66
2023-11-24*恩0.01
2023-12-30I*B1
2024-01-28*兴20
2024-02-01QYing20
2024-02-11*督6
2024-02-18一*x1
2024-02-20c*l18.88
2024-01-01*I5
2024-04-08*程150
2024-04-18*超20
2024-04-26.*V30
2024-05-08D*W5
2024-05-29*辉20
2024-05-30*雄10
2024-06-08*:10
2024-06-23小狮子666
2024-06-28*s6.66
2024-06-29*炼1
2024-06-30*!1
2024-07-08*方20
2024-07-18A*16.66
2024-07-31*北12
2024-08-13*基1
2024-08-23n*s2
2024-09-02*源50
2024-09-04*J2
2024-09-06*强8.8
2024-09-09*波1
2024-09-10*口1
2024-09-10*波1
2024-09-12*波10
2024-09-18*明1.68
2024-09-26B*h10
2024-09-3010
2024-10-02M*i1
2024-10-14*朋10
2024-10-22*海10
2024-10-23*南10
2024-10-26*节6.66
2024-10-27*o5
2024-10-28W*F6.66
2024-10-29R*n6.66
2024-11-02*球6
2024-11-021*鑫6.66
2024-11-25*沙5
2024-11-29C*n2.88
posted @   大奥特曼打小怪兽  阅读(5505)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
如果有任何技术小问题,欢迎大家交流沟通,共同进步

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)。

了解更多

点击右上角即可分享
微信分享提示