Я пытаюсь создать DNNClassifier для данных с 2 классами, но с несбалансированными данными. Я использую class_weight для увеличения потерь для низкочастотного класса во время тренировки.

classifier = tf.contrib.learn.DNNClassifier(
  feature_columns=feature_columns,                                              
  hidden_units=[220, 100, 10],
  n_classes=2,
  dropout=0.5,
  weight_column_name="class_weight",
  model_dir="./tf_model"
)
classifier.fit(input_fn=get_train_inputs, steps=500)

Однако DNNClassifier также должен быть установлен class_weight для метода прогнозирования. Какой class_weight я могу предоставить для свежих данных, которые я прохожу через модель для классификации?

Спасибо, -Прасад

1
Prasad 27 Май 2017 в 18:57

2 ответа

Лучший ответ

Это не тот ответ, на который вы или я бы надеялись, но требование, чтобы столбец tf.contrib.learn.DNNClassifier weight_column_name был признаком модели, фактически делает параметр совершенно бесполезным.

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

Результат таков:

  • Чтобы DNNClassifier использовал weight_column_name, это должен быть один из признаков модели.

  • Если это элемент, определенный в модели при обучении модели, это должен быть элемент, определенный в модели при тестировании модели, а также элемент, определенный в модели, когда модель используется для прогнозов.

Сначала я попробовал свой тестовый набор с присутствующим столбцом и, конечно, получил точность 99,96%, потому что обучение научилось соотносить значение столбца веса с меткой. (Я был в приподнятом настроении около 30-х годов ... и после этого провел несколько минут, злобно швыряясь.)

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

Object was never used (type <class 'tensorflow.python.framework.ops.Tensor'>):
<tf.Tensor 'report_uninitialized_variables_1/boolean_mask/Gather:0' shape=(?,) dtype=string>
If you want to mark it as used call its "mark_used()" method.

Я был заинтригован битом mark_used(), поэтому я попытался сделать это:

tf.contrib.layers.real_valued_column("outcome_class_weight").mark_used()

... но, видимо, это был не Тензор, на который ссылалась ошибка, так как я получил ошибку, AttributeError: '_RealValuedColumn' object has no attribute 'mark_used'

Чувствуя, что этот параметр представляет собой бездонную кроличью нору, кажется, что единственными способами устранения дисбаланса класса являются:

  1. Для каждой строки в наборе тестов и для прогнозов используйте значение для столбца weight_column_name, которое находится посередине между значением, используемым каждым из 2 классов. Или значение, которое является средним значением всех значений для всех классов. Я собираюсь попробовать это в первую очередь, но я сомневаюсь, что буду придерживаться этого в течение длительного времени, если это не приведет к улучшению воспоминания: это похоже на грубый удар

  2. Перейдите к низкоуровневому API и спроектируйте функцию потерь вручную. Это звучит довольно болезненно для меня, как новичка в TensorFlow, и будет последним средством. С другой стороны, как только я стану более легким с TensorFlow, я могу удивиться, почему я все еще возиться с высокоуровневым API.

  3. Основываясь на комментариях этого Tensor Flow Issue, выясните, как включить взвешивание класса только в InputFn, но никак не в саму модель. Я не уверен, что на самом деле правильно понимаю эти комментарии, поэтому, подумав и погуглив, я подозреваю, что в конечном итоге мне придется отказаться от этого подхода с пустыми руками.

  4. Превышение выборки неадекватно представленного класса (мое предпочтение) или занижение выборки широко представленного класса. Я сильно подозреваю, что возьму этот курс на долгий срок просто потому, что я уже знаю, как сделать это достаточно хорошо. (Я все еще обижен на это, поскольку взвешивание классов кажется менее подверженным ошибкам, чем недостаточная или избыточная выборка.)

=== Обновление ===

  • Я попробовал вариант 1. Он потопил все метрики. Мораль истории: вы не можете использовать линейное решение для нелинейной модели.

  • Вариант 3 был моим недоразумением. Если вы определяете объект-заполнитель для модели, функция ввода должна предоставлять данные для этого объекта, точка.

Итак, сейчас я собираюсь пересмотреть мой плохо представленный класс.

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

Также на этих выходных я напишу код для дополнительных комментариев в ветке github.

2
aec 20 Сен 2017 в 21:48

Это не вопрос программирования, а ответ:

По-разному.

Вы должны решить это.

Одним из простых подходов может быть установка веса класса обратно пропорционально количеству выборок, помеченных этим классом в вашем наборе данных.

0
onur güngör 27 Май 2017 в 16:09