Вопрос или проблема
Я обучаю CNN, она работает хорошо, но я получаю ошибку, когда пытаюсь получить precision_score
, recall_score
и f1_score
. Вот фрагмент моего кода;
# Следующий шаг - разделить обучающие и тестовые данные. Для этого мы будем использовать функцию sklearn train_test_split().
features_train, features_test, labels_train, labels_test = train_test_split(features, labels, test_size=.2)
features_train.shape, features_test.shape, labels_train.shape, labels_test.shape
((180568, 2677356), (45143, 2677356), (180568,), (45143,))
features_train.shape[0], features_train.shape[1], labels_train.shape[0]
(180568, 2677356, 180568)
n_timesteps, n_features, n_outputs = features_train.shape[0], features_train.shape[1], labels_train.shape[0]
X_train = np.zeros((180568, 82, 1))
y_train = np.zeros((180568, 82))
n_timesteps, n_features, n_outputs = X_train.shape[1], X_train.shape[2], y_train.shape[1]
n_samples = 1000
X = np.random.uniform(0,1, (n_samples, n_timesteps, n_features))
y = pd.get_dummies(np.random.randint(0,n_outputs, n_samples)).values
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(input_shape=(n_timesteps, n_features), activation='relu', kernel_size=2, filters=32),
tf.keras.layers.MaxPooling1D(strides=3),
#tf.nn.local_response_normalization((1, 1, 1, 1), depth_radius=5, bias=1, alpha=1, beta=0.5, name=None),
tf.keras.layers.LayerNormalization(axis=1),
tf.keras.layers.Conv1D(input_shape=(n_timesteps, n_features), activation='relu', kernel_size=2, filters=64),
tf.keras.layers.MaxPooling1D(strides=3), # также GlobalMaxPooling1D() нормально
tf.keras.layers.LayerNormalization(axis=1),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(n_outputs, activation='softmax')
])
model.compile('adam', 'binary_crossentropy', metrics=['accuracy'])
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d (Conv1D) (None, 81, 32) 96
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 27, 32) 0
_________________________________________________________________
layer_normalization (LayerNo (None, 27, 32) 54
_________________________________________________________________
conv1d_1 (Conv1D) (None, 26, 64) 4160
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 9, 64) 0
_________________________________________________________________
layer_normalization_1 (Layer (None, 9, 64) 18
_________________________________________________________________
flatten (Flatten) (None, 576) 0
_________________________________________________________________
dense (Dense) (None, 82) 47314
=================================================================
Total params: 51,642
Trainable params: 51,642
Non-trainable params: 0
history = model.fit(X_train, y_train, epochs=10, verbose=1, validation_data=(X, y))
Train on 180568 samples, validate on 1000 samples
Epoch 1/10
180568/180568 [==============================] - 130s 718us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0695 - val_acc: 0.9878
Epoch 2/10
180568/180568 [==============================] - 128s 707us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0695 - val_acc: 0.9878
Epoch 3/10
180568/180568 [==============================] - 101s 561us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0695 - val_acc: 0.9878
Epoch 4/10
180568/180568 [==============================] - 77s 426us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0694 - val_acc: 0.9878
Epoch 5/10
180568/180568 [==============================] - 75s 413us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0694 - val_acc: 0.9878
Epoch 6/10
180568/180568 [==============================] - 75s 418us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0694 - val_acc: 0.9878
Epoch 7/10
180568/180568 [==============================] - 113s 624us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0694 - val_acc: 0.9878
Epoch 8/10
180568/180568 [==============================] - 109s 602us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0694 - val_acc: 0.9878
Epoch 9/10
180568/180568 [==============================] - 115s 639us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0693 - val_acc: 0.9878
Epoch 10/10
180568/180568 [==============================] - 129s 716us/sample - loss: 0.0123 - acc: 1.0000 - val_loss: 0.0693 - val_acc: 0.9878
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
print("Precision: %f "%precision_score(y_train, pred)) <---- Здесь я получаю ошибку
print("Recall: %f "%recall_score(y_train, pred))
print("F1: %f"% f1_score(y_train, history))
Ошибка, которую я получил;
TypeError: Expected sequence or array-like, got <class 'tensorflow.python.keras.callbacks.History'>
Вы используете переменную pred
для расчета своих метрик, что не сработает, поскольку pred
является объектом обратного вызова. Прогнозы от модели не сохраняются во время обучения модели, только метрики вашей модели (например, потери и точность) сохраняются с использованием объекта обратного вызова истории. Если вы хотите получить предсказанный вывод для образцов, вы можете использовать метод model.predict
. Это вернёт массив numpy предсказанного вывода от вашей модели, который затем вы можете использовать в своих метрик.
Измените свой код на этот.
pred = model.predict(X_train)
print("Precision: %f "%precision_score(y_train, pred))
print("Recall: %f "%recall_score(y_train, pred))
print("F1: %f"% f1_score(y_train, pred))
Проблема в том, что вы обучаете модель, но не сделали прогнозы, чтобы сравнить их с истинными значениями. Вам сначала нужно сделать прогнозы с помощью метода model.predict(), а затем вы можете сравнить pred и y_train.
Ответ или решение
Ошибка TypeError: Expected sequence or array-like, got <class 'tensorflow.python.keras.callbacks.History'>
, с которой вы столкнулись во время вычисления метрик (таких как precision_score
, recall_score
и f1_score
), указывает на неправильное использование переменной pred
. В данном случае pred
– это объект истории (history callback), который не содержит предсказаний от вашей модели.
Основная проблема
Во время обучения модели с помощью метода fit
запоминаются только метрики, такие как потери (loss) и точность (accuracy), но не предсказания на обучающей или валидационной выборках. Чтобы получить предсказания, необходимо использовать метод predict
вашей модели.
Решение
Вам нужно заменить строку с вычислением метрик следующим образом:
- Используйте метод
model.predict()
для получения предсказаний для обучающих данных. - Преобразуйте эти предсказания, чтобы они соответствовали ожидаемому формату для метрик (например, преобразуйте вероятности в классы).
- Затем примените функции метрик к результатам.
Вот обновлённый код:
# Получаем предсказания от модели
pred_probs = model.predict(X_train)
# Если ваше выходное значение - это вероятности (например, в бинарной классификации),
# вам нужно преобразовать их в классы.
pred = np.argmax(pred_probs, axis=1) # Для многоклассовой классификации
# или для бинарной классификации можно использовать:
# pred = (pred_probs > 0.5).astype(int)
# Теперь вы можете вычислить метрики
print("Precision: %f "% precision_score(labels_train, pred, average='weighted'))
print("Recall: %f "% recall_score(labels_train, pred, average='weighted'))
print("F1: %f "% f1_score(labels_train, pred, average='weighted'))
Дополнительные Замечания
-
Формат выходных данных: Важно убедиться, что предсказания и истинные метки имеют одинаковую размерность и формат. Убедитесь, что
labels_train
имеют ту же форму, что иpred
. Если вы работаете с многоклассовой классификацией, используйтеnp.argmax
для получения меток из вероятностей (например, результирующий массив предсказаний имеет форму(n_samples, n_classes)
). -
Параметр average: В функциях
precision_score
,recall_score
, иf1_score
, параметрaverage
отвечает за то, как комбинировать метрики для разных классов. Вы можете установить значениеaverage
в'micro'
,'macro'
или'weighted'
, в зависимости от ваших требований и целей анализа. -
Отладка: Если возникнут дополнительные ошибки, полезно будет вывести форму массива
pred
иlabels_train
, чтобы удостовериться, что они соответствуют друг другу.
Следуя этим рекомендациям, вы сможете правильно вычислить необходимые метрики для вашей модели и устранить ошибку, приведшую к возникновению TypeError.