MLP с Scikitlearn: приложение искусственной нейронной сети для прогнозирования

У меня есть данные о трафике, и я хочу предсказать количество транспортных средств на следующий час, показав модели следующие входные данные: количество транспортных средств за этот час и значение средней скорости за этот час. Вот мой код:

dataset=pd.read_csv('/content/final - Sayfa5.csv',delimiter=',') 
dataset=dataset[[ 'MINIMUM_SPEED', 'MAXIMUM_SPEED', 'AVERAGE_SPEED','NUMBER_OF_VEHICLES','1_LAG_NO_VEHICLES']]
X = np.array(dataset.iloc[:,1:4])
L = len(dataset)
Y = np.array([dataset.iloc[:,4]])
Y= Y[:,0:L]
Y = np.transpose(Y)

#scaling with MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(X)
X = scaler.transform(X)
 
scaler.fit(Y)
Y = scaler.transform(Y)
print(X,Y)

X_train , X_test, Y_train, Y_test = train_test_split(X,Y,test_size=0.3)
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error 
mlp = MLPRegressor(activation='logistic')
mlp.fit(X_train,Y_train)
predictions = mlp.predict(X_test)
predictions1=mlp.predict(X_train)
print("mse_test :" ,mean_squared_error(Y_test,predictions), "mse_train :",mean_squared_error(Y_train,predictions1))


Я получил хорошие значения mse, такие как mse_test: 0,005467816018933008 mse_train: 0,005072774796622158

Но меня смущают два момента:

  1. Должен ли я масштабировать значения y, я прочитал так много блогов, написанных, что не следует масштабировать Ys, а только масштабировать X_train и X_test. Но я получил такие плохие оценки по mse, как 49, 50, 100 или даже больше.

  2. Как я могу получить прогнозы на будущее, но не масштабированные значения. Например я написал:

    Xnew=[[ 80 , 40 , 47],
    [ 80 , 30,  81],
    [ 80 , 33, 115]]
    Xnew = scaler.transform(Xnew)
    print("prediction for that input is" , mlp.predict(Xnew))

Но я получил масштабированные значения, такие как: прогноз для этого ввода равен [0.08533431 0.1402755 0.19497315]

Так должно было быть [81,115,102].


person Billur Selin Zaza    schedule 18.12.2020    source источник
comment
просто в качестве примечания: обычно запаздывающая переменная означает просмотр ПРЕДЫДУЩЕГО периода. Когда имена ваших переменных правильные, ваш y должен быть dataset.iloc[3]   -  person TiTo    schedule 18.12.2020
comment
Вы так правы, я неправильно использовал концепцию. Спасибо за исправление   -  person Billur Selin Zaza    schedule 19.12.2020


Ответы (3)


Поздравляем с использованием [sklearn's MLPRegressor][1], знакомство с нейронными сетями всегда полезно.

Масштабирование входных данных имеет решающее значение для нейронных сетей. Рекомендуем просмотреть главу 11 книги Этама Алпайдина "Введение в машинное обучение". Это также очень подробно описано в статье об эффективности BackProp. . Проще говоря, очень важно масштабировать входные данные, чтобы ваша модель научилась нацеливать выходные данные.

На английском языке scaling в этом случае означает преобразование ваших данных в значения между 0 and 1 (включительно). Хороший публикация Stats Exchange описывает различия в масштабировании. . Для масштабирования MinMax вы сохраняете то же распределение ваших данных, в том числе чувствительны к выбросам. В sklearn существуют более надежные методы (описанные в этом посте), такие как RobustScaler.

Возьмем, к примеру, очень простой набор данных:

| Feature 1 | Feature 2 | Feature 3 | Feature 4 | Feature 5 | Target |
|:---------:|:---------:|:---------:|:---------:|:---------:|:------:|
|     1     |     17    |     22    |     3     |     3     |   53   |
|     2     |     18    |     24    |     5     |     4     |   54   |
|     1     |     11    |     22    |     2     |     5     |   96   |
|     5     |     20    |     22    |     7     |     5     |   59   |
|     3     |     10    |     26    |     4     |     5     |   66   |
|     5     |     14    |     30    |     1     |     4     |   63   |
|     2     |     17    |     30    |     9     |     5     |   93   |
|     4     |     5     |     27    |     1     |     5     |   91   |
|     3     |     20    |     25    |     7     |     4     |   70   |
|     4     |     19    |     23    |     10    |     4     |   81   |
|     3     |     13    |     8     |     19    |     5     |   14   |
|     9     |     18    |     3     |     67    |     5     |   35   |
|     8     |     12    |     3     |     34    |     7     |   25   |
|     5     |     15    |     6     |     12    |     6     |   33   |
|     2     |     13    |     2     |     4     |     8     |   21   |
|     4     |     13    |     6     |     28    |     5     |   46   |
|     7     |     17    |     7     |     89    |     6     |   21   |
|     4     |     18    |     4     |     11    |     8     |    5   |
|     9     |     19    |     7     |     21    |     5     |   30   |
|     6     |     14    |     6     |     17    |     7     |   73   |

Я могу немного изменить ваш код, чтобы поиграть с этим:

import pandas as pd, numpy as np
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import RobustScaler
from sklearn.metrics import mean_squared_error 

df = pd.read_clipboard()

# Build data
y = df['Target'].to_numpy()
scaled_y = df['Target'].values.reshape(-1, 1) #returns a numpy array
df.drop('Target', inplace=True, axis=1)
X = df.to_numpy()

#scaling with RobustScaler
scaler = RobustScaler()
X = scaler.fit_transform(X)

# Scaling y just to show you the difference
scaled_y = scaler.fit_transform(scaled_y)

# Set random_state so we can replicate results
X_train , X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, random_state=8)
scaled_X_train , scaled_X_test, scaled_y_train, scaled_y_test = train_test_split(X,scaled_y,test_size=0.2, random_state=8)

