Простой классификатор Tensorflow 2 не научится - PullRequest
0 голосов
/ 10 апреля 2020

Это простая модель архитектуры, основанная на этого урока . Набор данных будет выглядеть так, хотя в 10 измерениях: enter image description here

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras import layers, optimizers
from sklearn.datasets import make_blobs

def pre_processing(inputs, targets):
    inputs = tf.cast(inputs, tf.float32)
    targets = tf.cast(targets, tf.int64)
    return inputs, targets

def get_data():
    inputs, targets = make_blobs(n_samples=1000, n_features=10, centers=7, cluster_std=1)
    data = tf.data.Dataset.from_tensor_slices((inputs, targets))
    data = data.map(pre_processing)
    data = data.take(count=1000).shuffle(buffer_size=1000).batch(batch_size=256)
    return data

model = Sequential([
    layers.Dense(8, input_shape=(10,), activation='relu'),
    layers.Dense(16, activation='relu'),
    layers.Dense(32, activation='relu'),
    layers.Dense(7)])

@tf.function
def compute_loss(logits, labels):
    return tf.reduce_mean(
        tf.nn.sparse_softmax_cross_entropy_with_logits(
            logits=logits, labels=labels))

@tf.function
def compute_accuracy(logits, labels):
    predictions = tf.argmax(logits, axis=1)
    return tf.reduce_mean(tf.cast(tf.equal(predictions, labels), tf.float32))

@tf.function
def train_step(model, optim, x, y):
    with tf.GradientTape() as tape:
        logits = model(x)
        loss = compute_loss(logits, y)

    grads = tape.gradient(loss, model.trainable_variables)
    optim.apply_gradients(zip(grads, model.trainable_variables))

    accuracy = compute_accuracy(logits, y)
    return loss, accuracy

def train(epochs, model, optim):
    train_ds = get_data()

    loss = 0.
    acc = 0.

    for step, (x, y) in enumerate(train_ds):
        loss, acc = train_step(model, optim, x, y)

        if step % 500 == 0:
            print(f'Epoch {epochs} loss {loss.numpy()} acc {acc.numpy()}')

    return loss, acc

optim = optimizers.Adam(learning_rate=1e-6)

for epoch in range(100):
    loss, accuracy = train(epoch, model, optim)
Epoch 85 loss 2.530677080154419 acc 0.140625
Epoch 86 loss 3.3184046745300293 acc 0.0
Epoch 87 loss 3.138179063796997 acc 0.30078125
Epoch 88 loss 3.7781732082366943 acc 0.0
Epoch 89 loss 3.4101686477661133 acc 0.14453125
Epoch 90 loss 2.2888522148132324 acc 0.13671875
Epoch 91 loss 5.993691444396973 acc 0.16015625

Что я сделал не так?

1 Ответ

1 голос
/ 11 апреля 2020

В вашем коде есть две проблемы:

  • Первая состоит в том, что вы генерируете новый набор обучающих данных в каждую эпоху (см. Первую строку функции train, т.е. get_data функция вызывается в каждую эпоху). Поскольку вы используете функцию sklearn.datasets.make_blobs для генерации кластеров данных, нет гарантии, что сгенерированные кластеры данных между различными вызовами будут следовать одному и тому же распределению и / или отображению меток. Следовательно, лучшее, что могла бы сделать модель в каждую эпоху для совершенно другого набора данных, - это просто случайное предположение (следовательно, средняя точность 1/7 ~ = 0,14, которую вы видите в результатах). Чтобы решить эту проблему, возьмите генерацию данных из функции train (т.е. сгенерируйте данные на глобальном уровне один раз, вызвав функцию get_data), а затем передайте сгенерированные данные в функцию train в качестве аргумента в каждой эпохе.

  • Вторая проблема заключается в том, что вы используете очень низкую скорость обучения, т.е. 1e-6, для оптимизатора; следовательно, модель застряла и фактически не тренируется вообще. Вместо этого используйте стандартную скорость обучения для оптимизатора Адама, т.е. 1e-3, и изменяйте ее только по мере необходимости (например, на основе результатов проведенных вами экспериментов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...