কেরাসে ভারসাম্যহীন ক্লাসের জন্য শ্রেণি ওজন কীভাবে সেট করবেন?


128

আমি জানি যে ক্যারাসে ফিটিংয়ের ক্ষেত্রে class_weightsপ্যারামিটার অভিধান সহ একটি সম্ভাবনা রয়েছে তবে আমি এর কোনও উদাহরণ পাইনি। কেউ সরবরাহ করতে এত দয়াবান হবে?

যাইহোক, এক্ষেত্রে উপযুক্ত প্রক্সিগুলি সংখ্যালঘু শ্রেণীর তুলনামূলকভাবে তার নিম্নোক্ততার তুলনায় ভার বাড়িয়ে তোলা?


কেরাস ব্যবহার করে কোনও নতুন আপডেট হওয়া পদ্ধতি আছে? কেন অভিধানটি তিনটি শ্রেণি এবং শ্রেণীর সমন্বয়ে গঠিত: 0: 1.0 1: 50.0 2: 2.0 ???? 2: 1.0 পাশাপাশি করা উচিত নয়?
চক

উত্তর:


112

আপনি যদি নিয়মিত কেসের বিষয়ে কথা বলছেন, যেখানে আপনার নেটওয়ার্কটি কেবল একটি আউটপুট তৈরি করে, তবে আপনার অনুমানটি সঠিক। আপনার অ্যালগরিদমকে 1 ম শ্রেণীর প্রতিটি উদাহরণকে ক্লাস 0 এর 50 টি উদাহরণ হিসাবে বিবেচনা করতে বাধ্য করতে আপনাকে:

  1. আপনার লেবেল এবং তাদের সম্পর্কিত ওজন সহ একটি অভিধান নির্ধারণ করুন

    class_weight = {0: 1.,
                    1: 50.,
                    2: 2.}
    
  2. প্যারামিটার হিসাবে অভিধানটি খাওয়ান:

    model.fit(X_train, Y_train, nb_epoch=5, batch_size=32, class_weight=class_weight)

সম্পাদনা: " ক্লাস 1 এর প্রতিটি উদাহরণকে ক্লাস 0 এর 50 টি উদাহরণ হিসাবে বিবেচনা করুন " এর অর্থ হ'ল আপনার ক্ষতির ফাংশনে আপনি এই দৃষ্টান্তগুলিকে উচ্চতর মান নির্ধারণ করেন। অতএব, ক্ষতি একটি ওজনযুক্ত গড় হয়ে যায়, যেখানে প্রতিটি নমুনার ওজন শ্রেণি- ওজন এবং এর সাথে সম্পর্কিত শ্রেণি দ্বারা নির্দিষ্ট করা হয় ।

কেরাস ডক্স থেকে: শ্রেণি-ওজন: ক্ষতির ক্রিয়াকলাপটি ওজন করার জন্য ব্যবহৃত (কেবল প্রশিক্ষণের সময়) মান মাপের শ্রেণিক সূচকগুলি (পূর্ণসংখ্যার) মান ( মানগুলি ) weight


1
আপনি যদি 3 ডি ডেটা নিয়ে কাজ করছেন তবে github.com/fchollet/keras/issues/3653একবার দেখুন ।
হার্ভে

আমার জন্য এটি একটি ত্রুটি দেয় ডিকের আকৃতির বৈশিষ্ট্য নেই।
ফ্লাভিও ফিলিহো

আমি বিশ্বাস করি কেরাস এইভাবে কাজ করার পদ্ধতি পরিবর্তন করতে পারে, এটি আগস্ট 2016 এর সংস্করণের জন্য I আমি এক সপ্তাহের মধ্যে আপনার জন্য যাচাই করব
লেজার

4
@layser এটি কি কেবল 'ক্যাটাগরি_ক্রসনট্রপি' ক্ষতির জন্য কাজ করে? 'সিগময়েড' এবং 'বাইনারি_ক্রসনট্রপি' ক্ষতির জন্য আপনি ক্যারাসকে কীভাবে ক্লাস_ওয়েট দেন?
নামান

1
@ লেজার আপনি কি ক্লাস 1 এর প্রতিটি উদাহরণকে ক্লাস 0 50 এর 50 টি উদাহরণ হিসাবে বিবেচনা করতে পারবেন? এটি কি প্রশিক্ষণ সেট, ক্লাস 1 এর সাথে সারি সারিটি 50 বার নকল করা হয়েছে যাতে এটি ভারসাম্যহীন বা অন্য কোনও প্রক্রিয়া অনুসরণ করে?
দিব্যংশু শেখর

121

