tensorflow_course2

神经网络优化

主要学会神经网络的优化过程,使用正则化减少过拟合,使用优化器更新网络参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A60DT1fr-1661261830777)(attachment:image.png)]

预备知识

tf.where()

tf.where(
    condition, x=None, y=None, name=None
)

功能:
根据condition,取x或y中的值。如果为True,对应位置取x的值;如果为
False,对应位置取y的值。

参数:
condition: bool型张量.
x: 与y shape相同的张量.
y: 与x shape相同的张量.

返回:
shape与x相同的张量

import tensorflow as tf
a = tf.constant([1,2,3,1,1])
b = tf.constant([0,1,3,4,5])

c = tf.where(tf.greater(a, b), a, b) #若a > b,返回a对应位置的元素,否则返回b对应位置的元素

print("c:",c)
c: tf.Tensor([1 2 3 4 5], shape=(5,), dtype=int32)

np.random.RandomState.rand()

功能:
返回一个[0,1)之间的随机数

参数:
np.random.RandomState.rand(维度) #维度为空,返回一个标量

import numpy as np

rdm = np.random.RandomState(seed=1) # seed=常数,每次生成随机数相同
a = rdm.rand() #返回一个随机标量
b = rdm.rand(2,3)
print('a:',a)
print('b:',b)
a: 0.417022004702574
b: [[7.20324493e-01 1.14374817e-04 3.02332573e-01]
 [1.46755891e-01 9.23385948e-02 1.86260211e-01]]

np.vstack()

功能

将两个数组按照垂直方向叠加

np.vstack(数组1, 数组2)

a = np.array([1,3,2])
b = np.array([4,5,6])
c = np.vstack((b, a))
print('c:',c)
c: [[4 5 6]
 [1 3 2]]

** np.mgrid[]、np.ravel()、np.c_[]**

np.mgrid [起始值, 结束值)

功能:生成网格数

np.mgrid[起始值:结束值:步长, 起始值:结束值:步长, …]

np.ravel()

功能:将x变成一维数组

np.c_[]

功能:使返回的间隔值点配对

np.c_[数组1,数组2,…]

x,y = np.mgrid[1:3:1, 2:4:0.5]
grid = np.c_[x.ravel(), y.ravel()]
print('x:',x)
print('y:',y)
print('grid:\n', grid)
x: [[1. 1. 1. 1.]
 [2. 2. 2. 2.]]
y: [[2.  2.5 3.  3.5]
 [2.  2.5 3.  3.5]]
grid:
 [[1.  2. ]
 [1.  2.5]
 [1.  3. ]
 [1.  3.5]
 [2.  2. ]
 [2.  2.5]
 [2.  3. ]
 [2.  3.5]]

1 神经网络复杂度

1.1 时间复杂度

NN复杂度:多用NN层数和NN参数的个数表示

空间复杂度

  • 层数 = 隐藏层的层数 + 1个输出层

  • 总参数 = 总w + 总b

时间复杂度

  • 乘加运算次数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RLiI5jJt-1661261830778)(attachment:image.png)]

2 学习率策略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEparrsp-1661261830779)(attachment:image.png)]

2.1 指数衰减

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dIubF5R3-1661261830779)(attachment:image-2.png)]

其中, 是初始学习率, 是衰减率, 表示从0到当前的训练次数, 用来控制衰减速度

指数衰减学习率是先使用较大的学习率来快速得到一个较优的解,然后随着迭代的继续,逐步减小
学习率,使得模型在训练后期 更加稳定。指数型学习率衰减法是最常用的衰减方法,在大量模型中都广
泛使用。

TensorFlow API: tf.keras.optimizers.schedules.ExponentialDecay

tf.keras.optimizers.schedules.ExponentialDecay(

    initial_learning_rate, decay_steps, decay_rate, staircase=False, name=None
    
)

功能:指数衰减学习率策略

等价API: tf.optimizers.schedules.ExponentialDecay

