tensorflow关于bn层使用问题,特别是train参数的设置问题

描述坑的过程:

resnet50做分类,使用了bn层

在训练的时候用了一个is_train占位符来区分训练和测试(单独区分开的,并不是一起做的)

训练的时候is_train=True,测试的时候is_train=False

现象:训练精度很高,测试精度不忍直视

问题原因:

这个可能是因为没有把bn层里面的训练时统计出的参数保持下来造成的,在保存模型的时候,除了保存weights,bias,还要保存bn中的mean,var等统计参数。测试的时候,is_training=True,用的是当前batch内的统计参数,这个没问题。is_training=False,用的是保存的参数,如果没保存,就直接初始化,这个肯定效果不好.

所以需要把bn层的统计参数在保存的时候也一起存起来.

存模型的时候不能只保存trainable_variables因为BN的参数不属于trainable_variables。为了方便,可以用tf.global_variables()。使用姿势如下

saver = tf.train.Saver(var_list=tf.global_variables())
savepath = saver.save(sess, 'here_is_your_personal_model_path’)

使用方法:

x_norm = tf.layers.batch_normalization(x, training=training)

# ...

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
    train_op = optimizer.minimize(loss)
好的,那我们就使用MNIST手写数字识别数据集。下面是实现的代码: ```python import tensorflow as tf from tensorflow.keras.datasets import mnist from tensorflow.keras.layers import Input, Conv2D, Dense, Flatten, BatchNormalization, Activation, MaxPooling2D from tensorflow.keras.models import Model # 加载数据集 (x_train, y_train), (x_test, y_test) = mnist.load_data() # 归一化数据 x_train, x_test = x_train / 255.0, x_test / 255.0 # 增加维度,将数据变成4D张量 x_train = x_train[..., tf.newaxis].astype("float32") x_test = x_test[..., tf.newaxis].astype("float32") # 定义模型 def LeNet5(): inputs = Input(shape=(28, 28, 1)) x = Conv2D(filters=6, kernel_size=(5, 5), activation='relu', padding='same')(inputs) x = MaxPooling2D(pool_size=(2, 2))(x) x = Conv2D(filters=16, kernel_size=(5, 5), activation='relu', padding='valid')(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Flatten()(x) x = Dense(units=120, activation='relu')(x) x = Dense(units=84, activation='relu')(x) outputs = Dense(units=10, activation='softmax')(x) model = Model(inputs=inputs, outputs=outputs) return model def LeNet5_BN(): inputs = Input(shape=(28, 28, 1)) x = Conv2D(filters=6, kernel_size=(5, 5), padding='same')(inputs) x = BatchNormalization()(x) x = Activation('relu')(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Conv2D(filters=16, kernel_size=(5, 5), padding='valid')(x) x = BatchNormalization()(x) x = Activation('relu')(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Flatten()(x) x = Dense(units=120)(x) x = BatchNormalization()(x) x = Activation('relu')(x) x = Dense(units=84)(x) x = BatchNormalization()(x) x = Activation('relu')(x) outputs = Dense(units=10, activation='softmax')(x) model = Model(inputs=inputs, outputs=outputs) return model def fully_connected(): inputs = Input(shape=(28, 28, 1)) x = Flatten()(inputs) x = Dense(units=128, activation='relu')(x) x = Dense(units=64, activation='relu')(x) outputs = Dense(units=10, activation='softmax')(x) model = Model(inputs=inputs, outputs=outputs) return model # 定义训练参数 batch_size = 64 epochs = 10 # 创建模型 model_LeNet5 = LeNet5() model_LeNet5_BN = LeNet5_BN() model_fully_connected = fully_connected() # 编译模型 model_LeNet5.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model_LeNet5_BN.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model_fully_connected.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 训练模型 history_LeNet5 = model_LeNet5.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test)) history_LeNet5_BN = model_LeNet5_BN.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test)) history_fully_connected = model_fully_connected.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test)) # 绘制训练曲线 import matplotlib.pyplot as plt plt.plot(history_LeNet5.history['accuracy'], label='LeNet-5') plt.plot(history_LeNet5_BN.history['accuracy'], label='LeNet-5 + BN') plt.plot(history_fully_connected.history['accuracy'], label='Fully connected') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.legend() plt.show() ``` 上述代码中,我们定义了三个模型:LeNet-5、LeNet-5+BN和全连接模型。然后,我们将这些模型编译,并使用MNIST数据集进行训练,并绘制出它们在训练集上准确度随epoch变化的曲线。 注意,由于BatchNormalization的存在,我们在准确度图表中应该看到LeNet-5+BN模型的收敛速度更快,并且在相同的epoch数下达到更高的准确度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值