ฉันรู้ว่ามีความเป็นไปได้ใน Keras ด้วยclass_weights
พจนานุกรมพารามิเตอร์ที่เหมาะสม แต่ฉันไม่พบตัวอย่างใด ๆ ใครบางคนจะใจดีที่จะให้อย่างใดอย่างหนึ่ง?
โดยวิธีการในกรณีนี้แพรคซิที่เหมาะสมเป็นเพียงการเพิ่มน้ำหนักให้กับชนกลุ่มน้อยตามสัดส่วนการแสดง?
ฉันรู้ว่ามีความเป็นไปได้ใน Keras ด้วยclass_weights
พจนานุกรมพารามิเตอร์ที่เหมาะสม แต่ฉันไม่พบตัวอย่างใด ๆ ใครบางคนจะใจดีที่จะให้อย่างใดอย่างหนึ่ง?
โดยวิธีการในกรณีนี้แพรคซิที่เหมาะสมเป็นเพียงการเพิ่มน้ำหนักให้กับชนกลุ่มน้อยตามสัดส่วนการแสดง?
คำตอบ:
หากคุณกำลังพูดถึงกรณีปกติที่เครือข่ายของคุณผลิตออกเดียวเท่านั้นการสันนิษฐานของคุณถูกต้อง ในการบังคับอัลกอริทึมของคุณให้ปฏิบัติต่อทุกอินสแตนซ์ของคลาส 1เป็น 50 อินสแตนซ์ของคลาส 0คุณต้อง:
กำหนดพจนานุกรมด้วยป้ายกำกับของคุณและน้ำหนักที่เกี่ยวข้อง
class_weight = {0: 1.,
1: 50.,
2: 2.}
ฟีดพจนานุกรมเป็นพารามิเตอร์:
model.fit(X_train, Y_train, nb_epoch=5, batch_size=32, class_weight=class_weight)
แก้ไข: "ปฏิบัติต่อทุกอินสแตนซ์ของคลาส 1เป็น 50 อินสแตนซ์ของคลาส 0 " หมายความว่าในฟังก์ชันการสูญเสียของคุณคุณกำหนดค่าที่สูงขึ้นให้กับอินสแตนซ์เหล่านี้ ดังนั้นการสูญเสียจะกลายเป็นค่าเฉลี่ยถ่วงน้ำหนักโดยน้ำหนักของตัวอย่างแต่ละตัวอย่างถูกระบุโดยclass_weightและคลาสที่เกี่ยวข้อง
จาก Keras docs: class_weight : ดัชนีคลาสการแม็พทางเลือก (จำนวนเต็ม) เป็นค่าน้ำหนัก (ลอย) ที่ใช้สำหรับถ่วงน้ำหนักฟังก์ชั่นการสูญเสีย (ระหว่างการฝึกอบรมเท่านั้น)
คุณสามารถใช้class_weight
จากsklearn
:
ลองนำเข้าโมดูลก่อน
from sklearn.utils import class_weight
ในการคำนวณน้ำหนักของชั้นเรียนให้ทำดังต่อไปนี้
class_weights = class_weight.compute_class_weight('balanced',
np.unique(y_train),
y_train)
ประการที่สามและสุดท้ายเพิ่มเข้าไปในรูปแบบที่เหมาะสม
model.fit(X_train, y_train, class_weight=class_weights)
ข้อควรระวัง : ฉันแก้ไขโพสต์นี้และเปลี่ยนชื่อตัวแปรจากclass_weightเป็นclass_weight sเพื่อไม่ให้เขียนทับโมดูลที่นำเข้า ปรับตามเมื่อคัดลอกรหัสจากความคิดเห็น
class_weight.compute_class_weight
สร้างอาร์เรย์ฉันต้องเปลี่ยนเป็น dict เพื่อทำงานกับ Keras โดยเฉพาะอย่างยิ่งหลังจากขั้นตอนที่ 2 ให้ใช้class_weight_dict = dict(enumerate(class_weight))
y_train
คือ(300096, 3)
อาร์เรย์ numpy ดังนั้นclass_weight=
บรรทัดให้ฉัน TypeError: unhashable ประเภท: 'numpy.ndarray'
y_ints = [y.argmax() for y in y_train]
เช่นนี้:
ฉันใช้กฎประเภทนี้เพื่อclass_weight
:
import numpy as np
import math
# labels_dict : {ind_label: count_label}
# mu : parameter to tune
def create_class_weight(labels_dict,mu=0.15):
total = np.sum(labels_dict.values())
keys = labels_dict.keys()
class_weight = dict()
for key in keys:
score = math.log(mu*total/float(labels_dict[key]))
class_weight[key] = score if score > 1.0 else 1.0
return class_weight
# random labels_dict
labels_dict = {0: 2813, 1: 78, 2: 2814, 3: 78, 4: 7914, 5: 248, 6: 7914, 7: 248}
create_class_weight(labels_dict)
math.log
ปรับน้ำหนักให้เรียบสำหรับคลาสที่ไม่สมดุล! ผลตอบแทนนี้:
{0: 1.0,
1: 3.749820767859636,
2: 1.0,
3: 3.749820767859636,
4: 1.0,
5: 2.5931008483842453,
6: 1.0,
7: 2.5931008483842453}
n_total_samples / n_class_samples
สำหรับแต่ละชั้น
หมายเหตุ: ดูความคิดเห็นคำตอบนี้ล้าสมัย
หากต้องการให้น้ำหนักทุกคลาสเท่ากันคุณสามารถตั้ง class_weight เป็น "auto" ได้ดังนี้:
model.fit(X_train, Y_train, nb_epoch=5, batch_size=32, class_weight = 'auto')
class_weight='auto'
ในเอกสารประกอบของKeras หรือในซอร์สโค้ด คุณช่วยแสดงให้เราเห็นว่าคุณพบสิ่งนี้ได้จากที่ใด
class_weight
และจะไม่มีผลกระทบใด ๆ คำตอบนี้ไม่ถูกต้อง
class_weight นั้นใช้ได้ แต่ @Aalok บอกว่ามันจะไม่ทำงานถ้าคุณเป็นคลาสที่มีการเข้ารหัสแบบหลายชั้น ในกรณีนี้ใช้sample_weight :
sample_weight: อาร์เรย์ที่เป็นตัวเลือกที่มีความยาวเท่ากับ x ซึ่งมีน้ำหนักที่จะนำไปใช้กับการสูญเสียของแบบจำลองสำหรับแต่ละตัวอย่าง ในกรณีของข้อมูลชั่วคราวคุณสามารถส่งอาร์เรย์ 2 มิติด้วยรูปร่าง (ตัวอย่าง, ลำดับความยาว) เพื่อนำน้ำหนักที่แตกต่างกันไปใช้กับการตั้งเวลาของทุกตัวอย่างทุกครั้ง ในกรณีนี้คุณควรตรวจสอบให้แน่ใจว่าได้ระบุ sample_weight_mode = "temporal" ในการคอมไพล์ ()
sample_weightsจะใช้ในการให้น้ำหนักสำหรับตัวอย่างการฝึกอบรมแต่ละ ซึ่งหมายความว่าคุณควรผ่านอาร์เรย์ 1D ที่มีจำนวนองค์ประกอบเท่ากันกับตัวอย่างการฝึกอบรมของคุณ (ระบุน้ำหนักของแต่ละตัวอย่างเหล่านั้น)
class_weightsถูกนำมาใช้เพื่อให้มีน้ำหนักหรืออคติสำหรับการเรียนการส่งออกในแต่ละ ซึ่งหมายความว่าคุณควรส่งผ่านน้ำหนักสำหรับแต่ละชั้นเรียนที่คุณพยายามจำแนก
sample_weight จะต้องได้รับอาร์เรย์ numpy เนื่องจากรูปร่างของมันจะถูกประเมิน
ดูคำตอบนี้ได้ที่: https://stackoverflow.com/questions/48315094/using-sample-weight-in-keras-for-sequence-labelling
เพิ่มเพื่อแก้ปัญหาที่https://github.com/keras-team/keras/issues/2115 หากคุณต้องการมากกว่าน้ำหนักชั้นเรียนที่คุณต้องการค่าใช้จ่ายที่แตกต่างกันสำหรับการบวกเชิงลบและเชิงลบที่ผิด ด้วย keras เวอร์ชั่นใหม่ตอนนี้คุณสามารถแทนที่ฟังก์ชั่นการสูญเสียที่เกี่ยวข้องตามที่ระบุด้านล่าง โปรดสังเกตว่าweights
เป็นเมทริกซ์จตุรัส
from tensorflow.python import keras
from itertools import product
import numpy as np
from tensorflow.python.keras.utils import losses_utils
class WeightedCategoricalCrossentropy(keras.losses.CategoricalCrossentropy):
def __init__(
self,
weights,
from_logits=False,
label_smoothing=0,
reduction=losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE,
name='categorical_crossentropy',
):
super().__init__(
from_logits, label_smoothing, reduction, name=f"weighted_{name}"
)
self.weights = weights
def call(self, y_true, y_pred):
weights = self.weights
nb_cl = len(weights)
final_mask = keras.backend.zeros_like(y_pred[:, 0])
y_pred_max = keras.backend.max(y_pred, axis=1)
y_pred_max = keras.backend.reshape(
y_pred_max, (keras.backend.shape(y_pred)[0], 1))
y_pred_max_mat = keras.backend.cast(
keras.backend.equal(y_pred, y_pred_max), keras.backend.floatx())
for c_p, c_t in product(range(nb_cl), range(nb_cl)):
final_mask += (
weights[c_t, c_p] * y_pred_max_mat[:, c_p] * y_true[:, c_t])
return super().call(y_true, y_pred) * final_mask
ฉันพบตัวอย่างต่อไปนี้ของการเขียนน้ำหนักของคลาสในฟังก์ชันการสูญเสียโดยใช้ชุดข้อมูล minist ดูลิงก์ที่นี่: https://github.com/keras-team/keras/issues/2115
def w_categorical_crossentropy(y_true, y_pred, weights):
nb_cl = len(weights)
final_mask = K.zeros_like(y_pred[:, 0])
y_pred_max = K.max(y_pred, axis=1)
y_pred_max = K.reshape(y_pred_max, (K.shape(y_pred)[0], 1))
y_pred_max_mat = K.equal(y_pred, y_pred_max)
for c_p, c_t in product(range(nb_cl), range(nb_cl)):
final_mask += (weights[c_t, c_p] * y_pred_max_mat[:, c_p] * y_true[:, c_t])
return K.categorical_crossentropy(y_pred, y_true) * final_mask
from collections import Counter
itemCt = Counter(trainGen.classes)
maxCt = float(max(itemCt.values()))
cw = {clsID : maxCt/numImg for clsID, numImg in itemCt.items()}
ใช้งานได้กับเครื่องกำเนิดไฟฟ้าหรือมาตรฐาน คลาสที่ใหญ่ที่สุดของคุณจะมีน้ำหนัก 1 ในขณะที่คนอื่นจะมีค่ามากกว่า 1 เมื่อเทียบกับคลาสที่ใหญ่ที่สุด
ตุ้มน้ำหนักสำหรับชั้นเรียนรับอินพุตประเภทพจนานุกรม