Нейронная сеть Keras, предсказывающая тот же результат

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

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

Вопрос:

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

Я решил начать с самого простого способа его прогнозирования — с сети, аналогичной логистической регрессии — один скрытый слой с одним нейроном и добился плохого, но хоть какого-то результата — 0,12-0,14 балла F1. Затем я попробовал использовать 2 скрытых и 1 выходной слои с разным количеством нейронов в первом скрытом слое — от 1 до 8. Оказывается, что в некоторых случаях он что-то изучает, а в некоторых прогнозирует один и тот же результат для каждого образца. Я отобразил функцию точности и потерь за эпохи, и это то, что я получаю:

Функция потерь сети по эпохам. Понятно, что функция потерь имеет примерно одинаковое значение для обучающих данных.

Точность сети по эпохам. Понятно, что точность не улучшается, а колеблется от 0 до 1

Я искал похожие вопросы, и предложения были следующими:

  1. Сделайте больше нейронов — мне просто нужно заставить его работать с 1, 2 или более нейронами в первом слое, поэтому я не могу добавить нейроны к этому. Я увеличил количество нейронов во втором скрытом слое до 20, но затем он перестал предсказывать что-либо с любым количеством нейронов в конфигурации первого слоя.
  2. Создайте больше слоев — я попытался добавить еще один слой, но все та же проблема
  3. Чтобы ввести отсев и увеличить его — о каком отсеве мы говорим, если он может учиться только с одним слоем и одним нейроном в нем
  4. Уменьшить скорость обучения — уменьшил ее с 10 ^ (-3) по умолчанию до 10 ^ (-4)
  5. Уменьшите размер пакета — измените его с 500 выборок в мини-пакете до 1 (стохастический градиентный спуск)
  6. Больше эпох — разве недостаточно от 20 до 50 эпох для выборки из 500 000 наборов данных?

Вот модель:

     
def run_nn_class_weights(data, labels, model):
    n_iter = 20
    predicted = None
    true = None

    print('Splitting the data')
    x_train, x_valid, y_train, y_valid = train_test_split(data, labels, test_size = 0.05)

    #model = create_model()
    early_stopping_monitor=EarlyStopping(patience=240)
    class_weights = class_weight.compute_class_weight('balanced',
                                             np.unique(labels),
                                             labels)

    class_weights = dict(enumerate(class_weights))

    hist = model.fit(x_train, y_train, validation_data=[x_valid, y_valid], class_weight=class_weights, 
                            epochs=n_iter, batch_size=500, shuffle=True, callbacks=[early_stopping_monitor],verbose=1)


    proba = model.predict(data)
    predicted = proba.flatten()
    true = labels

    return(model, proba, hist)


def old_model_n_pred(n_neurons_1st = 1):
    model = Sequential()
    
    model.add(Dense(n_neurons_1st, activation='relu', input_shape=(7516,), kernel_initializer='glorot_normal'))
    model.add(Dense(8, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    
    #model.add(Flatten())
    
    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])
    return model
  

Комментарии:

1. Ваш набор данных был нормализован?

2. С вашими ярлыками что-то не так. Являются ли тестовые данные только одним классом? Ваша точность увеличивается с 0 до 100 и обратно до 0 каждую эпоху

Ответ №1:

Это небольшая сеть, которая должна быть способна сходиться к чему-то, что не является atractor (застревание на одном значении).

Я предлагаю взглянуть на веса всех нейронов с активацией ReLU. RELU хороши тем, что позволяют выполнять быстрые вычисления; но половина relu имеет производную от нуля, что не помогает при градиентном спуске. Это может быть ваш случай.

В предположении, что в вашем случае врагом будет первый нейрон.

Чтобы преодолеть эту проблему, я бы попытался упорядочить входные данные (чтобы все выборки были сосредоточены вокруг 0,5 и масштабировались по стандартному отклонению). Если вы сделаете это с ReLU, вы заставите его игнорировать все, что находится между [-inf, sd] .

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

Кроме того, внимательно посмотрите на свое распределение входных данных. На самом деле ваша сеть выполняет сигмоидальную классификацию, затем использует от 4 до 8 нейронов для «масштабирования» / исправления важных частей функции, которые не учитывало первое преобразование.