tensorflow2.0学习笔记

tensorflow2.0学习笔记

正则化缓解过拟合

正则化在损失函数中引入模型复杂度指标,利用给w加权值,弱化了训练数据的噪声(一般不正则化b)
l o s s = l o s s ( y   与   y_ ) + REGULARIZER ∗ l o s s ( w ) loss = loss(\textbf{y 与 y\_}) + \textbf{REGULARIZER} * loss(w) loss=loss( y_)+REGULARIZERloss(w)
l o s s ( y   与   y_ ) loss(\textbf{y 与 y\_}) loss( y_):模型中所有参数的损失函数,如交叉熵,均方误差

REGULARIZER \textbf{REGULARIZER} REGULARIZER:用超参数给出参数w在总loss中的比列,即正则化的权重
loss ⁡ L 1 ( w ) = ∑ i ∣ w i ∣ \operatorname{loss}_{L_{1}}(w)=\sum_{i}\left|w_{i}\right| lossL1(w)=iwi

loss ⁡ L 2 ( w ) = ∑ i ∣ w i 2 ∣ \operatorname{loss}_{L 2}(w)=\sum_{i}\left|w_{i}^{2}\right| lossL2(w)=iwi2

正则化的选择:

  • L1正则化大概率会使很多参数变为零,因此该方法可通过稀疏参数,即减少参数的数量,降低复杂度。
  • L2正则化会使参数很接近零但不为零,因此该方法可通过减小参数值的大小降低复杂度。

神经网络参数优化器

待优化参数 w w w,损失函数 l o s s loss loss,学习率 l r lr lr,每次迭代一个batch, t t t 表示当前batch迭代的总次数:

  1. 计算 t t t 时刻损失函数关于当前参数的梯度 g t = ∇ loss ⁡ = ∂ loss ⁡ ∂ ( w t ) g_{t}=\nabla \operatorname{loss}=\dfrac{\partial \operatorname{loss}}{\partial\left(w_{t}\right)} gt=loss=(wt)loss
  2. 计算 t t t 时刻一阶动量 m t m_t mt 和二阶动量 V t V_t Vt
  3. 计算 t t t 时刻下降梯度: η t = l r ⋅ m t / V t \eta_{\mathrm{t}}=l r \cdot m_{\mathrm{t}} / \sqrt{V_{\mathrm{t}}} ηt=lrmt/Vt
  4. 计算 t + 1 t+1 t+1 时刻参数: w t + 1 = w t − η t = w t − l r ⋅ m t / V t w_{\mathrm{t}+1}=w_{t}-\eta_{t}=w_{t}-l r \cdot m_{t} / \sqrt{V_{t}} wt+1=wtηt=wtlrmt/Vt

其中:一阶动量:与梯度相关的函数,二阶动量:与梯度平方相关的函数

SGD(梯度下降):

class SGD:
	def __init__(self, lr=0.01):
		self.lr = lr
        
	def update(self, params, grads):
		for key in params.keys():
			params[key] -= self.lr * grads[key]

SGD的缺点是,如果函数的形状非均向,比如呈延伸状,搜索的路径就会非常低效。SGD低效的根本原因是,梯度的方向并没有指向最小值的方向。
m t = g t V t = 1 η t = l r ⋅ m t / V t = l r ⋅ g t w t + 1 = w t − η t = w t − l r ⋅ m t / V t = w t − l r ⋅ g t \begin{array}{l} m_{\mathrm{t}}=g_{\mathrm{t}} \quad V_{\mathrm{t}}=1 \\ \eta_{\mathrm{t}}=lr \cdot m_{\mathrm{t}} / \sqrt{V_{t}}= lr \cdot g_{t} \\ \begin{array}{l} w_{\mathrm{t}+1}=w_{t}-\eta_{t} =w_{t}-l r \cdot m_{t} / \sqrt{V_{t}}=w_{t}-l r \cdot g_{t} \end{array} \end{array} mt=gtVt=1ηt=lrmt/Vt =lrgtwt+1=wtηt=wtlrmt/Vt =wtlrgt

w t + 1 = w t − l r ∗ ∂ l o s s ∂ w t \mathrm{w}_{\mathrm{t}+1}=w_{t}-l r * \frac{\partial l o s s}{\partial w_{t}} wt+1=wtlrwtloss

w1.assign_sub(lr * grads[0])
b1.assign_sub(lr * grads[1])

