我想用知识蒸馏keras模型预测不平衡数据,y标签值计数是这样的,
y_train.value_counts()
0 9024
1 842
Name: Y_LABEL, dtype: int64`
为了预测不平衡数据,我尝试使用class_weight,但我不知道如何在自定义模型中应用class_weight。如何在知识蒸馏自定义模型中应用class_weight?
我使用keras平台构建知识蒸馏自定义模型,首先,如您所见,y标签不平衡,因此我想使用class_weight
class Distiller(keras.Model):
def __init__(self, student, teacher):
super(Distiller, self).__init__()
self.teacher = teacher
self.student = student
def compile(
self,
optimizer,
metrics,
student_loss_fn,
distillation_loss_fn,
alpha=0.1,
temperature=3,
):
""" Configure the distiller.
Args:
optimizer: Keras optimizer for the student weights
metrics: Keras metrics for evaluation
student_loss_fn: Loss function of difference between student
predictions and ground-truth
distillation_loss_fn: Loss function of difference between soft
student predictions and soft teacher predictions
alpha: weight to student_loss_fn and 1-alpha to distillation_loss_fn
temperature: Temperature for softening probability distributions.
Larger temperature gives softer distributions.
"""
super(Distiller, self).compile(optimizer=optimizer, metrics=metrics)
self.student_loss_fn = student_loss_fn
self.distillation_loss_fn = distillation_loss_fn
self.alpha = alpha
self.temperature = temperature
def train_step(self, data):
# Unpack data
x, y = data
# Forward pass of teacher
teacher_predictions = self.teacher(x[:,:52], training=False)
with tf.GradientTape() as tape:
# Forward pass of student
student_predictions = self.student(x[:,52:], training=True)
# Compute losses
student_loss = self.student_loss_fn(y, student_predictions)
distillation_loss = self.distillation_loss_fn(
tf.nn.softmax(teacher_predictions / self.temperature, axis=1),
tf.nn.softmax(student_predictions / self.temperature, axis=1),
)
loss = self.alpha * student_loss + (1 - self.alpha) * distillation_loss
# Compute gradients
trainable_vars = self.student.trainable_variables
gradients = tape.gradient(loss, trainable_vars)
# Update weights
self.optimizer.apply_gradients(zip(gradients, trainable_vars))
# Update the metrics
self.compiled_metrics.update_state(y, student_predictions, sample_weight = sample_weight)
# Return a dict of performance
results = {m.name: m.result() for m in self.metrics}
results.update(
{"student_loss": student_loss, "distillation_loss": distillation_loss}
)
return results
def test_step(self, data):
# Unpack the data
x, y = data
# Compute predictions
y_prediction = self.student(x, training=False) # validation_data
# y_prediction = self.student(x[:,52:], training=False) # validation_split
# Calculate the loss
student_loss = self.student_loss_fn(y, y_prediction)
# Update the metrics.
self.compiled_metrics.update_state(y, y_prediction)
# Return a dict of performance
results = {m.name: m.result() for m in self.metrics}
results.update({"student_loss": student_loss})
return results
这是类权重
class_weight
{0: 0.5466568414520633, 1: 5.858270989193683}
我编译和拟合模型就像这样
distiller.compile(
student_loss_fn= tf.keras.losses.BinaryCrossentropy(from_logits = True),
optimizer=keras.optimizers.Adam(learning_rate = 0.001),
metrics=[tf.keras.metrics.BinaryAccuracy()], # , f1
distillation_loss_fn=keras.losses.KLDivergence(),
alpha=0.1,
temperature=10)
distillarHistory = distiller.fit(
df_out,
y_train,
epochs=50,
batch_size = 256,
validation_data = (X_test_s, y_test),
verbose = 0,
class_weight = class_weight,
)
但是发生了这样的错误,我如何在train_step中应用class_weight??
TypeError: in user code:
File "/home/studio-lab-user/.conda/envs/default/lib/python3.9/site-packages/keras/engine/training.py", line 1160, in train_function *
return step_function(self, iterator)
File "/home/studio-lab-user/.conda/envs/default/lib/python3.9/site-packages/keras/engine/training.py", line 1146, in step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
File "/home/studio-lab-user/.conda/envs/default/lib/python3.9/site-packages/keras/engine/training.py", line 1135, in run_step **
outputs = model.train_step(data)
File "/tmp/ipykernel_22361/144175027.py", line 61, in train_step
self.compiled_metrics.update_state(y, student_predictions, class_weight = class_weight)
TypeError: update_state() got an unexpected keyword argument 'class_weight'
我尝试通过修改自定义模型来使用sample_weight,如下所示:
def train_step(self, data):
# Unpack data
x, y, sample_weight = data
# Forward pass of teacher
teacher_predictions = self.teacher(x[:,:52], training=False)
with tf.GradientTape() as tape:
# Forward pass of student
student_predictions = self.student(x[:,52:], training=True)
# Compute losses
student_loss = self.student_loss_fn(y, student_predictions)
distillation_loss = self.distillation_loss_fn(
tf.nn.softmax(teacher_predictions / self.temperature, axis=1),
tf.nn.softmax(student_predictions / self.temperature, axis=1),
)
loss = self.alpha * student_loss + (1 - self.alpha) * distillation_loss
# Compute gradients
trainable_vars = self.student.trainable_variables
gradients = tape.gradient(loss, trainable_vars)
# Update weights
self.optimizer.apply_gradients(zip(gradients, trainable_vars))
# Update the metrics
self.compiled_metrics.update_state(y, student_predictions, sample_weight = sample_weight)
# self.compiled_metrics.update_state(y, student_predictions, sample_weight = sample_weight)
# Return a dict of performance
results = {m.name: m.result() for m in self.metrics}
results.update(
{"student_loss": student_loss, "distillation_loss": distillation_loss}
)
return results
distillarHistory = distiller.fit(
df_out,
y_train,
epochs=50,
batch_size = 256,
validation_data = (X_test_s, y_test),
verbose = 0,
sample_weight = sample_weight,
)
但是输出与不使用sample_weight而使用分层的5k倍完全相同,
- 不使用sample_weight
Alpha - 0.10 / Temperature 10
62/62 [==============================] - 0s 2ms/step
KFold F1 scores : 0.561608878542233
62/62 [==============================] - 0s 2ms/step
KFold F1 scores : 0.5664106062792742
62/62 [==============================] - 0s 2ms/step
KFold F1 scores : 0.5908350815131695
62/62 [==============================] - 0s 2ms/step
KFold F1 scores : 0.5793267313367816
62/62 [==============================] - 0s 2ms/step
KFold F1 scores : 0.5918020295603292
--------------------------------------------------------
Alpha=0.1, Temperature=10, F-Score=0.578
--------------------------------------------------------
- 使用样品重量
Alpha - 0.10 / Temperature 10
62/62 [==============================] - 1s 5ms/step
KFold F1 scores : 0.561608878542233
62/62 [==============================] - 0s 2ms/step
KFold F1 scores : 0.5664106062792742
62/62 [==============================] - 1s 8ms/step
KFold F1 scores : 0.5908350815131695
62/62 [==============================] - 1s 8ms/step
KFold F1 scores : 0.5793267313367816
62/62 [==============================] - 1s 7ms/step
KFold F1 scores : 0.5918020295603292
--------------------------------------------------------
Alpha=0.1, Temperature=10, F-Score=0.578
--------------------------------------------------------
“我想知道对积极数据的采样是消极数据的10倍左右是否相同
1条答案
按热度按时间bgibtngc1#
就像在
self.compiled_metrics.update_state
中,你添加了参数sample_weight = sample_weight
,你也必须在self.student_loss_fn
和self.distillation_loss_fn
中添加相同的参数。