Я использую Pytorch для решения простой задачи регрессии. то, что я пытаюсь сделать, может показаться немного сложным. Итак, у меня есть две модели: грубая модель и модель разности. Я знаю, что моя простая проблема регрессии может быть решена с использованием только одной модели, но я изучаю, как уменьшить ошибку моделей регрессии нейронной сети, и именно поэтому я использую эту сложную архитектуру. Архитектура состоит из двух MLP, первая называется грубая модель и предназначена для изучения отношений ввода-вывода, и ее на самом деле должно быть достаточно для изучения и подгонки данных, а также для создания хороших прогнозов, но я добавляю дополнительную нейронную сеть, называемую моделью различий. который должен изучить отношение ошибок входных данных и добавить эти дополнительные знания обратно в грубую модель. Я знаю, что это может быть сложно понять, поэтому я напишу несколько шагов здесь, как работает моя Архитектура:
1. Обучите грубую Модель
2. Получите предсказания грубой Модели, назовем ее y_coarse
3. Рассчитать грубую ошибку модели (не MSE. Я просто вычисляю здесь отклонения прогнозов модели по истинным целевым значениям), другими словами, я делаю y_true - coarse_predictions
4. Обучите модель разности (входные данные - те же входные данные, что и у грубой модели, но здесь вывод - ошибка, которую я вычислил на шаге 3
. 5. Получите прогнозы модели разности, назовем ее y_diff * 1010. *
6. окончательные прогнозы были бы y_coarse + y_diff
смысл всего этого - получить более точные прогнозы в конце, добавив отклонение, полученное с помощью разностной модели, к предсказаниям грубой моделиПреимущество заключается в том, что такая архитектура может обеспечить лучшие прогнозы для зашумленных данных, но у меня была проблема с реализациейОб этом в Pytorch. Тренировка грубой модели хороша, и я получаю хорошие результаты, но тренировка модели различий дает странные результаты, модель разности nn не соответствует данным об ошибках. Я пытался настроить гиперпараметры, но без шансов. вот мой код:
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import TensorDataset, DataLoader
# create random dataset for regression
dataset = make_regression(n_samples=1000, n_features=1, noise=3, random_state=0)
X, y = dataset
# implementation using pytorch
# transform data to Tensors and split testset and validation set
y = y.reshape(-1, 1)
print(X.shape, y.shape)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42, test_size=0.2)
X_train_torch = torch.from_numpy(X_train.astype(np.float32))
y_train_torch = torch.from_numpy(y_train.astype(np.float32))
X_test_torch = torch.from_numpy(X_test.astype(np.float32))
y_test_torch = torch.from_numpy(y_test.astype(np.float32))
# normalize data
X_train_torch = (X_train_torch - torch.mean(X_train_torch)) / torch.std(X_train_torch)
X_test_torch = (X_test_torch - torch.mean(X_test_torch)) / torch.std(X_test_torch)
print(X_train_torch.shape, y_train_torch.shape)
# create a TensorDataset from the actual dataset
coarse_trainset = TensorDataset(X_train_torch, y_train_torch)
coarse_testset = TensorDataset(X_test_torch, y_test_torch)
# create the loader of the dataset
coarse_train_loader = DataLoader(coarse_trainset, batch_size=32, shuffle=True)
coarse_test_loader = DataLoader(coarse_testset, batch_size=32, shuffle=False)
# definition of the Coarse Model
class CoarseModel(nn.Module):
"""main neural network to learn input/position relationship"""
def __init__(self, n_features, n_hidden, n_out):
super().__init__()
self.fc1 = nn.Linear(n_features, n_hidden)
self.fc2 = nn.Linear(n_hidden, n_out)
def forward(self, x):
out = F.relu(self.fc1(x))
out = self.fc2(out)
return out
# definition of the Difference Model
class DifferenceModel(nn.Module):
"""difference model to enhance accuracy via predicting input/error relationship"""
def __init__(self, n_features, n_hidden, n_out):
super().__init__()
self.fc1 = nn.Linear(n_features, n_hidden)
self.fc2 = nn.Linear(n_hidden, n_out)
def forward(self, x):
out = F.relu(self.fc1(x))
out = self.fc2(out)
return out
coarse_model = CoarseModel(X.shape[1], 10, 1)
# training function => will perform a single training step given a batch
def training_func(model, criterion, optimizer):
def train_step(sample, target):
model.train()
optimizer.zero_grad()
out = model(sample)
loss = criterion(out, target)
loss.backward()
optimizer.step()
return loss.item()
return train_step
# fit function will train the given Model over defined epochs
def fit(epochs, model, lr, train_loader, test_loader):
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.9)
train_losses, test_losses, accuracy_list = ([] for _ in range(3))
train = training_func(model=model, criterion=criterion, optimizer=optimizer)
for e in range(epochs):
for x, y in train_loader:
loss_val = train(x, y)
train_losses.append(loss_val)
else:
with torch.no_grad():
model.eval()
for x_test, y_test in test_loader:
pred = model(x_test)
loss = criterion(pred, y_test)
test_losses.append(loss.item())
accuracy = r2_score(y_test.numpy(), pred.numpy())
accuracy_list.append(accuracy)
print(f"Epoch: {e} => average training loss= {sum(train_losses)/ len(train_losses)} average test losses= {sum(test_losses)/ len(test_losses)} and accuracy={sum(accuracy_list)/ len(accuracy_list)}")
return train_losses, test_losses, accuracy_list
# plot the results of the training and testing loss values over the iterations
def plot_results(train_losses, test_losses, accs):
plt.plot(train_losses, color="b")
plt.title("train losses over time")
plt.show()
plt.plot(test_losses, color= "b")
plt.title("test losses over time")
plt.show()
plt.plot(accs, color= "b")
plt.title("accuracy over time")
plt.show()
# train the Coarse Model
train_losses, test_losses, accs = fit(epochs=1000,
model=coarse_model,
lr=1e-4,
train_loader=coarse_train_loader,
test_loader=coarse_test_loader)
plot_results(train_losses, test_losses, accs)
print("final train loss value = ", train_losses[-1])
print("final test loss value = ", test_losses[-1])
print("final accuracy of the model => ", accs[-1])
#### and now I train the difference Model, My problem is that this Model is not fitting the data #####
# training process of the Difference Model: => the desired value is the difference between the desired output and the the coarse Model Predictions
diff_model = DifferenceModel(X.shape[1], 10, 1)
y_coarse = coarse_model(X_train_torch)
y_coarse = y_coarse.detach() # y_coarse: predictions of the Coarse Model
d_coarse = y_train_torch.detach() # d_coarse: desired Coarse Model output
d_diff_train = d_coarse - y_coarse # d_diff: desired difference Model output
y_coarse_test = coarse_model(X_test_torch)
y_coarse_test = y_coarse_test.detach() # y_coarse: predictions of the Coarse Model
d_coarse_test = y_test_torch.detach() # d_coarse: desired Coarse Model output
d_diff_test = d_coarse_test - y_coarse_test # d_diff: desired difference Model output
diff_trainset = TensorDataset(X_train_torch, d_diff_train)
diff_testset = TensorDataset(X_test_torch, d_diff_test)
diff_train_loader = DataLoader(diff_trainset, batch_size=32, shuffle=True)
diff_test_loader = DataLoader(diff_testset, batch_size=32, shuffle=False)
train_losses, test_losses, accs = fit(epochs=1000, model=diff_model, lr=1e-3, train_loader=diff_train_loader, test_loader=diff_test_loader)
plot_results(train_losses, test_losses, accs)
print("final train loss value = ", train_losses[-1])
print("final test loss value = ", test_losses[-1])
print("final accuracy = ", accs[-1])
Я также использую этот код для тестирования всей Модели и сравнения целых прогнозов с грубым прогнозом модели:
with torch.no_grad():
coarse_model.eval()
diff_model.eval()
criterion = nn.MSELoss()
coarse_preds = coarse_model(X_test_torch)
diff_model_preds = diff_model(X_test_torch)
y_final = coarse_preds + diff_model_preds
coarse_loss = criterion(coarse_preds, y_test_torch)
# diff_model_loss = criterion(diff_model_preds, y_test_torch)
y_final_loss = criterion(y_final, y_test_torch)
print(f"coarse Model loss = {coarse_loss.item()} / Final Loss = {y_final_loss.item()}")
coarse_score = r2_score(y_test_torch.detach().numpy(), coarse_preds.numpy())
y_final_score = r2_score(y_test_torch.detach().numpy(), y_final.numpy())
print(f"coarse Model score = {coarse_score} / y_final score = {y_final_score}")
, который вы можете запуститькод на google colab , чтобы вы могли получить то, что я точно хочу сделать. Самое странное, что если я прокомментирую coarse_model, модель различий сможет соответствовать данным и даст хорошие прогнозы, но когда я раскомментирую coarse_model, тогда модель различий потеряет способность соответствовать данным. как вы видите, я сначала нормализовал данные, поэтому не знаю, почему это происходит. Когда я использую каждую модель по отдельности, она работает как шарм, но если я объединю их таким образом, то модель различий не может соответствовать данным. кто-нибудь знает почему? Я надеюсь, что объяснил это достаточно хорошо, я знаю, что это немного сложно обойти, я надеюсь, что кто-то здесь может помочь мне с этим. Заранее спасибо