SGDM(在SGD基础上增加一阶动量)
m t = β ⋅ m t − 1 + ( 1 − β ) ⋅ g t V t = 1 η t = l r ⋅ m t / V t = l r ⋅ m t = l r ⋅ ( β ⋅ m t − 1 + ( 1 − β ) ⋅ g t ) w t + 1 = w t − η t = w t − l r ⋅ ( β ⋅ m t − 1 + ( 1 − β ) ⋅ g t ) \begin{array}{l} m_{\mathrm{t}}=\beta \cdot m_{t-1}+(1-\beta) \cdot g_{t} \quad V_{t}=1 \\ \begin{array}{l} \eta_{\mathrm{t}}= lr \cdot m_{\mathrm{t}} / \sqrt{V_{\mathrm{t}}}=l r \cdot m_{\mathrm{t}} =lr \cdot\left(\beta \cdot m_{\mathrm{t}-1}+(1-\beta) \cdot g_{\mathrm{t}}\right) \\ w_{\mathrm{t}+1}= w_{\mathrm{t}}-\eta_{\mathrm{t}} =w_{\mathrm{t}}-l r \cdot\left(\beta \cdot m_{\mathrm{t}-1}+(1-\beta) \cdot g_{\mathrm{t}}\right) \end{array} \end{array} mt=βmt1+(1β)gtVt=1ηt=lrmt/Vt =lrmt=lr(βmt1+(1β)gt)wt+1=wtηt=wtlr(βmt1+(1β)gt)
β \beta β是接近于1的超参数

m_w, m_b = 0, 0
beta = 0.9
m_w = beat * m_w + (1 - beta) * grads[0]
m_b = beat * m_b + (1 - beta) * grads[1]
w1.assign_sub(lr * m_w)
b1.assign_sub(lr * m_b)

Adagrad:是借鉴 l 2 \mathcal{l}_2 l2 正则化的思想,每次迭代时自适应地调整每个参数的学习率。其在SGD基础上增加二阶动量
m t = g t V t = ∑ τ = 1 t g τ 2 η t = l r ⋅ m t / ( V t ) = l r ⋅ g t / ( ∑ τ = 1 t g τ 2 + ϵ ) w t + 1 = w t − η t = w t − l r ⋅ g t / ( ∑ τ = 1 t g τ 2 + ϵ ) \begin{array}{c} m_{\mathrm{t}}=g_{t} \quad V_{t}=\sum\limits_{\tau=1}^{t} g_{\tau}^{2} \\ \eta_{\mathrm{t}}=lr \cdot m_{t} /(\sqrt{V_{t}}) =lr \cdot g_{t} /(\sqrt{\sum_{\tau=1}^{t} g_{\tau}^{2}+\epsilon}) \\ w_{t+1}=w_t-\eta_t=w_{t}-lr \cdot g_{t} /(\sqrt{\sum_{\tau=1}^{t} g_{\tau}^{2}+\epsilon}) \end{array} mt=gtVt=τ=1tgτ2ηt=lrmt/(Vt )=lrgt/(τ=1tgτ2+ϵ )wt+1=wtηt=wtlrgt/(τ=1tgτ2+ϵ )

其中 ϵ \epsilon ϵ 是为了保持数值稳定性而设置的非常小的常数,一般取值 e − 7 e^{-7} e7 e − 10 e^{-10} e10

v_w, v_b = 0, 0
v_w += tf.square(grads[0])
v_b += tf.square(grads[1])
w.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b.assign_sub(lr * grads[1] / tf.sqrt(v_b))

在 AdaGrad 算法中,如果某个参数的偏导数累积比较大,其学习率相对较小;相反,如果其偏导数累积较小,其学习率相对较大.但整体是随着迭代次数的
增加,学习率逐渐缩小。

AdaGrad 算法的缺点是在经过一定次数的迭代依然没有找到最优点时,由于这时的学习率已经非常小,很难再继续找到最优点。

