Простая модель, использующая TenorFlow 2 API, дает огромные потери и значения Acc - PullRequest
2 голосов
/ 18 марта 2019
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler


df = pd.DataFrame({'A': np.array([100, 105.4, 108.3, 111.1, 113, 114.7, 120, 125, 129]),
                   'B': np.array([11, 11.8, 12.3, 12.8, 13.1,13.6, 13.9, 14.4, 15]),
                   'C': np.array([55, 56.3, 57, 58, 59.5, 60.4, 61, 61.5, 62]),
                   'Target': np.array([4000, 4200.34, 4700, 5300, 5800, 6400, 6800, 7200, 7500])})

df.head()

X_train = df.iloc[:, :3]
y_train = df.iloc[:, 3]

scaler = StandardScaler()
scaler.fit(X_train)
X_train_std = scaler.transform(X_train)

features = {'A': X_train_std[:, 0],
            'B': X_train_std[:, 1],
            'C': X_train_std[:, 2]}

labels = y_train


batch_size = 1
def train_input_fn(features, labels, batch_size):
    train_dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
    train_dataset = train_dataset.shuffle(1).batch(batch_size)
    return train_dataset


def pack_features_vector(features, labels):
    '''Pack the features into a single array'''
    features = tf.stack(list(features.values()), axis=1)
    return features, labels


train_dataset = train_input_fn(features, labels, batch_size).map(pack_features_vector)


class Model(tf.keras.Model):

    def __init__(self):
        super().__init__()

        self.l1 = tf.keras.layers.Dense(8, activation='relu')
        self.l2 = tf.keras.layers.Dense(4, activation='relu')
        self.out = tf.keras.layers.Dense(1)

    def call(self, x):
        x = self.l1(x)
        x = self.l2(x)
        return self.out(x)


learning_rate = 0.1
optimizer = tf.keras.optimizers.RMSprop(learning_rate)
loss_object = tf.keras.losses.MeanSquaredError()


train_loss_res = []
train_acc_res = []
epochs = 100
model = Model()

for epoch in range(epochs):
    epoch_loss_avg = tf.keras.metrics.Mean()
    epoch_acc = tf.keras.metrics.MeanAbsoluteError()

    for x,y in train_dataset:
        with tf.GradientTape() as tape:
            y_ = model(x)
            loss = loss_object(y, y_)
        gradients = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))

        epoch_loss_avg(loss)
        epoch_acc(y, y_)

    train_loss_res.append(epoch_loss_avg.result())
    train_acc_res.append(epoch_acc.result())

    if epoch % 10 == 0:
        print("Epoch {:03d} Loss: {:.3f}, Acc: {:.3%}".format(epoch, epoch_loss_avg.result(), epoch_acc.result()))

Я использую простые данные и простую модель.

Я получаю следующие результаты:

Epoch 000 Loss: 32666856.000, Acc: 561536.963%
Epoch 010 Loss: 342012.625, Acc: 37158.075%
Epoch 020 Loss: 328074.844, Acc: 35578.772%
Epoch 030 Loss: 189751.594, Acc: 27069.794%
Epoch 040 Loss: 273142.312, Acc: 29358.673%
Epoch 050 Loss: 424036.625, Acc: 44175.562%
Epoch 060 Loss: 43667.957, Acc: 14025.812%
Epoch 070 Loss: 96341.156, Acc: 19105.350%
Epoch 080 Loss: 39308.691, Acc: 16228.386%
Epoch 090 Loss: 46950.699, Acc: 17407.053%

Я не могу выяснить, в чем проблема.

Я пробовал другие настройки (больше единиц, другие метрики, потери), но результат тот же.

1 Ответ

1 голос
/ 19 марта 2019

Потери настолько велики, потому что это квадрат разницы между предсказанным y и истинным y.Я заметил, что вы используете абсолютную ошибку для вашей потери метрика , но вы передаете в нее квадрат убытка.

  1. Ваше среднее значение y составляет приблизительно 5766
  2. Квадратный корень вашего окончательного MSE (т.е. фактическая разница) составляет примерно 216
  3. 216, что составляет около 3% * 1012.*
  4. Если вы тренируетесь в течение 1000 эпох, количество которых упадет менее чем на 1%

Есть две основные проблемы с точностью.Используемая метрика не будет выводить процент, она выводит абсолютное значение убытка.Вторая проблема состоит в том, что токен формата строки {:.3%} ожидает плавающее значение от 0 до 1, которое затем умножается на 100 для отображения в процентах.

См. Следующий код, в котором я разделил среднееMAE от среднего значения y (и вычел его из 100, чтобы он представлял «точность». Эта математика работает только тогда, когда потери не превышают среднее значение y).

import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler


df = pd.DataFrame({'A': np.array([100, 105.4, 108.3, 111.1, 113, 114.7, 120, 125, 129]),
                   'B': np.array([11, 11.8, 12.3, 12.8, 13.1,13.6, 13.9, 14.4, 15]),
                   'C': np.array([55, 56.3, 57, 58, 59.5, 60.4, 61, 61.5, 62]),
                   'Target': np.array([4000, 4200.34, 4700, 5300, 5800, 6400, 6800, 7200, 7500])})

df.head()

X_train = df.iloc[:, :3]
y_train = df.iloc[:, 3]

scaler = StandardScaler()
scaler.fit(X_train)
X_train_std = scaler.transform(X_train)

features = {'A': X_train_std[:, 0],
            'B': X_train_std[:, 1],
            'C': X_train_std[:, 2]}

labels = y_train


batch_size = 1
def train_input_fn(features, labels, batch_size):
    train_dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
    train_dataset = train_dataset.shuffle(1).batch(batch_size)
    return train_dataset


def pack_features_vector(features, labels):
    '''Pack the features into a single array'''
    features = tf.stack(list(features.values()), axis=1)
    return features, labels


train_dataset = train_input_fn(features, labels, batch_size).map(pack_features_vector)


class Model(tf.keras.Model):

    def __init__(self):
        super().__init__()

        self.l1 = tf.keras.layers.Dense(8, activation='relu')
        self.l2 = tf.keras.layers.Dense(4, activation='relu')
        self.out = tf.keras.layers.Dense(1)

    def call(self, x):
        x = self.l1(x)
        x = self.l2(x)
        return self.out(x)


learning_rate = 0.1
optimizer = tf.keras.optimizers.RMSprop(learning_rate)
loss_object = tf.keras.losses.MeanSquaredError()


train_loss_res = []
train_acc_res = []
epochs = 1000
model = Model()

for epoch in range(epochs):
    epoch_loss_avg = tf.keras.metrics.Mean()
    epoch_acc = tf.keras.metrics.MeanAbsoluteError()
    y_avg = tf.metrics.Mean()
    for x,y in train_dataset:
        with tf.GradientTape() as tape:
            y_ = model(x)
            loss = loss_object(y, y_)
        gradients = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))

        epoch_loss_avg(loss)
        epoch_acc(y, y_)
        y_avg(y)

    train_loss_res.append(epoch_loss_avg.result())
    train_acc_res.append(epoch_acc.result())

    if epoch % 10 == 0:
        print("Epoch {:03d} Squared Loss: {:.3f}, Acc: {:.3f}%".format(epoch, epoch_loss_avg.result(),100-(epoch_acc.result()/y_avg.result())))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...