#python #tensorflow #machine-learning #keras #neural-network
#python #тензорный поток #машинное обучение #keras #нейронная сеть
Вопрос:
Используйте нейронную сеть для изучения распределения значений для классификации
Цель состоит в том, чтобы классифицировать одномерные входные данные с использованием нейронной сети. Есть два класса, которые следует классифицировать, A
и B
. Каждый входной сигнал, используемый для определения класса, представляет собой число между 0.0
и 1.0
.
Входные значения для class A
равномерно распределены между 0
и 1
вот так:
Все входные значения для class B
находятся в диапазоне от 0.4
до 0.6
примерно так:
Теперь я хочу обучить нейронную сеть, которая может научиться классифицировать значения в диапазоне от 0.4
до 0.6
как B
, а остальные как A
. Итак, мне нужна нейронная сеть, которая может аппроксимировать верхнюю и нижнюю границы класса. Мои предыдущие попытки сделать это были безуспешными — нейронная сеть всегда возвращает вероятность 50% для любого ввода по всем направлениям, и потери не уменьшаются в течение эпох.
Используя Tensorflow и Keras в Python, я обучил простые модели, такие как следующие:
model = keras.Sequential([
keras.layers.Dense(1),
keras.layers.Dense(5, activation=tf.nn.relu),
keras.layers.Dense(5, activation=tf.nn.relu),
keras.layers.Dense(2, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])
(полный сценарий обучения, связанный ниже)
Кстати, я бы предположил, что нейронная сеть работает следующим образом: некоторые нейроны срабатывают только ниже 0,4, некоторые только выше 0,6. Если какая-либо из этих групп нейронов срабатывает, это класс A
, если ни один из них не срабатывает, это класс B
. К сожалению, это не то, что происходит.
Как можно классифицировать входные данные, описанные выше, с использованием нейронных сетей?
—
Пример сценария:https://pastebin.com/xNJUqXyU
Ответ №1:
Здесь можно изменить несколько вещей в архитектуре вашей модели.
Во-первых, потерь не должно быть loss='mean_squared_error'
, лучше использовать loss='binary_crossentropy'
, который лучше подходит для задач бинарной классификации. Я не буду здесь объяснять разницу, это то, что можно легко найти в документации Keras.
Вам также необходимо изменить определение вашего последнего слоя. Вам нужно иметь только один последний узел, который будет вероятностью принадлежности к классу 1 (следовательно, наличие узла для вероятности принадлежности к классу 0 является избыточным), и вы должны использовать activation=tf.nn.sigmoid
вместо softmax .
Что-то еще, что вы можете сделать, это определить веса классов, чтобы справиться с дисбалансом ваших данных. Похоже, что, учитывая, как вы определяете свой образец здесь, взвешивание класса 0 в 4 раза больше, чем класс 1, имело бы смысл.
Как только все эти изменения будут внесены, у вас должно остаться что-то похожее на это:
model = keras.Sequential([
keras.layers.Dense(1),
keras.layers.Dense(5, activation=tf.nn.relu),
keras.layers.Dense(5, activation=tf.nn.relu),
keras.layers.Dense(1, activation=tf.nn.sigmoid)
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(np.array(inputs_training), np.array(targets_training), epochs=5, verbose=1, class_weight = {0:4, 1:1})
Это дает мне точность 96% в наборе проверки, и каждая эпоха уменьшает потери.
(С другой стороны, мне кажется, что здесь гораздо лучше подходит дерево решений, поскольку оно будет вести себя так, как вы описали для выполнения классификации)
Комментарии:
1. Ты абсолютный герой! Все эти улучшения необходимы и очень полезны, особенно параметр class_weight является ключевым. Огромное спасибо.