参数:

 > initial_learning_rate: 初始学习率
 
 > deacy_steps:衰减步数,staircase为True时有效
 
 > decay_rate: 衰减率.
 
 > staircase: Bool型变量.如果为True, 学习率呈现阶梯型下降趋势

返回: tf.keras.optimizers.schedules.ExponentialDecay(step)返回计算得到的学习率.

链接: tf.keras.optimizers.schedules.ExponentialDecay

import matplotlib.pyplot as plt
N = 400
lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(

    0.5,
    decay_steps=10,
    decay_rate=0.9,
    staircase=False)
y = []
for global_step in range(N):
    lr = lr_schedule(global_step)
    y.append(lr)
    
x =range(N)
plt.figure(figsize=(8,5))
plt.plot(x, y,'r-')
plt.ylim([0, max(plt.ylim())])
plt.xlabel('Step')
plt.ylabel('Learning Rate')
plt.title('ExponentialDecay')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sXDX4ahl-1661261830783)(output_11_0.png)]

2.2 分段常数衰减

分段常数衰减可以让调试人员针对不同任务设置不同的学习率,进行精细调参,在任意步长后下降
任意数值的learning rate,要求调试人员对模型和数据集有深刻认识.

tf.keras.optimizers.schedules.PiecewiseConstantDecay

tf.keras.optimizers.schedules.PiecewiseConstantDecay(
    boundaries, values, name=None
)

功能: 分段常数衰减学习率策略.

等价API: tf.optimizers.schedules.PiecewiseConstantDecay

参数:

  • boundaries: [step_1, step_2, …, step_n]定义了在第几步进行学习率衰减.

  • values: [val_0, val_1, val_2, …, val_n]定义了学习率的初始值和后续衰减时的具体取值.

**返回:**tf.keras.optimizers.schedules.PiecewiseConstantDecay(step)返回计算得到的学习率

N = 400
lr_schedule = tf.keras.optimizers.schedules.PiecewiseConstantDecay(
    boundaries=[100, 200, 300],
    values=[0.1, 0.05, 0.025, 0.001])

y = []
for global_step in range(N):
    lr = lr_schedule(global_step)
    y.append(lr)
x = range(N)
plt.figure(figsize=(8,6))
plt.plot(x, y, 'r-')
plt.ylim([0,max(plt.ylim())])
plt.xlabel('Step')
plt.ylabel('Learning Rate')
plt.title('PiecewiseConstantDecay')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DO31f5Ve-1661261830784)(output_14_0.png)]

3 激活函数

激活函数是用来加入非线性因素的,因为线性模型的表达能力不够。引入非线性激活函数,可使深
层神经网络的表达能力更加强大。

优秀的激活函数应满足:

  • 非线性,激活函数非线性时,多层NN可逼近所有函数
  • 可微性,优化器大多用梯度下降更新参数
  • 单调性,当激活函数是单调的,能保证单层网络的损失函数是凸函数
  • ** 近似恒等性:**f(x)≈x,当参数初始化为随机小值时,神经网络更稳定

激活函数输出值的范围:

  • 激活函数输出为有限值时,基于梯度的优化方法更稳定
  • 激活函数输出为无限值时,建议调小学习率

常见的激活函数有:sigmoid,tanh,ReLU,Leaky ReLU,PReLU,RReLU,
ELU(Exponential Linear Units),softplus,softsign,softmax等,下面介绍几个典型的激活
函数:

3.1 sigmoid函数

TensorFlow API: tf.nn.sigmoid()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSFbkZqe-1661261830784)(attachment:image.png)]

优点:
(1):输出映射在(0,1)之间,单调连续,输出范围有限,优化稳定,可用作输出层

(2):求导容易

特点:

(1):易造成梯度消失

(2):输出非0均值,收敛慢

(3):幂运算复杂,训练时间长

