Вопрос или проблема
Я работал над своей тривиальной моделью LSTM на Keras, пытаясь реализовать Hyperas с помощью следующего кода, который вызывает ошибку, которую я не могу разрешить. Я просто экспериментировал с Hyperas, и было бы здорово заставить это работать. Мой код в одном файле выглядит следующим образом:
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Embedding, Dropout, Activation
from keras.layers import LSTM
from keras.datasets import imdb
from pandas import DataFrame
from sklearn.preprocessing import MinMaxScaler
from matplotlib import pyplot
import h5py
from keras.callbacks import TensorBoard
from numpy import *
from hyperas import optim
from hyperas.distributions import choice, uniform
from hyperopt import Trials, STATUS_OK, tpe
from configuration.data_loader import *
def data():
# нормализация признаков
scaler = MinMaxScaler(feature_range=(0, 1))
X_train_df , y_train_df , X_val_df , y_val_df , X_test_df , y_test_df = load_saved_datasets()
X_train_df = scaler.fit_transform(X_train_df.get_values())
X_val_df = scaler.fit_transform(X_val_df.get_values())
y_train_df = y_train_df.get_values()
y_val_df = y_val_df.get_values()
X_train = X_train_df
y_train = y_train_df
X_val = X_val_df
y_val = y_val_df
return (X_train, y_train, X_val, y_val)
def model(X_train, y_train, X_val, y_val):
"""
:param X_train: НОРМАЛИЗОВАННЫЙ
:param y_train:
:param X_val: НОРМАЛИЗОВАННЫЙ
:param y_val:
:return:
"""
X_train = X_train.reshape((X_train.shape[0], 1, X_train.shape[1]))
X_val = X_val.reshape((X_val.shape[0], 1, X_val.shape[1]))
model = Sequential()
# Уровень 1
model.add(LSTM({{uniform(4,70)}},
input_shape=(X_train.shape[1],X_train.shape[2])))
model.add(Activation({{choice(['tanh', 'relu'])}}))
model.add(Dropout({{uniform(0, 1)}}))
# Если мы выберем 'four', добавим дополнительный четвертый уровень
if {{choice(['two', 'three'])}} == 'two':
# Уровень 2
model.add(LSTM({{uniform(4,100)}},
input_shape=(X_train.shape[1],X_train.shape[2])))
model.add(Activation({{choice(['tanh', 'relu'])}}))
model.add(Dropout({{uniform(0, 1)}}))
model.add(Dense(1))
model.add(Activation({{choice(['softmax', 'relu', 'tanh'])}}))
model.compile(loss="rmse", metrics=['accuracy'],
optimizer={{choice(['rmsprop', 'adam', 'sgd'])}})
result = model.fit(X_train, y_train,
batch_size={{choice([64, 128])}},
epochs=2,
verbose=2,
validation_data=(X_val, y_val))
# получить наивысшую валидационную точность за эпохи обучения
validation_acc = amax(result.history['val_acc'])
print('Лучшая валидационная точность за эпоху:', validation_acc)
return {'loss': -validation_acc, 'status': STATUS_OK, 'model': model}
def hyperas_main():
trials = Trials()
best_run, best_model = optim.minimize(data=data,
model=model,
algo=tpe.suggest,
max_evals=20,
trials=trials)
X_train, Y_train, X_test, Y_test = data()
print("Оценка лучшей модели:")
print(best_model.evaluate(X_test, Y_test))
print("Лучшие гиперпараметры выбранной модели:")
print(best_run)
# print("Оценка лучшей модели:")
# # print(best_model.evaluate(X_val, y_val))
# print("Лучшие гиперпараметры выбранной модели:")
# print(best_run)
Где функция load_saved_datasets() просто загружает мои наборы данных с помощью pandas.
Тем не менее, вывод ошибки выглядит следующим образом:
>>> Пространство поиска Hyperas:
def get_space():
return {
'LSTM': hp.uniform('LSTM', 4,70),
'Activation': hp.choice('Activation', ['tanh', 'relu']),
'Dropout': hp.uniform('Dropout', 0, 1),
'Dropout_1': hp.choice('Dropout_1', ['two', 'three']),
'LSTM_1': hp.uniform('LSTM_1', 4,100),
'Activation_1': hp.choice('Activation_1', ['tanh', 'relu']),
'Dropout_2': hp.uniform('Dropout_2', 0, 1),
'Activation_2': hp.choice('Activation_2', ['softmax', 'relu', 'tanh']),
'optimizer': hp.choice('optimizer', ['rmsprop', 'adam', 'sgd']),
'batch_size': hp.choice('batch_size', [64, 128]),
}
>>> Данные
1:
2:
3: # нормализация признаков
4: scaler = MinMaxScaler(feature_range=(0, 1))
5:
6: X_train_df , y_train_df , X_val_df , y_val_df , X_test_df , y_test_df = load_saved_datasets()
7:
8: X_train_df = scaler.fit_transform(X_train_df.get_values())
9: X_val_df = scaler.fit_transform(X_val_df.get_values())
10:
11: y_train_df = y_train_df.get_values()
12: y_val_df = y_val_df.get_values()
13:
14: X_train = X_train_df
15: y_train = y_train_df
16: X_val = X_val_df
17: y_val = y_val_df
18:
19:
20:
21:
>>> Результирующая заменённая модель keras:
1: def keras_fmin_fnct(space):
2:
3: """
4:
5: :param X_train: НОРМАЛИЗОВАННЫЙ
6: :param y_train:
7: :param X_val: НОРМАЛИЗОВАННЫЙ
8: :param y_val:
9: :return:
10: """
11:
12: X_train = X_train.reshape((X_train.shape[0], 1, X_train.shape[1]))
13: X_val = X_val.reshape((X_val.shape[0], 1, X_val.shape[1]))
14:
15:
16: model = Sequential()
17:
18: # Уровень 1
19: model.add(LSTM(space['LSTM'],
20: input_shape=(X_train.shape[1],X_train.shape[2])))
21: model.add(Activation(space['Activation']))
22: model.add(Dropout(space['Dropout']))
23:
24: # Если мы выберем 'four', добавим дополнительный четвертый уровень
25: if space['Dropout_1'] == 'two':
26: # Уровень 2
27: model.add(LSTM(space['LSTM_1'],
28: input_shape=(X_train.shape[1],X_train.shape[2])))
29: model.add(Activation(space['Activation_1']))
30: model.add(Dropout(space['Dropout_2']))
31:
32:
33: model.add(Dense(1))
34: model.add(Activation(space['Activation_2']))
35:
36: model.compile(loss="rmse", metrics=['accuracy'],
37: optimizer=space['optimizer'])
38:
39: result = model.fit(X_train, y_train,
40: batch_size=space['batch_size'],
41: epochs=2,
42: verbose=2,
43: validation_data=(X_val, y_val))
44:
45: # получить наивысшую валидационную точность за эпохи обучения
46: validation_acc = amax(result.history['val_acc'])
47: print('Лучшая валидационная точность за эпоху:', validation_acc)
48: return {'loss': -validation_acc, 'status': STATUS_OK, 'model': model}
49:
Traceback (most recent call last):
File "C:/Users/user/Desktop/AI/Backend/src/main.py", line 40, in <module>
lstm_training.hyperas_main()
File "C:\Users\user\Desktop\AI\Backend\src\training\lstm_training.py", line 94, in hyperas_main
trials=trials)
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperas\optim.py", line 67, in minimize
verbose=verbose)
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperas\optim.py", line 133, in base_minimizer
return_argmin=True),
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\fmin.py", line 307, in fmin
return_argmin=return_argmin,
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\base.py", line 635, in fmin
return_argmin=return_argmin)
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\fmin.py", line 320, in fmin
rval.exhaust()
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\fmin.py", line 199, in exhaust
self.run(self.max_evals - n_done, block_until_done=self.async)
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\fmin.py", line 173, in run
self.serial_evaluate()
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\fmin.py", line 92, in serial_evaluate
result = self.domain.evaluate(spec, ctrl)
File "C:\Users\user\Anaconda3\envs\AI\lib\site-packages\hyperopt\base.py", line 840, in evaluate
rval = self.fn(pyll_rval)
File "C:\Users\user\Desktop\AI\Backend\src\temp_model.py", line 110, in keras_fmin_fnct
UnboundLocalError: local variable 'X_train' referenced before assignment
Где я ссылаюсь на X_train до его использования? Это связано с соглашениями о наименовании? Может быть, проблема заключается в вычислительном графе?
Любая помощь приветствуется.
Попробуйте разместить ваши два оператора reshape() в конце функции data() вместо функции model(), и в функции hyperas_main() определите data() перед тем, как выполнить optim.minimize().
Ответ или решение
Ошибка, с которой вы столкнулись при использовании Hyperas для настройки вашей LSTM модели с использованием Keras, связана с неправильным обращением к переменной X_train
в функции keras_fmin_fnct
. Эта ошибка вызвана тем, что вы не объявили X_train
в области видимости вашей функции, что приводит к исключению UnboundLocalError
.
Давайте разберем, как можно исправить данную ошибку и улучшить вашу модель. Также я дам несколько рекомендаций по работе с Hyperas и Keras.
Устранение ошибки UnboundLocalError
Эта ошибка возникает из-за того, что функция model
, которая обращается к X_train
, не имеет доступа к этой переменной, если она не была передана через аргументы. Чтобы решить эту проблему, необходимо переработать структуру вашего кода.
-
Убедитесь, что переменные
X_train
иy_train
передаются правильно в функциюkeras_fmin_fnct
. Ваша функцияdata
должна возвращать данные в правильной форме. -
Перенесите резайзинг входных данных в функцию
data()
вместо модели. Это избавит вашу модель от зависимости от переменных, которые могут не быть доступны во время оптимизации.
Пример исправленного кода
Ваша функция data()
должна выглядеть примерно так:
def data():
# нормализация признаков
scaler = MinMaxScaler(feature_range=(0, 1))
X_train_df, y_train_df, X_val_df, y_val_df, X_test_df, y_test_df = load_saved_datasets()
X_train_df = scaler.fit_transform(X_train_df.values)
X_val_df = scaler.transform(X_val_df.values)
y_train_df = y_train_df.values
y_val_df = y_val_df.values
X_train = X_train_df.reshape((X_train_df.shape[0], 1, X_train_df.shape[1]))
X_val = X_val_df.reshape((X_val_df.shape[0], 1, X_val_df.shape[1]))
return (X_train, y_train_df, X_val, y_val_df)
Обновление функции model
Ваша функция model
может выглядеть следующим образом:
def model(X_train, y_train, X_val, y_val):
model = Sequential()
# Первый слой
model.add(LSTM({{uniform(4,70)}}, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Activation({{choice(['tanh', 'relu'])}}))
model.add(Dropout({{uniform(0, 1)}}))
if {{choice(['two', 'three'])}} == 'two':
# Второй слой
model.add(LSTM({{uniform(4,100)}}, return_sequences=True))
model.add(Activation({{choice(['tanh', 'relu'])}}))
model.add(Dropout({{uniform(0, 1)}}))
model.add(Dense(1))
model.add(Activation({{choice(['softmax', 'relu', 'tanh'])}}))
model.compile(loss="rmse", metrics=['accuracy'], optimizer={{choice(['rmsprop', 'adam', 'sgd'])}})
result = model.fit(X_train, y_train,
batch_size={{choice([64, 128])}},
epochs=2,
verbose=2,
validation_data=(X_val, y_val))
validation_acc = amax(result.history['val_accuracy'])
print('Best validation accuracy of epoch:', validation_acc)
return {'loss': -validation_acc, 'status': STATUS_OK, 'model': model}
Заключение
После внесения указанных изменений вы сможете избежать ошибки, связанной с использованием переменных. Убедитесь, что все данные передаются корректно. Проводите отладку, используя print-операторы, чтобы отслеживать значения переменных в различных частях кода. Это поможет вам лучше понять, как данные течет через вашу модель и в каком состоянии они находятся на протяжении всего процесса оптимизации.
В случае возникновения прочих ошибок, посмотрите на трассировку стека – это даст вам указания на том, что именно пошло не так в вашем коде. Настройка моделей с использованием Hyperas и Keras требует внимательности, но, следуя данным рекомендациям, вы сможете улучшить свою модель и усовершенствовать ее работу.