RMSProp:可以在有些情况下避免 AdaGrad 算法中学习率不断单调下降以至于过早衰减的缺点。其在SGD基础上增加二阶动量
m t = g t V t = β ⋅ V t − 1 + ( 1 − β ) ⋅ g t 2 η t = l r ⋅ m t / V t = l r ⋅ g t / ( β ⋅ V t − 1 + ( 1 − β ) ⋅ g t 2 ) w t + 1 = w t − η t = w t − l r ⋅ g t / ( β ⋅ V t − 1 + ( 1 − β ) ⋅ g t 2 ) \begin{array}{l} m_{\mathrm{t}}=g_{t} \quad V_{t}=\beta \cdot V_{t-1}+(1-\beta) \cdot g_{t}^{2} \\ \eta_{t}=lr \cdot m_{\mathrm{t}} / \sqrt{V_{\mathrm{t}}} =l r \cdot g_{t} /(\sqrt{\beta \cdot V_{t-1}+(1-\beta) \cdot g_{t}^{2}}) \\ w_{\mathrm{t}+1}=w_{t}-\eta_{t}=w_{t}-l r \cdot g_{t} /(\sqrt{\beta \cdot V_{t-1}+(1-\beta) \cdot g_{t}^{2}}) \end{array} mt=gtVt=βVt1+(1β)gt2ηt=lrmt/Vt =lrgt/(βVt1+(1β)gt2 )wt+1=wtηt=wtlrgt/(βVt1+(1β)gt2 )

其中 β \beta β 为衰减率,一般取值为 0.9。

从上式可以看出,RMSProp 算法和 AdaGrad 算法的区别在于 V t V_t Vt 的计算由累积方式变成了指数衰减移动平均.在迭代过程中,每个参数的学习率并不是呈
衰减趋势,既可以变小也可以变大。

v_w, v_b = 0, 0
beta = 0
v_w = beta * v_w + (1 - beta) * tf.square(grads[0])
v_b = beta * v_b + (1 - beta) * tf.square(grads[1])
w.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b.assign_sub(lr * grads[1] / tf.sqrt(v_b))

Adam:同时结合SGDM一阶动量和RMSProp二阶动量
m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t V t = β 2 ⋅ V s t e p − 1 + ( 1 − β 2 ) ⋅ g t 2 m_{\mathrm{t}}=\beta_{1} \cdot m_{t-1}+\left(1-\beta_{1}\right) \cdot g_{t}\\ V_{t}=\beta_{2} \cdot V_{s t e p-1}+\left(1-\beta_{2}\right) \cdot g_{t}^{2} mt=β1mt1+(1β1)gtVt=β2Vstep1+(1β2)gt2
假设 M 0 = 0 , G 0 = 0 M_0 = 0, G_0 = 0 M0=0,G0=0,那么在迭代初期 M t M_t Mt G t G_t Gt 的值会比真实的均值和方差要小.特别是当 β 1 \beta_1 β1 β 2 \beta_2 β2 都接近于 1 时,偏差会很大。因此,需要对偏差进行修正。

修正一阶动量的偏差: m t ^ = m t 1 − β 1 t \hat{m_t}=\dfrac{m_t}{1-\beta_1^t} mt^=1β1tmt

修正二阶动量的偏差: V t ^ = V t 1 − β 2 t \hat{V_t}=\dfrac{V_t}{1-\beta_2^t} Vt^=1β2tVt
η t = l r ⋅ m ^ t / V ^ t = l r ⋅ m t 1 − β 1 t / V t 1 − β 2 t w t + 1 = w t − η t = w t − l r ⋅ m t 1 − β 1 t / V t 1 − β 2 t \begin{aligned} \eta_{t}=& l r \cdot \widehat{m}_{\mathrm{t}} / \sqrt{\widehat{V}_{t}} =l r \cdot \frac{m_{\mathrm{t}}}{1-\beta_{1}^{t}} / \sqrt{\frac{V_{t}}{1-\beta_{2}^{t}}} \\ w_{t+1} &=w_{t}-\eta_{t} =w_{t}-l r \cdot \frac{m_{\mathrm{t}}}{1-\beta_{1}^{t}} / \sqrt{\frac{V_{t}}{1-\beta_{2}^{t}}} \end{aligned} ηt=wt+1lrm t/V t =lr1β1tmt/1β2tVt =wtηt=wtlr1β1tmt/1β2tVt

m_w, m_b = 0, 0
v_w, v_b = 0, 0
beta1, beta2 = 0.9, 0.999
delta_w, delta_b = 0, 0
global_step = 0

m_w = beta1 * m_w + (1 - beta1) * grads[0]
m_b = beta1 * m_b + (1 - beta1) * grads[1]
v_w = beta2 * v_w + (1 - beta2) * tf.square(grads[0])
v_b = beta2 * v_b + (1 - beta2) * tf.square(grads[1])
        