sigmoid函数可应用在训练过程中。然而,当处理分类问题作出输出时,sigmoid却无能为力。简
单地说,sigmoid函数只能处理两个类,不适用于多分类问题。而softmax可以有效解决这个问题,并
且softmax函数大都运用在神经网路中的最后一层网络中,使得值得区间在(0,1)之间,而不是二分类
的。

3.2 tanh

TensoFlow API:tf.math.tanh(x)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JTQj2fDp-1661261830784)(attachment:image.png)]

优点:
1、比sigmoid函数收敛速度更快

2、相比sigmoid函数,输出以0为中心

缺点:

1、易造成梯度消失

2、幂运算复杂,训练时间长

3.3 ReLU

TensoFlow API:tf.nn.relu(x)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgLWPfvj-1661261830785)(attachment:image.png)]

优点:

1、解决了梯度消失问题(在正区间)

2、只需判断输出是否大于0,计算速度快

3、收敛速度远快于sigmoid和tanh,因为sigmoid和tanh涉及很多expensive的操作

4、 提供了NN的稀疏表达能力

缺点:

1、输出非0均值,收敛慢

2、Dead Relu问题:某些神经元可能永远不会被激活,导致相应的参数不能被更新

3.4 Leaky ReLU

TensoFlow API:tf.nn.leaky_relu(x)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cTF4hCbU-1661261830785)(attachment:image.png)]

理论上来讲,Leaky ReLU有ReLU的所有优点,外加不会有Dead ReLU问题,但是在实际操作当
中,并没有完全证明Leaky ReLU总是好于ReLU。

3.5 softmax

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3guKOd2U-1661261830785)(attachment:image.png)]

TensorFlow API: tf.nn.softmax

对神经网络全连接层输出进行变换,使其服从概率分布,即每个值都位于[0,1]区间且和为1。

3.6 建议

对于初学者建议:

1、首先Relu函数

2、学习率设置较小值

3、输出特征标准化,即让输入特征满足以0为均值,1为标准差的正态分布

4、初始化问题:初始参数中心化,即让随机生成的参数满足以0为均值,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aiKRxch3-1661261830786)(attachment:image.png)]为标准差的正态分布

4 损失函数

损失函数(loss):预测值(y)与已知答案(y_)的差距

NN优化目标:loss最小
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4BgZhmJY-1661261830786)(attachment:image.png)]

4.1 均方误差损失函数

均方误差(Mean Square Error)是回归问题最常用的损失函数。回归问题解决的是对具体数值的预测,比如房价预测、效率预测等。这些问题不是一个事先定义好的类别,而是一个任意实数。均方误差定义如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tjd2Oyh0-1661261830786)(attachment:image.png)]

loss_mse = tf.reduce_mean(tf.square(y - y_))

TensorFlow API:tf.keras.losses.MSE

tf.keras.losses.MSE(
    y_true, y_pred
)
y_true = tf.constant([0.5, 0.8])
y_pred = tf.constant([1.0,1.0])
print(tf.keras.losses.MSE(y_true, y_pred))
tf.Tensor(0.145, shape=(), dtype=float32)
print(tf.reduce_mean(tf.square(y_true - y_pred)))
tf.Tensor(0.145, shape=(), dtype=float32)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RArKMlZC-1661261830787)(attachment:image.png)]

#p19_mse.py
import tensorflow as tf
import numpy as np

SEED=23455

rdm = np.random.RandomState(seed=SEED)# 生成[0,1)之间的随机数
x = rdm.rand(32, 2)
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x] # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)

x = tf.cast(x, dtype=tf.float32)

w1 = tf.Variable(tf.random.normal([2,1], stddev=1, seed=1))

epoch = 15000
lr = 0.002

for epoch in range(epoch):
    with tf.GradientTape() as tape:
        y = tf.matmul(x, w1)
        loss_mse = tf.keras.losses.MSE(y_, y)
    grads = tape.gradient(loss_mse, w1)
    w1.assign_sub(lr*grads)
    
    if epoch % 500 == 0:
        print("After %d training steps,w1 is " % (epoch))
        print(w1.numpy(), "\n")
        
