Keras: вес класса (вес класса) для one-hot кодирования

Я хотел бы использовать аргумент class_weight в модели keras.подходит для обработки несбалансированных данных обучения. Посмотрев на некоторые документы, я понял, что мы можем передать такой словарь:

class_weight = {0 : 1,
    1: 1,
    2: 5}

(в этом примере класс-2 получит более высокий штраф в функции потерь.)

проблема в том, что выход моей сети имеет одну горячую кодировку, т. е. класс-0 = (1, 0, 0), класс-1 = (0, 1, 0), и класс-3 = (0, 0, 1).

как мы можем использовать class_weight для одного горячего кодированные выходные данные?

глядя на некоторые коды в Keras, это выглядит как _feed_output_names содержит список выходных классов, но в моем случае model.output_names/model._feed_output_names возвращает ['dense_1']

по теме: Как установить весы классов для несбалансированных классов в Keras?

4 ответов


немного запутанный ответ, но лучший, который я нашел до сих пор. Это предполагает, что ваши данные являются одним горячим закодированным, многоклассовым и работают только на ярлыках DataFrame df_y:

import pandas as pd
import numpy as np

# Create a pd.series that represents the categorical class of each one-hot encoded row
y_classes = df_y.idxmax(1, skipna=False)

from sklearn.preprocessing import LabelEncoder

# Instantiate the label encoder
le = LabelEncoder()

# Fit the label encoder to our label series
le.fit(list(y_classes))

# Create integer based labels Series
y_integers = le.transform(list(y_classes))

# Create dict of labels : integer representation
labels_and_integers = dict(zip(y_classes, y_integers))

from sklearn.utils.class_weight import compute_class_weight, compute_sample_weight

class_weights = compute_class_weight('balanced', np.unique(y_integers), y_integers)
sample_weights = compute_sample_weight('balanced', y_integers)

class_weights_dict = dict(zip(le.transform(list(le.classes_)), class_weights))

в результате sample_weights вектор, вычисленный для балансировки несбалансированного набора данных, который может быть передан Keras sample_weight собственность, а class_weights_dict которые можно скормить Керасу class_weight собственность в .fit метод. Вы на самом деле не хотите использовать оба, просто выберите один. Я использую class_weight прямо сейчас, потому что это сложно сделать sample_weight работает с fit_generator.


Я думаю, мы можем использовать . Внутри Кераса, на самом деле,class_weights превращается в sample_weights.

sample_weight: необязательный массив той же длины, что и x, содержащий веса, применяемые к потерям модели для каждого образца. В случае временные данные, вы можете передать 2D массив с формой (образцы, sequence_length), чтобы применить другой вес к каждому шагу времени каждый образец. В этом случае обязательно укажите sample_weight_mode= "temporal" в составлять.)(

https://github.com/fchollet/keras/blob/d89afdfd82e6e27b850d910890f4a4059ddea331/keras/engine/training.py#L1392


на _standardize_weights, keras делает:

if y.shape[1] > 1:
    y_classes = y.argmax(axis=1)

таким образом, в основном, если вы решите использовать одну горячую кодировку, классы являются индексом столбца.

вы также можете спросить себя, как вы можете сопоставить индекс столбца с исходными классами ваших данных. Ну, если вы используете класс LabelEncoder scikit learn для выполнения однократного кодирования, индекс столбца отображает порядок unique labels вычислить


вот решение, которое немного короче и быстрее. Если ваш один горячий кодированный y является np.массив:

import numpy as np
from sklearn.utils.class_weight import compute_class_weight

y_integers = np.argmax(y, axis=1)
class_weights = compute_class_weight('balanced', np.unique(y_integers), y_integers)
d_class_weights = dict(enumerate(class_weights))

d_class_weights затем можно передать в class_weight на .fit.