![]()
ライブラリをインポートする
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import mlflow
import mlflow.sklearn
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
import warnings
warnings.simplefilter('ignore', FutureWarning)
df = pd.DataFrame(pd.read_csv('london_weather.csv'))
df.describe()
| date | cloud_cover | sunshine | global_radiation | max_temp | mean_temp | min_temp | precipitation | pressure | snow_depth | |
|---|---|---|---|---|---|---|---|---|---|---|
| count | 1.534100e+04 | 15322.000000 | 15341.000000 | 15322.000000 | 15335.000000 | 15305.000000 | 15339.000000 | 15335.000000 | 15337.000000 | 13900.000000 |
| mean | 1.999567e+07 | 5.268242 | 4.350238 | 118.756951 | 15.388777 | 11.475511 | 7.559867 | 1.668634 | 101536.605594 | 0.037986 |
| std | 1.212176e+05 | 2.070072 | 4.028339 | 88.898272 | 6.554754 | 5.729709 | 5.326756 | 3.738540 | 1049.722604 | 0.545633 |
| min | 1.979010e+07 | 0.000000 | 0.000000 | 8.000000 | -6.200000 | -7.600000 | -11.800000 | 0.000000 | 95960.000000 | 0.000000 |
| 25% | 1.989070e+07 | 4.000000 | 0.500000 | 41.000000 | 10.500000 | 7.000000 | 3.500000 | 0.000000 | 100920.000000 | 0.000000 |
| 50% | 2.000010e+07 | 6.000000 | 3.500000 | 95.000000 | 15.000000 | 11.400000 | 7.800000 | 0.000000 | 101620.000000 | 0.000000 |
| 75% | 2.010070e+07 | 7.000000 | 7.200000 | 186.000000 | 20.300000 | 16.000000 | 11.800000 | 1.600000 | 102240.000000 | 0.000000 |
| max | 2.020123e+07 | 9.000000 | 16.000000 | 402.000000 | 37.900000 | 29.000000 | 22.300000 | 61.800000 | 104820.000000 | 22.000000 |
date 列を pd.to_datetime() に渡して、datetime データ型に変換します。 %Y%m%d 形式を使用します。.groupby() を使用してデータを簡単にグループ化できるように、日付の年と月の列を作成することもできます。lineplot() メソッドを使用して温度を視覚化できます。heatmap() および .corr() 関数を使用すると、特徴間の相関関係を視覚化できます。df['datetime'] = pd.to_datetime(df['date'], format = '%Y%m%d')
df.sample(10)
| date | cloud_cover | sunshine | global_radiation | max_temp | mean_temp | min_temp | precipitation | pressure | snow_depth | datetime | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1564 | 19830414 | 5.0 | 2.6 | 124.0 | 18.0 | 7.2 | 2.4 | 0.0 | 102930.0 | 0.0 | 1983-04-14 |
| 948 | 19810806 | 6.0 | 0.0 | 70.0 | 18.2 | 17.4 | 15.6 | 23.8 | 101690.0 | 0.0 | 1981-08-06 |
| 7478 | 19990623 | 6.0 | 5.9 | 219.0 | 23.0 | 16.9 | 12.1 | 0.0 | 102270.0 | 0.0 | 1999-06-23 |
| 1020 | 19811017 | 8.0 | 0.0 | 30.0 | 13.2 | 5.6 | 1.9 | 4.7 | 101580.0 | 0.0 | 1981-10-17 |
| 9556 | 20050301 | 8.0 | 0.2 | 41.0 | 5.9 | 2.4 | -1.0 | 3.8 | 100550.0 | 0.0 | 2005-03-01 |
| 4149 | 19900512 | 6.0 | 3.8 | 169.0 | 17.2 | 13.0 | 10.0 | 0.0 | 101270.0 | 0.0 | 1990-05-12 |
| 11531 | 20100728 | 5.0 | 6.9 | 220.0 | 23.3 | 20.3 | 15.4 | 0.0 | 101710.0 | NaN | 2010-07-28 |
| 6000 | 19950606 | 7.0 | 0.5 | 105.0 | 20.1 | 14.4 | 11.0 | 0.1 | 102330.0 | 0.0 | 1995-06-06 |
| 8655 | 20020912 | 3.0 | 9.2 | 182.0 | 24.6 | 18.9 | 14.3 | 0.0 | 102520.0 | 0.0 | 2002-09-12 |
| 12399 | 20121212 | 6.0 | 0.9 | 21.0 | 6.7 | -1.9 | -4.1 | 0.0 | 102060.0 | 0.0 | 2012-12-12 |
欠損値をヒートマップで可視化してみます。
plt.figure(figsize=(8, 6))
sns.heatmap(df.isnull(), cmap="YlGnBu")
plt.show()
平均気温をプロットします。
fig = plt.subplots(figsize=(16, 6))
sns.lineplot(df,
x = 'datetime',
y = 'mean_temp',
alpha = .3,
)
plt.show()
平均気温、最高気温、最低気温をそれぞれ年ごとにまとめます。
df_year_mean = df.groupby(pd.Grouper(key="datetime", freq="Y")).agg({'mean_temp':'mean'})
df_year_max = df.groupby(pd.Grouper(key="datetime", freq="Y")).agg({'max_temp':'max'})
df_year_min = df.groupby(pd.Grouper(key="datetime", freq="Y")).agg({'min_temp':'min'})
fig = plt.subplots(figsize=(12, 5))
sns.lineplot(df_year_max, x= 'datetime', y = 'max_temp')
sns.lineplot(df_year_mean, x= 'datetime', y = 'mean_temp')
sns.lineplot(df_year_min, x= 'datetime', y = 'min_temp')
<AxesSubplot: xlabel='datetime', ylabel='max_temp'>
特徴の相関図を出力します。
fig = plt.subplots(figsize=(10, 8))
sns.heatmap(df.corr(), annot=True)
plt.show()
feature_selection = ['sunshine',
'cloud_cover',
'max_temp',
'min_temp',
'precipitation',
'pressure']
target_var = 'mean_temp'
weather_metrics = ["sunshine", "cloud cover", 'global_radiation']
df = df.dropna()
imputer を使用して欠損値を考慮し、スケーラーを使用して特徴を正規化します。適切なタイミングでデータをトレーニング サンプルとテスト サンプルに分割します。
これらの前処理ステップはパイプラインに入れる必要があります。
train_test_split() メソッドを使用してデータを分割します。SimpleImputer() メソッドは値を代入できます。StandardScaler() メソッドは値を正規化できます。データの代入と正規化を、トレーニングとテストセットに必ず個別に適用します。preprocess_data 関数に組み込みます。欠損値の数を確認します。
df.isnull().sum()
date 0 cloud_cover 0 sunshine 0 global_radiation 0 max_temp 0 mean_temp 0 min_temp 0 precipitation 0 pressure 0 snow_depth 0 datetime 0 dtype: int64
関数を定義します
def preprocess_df(df, feature_selection, target_var):
"""
データフレームを X と y に分割し、train と test を連続して実行します
次に、train と test の両方を代入してスケーリングします
トレインとテスト ET を返します
"""
X = df[feature_selection]
y = df[target_var]
X_train, X_test, y_train, y_test = train_test_split(X, y)
imputer = SimpleImputer(strategy="mean")
X_train = imputer.fit_transform(X_train)
X_test = imputer.transform(X_test)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
return X_train, X_test, y_train, y_test
定義した関数を使用してX,y ををれぞれ train と test に分離します。
X_train, X_test, y_train, y_test = preprocess_df(df, feature_selection, target_var)
線形回帰、デシジョン ツリー、ランダム フォレスト回帰の 3 つの回帰モデルに適合する関数を作成し、MLflow を使用してログに記録します。
.predict() および .mean_squared_error() メソッドを使用して predict_and_evaluate() を評価する関数を作成します。max_Depth_parameters を使用して少なくとも 5 つの異なる実験を実行します。with mlflow.start_run() メソッドを使用して MLflow 実験を実行します。log_param() および log_metric() メソッドを使用してパラメータとメトリクスをログに記録します。関数を定義
def predict_and_evaluate(model, x_test, y_test):
"""
テスト セットから値を予測し、二乗平均平方根誤差を計算して返します。
"""
# Complete this function
y_pred = model.predict(x_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
return rmse
EXPERIMENT_NAME = "temp_prediction"
EXPERIMENT_ID = mlflow.create_experiment(EXPERIMENT_NAME)
max_depth_parameters = [1, 2, 5, 10, 20]
for idx, depth in enumerate(max_depth_parameters):
parameters = {
'max_depth': depth,
'random_state': 1
}
RUN_NAME = f"run_{idx}"
with mlflow.start_run(experiment_id=EXPERIMENT_ID, run_name=RUN_NAME):
lr = LinearRegression().fit(X_train, y_train)
dt = DecisionTreeRegressor(random_state=3, max_depth=depth).fit(X_train, y_train)
rf = RandomForestRegressor(random_state=3, max_depth=depth).fit(X_train, y_train)
mlflow.sklearn.log_model(lr, "lr")
mlflow.sklearn.log_model(dt, "dt")
mlflow.sklearn.log_model(rf, "rf")
lr_rmse = predict_and_evaluate(lr, X_test, y_test)
dt_rmse = predict_and_evaluate(dt, X_test, y_test)
rf_rmse = predict_and_evaluate(rf, X_test, y_test)
mlflow.log_param("max_depth", depth)
mlflow.log_metric("rmse_lr", lr_rmse)
mlflow.log_metric("rmse_dt", dt_rmse)
mlflow.log_metric("rmse_rf", rf_rmse)
experiment_results = mlflow.search_runs(experiment_names=[EXPERIMENT_NAME])
select_col = ['metrics.rmse_rf', 'metrics.rmse_lr', 'metrics.rmse_dt','params.max_depth']
ex_selected = experiment_results[select_col]
ex_selected
| metrics.rmse_rf | metrics.rmse_lr | metrics.rmse_dt | params.max_depth | |
|---|---|---|---|---|
| 0 | 0.890582 | 0.906798 | 1.286103 | 20 |
| 1 | 0.876378 | 0.906798 | 1.055993 | 10 |
| 2 | 1.093600 | 0.906798 | 1.272120 | 5 |
| 3 | 2.258520 | 0.906798 | 2.362033 | 2 |
| 4 | 3.352830 | 0.906798 | 3.456210 | 1 |
| 5 | 0.892092 | 0.906798 | 1.287195 | 20 |
| 6 | 0.877652 | 0.906798 | 1.056883 | 10 |
| 7 | 1.097111 | 0.906798 | 1.272120 | 5 |
| 8 | 2.267905 | 0.906798 | 2.362033 | 2 |
| 9 | 3.374730 | 0.906798 | 3.456210 | 1 |
データフレームを見やすく加工します。
pd.DataFrame({
'RandomForestRegression': experiment_results['metrics.rmse_rf'],
'LinerRegression': experiment_results['metrics.rmse_lr'],
'DecisionTreeRegression': experiment_results['metrics.rmse_dt'],
'MaxDepth': experiment_results['params.max_depth']
})
| RandomForestRegression | LinerRegression | DecisionTreeRegression | MaxDepth | |
|---|---|---|---|---|
| 0 | 0.892092 | 0.906798 | 1.287195 | 20 |
| 1 | 0.877652 | 0.906798 | 1.056883 | 10 |
| 2 | 1.097111 | 0.906798 | 1.272120 | 5 |
| 3 | 2.267905 | 0.906798 | 2.362033 | 2 |
| 4 | 3.374730 | 0.906798 | 3.456210 | 1 |