Как переписать данные с помощью Keras? - PullRequest
3 голосов
/ 16 апреля 2020

Я пытаюсь построить простую регрессионную модель, используя керасы и тензор потока. В моей задаче у меня есть данные в виде (x, y), где x и y - просто числа. Я хотел бы построить модель keras, чтобы предсказать y, используя x в качестве входных данных.

Поскольку я думаю, что изображения лучше объясняют, это мои данные:

enter image description here

Мы можем обсудить, хороши они или нет, но в моей проблеме я не могу их обмануть.

Моя модель keras следующая (данные разделены 30% тест (X_test, y_test) и 70% тренировка (X_train, y_train)):

model = tf.keras.Sequential()

model.add(tf.keras.layers.Dense(32, input_shape=() activation="relu", name="first_layer"))
model.add(tf.keras.layers.Dense(16, activation="relu", name="second_layer"))
model.add(tf.keras.layers.Dense(1, name="output_layer"))

model.compile(loss = "mean_squared_error", optimizer = "adam", metrics=["mse"] )

history = model.fit(X_train, y_train, epochs=500, batch_size=1, verbose=0, shuffle=False) 
eval_result = model.evaluate(X_test, y_test)
print("\n\nTest loss:", eval_result, "\n")

predict_Y = model.predict(X)

примечание: X содержит как X_test, так и X_train.

Построение полученного прогноза (синие квадраты - это предсказание predict_Y)

enter image description here

Я много играю со слоями, функциями активации и другими параметрами. Моя цель - найти наилучшие параметры для обучения модели, но реальный вопрос здесь немного другой: на самом деле у меня трудные времена, чтобы заставить модель соответствовать данным (как вы можете видеть из приведенных выше результатов).

Кто-нибудь имеет какое-то представление о том, как воспроизвести переоснащение?

Вот какой результат я бы хотел получить: enter image description here

( красные точки находятся под синими квадратами!)

РЕДАКТИРОВАТЬ:

Здесь я предоставлю вам данные, использованные в примере выше: вы можете скопировать вставить непосредственно в интерпретатор python:

X_train = [0.704619794270697, 0.6779457393024553, 0.8207082120250023, 0.8588819357831449, 0.8692320257603844, 0.6878750931810429, 0.9556331888763945, 0.77677964510883, 0.7211381534179618, 0.6438319113259414, 0.6478339581502052, 0.9710222750072649, 0.8952188423349681, 0.6303124926673513, 0.9640316662124185, 0.869691568491902, 0.8320164648420931, 0.8236399177660375, 0.8877334038470911, 0.8084042532069621, 0.8045680821762038]
y_train = [0.7766424210611557, 0.8210846773655833, 0.9996114311913593, 0.8041331063189883, 0.9980525368790883, 0.8164056182686034, 0.8925487603333683, 0.7758207470960685, 0.37345286573743475, 0.9325789202459493, 0.6060269037514895, 0.9319771743389491, 0.9990691225991941, 0.9320002808310418, 0.9992560731072977, 0.9980241561997089, 0.8882905258641204, 0.4678339275898943, 0.9312152374846061, 0.9542371205095945, 0.8885893668675711]
X_test = [0.9749191829308574, 0.8735366740730178, 0.8882783211709133, 0.8022891400991644, 0.8650601322313454, 0.8697902997857514, 1.0, 0.8165876695985228, 0.8923841531760973]
y_test = [0.975653685270635, 0.9096752789481569, 0.6653736469114154, 0.46367666660348744, 0.9991817903431941, 1.0, 0.9111205717076893, 0.5264993912088891, 0.9989199241685126]
X = [0.704619794270697, 0.77677964510883, 0.7211381534179618, 0.6478339581502052, 0.6779457393024553, 0.8588819357831449, 0.8045680821762038, 0.8320164648420931, 0.8650601322313454, 0.8697902997857514, 0.8236399177660375, 0.6878750931810429, 0.8923841531760973, 0.8692320257603844, 0.8877334038470911, 0.8735366740730178, 0.8207082120250023, 0.8022891400991644, 0.6303124926673513, 0.8084042532069621, 0.869691568491902, 0.9710222750072649, 0.9556331888763945, 0.8882783211709133, 0.8165876695985228, 0.6438319113259414, 0.8952188423349681, 0.9749191829308574, 1.0, 0.9640316662124185]
Y = [0.7766424210611557, 0.7758207470960685, 0.37345286573743475, 0.6060269037514895, 0.8210846773655833, 0.8041331063189883, 0.8885893668675711, 0.8882905258641204, 0.9991817903431941, 1.0, 0.4678339275898943, 0.8164056182686034, 0.9989199241685126, 0.9980525368790883, 0.9312152374846061, 0.9096752789481569, 0.9996114311913593, 0.46367666660348744, 0.9320002808310418, 0.9542371205095945, 0.9980241561997089, 0.9319771743389491, 0.8925487603333683, 0.6653736469114154, 0.5264993912088891, 0.9325789202459493, 0.9990691225991941, 0.975653685270635, 0.9111205717076893, 0.9992560731072977]