m_w_correction = m_w / (1 - tf.pow(beta1, int(global_step)))
m_b_correction = m_b / (1 - tf.pow(beta1, int(global_step)))
v_w_correction = v_w / (1 - tf.pow(beta2, int(global_step)))
v_b_correction = v_b / (1 - tf.pow(beta2, int(global_step)))
        
w.assign_sub(lr * m_w_correction / tf.sqrt(v_w_correction))
b.assign_sub(lr * m_b_correction / tf.sqrt(v_b_correction))

Adam 会设置 3 个超参数。一个是学习率 α \alpha α,一般设为0.001,并且也可以进行衰减。另外两个是一次momentum系数 β 1 \beta_1 β1 和二次momentum系数 β 2 \beta_2 β2。根据论文,标准的设定值是 β 1 \beta_1 β1 为0.9, β 2 \beta_2 β2 为0.999。设置了这些值后,大多数情况下都能顺利运行。

Momentum
v ← α v − η ∂ L ∂ W W ← W + v \begin{array}{c} \boldsymbol{v} \leftarrow \alpha \boldsymbol{v}-\eta \frac{\partial L}{\partial \boldsymbol{W}} \\ \boldsymbol{W} \leftarrow \boldsymbol{W}+\boldsymbol{v} \end{array} vαvηWLWW+v

class Momentum:
	def __init__(self, lr=0.01, momentum=0.9):
        self.lr = lr
        self.momentum = momentum
        self.v = None
	def update(self, params, grads):
		if self.v is None:
            self.v = {}
            for key, val in params.items():
				self.v[key] = np.zeros_like(val)
		for key in params.keys():
			self.v[key] = self.momentum*self.v[key] - self.lr*grads[key]
			params[key] += self.v[key]

每个参数的实际更新差值取决于最近一段时间内梯度的加权平均值.当某个参数在最近一段时间内的梯度方向不一致时,其真实的参数更新幅度变小;相反,当在最近一段时间内的梯度方向都一致时,其真实的参数更新幅度变大,起到加速作用。一般而言,在迭代初期,梯度方向都比较一致,动量法会起到加速作用,可以更快地到达最优点.在迭代后期,梯度方向会不一致,在收敛值附近振荡,动量法会起到减速作用,增加稳定性.从某种角度来说,当前梯度叠加上部分的上次梯度,一定程度上可以近似看作二阶梯度。

tensorflow2.1笔记

用Tensorflow API: tf. keras搭建网络八股

六步法:

  • import
  • train, test
  • model = tf.keras.models .Sequential
  • model.compile
  • model.fit
  • model.summary
model = tf.keras.models.Sequential ([网络结构])   #描述各层网络

网络结构举例:

拉直层: tf.keras.layers.Flatten( )

全连接层: tf.keras.layers.Dense(神经元个数,activation=“激活函数“,kernel_ regularizer=哪种正则化)

activation (字符串给出)可选: relu、softmax、 sigmoid 、tanh
kernel regularizer可选: tf.keras.regularizers.1()、tf.keras.regularizers.l2()

卷积层: tf.keras.layers.Conv2D(filters = 卷积核个数,kernel size =卷积核尺寸,strides=卷积步长,padding =”valid" or "same")

LSTM层: tf.keras.layers.LSTM()

model.compile(optimizer =优化器,loss =损失函数,metrics = [“准确率"] )

Optimizer可选:

‘sgd’ or tf.keras optimizers.SGD (Ir=学习率,momentum=动量参数)
‘adagrad’ or tf.keras. optimizers. Adagrad (r=学习率)
'adadelta or tf.keras. optimizers.Adadelta (r=学习率)
‘adam’ or tf.keras.optimizers.Adam (r=学习率,beta_ 1=0.9, beta_ 2=0.999)

loss可选:

‘mse’ or tf.keras.losses.MeanSquaredError()
‘sparse_categorical_crossentropy’ or tf.keras losses SparseCategoricalCrossentropy(from_logits=False)

Metrics可选:

‘accuracy’ : y _ y\_ y_和y都是数值,如 y_ =[1] y=[1]
'categorical_accuracy : y_ 和y都是独热码(概率分布).如y_ =[0,1,0] y=[0 256,0.695,0.048]
'sparse_categorical_accuracy : y_ 是数值,y是独热码(概率分布),如y_ =[1] y=[0.256,0.695,0.048]

model.fit (训练集的输入特征,训练集的标签,batch_ size= , epochs= , validation_ data=(测试集的输入特征,测试集的标签),validation_ split=从 训练集划分多少比例给测试集,validation_ freq =多少次epoch测试次)

model.summary()

代码示例:

import tensorflow as tf

fashion = tf.keras.datasets.fashion_mnist

(x_train, y_train), (x_test, y_test) = fashion.load_data()

x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation="softmax")
])

