Машинное обучение переполнено потенциальными приложениями, но одно важное (и простое!) применение — это использование алгоритма машинного обучения для интерполяции. В этом посте я покажу, как можно использовать простую нейронную сеть для интерполяции на одномерных или двумерных сетках. Это представляет для меня особый интерес при интерполяции больших векторов на двумерной пространственной сетке.

Одномерная интерполяция задает простой вопрос: заданное значение x предсказывает значение y. Поскольку нейронные сети считаются универсальными оценщиками функций, они должны хорошо подходить для этого типа задач (спойлер — они подходят). Проверим, как это выглядит на практике.

Но сначала! Сделаем импорт. Мы собираемся использовать последовательную модель keras для нейронной сети, numpy для создания наших данных, matplotlib для визуализации наших результатов и sklearn для разделения наших данных на наборы для обучения и тестирования.

from keras.models import Sequential
from keras.layers import Dense
import numpy as np
import matplotlib.pyplot as plt
import sklearn.model_selection as skm

Давайте создадим простую синусоиду с небольшим количеством случайного шума.

# Define 1D function we want to learn
def function1d(x):
    return np.sin(2*np.pi*x)
# Create sample
x = np.random.random_sample(1000)
y = function1d(x) + np.random.normal(0, .1, 1000)
# Plot
plt.scatter(x,y, label='Generated Data')
plt.plot(np.linspace(0,1,100), function1d(np.linspace(0,1,100)), label='Real Sine Function', color='r', linestyle='--', linewidth=3)
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("Randomly Sampled Sine Function")

И давайте продолжим и создадим действительно простую нейронную сеть с двумя скрытыми слоями и всего 100

### Model creation: adding layers and compilation
model = Sequential()
model.add(Dense(100, input_dim=1, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(1, activation='linear'))

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

Мы также сделаем стандартное разделение данных (т.е. 80% для обучения и 20% для тестирования).

X_train, X_test, y_train, y_test = skm.train_test_split(x, y, test_size=0.2)
plt.scatter(X_train, y_train, label='training data')
plt.scatter(X_test, y_test, label='test data')
plt.legend()
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("Randomly Sampled Sine Function")

Теперь мы собираемся обучить нашу нейронную сеть, используя некоторые стандартные параметры.

history = model.fit(X_train, y_train, epochs=20, batch_size=4)

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

y_pred = model.predict(X_test)

plt.scatter(X_train, y_train, label='Training Data')
plt.scatter(X_test, y_pred, label='Model Predictions')
plt.plot(np.linspace(0,1,100), function1d(np.linspace(0,1,100)), label='Real Sine Function', color='r', linestyle='--', linewidth=3)
plt.legend()
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("Randomly Sampled Sine Function")

И вуаля! Мы видим, что даже очень простая нейронная сеть отлично справляется с этой задачей интерполяции с зашумленными данными.

Давайте проверим случай 2D. Во-первых, нам нужно начать с создания нашего набора данных.

# Define 2D function we want to learn
def function2d(x, y):
    return (x+y)*np.exp(-5.0*(x**2+y**2))
# Create sample
x = 2*np.random.random_sample(2000) - 1
y = 2*np.random.random_sample(2000) - 1
z = function2d(x, y)
# Plot
plt.scatter(x,y, c=z)
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("Randomly Sampled 2D Function")
plt.colorbar()

Итак, здесь мы хотим взять наши пары значений x и y (x, y) в качестве входных данных и предсказать значение z (то есть цвет). Давайте начнем с разделения наших данных.

X_train, X_test, y_train, y_test = skm.train_test_split(np.column_stack((x, y)), z, test_size=0.2)
# Plot
plt.scatter(X_train[:,0], X_train[:,1], c=y_train)
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("Training Set")
plt.colorbar()

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

### Model creation: adding layers and compilation
model2D = Sequential()
model2D.add(Dense(100, input_shape=(None, 2), activation='relu'))
model2D.add(Dense(100, activation='relu'))
model2D.add(Dense(1, activation='linear'))

model2D.compile(optimizer='adam', loss='mse', metrics=['mse'])

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

history = model2D.fit(X_train, y_train, epochs=20, batch_size=4)

z_pred = model2D.predict(X_test)
plt.scatter(X_test[:,0], X_test[:,1], c=z_pred)
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("Predicted Set")
plt.colorbar()

Хорошо, так что это выглядит многообещающе. Давайте построим это и наши тренировочные данные, чтобы увидеть, все ли в порядке.

plt.scatter(X_train[:,0], X_train[:,1], c=y_train)
plt.scatter(X_test[:,0], X_test[:,1], c=z_pred)
plt.xlabel('X value')
plt.ylabel('Y value')
plt.title("All Data")
plt.colorbar()

И все проверяется!

Итак, в этой короткой статье я показал вам, как нейронную сеть можно использовать для одномерной или двумерной интерполяции!

Полный блокнот можно найти здесь:

https://github.com/crhea93/Medium/blob/master/MachineLearning/BasicInterpolation.ipynb