Где X содержит список значений x и Y соответствующее значение y. (X_test, y_test) и (X_train, y_train) являются двумя (не перекрывающимися) подмножествами (X, Y).

Для прогнозирования и отображения результатов модели я просто использую matplotlib (импортированный как plt):

predict_Y = model.predict(X)
plt.plot(X, Y, "ro", X, predict_Y, "bs")
plt.show()

Ответы [ 3 ]

2 голосов
/ 20 апреля 2020

Переоборудованные модели редко бывают полезны в реальной жизни. Мне кажется, что OP хорошо знает об этом, но хочет посмотреть, способны ли NN действительно соответствовать (ограниченным) произвольным функциям или нет. С одной стороны, данные ввода-вывода в примере , кажется, не подчиняются какой-либо заметной схеме. С другой стороны, и вход, и выход являются скалярами в [0, 1], и в обучающем наборе есть только 21 точка данных.

Исходя из моих экспериментов и результатов, мы действительно можем переодеться по запросу. См. Изображение ниже.

enter image description here

Числовые результаты:

           x    y_true    y_pred     error
0   0.704620  0.776642  0.773753 -0.002889
1   0.677946  0.821085  0.819597 -0.001488
2   0.820708  0.999611  0.999813  0.000202
3   0.858882  0.804133  0.805160  0.001026
4   0.869232  0.998053  0.997862 -0.000190
5   0.687875  0.816406  0.814692 -0.001714
6   0.955633  0.892549  0.893117  0.000569
7   0.776780  0.775821  0.779289  0.003469
8   0.721138  0.373453  0.374007  0.000554
9   0.643832  0.932579  0.912565 -0.020014
10  0.647834  0.606027  0.607253  0.001226
11  0.971022  0.931977  0.931549 -0.000428
12  0.895219  0.999069  0.999051 -0.000018
13  0.630312  0.932000  0.930252 -0.001748
14  0.964032  0.999256  0.999204 -0.000052
15  0.869692  0.998024  0.997859 -0.000165
16  0.832016  0.888291  0.887883 -0.000407
17  0.823640  0.467834  0.460728 -0.007106
18  0.887733  0.931215  0.932790  0.001575
19  0.808404  0.954237  0.960282  0.006045
20  0.804568  0.888589  0.906829  0.018240
{'me': -0.00015776709314323828, 
 'mae': 0.00329163070145315, 
 'mse': 4.0713782563067185e-05, 
 'rmse': 0.006380735268216915}

Код OP кажется мне хорошим. Мои изменения были незначительными:

  1. Используйте более глубокие сети. На самом деле, возможно, нет необходимости использовать глубину в 30 слоев, но, поскольку мы просто хотим переодеться, я не слишком много экспериментировал с минимальной необходимой глубиной.
  2. Каждый плотный слой имеет 50 единиц. Опять же, это может быть излишним.
  3. Добавлен слой нормализации партии для каждого 5-го плотного слоя.
  4. Снижение скорости обучения вдвое.
  5. Ранняя оптимизация для более длительного использования всех 21 обучающих примеров в пакете.
  6. Использование MAE в качестве целевой функции. MSE - это хорошо, но так как мы хотим перефразировать, я хочу штрафовать маленькие ошибки так же, как большие ошибки.
  7. Случайные числа здесь важнее, потому что данные кажутся произвольными. Тем не менее, вы должны получить аналогичные результаты, если измените начальное число случайных чисел и дайте оптимизатору поработать достаточно долго. В некоторых случаях оптимизация застревает в локальных минимумах и не приводит к переоснащению (как требует OP).

