要给yolo添加多尺度训练,因为tf.keras无法对dataset对象进行callback操作这也就算了,但是我没法得知dataset对象目前在生成训练数据还是测试数据,这个就很蛋疼,需要能在尽量不大改代码的同时添加多尺度训练方式,所以还得看tf.keras.callback.

测试1

最重要的就是能得到目前是训练还是测试状态,我写了个小程序去测试:

class T(k.callbacks.Callback):
def __init__(self):
super().__init__()

def on_train_begin(self, logs=None):
print('on_train_begin')

def on_train_end(self, logs=None):
print('on_train_end')

def on_test_begin(self, logs=None):
print('on_test_begin')

def on_test_batch_end(self, batch, logs=None):
print('on_test_batch_end')

def on_test_end(self, logs=None):
print('on_test_begin')

def on_predict_begin(self, logs=None):
print('predict')


def test_train_callback():
train_x = np.random.randn(1000, 10).astype(np.float32)
train_y = np.random.randn(1000, 1).astype(np.float32)

test_x = np.random.randn(1000, 10).astype(np.float32)
test_y = np.random.randn(1000, 1).astype(np.float32)
train_ds = (tf.data.Dataset.from_tensor_slices((train_x, train_y)).
shuffle(5000).
repeat().
batch(400, True).
map(lambda x, y: ((x), y)))
test_ds = (tf.data.Dataset.from_tensor_slices((test_x, test_y)).
shuffle(5000).
repeat().
batch(400, True).
map(lambda x, y: ((x), y)))

model = k.Sequential([kl.Dense(1)])
model.compile(k.optimizers.Adam(), 'mse')
model.fit(train_ds, epochs=3, steps_per_epoch=4, validation_data=test_ds, validation_steps=4, callbacks=[T()], verbose=0)


test_train_callback()

获得:

on_train_begin
on_test_begin
on_test_batch_end
on_test_batch_end
on_test_batch_end
on_test_batch_end
on_test_begin
on_test_begin
on_test_batch_end
on_test_batch_end
on_test_batch_end
on_test_batch_end
on_test_begin
on_test_begin
on_test_batch_end
on_test_batch_end
on_test_batch_end
on_test_batch_end
on_test_begin
on_train_end

这里可以分析得整一个周期都是train,但在验证过程中只有on_test_begin,没有on_test_end,只有on_test_batch_end.这就很难受了.除非我每个on_test_batch_end都调用一下禁止多尺度训练.

不过使用dataset至少还是有个好处的,可以使用validation_steps统计on_test_batch_end次数~

测试2

我发现其实在进入测试阶段之后,on_train_batch_end是不会被调用的,那么我们其实直接可以直接设定就完事了,不需要再搞什么计数啥的,完美解决问题

class T(k.callbacks.Callback):
def __init__(self):
super().__init__()
self.cnt = 0
self.change_flag = True

def on_train_batch_end(self, batch, logs=None):
if self.cnt == 3:
print('change input scale')
self.change_flag = True
self.cnt = 0
else:
self.cnt += 1
print(f'Now change is {self.change_flag}')

def on_test_batch_end(self, batch, logs=None):
print(f'Now change is {self.change_flag}')

def on_test_begin(self, batch, logs=None):
print('reverse change input scale')
self.change_flag = False


def test_train_callback():
train_x = np.random.randn(1000, 10).astype(np.float32)
train_y = np.random.randn(1000, 1).astype(np.float32)

test_x = np.random.randn(1000, 10).astype(np.float32)
test_y = np.random.randn(1000, 1).astype(np.float32)
train_ds = (tf.data.Dataset.from_tensor_slices((train_x, train_y)).
shuffle(5000).
repeat().
batch(400, True).
map(lambda x, y: ((x), y)))
test_ds = (tf.data.Dataset.from_tensor_slices((test_x, test_y)).
shuffle(5000).
repeat().
batch(400, True).
map(lambda x, y: ((x), y)))

model = k.Sequential([kl.Dense(1)])
model.compile(k.optimizers.Adam(), 'mse')
model.fit(train_ds, epochs=3, steps_per_epoch=10, validation_data=test_ds, validation_steps=3, callbacks=[T()], verbose=0)


test_train_callback()
Now change is True
Now change is True
Now change is True
change input scale
Now change is True
Now change is True
Now change is True
Now change is True
change input scale
Now change is True
Now change is True
Now change is True
reverse change input scale
Now change is False
Now change is False
Now change is False
Now change is False
change input scale
Now change is True
Now change is True
Now change is True
Now change is True
change input scale
Now change is True
Now change is True
Now change is True
Now change is True
change input scale
Now change is True
reverse change input scale
Now change is False
Now change is False
Now change is False
Now change is False
Now change is False
Now change is False
change input scale
Now change is True
Now change is True
Now change is True
Now change is True
change input scale
Now change is True
Now change is True
Now change is True
reverse change input scale
Now change is False
Now change is False
Now change is False