Сколько нейронов должно быть в последнем слое нейронной сети?

#python #tensorflow #machine-learning #keras

#python #tensorflow #машинное обучение #keras

Вопрос:

Я использую следующий код для классификации обзоров фильмов на три класса (отрицательные как -1, нейтральные как 0 и 1 как положительные). Но правда ли, что в последнем слое есть только один выходной нейрон для задачи классификации трех классов?

 import tensorflow as tf
import numpy as np
import pandas as pd
import numpy as K

csvfilename_train = 'train(cleaned).csv'
csvfilename_test = 'test(cleaned).csv'

# Read .csv files as pandas dataframes
df_train = pd.read_csv(csvfilename_train)
df_test = pd.read_csv(csvfilename_test)

train_sentences  = df_train['Comment'].values
test_sentences  = df_test['Comment'].values

# Extract labels from dataframes
train_labels = df_train['Sentiment'].values
test_labels = df_test['Sentiment'].values

vocab_size = 10000
embedding_dim = 16
max_length = 30
trunc_type = 'post'
oov_tok = '<OOV>'

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

tokenizer = Tokenizer(num_words = vocab_size, oov_token = oov_tok)
tokenizer.fit_on_texts(train_sentences)
word_index = tokenizer.word_index
sequences = tokenizer.texts_to_sequences(train_sentences)
padded = pad_sequences(sequences, maxlen = max_length, truncating = trunc_type)

test_sequences = tokenizer.texts_to_sequences(test_sentences)
test_padded = pad_sequences(test_sequences, maxlen = max_length)

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length = max_length),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(6, activation = 'relu'),
    tf.keras.layers.Dense(1, activation = 'sigmoid'),
])
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])

num_epochs = 10
model.fit(padded, train_labels, epochs = num_epochs, validation_data = (test_padded, test_labels))
  

Когда я меняю tf.keras.layers.Dense(1, activation = 'sigmoid') на tf.keras.layers.Dense(2, activation = 'sigmoid') , это выдает мне следующую ошибку:

 ---> 10 model.fit(padded, train_labels, epochs = num_epochs, validation_data = (test_padded,test_labels))
     ValueError: logits and labels must have the same shape ((None, 2) vs (None, 1))
  

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

1. вам нужно иметь столько выходных данных, сколько у вас разных классов (т. Е. 3). ошибка, которую вы получаете, заключается в том, что ваши метки не совпадают с вашими выходными данными. итак, сначала соответствующим образом закодируйте свои метки (то есть у каждого класса должна быть отдельная метка)

2. Спасибо! @Rika. Вы имеете в виду, что я должен изменить метки на что-то вроде [0,0,1], [0,1,0], [1,0,0]?

Ответ №1:

У вас должно быть 3 нейрона, если вы классифицируете между 3 категориями.

Кроме того, вы должны использовать 'softmax' активацию для вашего последнего слоя, предполагая, что все наблюдения относятся только к одному классу.

Далее, вы должны использовать 'sparse_categorical_crossentropy' , поскольку ваш ввод не является одноразовым кодированием. Такие цели, как [0,0,1], [0,1,0], [1,0,0] необязательны, вы также можете иметь [1, 2, 0, 1, 2, 1, 0] .

Наконец, ваши цели должны быть [0, 1, 2] , а не [-1, 0, 1] поэтому я предлагаю вам добавить 1 к вашим меткам.

 test_labels = df_test['Sentiment'].values   1
  

Это то, что происходит, если метки [-1, 0, 1] вместо [0, 1, 2] :

 import tensorflow as tf

sparse_entropy = tf.losses.SparseCategoricalCrossentropy()

a = tf.convert_to_tensor([[-1., 0., 1.]]) #  1
b = tf.convert_to_tensor([[.4, .2, .4], [.1, .7, .2], [.8, .1, .1]])

sparse_entropy(a, b)
  
 nan
  

Если вы раскомментируете 1 , который преобразует метки в [0, 1, 2] , это сработает:

 <tf.Tensor: shape=(), dtype=float32, numpy=1.1918503>
  

Ответ №2:

Краткий ответ:

Один горячий кодирует ваши метки поездов и использует категориальную кроссэнтропию в качестве функции потерь.

Причина:

  1. Ваши логиты имеют форму (n, 2), а метки — (n, 1).
  2. Ваши логины и метки должны иметь форму (n, 3), если вы используете кроссэнтропию (если только она не разреженная).

Решение:

  1. Одно горячее кодирование меток поездов, и вы получите форму меток поездов (n, 3)
  2. Используйте категориальную кроссэнтропию с конечным плотным нейроном, имеющим 3 выхода, тогда вы получите логическую форму (n, 3)

После этого ваша модель начнет обучение.

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

1. Это не всегда True . Их метки не являются одноразовыми, но они все еще могут использовать потерю кроссэнтропии. Также возникнет другая проблема, смотрите внизу моего ответа.

2. Я предположил, что sparse_categorical_entropy обычно не используется, поэтому я проигнорировал его. Спасибо за исправление

Ответ №3:

У вас есть 3 класса -> num_classes=3 Ваш последний слой должен выглядеть следующим образом:

 tf.keras.layers.Dense(num_classes, activation = 'sigmoid'),
  

На выходе вы получите np.array с 3 вероятностями. Более того, вам следует изменить свой класс на categorical_crossentropy, потому что вы не решаете двоичную задачу.

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

1. Спасибо! @MareSeestern. Но, как я уже сказал, когда я меняю num_classes на более чем один, это выдает ошибку.

2. Да, какая ошибка выдает это? Вы изменили свою функцию потерь?