tf中的过拟合和欠拟合

tf中的过拟合和欠拟合

1. 过拟合和欠拟合概念

  • 欠拟合:模型的表达能力小于真实数据分布的复杂度(如用一个线性函数表达一个非线性分布时存在欠拟合问题)
  • 过拟合:模型的表达能力大于真实数据分布的复杂度(如用一个非线性函数表达一个线性分布时存在过拟合问题)
  • 欠拟合的表现:训练准确率差,测试准确率也差
  • 过拟合的表现:训练准确率好,测试准确率差,即泛化能力变差
  • 目前,欠拟合比较少见,过拟合比较常见

2. 交叉验证

  • 相比传统的将数据集分为训练集(train)和测试集(test),把数据集分为train,val和test。其中将原来的train分为train和val。
(x, y), (x_test, y_test) = datasets.mnist.load_data()
# train 50k,val 10k
x_train, x_val = tf.split(x, num_or_size_splits=[50000,10000])
y_train, y_val = tf.split(y, num_or_size_splits=[50000,10000])
db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
db_train = db_train.map(preprocess).shuffle(50000).batch(batch_size)
db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
db_val = db_val.map(preprocess).shuffle(10000).batch(batch_size)
db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
db_test = db_test.map(preprocess).batch(batch_size)
  • 用val来验证参数。test仅作最后的测试,其与更新参数无关
network.compoile(
    optimizer=optimizers.Adam(lr=1e-3),
    loss=tf.losses.CategoricalCrossentropy(from_logits=True),
    metrics=['accuracy']
)
network.fit(db_train, epoch=5, validation_data=db_val, validation_freq=2)
network.evaluate(db_test)
  • 在实际使用交叉验证的时候,仅把训练分成两个固定部分并能很好胜任解决过拟合问题,通常把训练分成两个不固定部分,循环多次交叉验证过程
for epoch in range(500):
    # train加上val一共60k
    idx = tf.range(60000)
    idx = tf.random.shuffle(idx)
    x_train, y_train = tf.gather(x, idx[:50000]), tf.gather(y, idx[:50000])
    x_val, y_val = tf.gather(x, idx[-10000:]), tf.gather(y, idx[-10000:])
    db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
    db_train = db_train.map(preprocess).shuffle(50000).batch(batch_size)
    db_val = tf.data.Dataset.from_tensor_slices((x_val, y_val))
    db_val = db_val.map(preprocess).shuffle(10000).batch(batch_size)
  • keras对上述把训练分成两个不固定部分,循环多次交叉验证过程有简化写法,其中validation_split=0.1表示将0.9作为train,0.1做val
network.fit(db_train_val, epoch=5, validation_split=0.1, validation_freq=2)

3. 过拟合解决方法

3.1 获得更多的数据

3.2 限制模型复杂度(Regularization)

  • 对于一个二分类问题,其损失函数(交叉熵)为 J ( θ ) = − ∑ i = 1 m [ y i ln ⁡ y ^ i + ( 1 − y i ) ln ⁡ ( 1 − y ^ i ) ] m J(\theta)=-\frac{\sum_{i=1}^m[y_i\ln\hat{y}_i+(1-y_i)\ln(1-\hat{y}_i)]}{m} J(θ)=mi=1m[yilny^i+(1yi)ln(1y^i)]模型的输出表示为 y = β 0 + β 1 x + β 2 x 2 + . . . + β n x n + ε y=\beta_0+\beta_1x+\beta_2x^2+...+\beta_nx^n+\varepsilon y=β0+β1x+β2x2+...+βnxn+ε对损失函数添加一个约束项,在最小化损失函数的时候也最小化这个约束项, θ \theta θ代表y中的参数,即 β \beta β,更改后的损失函数如下 J ( θ ) = − ∑ i = 1 m [ y i ln ⁡ y ^ i + ( 1 − y i ) ln ⁡ ( 1 − y ^ i ) ] m + λ ∑ i = 1 n ∣ θ i ∣ J(\theta)=-\frac{\sum_{i=1}^m[y_i\ln\hat{y}_i+(1-y_i)\ln(1-\hat{y}_i)]}{m} +\lambda\sum_{i=1}^n|\theta_i| J(θ)=mi=1m[yilny^i+(1yi)ln(1y^i)]+λi=1nθi其中约束项可以是上式的L1范数形式,也可以是L2范数形式 λ ∑ i = 1 n ∣ ∣ θ ∣ ∣ 2 2 \frac{\lambda\sum_{i=1}^{n}||\theta||^2}{2} 2λi=1nθ2
    L2_model = keras.models.Sequential([
        keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
        activation=tf.nn.relu, input_shape=(NUM_WORDS)),
        keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
        activation=tf.nn.relu),
        keras.layers.Dense(1, activation=tf.nn.sigmoid)
    ])
  • 另一种更灵活的写法
    for step, (x, y) in enumerate(db):
        with tf.GradientTape() as tape:
            loss = tf.reduce_mean(tf.losses.categorical_crossentropy(y_onehot, out, from_logits=True))
            loss_regularization = []
            for p in network.trainable_variables:
                loss_regularization.append(tf.nn.l2_loss(p))
            loss_regularization = tf.reduce_sum(tf.stack(loss_regularization))
            loss = loss + 0.001*loss_regularization
        grads = tape.gradient(loss, network.trainable_variables)
        optimizer.apply_gradients(zip(grads, network.trainable_variables))       