model.compile(optimizer="adam",
              loss=tf.keras.losses.SparseCategoricalCrossentropy(
                  from_logits=False),
              metrics=["sparse_categorical_accuracy"])

model.fit(x_train, y_train, batch_size=32, epochs=5,
          validation_data=(x_test, y_test), validation_freq=1)

model.summary()

与学习相关的技巧

权重的初始值

将权重初始值设为 0 的话,将无法正确进行学习。

为了防止“权重均一化”(严格地讲,是为了瓦解权重的对称结构),必须随机生成初始值。

激活值在分布上有所偏向会出现“表现力受限”的问题。

sigmoid激活函数:为了使各层的激活值呈现出具有相同广度的分布,推导了合适的权重尺度。推导出的结论是,如果前一层的节点数为 n n n,则初始值使用标准差为 1 n \dfrac{1}{\sqrt{n}} n 1 的分布。

Relu激活函数:当前一层的节点数为 $n $ 时,He 初始值使用标准差为 2 n \sqrt{\dfrac{2}{n}} n2 的高斯分布

当激活函数使用ReLU时,权重初始值使用He初始值,当激活函数为sigmoid 或tanh 等S 型曲线函数时,初始值使用Xavier 初始值。

Batch Normalization

Batch Norm有以下优点:

  • 可以使学习快速进行(可以增大学习率)。
  • 不那么依赖初始值(对于初始值不用那么神经质)。
  • 抑制过拟合(降低Dropout等的必要性)。

Batch Norm的思路是调整各层的激活值分布使其拥有适当的广度。为此,要向神经网络中插入对数据分布进行正规化的层。

Batch Norm,顾名思义,以进行学习时的mini-batch 为单位,按mini-batch进行正规化。具体而言,就是进行使数据分布的均值为0、方差为1 的正规化。
μ B ← 1 m ∑ i = 1 m x i σ B 2 ← 1 m ∑ i = 1 m ( x i − μ B ) 2 x ^ i ← x i − μ B σ B 2 + ε \begin{array}{l} \mu_{B} \leftarrow \frac{1}{m} \sum_{i=1}^{m} x_{i} \\ \sigma_{B}^{2} \leftarrow \frac{1}{m} \sum_{i=1}^{m}\left(x_{i}-\mu_{B}\right)^{2} \\ \hat{x}_{i} \leftarrow \frac{x_{i}-\mu_{B}}{\sqrt{\sigma_{B}^{2}+\varepsilon}} \end{array} μBm1i=1mxiσB2m1i=1m(xiμB)2x^iσB2+ε xiμB
通过将这个处理插入到激活函数的前面(或者后面)A,可以减小数据分布的偏向。接着,Batch Norm层会对正规化后的数据进行缩放和平移的变换,用数学式可以如下表示。
y i ← γ x ^ i + β y_{i} \leftarrow \gamma \hat{x}_{i}+\beta yiγx^i+β
Dropout

Dropout 是一种在学习的过程中随机删除神经元的方法。通过使用Dropout,即便是表现力强的网络,也可以抑制过拟合。

数据增强

image_gen_train = tf.keras.preprocessing.image.lmageDataGenerator(
    rescale = #所有数据将乘以该数值
    rotation_range = #随机旋转角度数范围
    width_shift_range = #随机宽度偏移量
    height_shift_range = #随机高度偏移量
    水平翻转: horizontal_flip = #是否随机水平翻转
    随机缩放: zoom_range = #随机缩放的范围[1-n, 1+n] 
)
image_gen_train.fit(x_train) #这里输入得数据必须是4维数据

读取保存模型

load weights(路径文件名)

checkpoint_save_path = "./checkpoint/mnist.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
    print('-------------load the model-----------------')
    model.load_weights(checkpoint_save_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
                                                 save_weights_only=True,
                                                 save_best_only=True)

history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,callbacks=[cp_callback])
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的西瓜瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值