print("Final w1 is: ", w1.numpy())
After 0 training steps,w1 is 
[[-1.5136462 ]
 [ 0.35048607]] 

After 500 training steps,w1 is 
[[1.0024375]
 [0.9964705]] 

After 1000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 1500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 2000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 2500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 3000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 3500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 4000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 4500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 5000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 5500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 6000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 6500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 7000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 7500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 8000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 8500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 9000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 9500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 10000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 10500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 11000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 11500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 12000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 12500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 13000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 13500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 14000 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

After 14500 training steps,w1 is 
[[1.0043048]
 [0.9948319]] 

Final w1 is:  [[1.0043048]
 [0.9948319]]

4.2 交叉熵损失函数

交叉熵(Cross Entropy)表征两个概率之间的距离, =交叉熵越小说明二者分布越接近,是分类问题中使用较广泛的损失函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-afUKQmXf-1661261830787)(attachment:image.png)]

其中y_代表数据真实值, y代表神经网络的预测值

对于多分类问题,神经网络的输出一般不是概率分布,因此需要引入softmax层,使得输出服从概
率分布, tensorflow中可计算交叉熵损失函数的API:

**TensorFlow API:tf.keras.losses.categorical_crossentropy **

**TensorFlow API: tf.nn.softmax_cross_entropy_with_logits **

**TensorFlow API: tf.nn.sparse_softmax_cross_entropy_with_logits *

tf.keras.losses.categorical_crossentropy

tf.keras.losses.categorical_crossentropy(
    y_true, y_pred, from_logits=False, label_smoothing=0
)

**功能:**计算交叉熵

**等价API:**tf.losses.categorical_crossentropy

参数:

- y_true: 真实值.
- y_pred:预测值
- from_logits:y_pred是否为logits张量.
- label_smoothing: [0,1]之间的小数.
y_true = [1, 0, 0]
y_pred1 = [0.5, 0.4, 0.1]
y_pred2 = [0.8, 0.1, 0.1]
print(tf.keras.losses.categorical_crossentropy(y_true, y_pred1))
print(tf.keras.losses.categorical_crossentropy(y_true, y_pred2))
tf.Tensor(0.6931472, shape=(), dtype=float32)
tf.Tensor(0.22314353, shape=(), dtype=float32)
#等价实现
print(-tf.reduce_sum(y_true* tf.math.log(y_pred1)))
print(-tf.reduce_sum(y_true * tf.math.log(y_pred2)))
tf.Tensor(0.6931472, shape=(), dtype=float32)
tf.Tensor(0.22314353, shape=(), dtype=float32)

tf.nn.softmax_cross_entropy_with_logits

tf.nn.softmax_cross_entropy_with_logits(

    labels, logits, axis=-1, name=None
    
)

**功能:**logits经过softmax之后,与labels进行交叉熵计算

在机器学习中,对于多分类问题,把未经softmax归一化的向量值称为logits。logits经过softmax
层后,输出服从概率分布的向量(来源

参数:

  • labels: 在类别这一维度上,每个向量应服从有效的概率分布. 例如,在labels的shape为[batch_size, num_classes]的情况下,labels[i]应服从概率分布.

  • logits: 每个类别的激活值,通常是线性层的输出. 激活值需要经过softmax归一化.

  • axis: 类别所在维度,默认是-1,即最后一个维度.

**返回:**softmax交叉熵损失值

labels = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
logits = [[4.0, 2.0, 1.0], [0.0, 5.0, 1.0]]
print(tf.nn.softmax_cross_entropy_with_logits(labels, logits))
tf.Tensor([0.16984604 0.02474492], shape=(2,), dtype=float32)
y_ = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0]])
y = np.array([[12, 3, 2], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])
y_pro = tf.nn.softmax(y)
loss_ce1 = tf.losses.categorical_crossentropy(y_,y_pro)
loss_ce2 = tf.nn.softmax_cross_entropy_with_logits(y_, y)

