tf.losses.log_loss для нескольких классов - PullRequest
0 голосов
/ 28 октября 2018

Я протестировал tf.losses.log_loss с проблемой двоичной классификации по сравнению с реализацией numpy и реализацией sklearn, выглядит хорошо:

# Array of samples
y_pred_arr = np.array([0.6,0.3,0.9], np.float32)
y_true_arr = np.array([1,0,1], np.float32)

print('y_pred_arr.shape', y_pred_arr.shape)
print('y_true_arr.shape', y_true_arr.shape)

# 1 : Implemented in numpy
def cross_entropy_loss(y_pred_arr, y_true_arr, eps=1e-6):
    p_arr = np.clip(y_pred_arr, eps, 1 - eps)
    n_samples = p_arr.shape[0]
    loss_arr = np.zeros((n_samples,), np.float32)
    for i in range(n_samples):        
        if y_true_arr[i] == 1:
            loss_arr[i] = -np.log(p_arr[i])
        else:
            loss_arr[i] = -np.log(1 - p_arr[i])
    loss = np.mean(loss_arr)
    return loss
loss = cross_entropy_loss(y_pred_arr, y_true_arr)
print(loss)

# 2 : Implemented in sklearn
from sklearn.metrics import log_loss
loss = log_loss(y_true_arr, y_pred_arr, labels=[0,1], eps=1e-6)
print(loss)

# 3 : Impemented in tensorflow using tf.losses.log_loss
y_pred_tf = tf.convert_to_tensor(y_pred_arr, np.float32)
y_true_tf = tf.convert_to_tensor(y_true_arr, np.float32)
loss_tf = tf.losses.log_loss(labels=y_true_tf, predictions=y_pred_tf, epsilon=1e-6)
with tf.Session() as sess:
    loss = sess.run(loss_tf)
    print(loss)

Вывод:

y_pred_arr.shape (3,)
y_true_arr.shape (3,)
0.32428703
0.3242870296041171
0.32428563

Но для результатов задачи мультиклассабывают разные:

# Array of samples
y_pred_arr = np.array([[0.4,0.3,0.3], [1.0,0.0,0.0], [0.0,0.0,1.0]], np.float32)
y_true_arr = np.array([[1,0,0], [1,0,0], [0,0,1]], np.float32)

print('y_pred_arr.shape', y_pred_arr.shape)
print('y_true_arr.shape', y_true_arr.shape)

# 1 : Implemented in numpy
def cross_entropy_loss(y_pred_arr, y_true_arr, eps=1e-6):
    p_arr = np.clip(y_pred_arr, eps, 1 - eps)
    n_samples = p_arr.shape[0]
    n_classes = p_arr.shape[1]
    loss_arr = np.zeros((n_samples,), np.float32)
    for i in range(n_samples):
        for c in range(n_classes):
            loss_arr[i] += -y_true_arr[i][c] * np.log(p_arr[i][c])
    loss = np.mean(loss_arr)
    return loss
loss = cross_entropy_loss(y_pred_arr, y_true_arr)
print(loss)

# 2 : Implemented in sklearn
from sklearn.metrics import log_loss
loss = log_loss(np.argmax(y_true_arr,axis=1), y_pred_arr, labels=[0,1,2], eps=1e-6)
print(loss)

# 3 : Impemented in tensorflow using tf.losses.log_loss
y_pred_tf = tf.convert_to_tensor(y_pred_arr, np.float32)
y_true_tf = tf.convert_to_tensor(y_true_arr, np.float32)
loss_tf = tf.losses.log_loss(labels=y_true_tf, predictions=y_pred_tf, epsilon=1e-6)
with tf.Session() as sess:
    loss = sess.run(loss_tf)
    print(loss)

Вывод:

y_pred_arr.shape (3, 3)
y_true_arr.shape (3, 3)
0.30543092
0.30543154478209544
0.18106996

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Как упомянуто @functor tf.losses.log_loss для двоичной кроссентропии, вы можете проверить исходный код здесь: https://github.com/tensorflow/tensorflow/blob/r1.1/tensorflow/python/ops/losses/losses_impl.py#L309

Также https://github.com/tensorflow/tensorflow/issues/2462

Вот пример:

# Array of samples
y_pred_arr = np.array([[0.4,0.3,0.3], [1.0,0.0,0.0], [0.0,0.0,1.0]], np.float32)
y_true_arr = np.array([[1,0,0], [1,0,0], [0,0,1]], np.float32)

print('y_pred_arr.shape', y_pred_arr.shape)
print('y_true_arr.shape', y_true_arr.shape)

# 1 : Implemented in numpy
def cross_entropy_loss(y_pred_arr, y_true_arr, eps=1e-6):
    p_arr = np.clip(y_pred_arr, eps, 1 - eps)
    n_samples = p_arr.shape[0]
    n_classes = p_arr.shape[1]
    loss_arr = np.zeros((n_samples,), np.float32)
    for i in range(n_samples):
        for c in range(n_classes):
            loss_arr[i] += -y_true_arr[i][c] * np.log(p_arr[i][c])
    loss = np.mean(loss_arr)
    return loss
loss = cross_entropy_loss(y_pred_arr, y_true_arr)
print(loss)

# 2 : Implemented in sklearn
from sklearn.metrics import log_loss
loss = log_loss(np.argmax(y_true_arr,axis=1), y_pred_arr, labels=[0,1,2], eps=1e-6)
print(loss)

# 3 : Implemented in tensorflow
y_pred_tf = tf.convert_to_tensor(y_pred_arr, np.float32)
y_true_tf = tf.convert_to_tensor(y_true_arr, np.float32)
eps = 1e-6
cliped_y_pref_tf = tf.clip_by_value(y_pred_tf, eps, 1-eps)
loss_tf = tf.reduce_mean(-tf.reduce_sum(y_true_tf * tf.log(cliped_y_pref_tf), axis=1))
with tf.Session() as sess:
    loss = sess.run(loss_tf)
    print(loss)

Вывод:

y_pred_arr.shape (3, 3)
y_true_arr.shape (3, 3)
0.30543092
0.30543154478209544
0.30543092
0 голосов
/ 28 октября 2018

tf.losses.log_loss работает только для двоичных классов.Для потери мультикласса вам нужно вычислить вручную,

как:

cliped_y_pref_tf = tf.clip_by_value(y_pred_tf, eps, 1-eps)
loss_tf = tf.reduce_sum(tf.multiply(-y_true_tf,tf.log(cliped_y_pref_tf )))/len(y_pred_arr)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...