Модель Keras CNN предсказывает одно и то же значение для всех входов и не повышает точность во время обучения - PullRequest
1 голос
/ 25 марта 2020

Я пытаюсь следить за тем, как Nvidia самостоятельно управляет бумагой CNN (https://images.nvidia.com/content/tegra/automotive/images/2016/solutions/pdf/end-to-end-dl-using-px.pdf). Однако когда я запускаю код, моя точность остается неизменной во время обучения, и потери очень малы. Модель также предсказывает одно и то же значение для любого входа, очень близкого к 0. Ожидаемые результаты в основном находятся между -4 и + 4.

import tensorflow.compat.v1 as tf
import scipy.misc
import random
from tensorflow import keras
from tensorflow.keras import datasets, layers, models
import numpy as np

model = models.Sequential()
model.add(layers.Conv2D(24, (5, 5), strides=(2, 2), input_shape=(66, 200, 3)))
model.add(layers.Activation('relu'))
model.add(layers.Conv2D(36, (5, 5), strides=(2, 2)))
model.add(layers.Activation('relu'))
model.add(layers.Conv2D(48, (5, 5), strides=(2, 2)))
model.add(layers.Activation('relu'))
model.add(layers.Conv2D(64, (3, 3), strides=(1, 1)))
model.add(layers.Activation('relu'))
model.add(layers.Conv2D(64, (3, 3), strides=(1, 1)))
model.add(layers.Activation('relu'))
model.add(layers.Flatten())
model.add(layers.Dense(1164))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(100))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(50))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(10))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(1))
model.add(layers.Activation('linear'))

model.compile(optimizer = 'adam', loss= 'mse', metrics=['accuracy'])
epochs = 30
batchSize = 100
xs, ys = LoadTrainSet()
print("train batch loaded")
x, y = LoadTestSet()
print("test batch loaded")

xs = np.array(xs)
x = np.array(x)
#ys = tf.math.l2_normalize(np.array(ys))
#y = tf.math.l2_normalize(np.array(y))
#(Suggestion by Simon)Replaced by:
epsilon = 1e-12
ys =  np.array(ys) / tf.math.sqrt(tf.math.reduce_mean(np.array(ys)**2), epsilon)
y =  np.array(y) / tf.math.sqrt(tf.math.reduce_mean(np.array(y)**2), epsilon)

history = model.fit(xs, ys, batch_size=batchSize, epochs=epochs)
testLoss, testAcc = model.evaluate(x, y, verbose=2)

Обучение:

Epoch 4/30
5001/5001 [==============================] - 9s 2ms/sample - loss: 1.9974e-04 - accuracy: 0.0382
Epoch 5/30
5001/5001 [==============================] - 9s 2ms/sample - loss: 2.0004e-04 - accuracy: 0.0382
Epoch 6/30
5001/5001 [==============================] - 8s 2ms/sample - loss: 2.0040e-04 - accuracy: 0.0382
Epoch 7/30
5001/5001 [==============================] - 8s 2ms/sample - loss: 1.9986e-04 - accuracy: 0.0382
Epoch 8/30
5001/5001 [==============================] - 8s 2ms/sample - loss: 2.0064e-04 - accuracy: 0.0382
Epoch 9/30
5001/5001 [==============================] - 8s 2ms/sample - loss: 2.0014e-04 - accuracy: 0.0382
Epoch 10/30
5001/5001 [==============================] - 8s 2ms/sample - loss: 1.9993e-04 - accuracy: 0.0382

Прогнозы:

MODEL PREDICTIONS:
[[0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]
 [0.00018978]]
ACTUAL VALUES:
[[ 0.01337768]
 [-0.00774151]
 [-0.00143646]
 [ 0.        ]
 [ 0.00287291]
 [-0.00287291]
 [ 0.        ]
 [-0.00199569]
 [ 0.02122884]
 [ 0.01083373]]

Первое сообщение, извините за любые ошибки. Любая помощь будет высоко ценится.

1 Ответ

0 голосов
/ 25 марта 2020

Поскольку ваши ярлыки довольно маленькие (<< 1), возможно, лучше их масштабировать. Это в основном потому, что возведение в квадрат среднеквадратичной ошибки делает маленькие значения еще меньше (обратите внимание, что ваш убыток имеет порядок 10 ^ -4) и, что более важно, имеет производную, которая очень мала для малых входных значений. Это затрудняет тренировку вашей модели с использованием методов на основе градиента. </p>

В качестве альтернативы вы можете попытаться использовать среднюю абсолютную ошибку, поскольку для этого градиенты не становятся маленькими для небольших входных данных.

Редактировать: после второго взгляда я, кажется, упустил, что вы действительно нормализуете данные с помощью tf.math.l2_normalize. Но я думаю, что вам нужно передать ему аргумент оси (кажется, что вы нормализуетесь с нормой всего набора меток, рассматриваемой как тензор). Используя этот метод, вы делите на квадрат root из сумма квадратов ваших оригинальных этикеток. Вместо этого вы должны разделить на квадрат root среднего квадрата.

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