I'm trying to add various simple metrics for each class. tf.keras.metrics.TruePositives, tf.keras.metrics.Precision ... This results in crash bellow when last Dense layer is two or more.
InvalidArgumentError: Incompatible shapes: [2,128] vs. [2,64]
[[{{node metrics_12/fp/LogicalAnd}}]]
It works if I only use accuracy as metric. I am pretty sure I'm missing something fundamental. As I am but a dilettante when it come to TensorFlow and Deep Learning. What am I doing wrong? How do I get metrics for each class (True/False positives/negatives mainly)? (Sample code only has 0,1 classes, in real app there are more)
Colab link: https://colab.research.google.com/drive/1aAz1pfN6ttBp8nU6rZgo8OA_Hwdseyg8
#%%
from typing import List, Set, Dict, Tuple, Optional, Any
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, BatchNormalization, CuDNNLSTM, LSTM, Flatten
#%%
# Create random training values for demo purposes.
#
# train_x is [
# [
# [0.3, 0.54 ... 0.8],
# [0.4, 0.6 ... 0.55],
# ...
# ],
# [
# [0.3, 0.54 ... 0.8],
# [0.4, 0.6 ... 0.55],
# ...
# ],
# ...
# ]
#
# train_y is corresponding classification of train_x sequences, always 0 or 1
# [0, 1, 0, 1, 0, ... 0]
SAMPLES_CNT = 1000
train_x = np.random.rand(SAMPLES_CNT,5,4)
train_y = np.vectorize(lambda x: int(round(x)))(np.random.rand(SAMPLES_CNT))
val_x = np.random.rand(int(SAMPLES_CNT * 0.1),5,4)
val_y = np.vectorize(lambda x: int(round(x)))(np.random.rand(int(SAMPLES_CNT * 0.1)))
#%%
shape = Tuple[int, int]
model = Sequential()
model.add(LSTM(32,input_shape=train_x.shape[1:], return_sequences=True, stateful=False))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(LSTM(32,input_shape=train_x.shape[1:], return_sequences=False, stateful=False))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Dense(16, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(2, activation="softmax"))
metrics = [
'accuracy',
tf.keras.metrics.TruePositives(name='tp'),
tf.keras.metrics.FalsePositives(thresholds=[0.5, 0.5], name='fp'),
tf.keras.metrics.TrueNegatives(name='tn'),
tf.keras.metrics.FalseNegatives(name='fn'),
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc'),
]
model.compile(
optimizer=tf.keras.optimizers.Adam(lr=0.001, decay=1e-6),
loss='sparse_categorical_crossentropy',
metrics=metrics
)
fit = model.fit(
train_x, train_y,
batch_size=64,
epochs=2,
validation_data=(val_x, val_y),
shuffle=False,
)
for i, val in enumerate(model.metrics_names):
print(model.metrics_names[i], fit.history[val][:1])
Some of these metrics are supposed to work with one class only.
You need Dense(1, activation='sigmoid') and 'binary_crossentropy'.
Notice that these two problems are exactly the same:
Dense(1, activation='sigmoid'), with loss='binary_crossentropy' Dense(2, activation='softmax'), with loss='sparse_categorical_crossentropy'If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With