分类问题loss为nan
卡在这里很久了,希望苏神赐教!
基本信息
- 你使用的操作系统: ubuntu
- 你使用的Python版本: 3.6
- 你使用的Tensorflow版本:tensorflow-gpu==1.11.0
- 你使用的Keras版本: 2.2.4
- 你使用的bert4keras版本: 0.7.8
- 你使用纯keras还是tf.keras: keras
- 你加载的预训练模型:chinese_roberta_L-4_H-312_A-12/chinese_roberta_wwm_ext_L-12_H-768_A-12等
核心代码
DataSet = load_data()
train_data,valid_data,test_data = split_dataset(DataSet.data)
train_data.dropna()
tokenizer = Tokenizer(dict_path, do_lower_case=True)
bert = build_transformer_model(
config_path=config_path,
checkpoint_path=checkpoint_path,
model=config['BERT_CONFIG']['model'],
return_keras_model=False,
)
output = Lambda(lambda x: x[:, 0], name='CLS-token')(bert.model.output)
output = Dense(
units=num_classes,
activation='softmax',
kernel_initializer=bert.initializer
)(output)
output = Lambda(lambda x: x+1e-8)(output)
model = keras.models.Model(bert.model.input, output)
model.summary()
AdamLR = extend_with_piecewise_linear_lr(Adam, name='AdamLR')
model.compile(
loss='sparse_categorical_crossentropy',
# optimizer=Adam(1e-5,
optimizer=AdamLR(lr=1e-4, lr_schedule={
1000: 1,
2000: 0.1
}),
# optimizer='sgd',
metrics=['accuracy'],
)
train_generator = data_generator(train_data, batch_size)
valid_generator = data_generator(valid_data, batch_size)
test_generator = data_generator(test_data, batch_size)
evaluator = Evaluator()
model.fit_generator(
train_generator.forfit(),
steps_per_epoch=len(train_generator),
epochs=20,
callbacks=[evaluator]
)
model.load_weights('best_model.weights')
print(u'final test acc: %05f\n' % (evaluate(test_generator)))
#
### 输出信息
```shell
数据为22000条左右,batch_size=32,lr=1e-4时如下(当将batch_size调整地非常小,并且学习率也很小的时候,起初的几个batch的loss不为nan):
__________________________________________________________________________________________________
Epoch 1/20
1/351 [..............................] - ETA: 35:48 - loss: 3.2497 - acc: 0.0000e+00
3/351 [..............................] - ETA: 12:05 - loss: 3.2328 - acc: 0.0000e+00
4/351 [..............................] - ETA: 9:09 - loss: 3.2325 - acc: 0.0000e+00
5/351 [..............................] - ETA: 7:22 - loss: 3.2265 - acc: 0.0000e+00
7/351 [..............................] - ETA: 5:19 - loss: 3.2272 - acc: 0.0179
8/351 [..............................] - ETA: 4:41 - loss: 3.2187 - acc: 0.0312
10/351 [..............................] - ETA: 3:46 - loss: 3.2213 - acc: 0.0281
11/351 [..............................] - ETA: 3:26 - loss: 3.2241 - acc: 0.0284
数据为37000条左右,batch_size=32,lr=1e-4时如下:
__________________________________________________________________________________________________
Epoch 1/20
1/582 [..............................] - ETA: 1:05:03 - loss: nan - acc: 0.0938
2/582 [..............................] - ETA: 32:52 - loss: nan - acc: 0.0938
3/582 [..............................] - ETA: 22:09 - loss: nan - acc: 0.0833
4/582 [..............................] - ETA: 16:45 - loss: nan - acc: 0.0938
6/582 [..............................] - ETA: 11:16 - loss: nan - acc: 0.0781
7/582 [..............................] - ETA: 9:43 - loss: nan - acc: 0.0759
自我尝试
在此基础上做了几组实验排查原因,由于实验思路不一定正确,因此附上实验步骤的描述
- 首先是排查数据本身的问题: 1.使用18000条数据进行训练,没有出现loss为nan的问题。 2.因此在此基础上,复制了一倍,即共36000条数据进行训练,出现loss为nan的问题。 3.此后又在这份原始数据的基础上生成不同数量的数据进行训练,发现当所有参数都不变的情况下(包括batch_size),单单增加训练数据总数至30000条左右就会出现loss为nan的情况。
- 接着对lr进行测试: 不断的改小lr(每次降低10倍),确实有一些提升(可训练数据总量略有提升),但在1e-8以后基本无效
- 对batch_size进行测试: 当且仅当batch_size为1时,某些时候头几个batch的loss不为nan
- 对损失函数进行测试: 为了避免是损失函数计算log(0)产生的nan,增加lambda层,output = Lambda(lambda x: x+1e-8)(output),避免为output为0的情况,但是loss为nan仍然出现
- 对优化器进行测试: 更换了几类优化器,loss为nan仍然出现
检查过所有数据,确认标签都是在[0, num_classes)范围内了吗?
检查过了,增加的数据仅是用pandas和numpy做了复制操作而已
方便提供一份可复现的代码和数据吗?如果可以的话发到我邮箱,我来调试下
谢谢苏神!不过是公司的代码和数据,所以没有办法,我再调试调试,如果找出原因,会再在issue下回复,感谢!
好的,但是我还是感觉是数据异常的问题。如果真的是数据量,你可以试试几条数据复制几万份看看。
没错,我也感觉应该是这个原因,回去看了一下自己建数据集的代码,是先复制数据再划分训练集测试集和验证集的划分,并且是固定随机种子。因此很有可能是之前脏数据碰巧没有被划分到训练集中,增多数据后被划分进了训练集中。验证后会再来回复,再次感谢!
用7条数据复制了几万份,确实没有出现为nan的问题,这么看应该是数据的问题了。但是我将一整份数据放入到网络当中,并且将batch_size调为1,但是没有哪个batch出现为nan的情况,不知道苏神对这种情况还有什么建议吗
这个应该不只是数据的问题,模型也有关系。我是先用垂直领域的语料训练albert模型,然后再做下游分类任务。同样的下游任务,如果预训练过程过拟合越严重,下游分类任务出现nan的概率就越高