tldr
KggleのDissolved oxygen prediction in river waterをPredicting Oxygen in Rivers - Data Every Day #036に沿ってやっていきます。
実行環境はGoogle Colaboratorです。
インポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn.preprocessing as sp
from sklearn.model_selection import train_test_split
import sklearn.linear_model as slm
import tensorflow as tf
データのダウンロード
Google Driveをマウントします。
from google.colab import drive
drive.mount('/content/drive')
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
KaggleのAPIクライアントを初期化し、認証します。
認証情報はGoogle Drive内(/content/drive/My Drive/Colab Notebooks/Kaggle
)にkaggle.json
として置いてあります。
import os
kaggle_path = "/content/drive/My Drive/Colab Notebooks/Kaggle"
os.environ['KAGGLE_CONFIG_DIR'] = kaggle_path
from kaggle.api.kaggle_api_extended import KaggleApi
api = KaggleApi()
api.authenticate()
Kaggle APIを使ってデータをダウンロードします。
dataset_id = 'vbmokin/dissolved-oxygen-prediction-in-river-water'
dataset = api.dataset_list_files(dataset_id)
file_name = dataset.files[0].name
file_path = os.path.join(api.get_default_download_dir(), file_name)
file_path
Warning: Looks like you're using an outdated API Version, please consider updating (server 1.5.10 / client 1.5.9)
'/content/train.csv'
api.dataset_download_file(dataset_id, file_name, force=True, quiet=False)
100%|██████████| 17.6k/17.6k [00:00<00:00, 7.13MB/s]
Downloading train.csv to /content
True
データの読み込み
Padasを使ってダウンロードしてきたCSVファイルを読み込みます。
data = pd.read_csv(file_path)
data
Id | target | O2_1 | O2_2 | O2_3 | O2_4 | O2_5 | O2_6 | O2_7 | NH4_1 | NH4_2 | NH4_3 | NH4_4 | NH4_5 | NH4_6 | NH4_7 | NO2_1 | NO2_2 | NO2_3 | NO2_4 | NO2_5 | NO2_6 | NO2_7 | NO3_1 | NO3_2 | NO3_3 | NO3_4 | NO3_5 | NO3_6 | NO3_7 | BOD5_1 | BOD5_2 | BOD5_3 | BOD5_4 | BOD5_5 | BOD5_6 | BOD5_7 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 12.58 | 9.875 | 9.20 | NaN | NaN | NaN | NaN | NaN | 0.690 | 1.040 | NaN | NaN | NaN | NaN | NaN | 0.0940 | 0.0990 | NaN | NaN | NaN | NaN | NaN | 1.58 | 1.825 | NaN | NaN | NaN | NaN | NaN | 4.80 | 5.850 | NaN | NaN | NaN | NaN | NaN |
1 | 3 | 9.37 | 10.300 | 10.75 | NaN | NaN | NaN | NaN | NaN | 0.710 | 0.725 | NaN | NaN | NaN | NaN | NaN | 0.0585 | 0.0515 | NaN | NaN | NaN | NaN | NaN | 1.21 | 0.905 | NaN | NaN | NaN | NaN | NaN | 5.88 | 6.835 | NaN | NaN | NaN | NaN | NaN |
2 | 4 | 8.35 | 8.290 | 7.90 | NaN | NaN | NaN | NaN | NaN | 2.210 | 2.210 | NaN | NaN | NaN | NaN | NaN | 0.1000 | 0.1100 | NaN | NaN | NaN | NaN | NaN | 1.34 | 1.250 | NaN | NaN | NaN | NaN | NaN | 3.20 | 2.700 | NaN | NaN | NaN | NaN | NaN |
3 | 5 | 9.57 | 8.820 | 6.80 | NaN | NaN | NaN | NaN | NaN | 0.595 | 0.675 | NaN | NaN | NaN | NaN | NaN | 0.0460 | 0.0535 | NaN | NaN | NaN | NaN | NaN | 0.59 | 0.790 | NaN | NaN | NaN | NaN | NaN | 7.70 | 7.055 | NaN | NaN | NaN | NaN | NaN |
4 | 6 | 6.00 | 6.000 | 6.50 | NaN | NaN | NaN | NaN | NaN | 0.600 | 0.900 | NaN | NaN | NaN | NaN | NaN | 0.1800 | 0.3400 | NaN | NaN | NaN | NaN | NaN | 1.36 | 1.820 | NaN | NaN | NaN | NaN | NaN | 5.50 | 5.300 | NaN | NaN | NaN | NaN | NaN |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
142 | 208 | 6.80 | 7.700 | 7.50 | NaN | NaN | NaN | NaN | NaN | 0.380 | 1.900 | NaN | NaN | NaN | NaN | NaN | 0.6200 | 0.0640 | NaN | NaN | NaN | NaN | NaN | 2.80 | 3.330 | NaN | NaN | NaN | NaN | NaN | 5.00 | 5.800 | NaN | NaN | NaN | NaN | NaN |
143 | 211 | 5.30 | 6.300 | 5.65 | NaN | NaN | NaN | NaN | NaN | 0.370 | 0.500 | NaN | NaN | NaN | NaN | NaN | 0.6900 | 0.9500 | NaN | NaN | NaN | NaN | NaN | 4.37 | 3.160 | NaN | NaN | NaN | NaN | NaN | 8.00 | 8.000 | NaN | NaN | NaN | NaN | NaN |
144 | 212 | 8.60 | 8.600 | 11.00 | NaN | NaN | NaN | NaN | NaN | 2.400 | 3.600 | NaN | NaN | NaN | NaN | NaN | 0.1500 | 0.1400 | NaN | NaN | NaN | NaN | NaN | 0.53 | 3.000 | NaN | NaN | NaN | NaN | NaN | 6.80 | 7.200 | NaN | NaN | NaN | NaN | NaN |
145 | 213 | 9.90 | 9.600 | 14.10 | NaN | NaN | NaN | NaN | NaN | 0.310 | 0.500 | NaN | NaN | NaN | NaN | NaN | 0.2100 | 0.0800 | NaN | NaN | NaN | NaN | NaN | 3.10 | 3.500 | NaN | NaN | NaN | NaN | NaN | 5.20 | 7.800 | NaN | NaN | NaN | NaN | NaN |
146 | 214 | 6.50 | 6.500 | 7.70 | NaN | NaN | NaN | NaN | NaN | 0.190 | 0.260 | NaN | NaN | NaN | NaN | NaN | 0.1300 | 0.0720 | NaN | NaN | NaN | NaN | NaN | 0.00 | 0.000 | NaN | NaN | NaN | NaN | NaN | 3.40 | 4.100 | NaN | NaN | NaN | NaN | NaN |
147 rows × 37 columns
下準備
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 147 entries, 0 to 146
Data columns (total 37 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Id 147 non-null int64
1 target 147 non-null float64
2 O2_1 145 non-null float64
3 O2_2 145 non-null float64
4 O2_3 32 non-null float64
5 O2_4 31 non-null float64
6 O2_5 33 non-null float64
7 O2_6 37 non-null float64
8 O2_7 37 non-null float64
9 NH4_1 145 non-null float64
10 NH4_2 145 non-null float64
11 NH4_3 32 non-null float64
12 NH4_4 31 non-null float64
13 NH4_5 33 non-null float64
14 NH4_6 37 non-null float64
15 NH4_7 37 non-null float64
16 NO2_1 145 non-null float64
17 NO2_2 145 non-null float64
18 NO2_3 32 non-null float64
19 NO2_4 31 non-null float64
20 NO2_5 33 non-null float64
21 NO2_6 37 non-null float64
22 NO2_7 37 non-null float64
23 NO3_1 145 non-null float64
24 NO3_2 145 non-null float64
25 NO3_3 32 non-null float64
26 NO3_4 31 non-null float64
27 NO3_5 33 non-null float64
28 NO3_6 37 non-null float64
29 NO3_7 37 non-null float64
30 BOD5_1 145 non-null float64
31 BOD5_2 145 non-null float64
32 BOD5_3 32 non-null float64
33 BOD5_4 31 non-null float64
34 BOD5_5 33 non-null float64
35 BOD5_6 37 non-null float64
36 BOD5_7 37 non-null float64
dtypes: float64(36), int64(1)
memory usage: 42.6 KB
欠損値の処理
data.isna().sum()
Id 0
target 0
O2_1 2
O2_2 2
O2_3 115
O2_4 116
O2_5 114
O2_6 110
O2_7 110
NH4_1 2
NH4_2 2
NH4_3 115
NH4_4 116
NH4_5 114
NH4_6 110
NH4_7 110
NO2_1 2
NO2_2 2
NO2_3 115
NO2_4 116
NO2_5 114
NO2_6 110
NO2_7 110
NO3_1 2
NO3_2 2
NO3_3 115
NO3_4 116
NO3_5 114
NO3_6 110
NO3_7 110
BOD5_1 2
BOD5_2 2
BOD5_3 115
BOD5_4 116
BOD5_5 114
BOD5_6 110
BOD5_7 110
dtype: int64
欠損値が100以上ある列は削除します。
null_columns = list(data.columns[data.isna().sum() > 100])
data = data.drop(null_columns, axis=1)
data
Id | target | O2_1 | O2_2 | NH4_1 | NH4_2 | NO2_1 | NO2_2 | NO3_1 | NO3_2 | BOD5_1 | BOD5_2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 12.58 | 9.875 | 9.20 | 0.690 | 1.040 | 0.0940 | 0.0990 | 1.58 | 1.825 | 4.80 | 5.850 |
1 | 3 | 9.37 | 10.300 | 10.75 | 0.710 | 0.725 | 0.0585 | 0.0515 | 1.21 | 0.905 | 5.88 | 6.835 |
2 | 4 | 8.35 | 8.290 | 7.90 | 2.210 | 2.210 | 0.1000 | 0.1100 | 1.34 | 1.250 | 3.20 | 2.700 |
3 | 5 | 9.57 | 8.820 | 6.80 | 0.595 | 0.675 | 0.0460 | 0.0535 | 0.59 | 0.790 | 7.70 | 7.055 |
4 | 6 | 6.00 | 6.000 | 6.50 | 0.600 | 0.900 | 0.1800 | 0.3400 | 1.36 | 1.820 | 5.50 | 5.300 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
142 | 208 | 6.80 | 7.700 | 7.50 | 0.380 | 1.900 | 0.6200 | 0.0640 | 2.80 | 3.330 | 5.00 | 5.800 |
143 | 211 | 5.30 | 6.300 | 5.65 | 0.370 | 0.500 | 0.6900 | 0.9500 | 4.37 | 3.160 | 8.00 | 8.000 |
144 | 212 | 8.60 | 8.600 | 11.00 | 2.400 | 3.600 | 0.1500 | 0.1400 | 0.53 | 3.000 | 6.80 | 7.200 |
145 | 213 | 9.90 | 9.600 | 14.10 | 0.310 | 0.500 | 0.2100 | 0.0800 | 3.10 | 3.500 | 5.20 | 7.800 |
146 | 214 | 6.50 | 6.500 | 7.70 | 0.190 | 0.260 | 0.1300 | 0.0720 | 0.00 | 0.000 | 3.40 | 4.100 |
147 rows × 12 columns
(data.isna().sum(axis=1) != 0).sum()
3
欠損値を含む行は3行だけなので、削除します。
data = data.dropna(axis=0)
不要な列の削除
data = data.drop('Id', axis=1)
X, Yデータの分割
y = data['target']
X = data.drop('target', axis=1)
スケーリング
scaler = sp.StandardScaler()
X = scaler.fit_transform(X)
トレーニング、テストデータの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7)
トレーニング
model = slm.LinearRegression()
model.fit(X_train, y_train)
model_R2 = model.score(X_test, y_test)
print('Model R^2 Score:', model_R2)
Model R^2 Score: -0.6563668417383994
次はyが高いか低いかの2値の予測をしてみます。
y
0 12.58
1 9.37
2 8.35
3 9.57
4 6.00
...
142 6.80
143 5.30
144 8.60
145 9.90
146 6.50
Name: target, Length: 144, dtype: float64
y_new = pd.qcut(y, q=2, labels=[0,1])
X_train, X_test, y_train, y_test = train_test_split(X, y_new, train_size=0.7)
model = slm.LogisticRegression()
model.fit(X_train, y_train)
model_acc = model.score(X_test, y_test)
print('Model Accuracy:', model_acc)
Model Accuracy: 0.8181818181818182