print('分步计算的结果:\n', loss_ce1)
print('结合计算的结果:\n', loss_ce2)
分步计算的结果:
 tf.Tensor(
[1.68795487e-04 1.03475622e-03 6.58839038e-02 2.58349207e+00
 5.49852354e-02], shape=(5,), dtype=float64)
结合计算的结果:
 tf.Tensor(
[1.68795487e-04 1.03475622e-03 6.58839038e-02 2.58349207e+00
 5.49852354e-02], shape=(5,), dtype=float64)
# 等价实现
print(-tf.reduce_sum(labels * tf.math.log(tf.nn.softmax(logits)), axis=1))
tf.Tensor([0.16984606 0.02474495], shape=(2,), dtype=float32)

tf.nn.sparse_softmax_cross_entropy_with_logits

tf.nn.sparse_softmax_cross_entropy_with_logits(

    labels, logits, name=None
    
)

**功能:**labels经过one-hot编码,logits经过softmax,两者进行交叉熵计算. 通常labels的shape为[batch_size],logits的shape为[batch_size, num_classes]. sparse可理解为对labels进行稀疏化处理(即进行one-hot编码)

参数:

labels: 标签的索引值.

logits: 每个类别的激活值,通常是线性层的输出. 激活值需要经过softmax归一化.

**返回:**softmax交叉熵损失值.

例子:(下例中先对labels进行one-hot编码为[[1,0,0], [0,1,0]],logits经过softmax变为[[0.844,
0.114,0.042], [0.007,0.976,0.018]],两者再进行交叉熵运算)

labels = [0,1]
logits = [[4.0, 2.0, 1.0], [0.0, 5.0, 1.0]]
print(tf.nn.sparse_softmax_cross_entropy_with_logits(labels, logits))
tf.Tensor([0.16984604 0.02474492], shape=(2,), dtype=float32)
# 等价实现
print(-tf.reduce_sum(tf.one_hot(labels, tf.shape(logits)[1]) * tf.math.log(tf.nn.softmax(logits)), axis=1))
tf.Tensor([0.16984606 0.02474495], shape=(2,), dtype=float32)

4.3 自定义损失函数

根据具体任务和目的,可设计不同的损失函数。从老师课件和讲解中对于酸奶预测损失函数的设计,我们可以得知损失函数的定义能极大影响模型预测效果。好的损失函数设计对于模型训练能够起到良好的引导作用。

例如,我们可以看目标检测中的多种损失函数。目标检测的主要功能是定位和识别,损失函数的功
能主要就是让定位更精确,识别准确率更高。目标检测任务的损失函数由分类损失(Classificition
Loss)和回归损失(Bounding Box Regeression Loss)两部分构成。近几年来回归损失主要有
Smooth L1 Loss(2015), IoU Loss(2016 ACM), GIoU Loss(2019 CVPR), DIoU Loss & CIoU Loss(2020
AAAI)等,分类损失有交叉熵、softmax loss、logloss、focal loss等。在此由于篇幅原因不细究,有兴
趣的同学可自行研究。主要是给大家一个感性的认知:需要针对特定的背景、具体的任务设计损失函

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ie4iO2X0-1661261830787)(attachment:image.png)]

#p20_custom.py
import tensorflow as tf
import numpy as np

SEED = 23455
COST = 1
PROFIT = 99

rdm = np.random.RandomState(SEED)
x = rdm.rand(32, 2)
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x]  # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32)

w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1))

epoch = 10000
lr = 0.002

for epoch in range(epoch):
    with tf.GradientTape() as tape:
        y = tf.matmul(x, w1)
        loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * COST, (y_ - y) * PROFIT))

    grads = tape.gradient(loss, w1)
    w1.assign_sub(lr * grads)

    if epoch % 500 == 0:
        print("After %d training steps,w1 is " % (epoch))
        print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())