Код ниже.

0 голосов
/ 20 апреля 2020

Проблема, с которой вы можете столкнуться, заключается в том, что у вас недостаточно данных для тренировки, чтобы модель могла хорошо соответствовать. В вашем примере, , у вас есть только 21 обучающий экземпляр, в каждом из которых только 1 функция . Вообще говоря, для моделей нейронной сети вам нужно порядка 10K или более обучающих экземпляров, чтобы создать достойную модель.

Рассмотрим следующий код, который генерирует шумовую синусоидальную волну и пытается обучить плотно соединенную линию питания. вперед нейронной сети, чтобы соответствовать данным. Моя модель имеет два линейных слоя, каждый из которых содержит 50 скрытых единиц и функцию активации ReLU. Эксперименты параметризуются с помощью переменной num_points, которую я буду увеличивать.

import tensorflow as tf
from tensorflow import keras

from tensorflow.keras import layers
import numpy as np
import matplotlib.pyplot as plt


np.random.seed(7)

def generate_data(num_points=100):
    X = np.linspace(0.0 , 2.0 * np.pi, num_points).reshape(-1, 1)
    noise = np.random.normal(0, 1, num_points).reshape(-1, 1)
    y = 3 * np.sin(X) + noise
    return X, y

def run_experiment(X_train, y_train, X_test, batch_size=64):
    num_points = X_train.shape[0]

    model = keras.Sequential()
    model.add(layers.Dense(50, input_shape=(1, ), activation='relu'))
    model.add(layers.Dense(50, activation='relu'))
    model.add(layers.Dense(1, activation='linear'))
    model.compile(loss = "mse", optimizer = "adam", metrics=["mse"] )
    history = model.fit(X_train, y_train, epochs=10,
                        batch_size=batch_size, verbose=0)

    yhat = model.predict(X_test, batch_size=batch_size)
    plt.figure(figsize=(5, 5))
    plt.plot(X_train, y_train, "ro", markersize=2, label='True')
    plt.plot(X_train, yhat, "bo", markersize=1, label='Predicted')
    plt.ylim(-5, 5)
    plt.title('N=%d points' % (num_points))
    plt.legend()
    plt.grid()
    plt.show()

Вот как я вызываю код:

num_points = 100
X, y = generate_data(num_points)
run_experiment(X, y, X)

Теперь, если я проведу эксперимент с num_points = 100, предсказания модели (синим цветом) делают ужасную работу по подгонке истинной шумной синусоидальной волны (красным).

enter image description here

Теперь, здесь num_points = 1000:

enter image description here

Здесь num_points = 10000:

enter image description here

А вот num_points = 100000:

enter image description here

Как видите, для выбранной мной архитектуры NN , добавление еще Обучающие экземпляры позволяют нейронной сети лучше (сверх) соответствовать данным.

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

  • увеличивать количество слоев
  • увеличивать количество скрытых единиц
  • увеличивать количество объектов на экземпляр данных
  • уменьшить регуляризацию (например, удаляя выпадающие слои)
  • использовать более сложную архитектуру нейронной сети (например, блоки трансформаторов вместо RNN)

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

0 голосов
/ 16 апреля 2020

Как обсуждалось в комментариях, вы должны сделать массив Python (с NumPy) следующим образом: -

Myarray = [[0.65, 1], [0.85, 0.5], ....] 

Тогда вы просто вызовете эти указанные c части массива кого вы должны предсказать. Здесь первое значение является значением оси X. Таким образом, вы бы назвали его, чтобы получить соответствующую пару, хранящуюся в Myarray

Существует множество ресурсов для изучения этих типов вещей. некоторые из них ===>

  1. https://www.geeksforgeeks.org/python-using-2d-arrays-lists-the-right-way/

  2. https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=video&cd=2&cad=rja&uact=8&ved=0ahUKEwjGs-Oxne3oAhVlwTgGHfHnDp4QtwIILTAB&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DQgfUT7i4yrc&usg=AOvVaw3LympYRszIYi6_OijMXH72

...