Используйте нейронную сеть, чтобы узнать распределение значений для классификации - PullRequest
1 голос
/ 24 апреля 2019

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

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

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

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

class B distribution

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

2 голосов
/ 24 апреля 2019

Здесь можно изменить некоторые вещи в архитектуре вашей модели.

Во-первых, потери не должны быть 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% точности в наборе валидации, и каждая эпоха уменьшает потери.

(С другой стороны, мне кажется, что дерево решенийздесь будет лучше подходить, поскольку он будет вести себя точно так же, как вы описали для выполнения классификации)

...