After 0 training steps,w1 is 
[[3.4457052]
 [3.2526264]] 

After 500 training steps,w1 is 
[[1.1493957]
 [1.0595962]] 

After 1000 training steps,w1 is 
[[1.1397758]
 [1.09088  ]] 

After 1500 training steps,w1 is 
[[1.1301556]
 [1.1221637]] 

After 2000 training steps,w1 is 
[[1.1791688]
 [1.1647406]] 

After 2500 training steps,w1 is 
[[1.1487305]
 [1.019554 ]] 

After 3000 training steps,w1 is 
[[1.1391103]
 [1.0508376]] 

After 3500 training steps,w1 is 
[[1.1294906]
 [1.0821217]] 

After 4000 training steps,w1 is 
[[1.1198705]
 [1.1134055]] 

After 4500 training steps,w1 is 
[[1.1688839]
 [1.1559825]] 

After 5000 training steps,w1 is 
[[1.1384457]
 [1.0107961]] 

After 5500 training steps,w1 is 
[[1.1288261]
 [1.0420803]] 

After 6000 training steps,w1 is 
[[1.1192057]
 [1.0733637]] 

After 6500 training steps,w1 is 
[[1.1095855]
 [1.1046473]] 

After 7000 training steps,w1 is 
[[1.1585989]
 [1.1472243]] 

After 7500 training steps,w1 is 
[[1.1489792]
 [1.1785084]] 

After 8000 training steps,w1 is 
[[1.1185408]
 [1.0333217]] 

After 8500 training steps,w1 is 
[[1.1089209]
 [1.0646057]] 

After 9000 training steps,w1 is 
[[1.1579342]
 [1.1071826]] 

After 9500 training steps,w1 is 
[[1.1483142]
 [1.1384665]] 

Final w1 is:  [[1.1289538]
 [1.0160426]]

5 欠拟合与过拟合

欠拟合的解决方法:

  • 增加输入特征项
  • 增加网络参数
  • 减少正则化参数

过拟合的解决方法

  • 数据清洗
  • 增大训练集
  • 采用正则化
  • 增大正则化参数

正则化缓解过拟合

正则化在损失函数中引入模型复杂度指标,利用给W加权值,弱化了训练数据的噪声(一般不正则化)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TgahcSyN-1661261830788)(attachment:image.png)]

正则化的选择:

  • L1正则化大概率会使很多参数变为0,因此该方法可通过稀疏参数,即减少参数的数量,降低复杂度
  • L2正则化会使参数很接近0但不为0,因此该方法可通过减小参数的值来降低复杂度
# 导入所需模块
import tensorflow as tf
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

# 读入数据/标签 生成x_train y_train
df = pd.read_csv('E:\BaiduNetdiskDownload\中国大学MOOCTF笔记2.1共享给所有学习者\class2\dot.csv')
x_data = np.array(df[['x1', 'x2']])
y_data = np.array(df['y_c'])

x_train = x_data
y_train = y_data.reshape(-1, 1)

Y_c = [['red' if y else 'blue'] for y in y_train]

# 转换x的数据类型,否则后面矩阵相乘时会因数据类型问题报错
x_train = tf.cast(x_train, dtype = tf.float32)
y_train = tf.cast(y_train, tf.float32)

# from_tensor_slices函数切分传入的张量的第一个维度,生成相应的数据集,使输入特征和标签值一一对应
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)

# 生成神经网络的参数,输入层为4个神经元,隐藏层为32个神经元,2层隐藏层,输出层为3个神经元
# 用tf.Variable()保证参数可训练
w1 = tf.Variable(tf.random.normal([2,11]), dtype = tf.float32)
b1 = tf.Variable(tf.constant(0.01, shape=[11]))

w2 = tf.Variable(tf.random.normal([11, 1]), dtype=tf.float32)
b2 = tf.Variable(tf.constant(0.01, shape=[1]))

