Введение
Как гласит индонезийская пословица: «приготовьте зонт до дождя», эта модель также пытается подготовить нас к предстоящей погоде.
В это неопределенное время изменения климата мы знаем, что погода сейчас непростая штука. Сегодня мы, возможно, вспотеем до мозга костей. Завтра? Мы можем одеваться слишком мало для того маленького солнца, которое у нас будет.
Поэтому прогноз температуры жизненно важен для того, чтобы мы могли лучше планировать свои дни.
Цель
Эта модель пытается предоставить пользователю три различных значения температуры: среднюю, минимальную и максимальную при определенных входных данных.
Набор данных
Эта модель использует данные Kaggle. Для более чистого набора данных используются стандартные методы очистки и предварительной обработки. Подробное объяснение приведено ниже.
Объединение и очистка:
Наборы данных climate
и station
объединяются, чтобы получить province_id
для каждого наблюдения. После этого удаляем ненужные столбцы, а именно station_name
, region_name
, latitude
, longitude
и region_id.
.
# Merging data to show province_id for every observation in climate dataset = pd.merge(climate, station, on='station_id', how='left') dataset = dataset.drop(['station_name', 'region_name', 'latitude', 'longitude', 'region_id'], axis=1) dataset.head()
Очистка
Преобразование date
в дату и время и последующее извлечение из него month
для последующего использования.
# Changing 'date' type into datetime dataset['date'] = pd.to_datetime(dataset['date'], format='%d-%m-%Y') dataset.info() # Adding a column consisting month value with int type dataset['month'] = dataset['date'].dt.month # Drop date and station column dataset = dataset.drop(['date', 'station_id'], axis=1)
Защита данных
Создайте функцию для обеспечения соответствующих входных данных.
# Check data types def check_data(input_data, config): assert input_data.select_dtypes("int").columns.to_list() == config["int_columns"], "an error occurs in int column(s)." assert input_data.select_dtypes("float").columns.to_list() == config["float_columns"], "an error occurs in float column(s)." assert input_data.select_dtypes("object").columns.to_list() == config["object_columns"], "an error occurs in object column(s)."
Разделение
Разделите данные на входные и выходные, а затем на обучающий, действительный и тестовый набор данных.
x = dataset[config["input"]].copy() y = dataset[config["output"]].copy() # Splitting data into train and test x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 123) # Splitting test data into validation and test x_valid, x_test, y_valid, y_test = train_test_split(x_test, y_test, test_size = 0.2, random_state = 123)
Вменение
В train_data
найдено несколько нулевых значений. Следовательно, нам нужно сделать некоторые вменения. Для столбцов с плавающей запятой вмененные значения являются медианными, а для столбцов с плавающей запятой — новой меткой «неизвестно».
# change non-float null into 'unknown' and float null into median for train data def impute_train_missing(df): columns = list(df.columns.values) for column in columns: try: if df[column].dtypes.name == 'float64': median = df[column].median() df[column] = df[column].fillna(median) if df[column].dtypes.name == 'int64': df[column] = df[column].fillna('unknown') else: df[column] = df[column].fillna('unknown') except: pass
После завершения вменения train_data
следующим шагом будет вменение valid_data
и test_data
. Это вменение выполняется с использованием train_data
в качестве базы во избежание утечки данных.
# change non-float null into 'unknown' and float null into median for valid and test data using train data def impute_valid_test_missing(train_df, imputed_df): columns = list(imputed_df.columns.values) for column in columns: try: if imputed_df[column].dtypes.name == 'float64': median = train_df[column].median() imputed_df[column] = imputed_df[column].fillna(median) if imputed_df[column].dtypes.name == 'int64': imputed_df[column] = imputed_df[column].fillna('unknown') else: imputed_df[column] = imputed_df[column].fillna('unknown') except: pass
Масштабирование
Масштабирование выполняется для всех наборов данных с использованием train_data
в качестве базы.
train_data
масштабирование:
def train_scaler(train_data, scaler = None): """ Standardizing train data :param x: <pandas DataFrame> data :param scaler: <sklearn object> scaler, default None :return x_scaled: <pandas Dataframe> standardized data :param scaler: <sklearn object> scaler, default None """ if scaler != None: pass else: # Buat & fit encoder scaler = StandardScaler() scaler.fit(train_data) # Tranform data train_data_scaled = scaler.transform(train_data) train_data_scaled = pd.DataFrame(train_data_scaled, columns = train_data.columns, index = train_data.index) return train_data_scaled, scaler # standardizing numerical columns in train data using StandardScaler train_set_clean[numerical_cols], scaler = train_scaler(train_data = train_set_clean[numerical_cols]) train_set_clean.head()
valid_data
и test_data
:
def valid_test_scaler(data, scaler): # Standardizing test data using train data parameter test_data_scaled = scaler.transform(data) test_data_scaled = pd.DataFrame(test_data_scaled, columns = data.columns, index = data.index) return test_data_scaled # standardizing numerical columns in valid data using StandardScaler valid_set_clean[numerical_cols] = valid_test_scaler(data = valid_set_clean[numerical_cols], scaler=scaler) valid_set_clean.head() # standardizing numerical columns in test data using StandardScaler test_set_clean[numerical_cols] = valid_test_scaler(data = test_set_clean[numerical_cols], scaler=scaler) test_set_clean.head()
Метод
Алгоритм
Эта модель использует усиление градиента.
Метрики
В этой модели в качестве показателей используется среднеквадратическая ошибка (MSE).
Результаты
Как указано выше в разделе «Цель», эта модель пытается найти три значения, а именно среднюю, минимальную и максимальную температуру. Поэтому все действия ниже выполняются для каждого из них. В демонстрационных целях последующие описания записываются, чтобы показать результаты для Tn
, который является столбцом для минимальной температуры.
Базовый уровень
В качестве базового уровня в этой модели используется среднее значение от train_data
.
Тренироваться
Используя GradientBoostingRegressor
, эта модель вписывается как в данные train
, так и в test
.
grad_tree_Tn = GradientBoostingRegressor(random_state=123) grad_tree_Tn.fit(x_train_clean, y_train_clean['Tn']) y_pred_train_Tn = grad_tree_Tn.predict(x_train_clean) y_pred_test_Tn = grad_tree_Tn.predict(x_test_clean) mse_train_Tn = mean_squared_error(y_pred_train_Tn, y_train_clean['Tn']) mse_test_Tn = mean_squared_error(y_pred_test_Tn, y_test_clean['Tn']) mse_train_Tn, mse_test_Tn
Перекрестная проверка
После получения результатов вышеуказанного процесса модель продолжает выполнять перекрестную проверку, чтобы получить наилучшие параметры. Этот процесс использует valid_data
, который сам был отделен от train_data.
.
# Create GridSearch for Tn using such parameters as stated in config file gb_tree_Tn_valid = GradientBoostingRegressor(random_state = 123) # Run GridSearch gb_tree_Tn_cv = GridSearchCV(estimator = gb_tree_Tn_valid, param_grid = config['params'], cv = 5, scoring = "neg_mean_squared_error") # Fit the model using validation data gb_tree_Tn_cv.fit(x_valid_clean, y_valid_clean['Tn']) # Find the best params gb_tree_Tn_cv.best_params_ # Find the best score gb_tree_Tn_cv.best_score_
Количество складок равно 5, и причиной этого являются просто лучшие практики и ограничения по времени. Использование большего количества данных может дать более точные параметры, но все же время обработки является ограничением.
Тест
После получения лучших параметров в процессе перекрестной проверки, описанном выше, модель соответствует train_data
, используя эти значения.
# Refitting a random forest for Tn using the best parameters gb_tree_Tn_final = GradientBoostingRegressor(n_estimators = gb_tree_Tn_cv.best_params_['n_estimators'], learning_rate = gb_tree_Tn_cv.best_params_["learning_rate"], random_state = 123) gb_tree_Tn_final.fit(x_train_clean, y_train_clean['Tn'])
Выход
Наконец, модель прогнозирует, используя данные train
и test
.
# Predict y_pred_train_Tn_final = gb_tree_Tn_final.predict(x_train_clean) y_pred_test_Tn_final = gb_tree_Tn_final.predict(x_test_clean) # MSE mse_train_Tn_final = mean_squared_error(y_train_clean['Tn'], y_pred_train_Tn_final) mse_test_Tn_final = mean_squared_error(y_test_clean['Tn'], y_pred_test_Tn_final) mse_train_Tn_final, mse_test_Tn_final
При использовании этой модели результаты следующие:
| | MSE Baseline | MSE Train | MSE Test | (Test/Baseline) - 1 | | --------|:------------:| :--------:| :-------:| :------------------:| | Minumum | 4.924533 | 2.990025 | 3.049104 | 38,21% | | Maximum | 5.148906 | 2.765183 | 2.328772 | 53,85% | | Average | 3.466188 | 1.620189 | 1.659483 | 52,31% |
Заключение и дальнейшая работа
Используя повышение градиента с MSE в качестве метрики, было обнаружено, что модель работает значительно лучше, чем базовый уровень, особенно для максимальной и средней температуры.
Несмотря на это, существует тревожное представление о минимальной температуре, при которой тестовая MSE довольно далека от двух других. Должна быть проведена дальнейшая работа по выявлению причин этого.
Репо доступно здесь.