আপনি কেবল এগুলি class_weightথেকে প্রয়োগ করতে পারেন sklearn:

  1. প্রথমে মডিউলটি আমদানি করা যাক

    from sklearn.utils import class_weight
  2. শ্রেণীর ওজন নিরূপণের জন্য নিম্নলিখিতটি করুন

    class_weights = class_weight.compute_class_weight('balanced',
                                                     np.unique(y_train),
                                                     y_train)
    
  3. তৃতীয়ত এবং শেষ অবধি এটি মডেল ফিটিংয়ে যুক্ত করুন

    model.fit(X_train, y_train, class_weight=class_weights)

দৃষ্টি আকর্ষণ করছি : আমি এই পোস্ট সম্পাদিত এবং পরিবর্তনশীল নাম থেকে পরিবর্তিত class_weight করার class_weight গুলি না করার জন্য আমদানিকৃত মডিউল ওপর দিয়েই লিখতে। মন্তব্যগুলি থেকে কোড অনুলিপি করার সময় সেই অনুযায়ী সামঞ্জস্য করুন।


20
আমার জন্য, class_weight.compute_class_weight একটি অ্যারে উত্পাদন করে, কেরাসের সাথে কাজ করার জন্য আমার এটিকে ডিকে পরিবর্তন করতে হবে। আরও সুনির্দিষ্টভাবে, দ্বিতীয় পদক্ষেপের পরে, ব্যবহার করুনclass_weight_dict = dict(enumerate(class_weight))
C.Lee

5
এটি আমার পক্ষে কাজ করে না। কেরাসে একটি তিন শ্রেণির সমস্যার y_trainজন্য (300096, 3)নমপি অ্যারে। সুতরাং class_weight=লাইনটি আমাকে টাইপরেয়ার দেয়: অপসারণযোগ্য প্রকার: 'numpy.ndarray'
লেম্বিক

3
@ ল্যাম্বিক আমার একই রকম সমস্যা ছিল, যেখানে y এর প্রতিটি সারিতে শ্রেণি সূচকগুলির এক-গরম এনকোডযুক্ত ভেক্টর। আমি ভালো কোন int- এ এক গরম উপস্থাপনা রূপান্তর দ্বারা এটি সংশোধন করা হয়েছে: y_ints = [y.argmax() for y in y_train]
tkocmathla

3
আমি যদি মাল্টিক্লাস লেবেলিং করছি যাতে আমার y_true ভেক্টরগুলির একাধিক 1 রয়েছে: [1 0 0 0 1 0 0] উদাহরণস্বরূপ, যেখানে কিছু এক্স এর লেবেল 0 এবং 4 রয়েছে তবুও, আমার প্রতিটি # এর মোট # লেবেলগুলি ভারসাম্যপূর্ণ নয়। এর সাথে আমি কীভাবে ক্লাস ওজন ব্যবহার করব?
অ্যালোক

22

আমি এই জাতীয় নিয়ম এর জন্য ব্যবহার করি 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}

3
মোট শ্রেণির নমুনার দ্বারা শ্রেণীর জন্য মাত্র নমুনার সংখ্যা ভাগ করার পরিবর্তে লগ কেন ব্যবহার করবেন? আমি ধরে নিচ্ছি এমন কিছু আছে যা আমি বুঝতে পারছি না মডেল.ফিট_জেনেরেটর (...)
পরম

@ স্টার্টফটেক্সট এটাই আমি করেছি, তবে আমি মনে করি এটি উল্টে গেছে। আমি n_total_samples / n_class_samplesপ্রতিটি ক্লাসের জন্য ব্যবহার করেছি ।
কল্লিন

2
আপনার উদাহরণে ক্লাস 0 (2813 উদাহরণ রয়েছে) এবং 6 ম শ্রেণীর (79৯১৪ টি উদাহরণ রয়েছে) ওজনের সঠিক ওজন 1.0 have তা কেন? ক্লাস এ কয়েকগুণ বড়! আপনি চাইছেন যে ক্লাস 0 এটিকে সমতল করা হবে এবং ক্লাস 6 এটিকে একই স্তরে নিয়ে যেতে ডাউনস্কেল করা হবে।
ভ্লাদিস্লাভস ডোভলেলেকস

9

দ্রষ্টব্য: মন্তব্য দেখুন, এই উত্তরটি পুরানো।

সমস্ত শ্রেণীর সমানভাবে ওজন করতে, আপনি কেবল শ্রেণিক-ওজনকে "অটো" তে এভাবে সেট করতে পারেন:

model.fit(X_train, Y_train, nb_epoch=5, batch_size=32, class_weight = 'auto')