3.3 动量与学习率

  1. 动量
  • 之前的参数更新方式为 w k + 1 = w k − α ∇ f ( w k ) w^{k+1}=w^{k}-\alpha \nabla f(w^k) wk+1=wkαf(wk)增加动量为 z k + 1 = β z k + α ∇ f ( w k ) z^{k+1}=\beta z^{k}+\alpha \nabla f(w^k) zk+1=βzk+αf(wk)则参数更新方式变为 w k + 1 = w k − α z k + 1 w^{k+1}=w^{k}-\alpha z^{k+1} wk+1=wkαzk+1
  • tf中动量实现如下所示,其中momentum参数代表 α \alpha α
optimizer = SGD(learning_rate=0.02, momentum=0.9)
optimizer = RMSprop(learning_rate=0.02, momentum=0.9)
optimizer = Adam(learning_rate=0.02, beta_1=0.9, beta_2=0.99)
  1. 学习率
  • 动态学习率比固定值学习率更适用,一般有学习率逐渐递减和准确率到一定值后更换学习率值两种方式
optimizer = SGD(learning_rate=0.02)
for epoch in range(100):
    optimizer.learning_rate=0.02*(100-epoch)/100

3.4 数据增强(扩充)

3.5 提前结束训练与Dropout

  • 提前结束,当测试准确率到达最高点时结束,此处的最高点指的是当准确率上升到一定值后开始下降,并下降一段时间后仍然下降,则认为到达了最高点(不一定是实际最高点)
  • Dropout:在全连层中,每次遗忘掉(去掉)某些连接线,这样相当于变相的减少了参数
network = Sequential([
    layers.Dense(256, activation='relu'),
    layers.Dropout(0.5), # 表示遗忘这个层与下个层之间50%的连接线
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.5), 
    layers.Dense(64, activation='relu'),
    layers.Dense(32, activation='relu'),
    layers.Dense(10)
])
  • 训练与测试之间的行为区别
for step, (x, y) in enumerate(db):
    with tf.GradientTape() as tape:
        x = tf.reshape(x, (-1, 28*28))
        out = network(x, training=True) # 训练
    out = network(x, training=False) # 测试  

3.6 随机梯度下降

  • 在进行梯度下降时,如果数据集很大,则不适合把所有数据都放到参数更新中。因此随机(按照某种分布)选取一个batch大小的数据作为参数跟新的标准
  • 之前的参数更新如下所示 ∂ ∂ θ j J ( θ ) = 1 m ∑ i = 1 m ( y ^ i − y i ) x j i \frac{\partial}{\partial \theta_j}J(\theta)=\frac{1}{m}\sum_{i=1}^m(\hat{y}^i-y^i)x^i_j θjJ(θ)=m1i=1m(y^iyi)xji θ j = θ j − α ∂ ∂ θ j J ( θ ) \theta_j = \theta_j -\alpha \frac{\partial}{\partial \theta_j}J(\theta) θj=θjαθjJ(θ)进行随机梯度下降后 θ j = θ j − α ( y ^ i − y i ) x j i ∇ J ∇ θ j \theta_j = \theta_j -\alpha(\hat{y}^i-y^i)x^i_j\frac{\nabla J}{\nabla \theta_j} θj=θjα(y^iyi)xjiθjJ其中, ( y ^ i − y i ) x j i (\hat{y}^i-y^i)x^i_j (y^iyi)xji为一个sample,将此式子循环一个batch
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值