Понимание, когда и когда не следует использовать Softmax в качестве активации выходного слоя - PullRequest
0 голосов
/ 06 мая 2020

Итак, я только начал работать с нейронными сетями и решил создать базовую c сеть классификации изображений с бинарными метками. Исходя из моего понимания нейронных сетей, я подумал, что цель наличия функции активации Softmax в выходном слое состоит в том, чтобы преобразовать входящую информацию в вероятности меток, причем прогнозируемая метка имеет более высокую вероятность. Итак, мой первый вопрос -

  • Почему и как моя модель может повысить свою точность и достаточно хорошо предсказывать без функции активации softmax в выходном слое? (здесь не добавлены выходные изображения, но это правда)
  • Во-вторых, я наблюдаю это странное поведение, когда действительно добавляю Softmax в качестве функции активации в выходной слой. Моя точность проверки застревает на 0,5 для всех эпох. (Точность обучения застряла на уровне 0,813).

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

#Train Data
INPUT_FOLDER = '../input/chest-xray-pneumonia/chest_xray/train/NORMAL'
images = os.listdir(INPUT_FOLDER)
X_train_1 = []
for instance in images:
    image = Image.open('../input/chest-xray-pneumonia/chest_xray/train/NORMAL/' + instance)
    image_rz = image.resize((100,100)).convert('L')
    array = np.array(image_rz)
    X_train_1.append(array)
X_train_1 = np.array(X_train_1)
print(X_train_1.shape)

INPUT_FOLDER = '../input/chest-xray-pneumonia/chest_xray/train/PNEUMONIA'
images = os.listdir(INPUT_FOLDER)
X_train_2 = []
for instance in images:
    image = Image.open('../input/chest-xray-pneumonia/chest_xray/train/PNEUMONIA/' + instance)
    image_rz = image.resize((100,100)).convert('L')
    array = np.array(image_rz)
    X_train_2.append(array)
X_train_2 = np.array(X_train_2)
print(X_train_2.shape)
X_trn = np.concatenate((X_train_1, X_train_2))
print(X_trn.shape)

#Make Labels
y_trn = np.zeros(5216, dtype = str)
y_trn[:1341] = 'NORMAL'
y_trn[1341:] = 'PNEUMONIA'
y_trn = y_trn.reshape(5216,1)

#Shuffle Labels 
X_trn, y_trn = shuffle(X_trn, y_trn)

#Onehot encode categorical labels
onehot_encoder = OneHotEncoder(sparse=False)
y_trn = onehot_encoder.fit_transform(y_trn)

#Model
model = keras.Sequential([
    keras.layers.Flatten(input_shape = (100,100)),
    keras.layers.Dense(256, activation = 'selu'),
    keras.layers.Dense(2, activation = 'softmax')
])

adm = optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, amsgrad=False)

model.compile(optimizer = adm,
              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

for layer in model.layers:
    print(layer, layer.trainable)

model.fit(X_trn, y_trn, validation_data = (X_val, y_val), epochs=30, shuffle = True)



1 Ответ

2 голосов
/ 06 мая 2020

Секрет кроется в вашей функции потерь. Когда вы устанавливаете from_logits=True в своей функции потерь:

loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True) 

, он ожидает, что значения поступают из уровня без активации softmax, поэтому он сам выполняет операцию softmax. Если у вас уже есть функция softmax в вашем последнем слое, вам не следует устанавливать from_logits на True, установите его на False.

Ваша модель хорошо работает без функции softmax и по этой причине плохо работает с функцией softmax.

...