1
আমি class_weight='auto'কেরাস ডকুমেন্টেশনে বা উত্স কোডে কোনও রেফারেন্স পাইনি । আপনি এটি কোথায় পেয়েছেন তা আমাদের দেখাতে পারেন?
ফেবিও পেরেজ

2
এই উত্তর সম্ভবত ভুল। এই সমস্যাটি দেখুন: github.com/fchollet/keras/issues/5116
ফেবিও পেরেজ

বিজোড়। আমি মন্তব্য পোস্ট করার সময় আমি ক্লাস_সাম্যযুক্ত = 'অটো' ব্যবহার করছি, তবে এখনই এর উল্লেখ খুঁজে পাচ্ছি না। কেরাস দ্রুত বিকশিত হওয়ায় সম্ভবত এটি পরিবর্তন করা হয়েছে।
ডেভিড গ্রোপ

হিসাবে উল্লেখিত Keras ইস্যু উপরে উল্লিখিত , আপনি যাই হোক না কেন র্যান্ডম স্ট্রিং পাস করতে পারেন class_weightএবং এটি কোনো প্রভাব থাকবে না। এই উত্তর তাই সঠিক নয়।
এনকেসাস

3

ক্লাস_ওয়েট ঠিক আছে তবে @ অ্যালোক যেমনটি বলেছে আপনি ওয়ান-হট এনকোডিং মাল্টিলেবলযুক্ত ক্লাস হলে এটি কাজ করবে না। এই ক্ষেত্রে, নমুনা_জন ব্যবহার করুন :

নমুনা_ ওজন: এক্স এর সমান দৈর্ঘ্যের alচ্ছিক অ্যারে, প্রতিটি নমুনার জন্য মডেলের ক্ষতির জন্য প্রয়োগ করতে ওজন যুক্ত containing টেম্পোরাল ডেটার ক্ষেত্রে, আপনি প্রতিটি নমুনার প্রতিটি টাইমস্টেপে আলাদা ওজন প্রয়োগ করতে, আকৃতির (নমুনা, সিকোয়েন্স_ দৈর্ঘ্য) সহ একটি 2 ডি অ্যারে পাস করতে পারেন। এই ক্ষেত্রে আপনার কম্পাইল () মধ্যে নমুনা_জন_মোড = "অস্থায়ী" নির্দিষ্ট করা নিশ্চিত করা উচিত।

নমুনা_উইট প্রতিটি প্রশিক্ষণের নমুনার জন্য ওজন সরবরাহ করতে ব্যবহৃত হয় । এর অর্থ হ'ল আপনার প্রশিক্ষণের নমুনাগুলির মতো একই সংখ্যক উপাদানের সাথে আপনার 1 ডি অ্যারে পাস করা উচিত (সেই সমস্ত নমুনার প্রত্যেকটির ওজন নির্দেশ করে)।

শ্রেণি_উইট প্রতিটি আউটপুট শ্রেণীর জন্য ওজন বা পক্ষপাত প্রদান করতে ব্যবহৃত হয় । এর অর্থ হল যে আপনি প্রতিটি শ্রেণীর শ্রেণিবদ্ধ করার চেষ্টা করছেন তার জন্য আপনার একটি ওজন উত্তরণ করা উচিত।

নমুনা_জনকে অবশ্যই একটি আকাঙ্ক্ষিত অ্যারে দেওয়া উচিত, যেহেতু এর আকারটি মূল্যায়ন করা হবে।

এই উত্তরটিও দেখুন: https://stackoverflow.com/questions/48315094/ using-sample- વજન-in-keras-for-sequence-labelling


2

Https://github.com/keras-team/keras/issues/2115 এ সমাধানটিতে যুক্ত করা হচ্ছে । আপনার যদি শ্রেণি ওজনের চেয়ে বেশি প্রয়োজন যেখানে আপনি মিথ্যা ধনাত্মক এবং মিথ্যা নেতিবাচক জন্য বিভিন্ন ব্যয় চান। নতুন কেরাস সংস্করণটি দিয়ে এখন আপনি নীচের বর্ণিত ক্ষতি সম্পর্কিত ফাংশনটিকে ওভাররাইড করতে পারেন। নোট যে 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

0

মিনিস্ট ডেটাসেট ব্যবহার করে লোকসান ফাংশনে ক্লাস ওজনে কোডিংয়ের নিম্নলিখিত উদাহরণটি পেয়েছি। লিঙ্কটি এখানে দেখুন: 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

0
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 টির বেশি মান হবে।

শ্রেণি ওজন একটি অভিধান টাইপ ইনপুট গ্রহণ করে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.