lr = 0.005  # 学习率为
epoch = 800  # 循环轮数

## 训练部分
for epoch in range(epoch):
    for step, (x_train, y_train) in enumerate(train_db):
        with tf.GradientTape() as tape: # 记录梯度信息

            h1 = tf.matmul(x_train, w1) + b1  # 记录神经网络乘加运算
            h1 = tf.nn.relu(h1)
            y = tf.matmul(h1, w2) + b2
            
            
            # 采用均方误差损失函数mse = mean(sum(y-out)^2)
            losses_mse = tf.reduce_mean(tf.square(y_train - y))
            
            #添加l2正则化
            loss_regularization = []
            loss_regularization.append(tf.nn.l2_loss(w1))
            loss_regularization.append(tf.nn.l2_loss(w2))
            
            loss_regularization = tf.reduce_sum(loss_regularization)
            loss = losses_mse + 0.03 * loss_regularization
            
        #计算loss对各个参数的梯度
        variables = [w1, b1, w2, b2]
        grads = tape.gradient(loss, variables)
        
        # 实现梯度更新
        # w1 = w1 - lr * w1_grad
        w1.assign_sub(lr * grads[0])
        b1.assign_sub(lr * grads[1])
        w2.assign_sub(lr * grads[2])
        b2.assign_sub(lr * grads[3])
        
    # 每200个epoch,打印loss信息
    if epoch % 40 == 0:
        print('epoch:', epoch, 'loss:', float(loss))
        
        
# 预测部分
print("*******predict*******")
# xx在-3到3之间以步长为0.01,yy在-3到3之间以步长0.01,生成间隔数值点
xx,yy = np.mgrid[-3:3:.1, -3:3:.1]

# 将xx, yy拉直,并合并配对为二维张量,生成二维坐标点
grid = np.c_[xx.ravel(), yy.ravel()]
grid = tf.cast(grid, tf.float32)
# 将网格坐标点喂入神经网络,进行预测,probs为输出
probs = []
for x_predict in grid:
    # 使用训练好的参数进行预测
    h1 = tf.matmul([x_predict], w1) + b1
    h1 = tf.nn.relu(h1)
    y = tf.matmul(h1, w2) + b2 # y为预测结果
    probs.append(y)
    
# 取第0列给x1,取第1列给x2
x1 = x_data[:, 0]
x2 = x_data[:, 1]
# probs的shape调整成xx的样子
probs = np.array(probs).reshape(xx.shape)
plt.scatter(x1, x2, color=np.squeeze(Y_c))
# 把坐标xx yy和对应的值probs放入contour函数,给probs值为0.5的所有点上色  plt.show()后 显示的是红蓝点的分界线
plt.contour(xx, yy, probs, levels=[.5])
plt.show()
epoch: 0 loss: 5.472182750701904
epoch: 40 loss: 0.4817494750022888
epoch: 80 loss: 0.36840903759002686
epoch: 120 loss: 0.31256160140037537
epoch: 160 loss: 0.27391085028648376
epoch: 200 loss: 0.24360911548137665
epoch: 240 loss: 0.21865178644657135
epoch: 280 loss: 0.1976892352104187
epoch: 320 loss: 0.17977286875247955
epoch: 360 loss: 0.16461075842380524
epoch: 400 loss: 0.1515084207057953
epoch: 440 loss: 0.14020243287086487
epoch: 480 loss: 0.13045549392700195
epoch: 520 loss: 0.12212586402893066
epoch: 560 loss: 0.11479806900024414
epoch: 600 loss: 0.10838881880044937
epoch: 640 loss: 0.10294126719236374
epoch: 680 loss: 0.09831778705120087
epoch: 720 loss: 0.094314344227314
epoch: 760 loss: 0.09065239131450653
*******predict*******

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExiijTY0-1661261830788)(output_42_1.png)]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340