mlp = MLPRegressor(activation='logistic')
scaled_mlp = MLPRegressor(activation='logistic')

mlp.fit(X_train, y_train)
scaled_mlp.fit(scaled_X_train, scaled_y_train)

preds = mlp.predict(X_test)
scaled_preds = mlp.predict(scaled_X_test)

for pred, scaled_pred, tar, scaled_tar in zip(preds, scaled_preds, y_test, scaled_y_test):
    print("Regular MLP:")
    print("Prediction: {} | Actual: {} | Error: {}".format(pred, tar, tar-pred))
    
    print()
    print("MLP that was shown scaled labels: ")
    print("Prediction: {} | Actual: {} | Error: {}".format(scaled_pred, scaled_tar, scaled_tar-scaled_pred))

Короче говоря, уменьшение цели естественным образом уменьшит вашу ошибку, поскольку ваша модель изучает не фактическое значение, а значение от 0 до 1.

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

person wundermahn    schedule 18.12.2020
comment
Очень интересно узнавать что-то новое! Я благодарю вас миллион раз! :) Я пытаюсь прямо вперед. На самом деле мой набор данных не сильно отличается, но также похож на ваш пример. Так что буду пробовать, чтобы увидеть результаты! Желаю вам идеального дня! - person Billur Selin Zaza; 19.12.2020
comment
Конечно! Если вы считаете, что это ответило на ваш вопрос, пожалуйста, не стесняйтесь принять мой ответ, чтобы другие тоже могли его использовать. - person wundermahn; 20.12.2020

  1. вы не можете сравнить MSE между этими двумя моделями, так как он зависит от масштаба. Понятно, что ваш MSE меньше, когда вы масштабируете свой y, поскольку y (в вашем случае) становится меньше, применяя MinMaxScaler. Когда вы масштабируете свои прогнозируемые и фактические значения y, а затем снова вычисляете MSE, оно должно быть таким же, как и для модели с необработанными значениями y (хотя и не на 100%).

Главный вывод: не сравнивайте MSE между моделями только внутри модели. Абсолютное значение MSE трудно интерпретировать.

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

Что делает MinMaxScaler, так это вычисляет следующее:

X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min

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

person TiTo    schedule 18.12.2020
comment
Классическим масштабно-инвариантным показателем является средняя абсолютная масштабированная ошибка, которая была разработана специально для методов прогнозирования: en.wikipedia. org/wiki/Mean_absolute_scaled_error - person blacksite; 18.12.2020
comment
Это было действительно поучительно, большое спасибо! Я был немного смущен, но теперь я вижу это лучше. - person Billur Selin Zaza; 19.12.2020

  1. Поскольку это проблема регрессии, вы вряд ли захотите масштабировать переменную цель/ответ в этом случае. Вы захотите масштабировать определенные функции, особенно учитывая большие числа величин, которые сочетаются с другими функциями, которые могут быть, например, двоичными. Но, не видя полного набора данных, я не могу подтвердить, будет ли это подходящим способом. Кроме того, вы должны сравнить это с базовой моделью. СКО 45 000 может показаться плохим, но если СКО базового уровня в 10 раз больше, то ваша модель только что улучшила базовый показатель СКО на 1000 %.

TL;DR Пытайтесь масштабировать только в том случае, если функции различаются по величине или в данной функции есть большие выбросы. введите код сюда

  1. Если вы не масштабируете целевую переменную, вам не нужно пытаться «перемасштабировать ее». Однако, если вам нужно/хотите, вы можете изучить использование TransformedTargetRegressor здесь
person Steven Barnard    schedule 18.12.2020
comment
точность, оценка F1, полнота и точность применяются для классификации, а не для регрессионных моделей. Я думаю, что MASE, предложенный @blacksite, является лучшим предложением. - person TiTo; 18.12.2020
comment
спасибо! еще не пил утренний кофе, ха-ха, матрицы путаницы применимы только к классификации. Сделано изменение - person Steven Barnard; 18.12.2020
comment
Это было идеальное объяснение. Я очень ценю ваше время и усилия. И вы правы тогда насчет второй части. Значения набора данных не так сильно различаются, поэтому мне лучше не масштабировать их. Я вижу сейчас. Я надеюсь, что вы прекрасный день! @СтивенБарнард - person Billur Selin Zaza; 19.12.2020