Используйте нейронную сеть для изучения распределения значений для классификации

#python #tensorflow #machine-learning #keras #neural-network

#python #тензорный поток #машинное обучение #keras #нейронная сеть

Вопрос:

Используйте нейронную сеть для изучения распределения значений для классификации

Цель состоит в том, чтобы классифицировать одномерные входные данные с использованием нейронной сети. Есть два класса, которые следует классифицировать, A и B . Каждый входной сигнал, используемый для определения класса, представляет собой число между 0.0 и 1.0 .

Входные значения для class A равномерно распределены между 0 и 1 вот так: распределение класса A

Все входные значения для class B находятся в диапазоне от 0.4 до 0.6 примерно так:

распределение класса B

Теперь я хочу обучить нейронную сеть, которая может научиться классифицировать значения в диапазоне от 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 является ключевым. Огромное спасибо.