Notebook ini hanya contoh dan dibuat untuk pembelajaran mengenai Deep Learning/Neural Networks dan penggunaan praktis bidang sumberdaya air menggunakan Python. Notebook ini masih perlu dievaluasi kembali jika digunakan untuk kepenting riset/penelitian ataupun proyek.
taruma_demo_ann_ka_2.0.0
2.0.0
/20190713
0.2.0
3.7
Bagian ini akan menjelaskan gambaran umum mengenai dataset, permasalahan/tujuan, dan langkah penyelesaiannya
Dataset merupakan data kualitas air bulanan dari Juni 2000 hingga Desember 2017 (211 data bulanan). Dataset memiliki 15 kolom yaitu (berurutan):
1 kolom berupa tanggal
11 kolom independent variables yang diperoleh di stasiun A:
temp_udara
), lama penyinaran (lama_sinar
), kecepatan angin (kec_angin
), Qin (debit_masuk
), Qout (debit_keluar
), volume (volume
), temperatur air (temp_air
), O2, Oksigen (oksigen
), NO2, Nitrogen (nitrogen
), NO3, Nitrat (nitrat
), NH3, Amonia (amonia
).3 kolom dependent variables pada stasiun B:
out_nitrogen
), NO3, Nitrat (out_nitrat
), NH3, Amonia (out_amonia
).Permasalahan:
Batasan Masalah:
Pertanyaan:
Catatan: Dalam kasus ini akan digunakan 2 timesteps yang berarti data dua bulan yang lalu akan digunakan sebagai input untuk memprediksikan target pada waktu t.
pandas.DataFrame
.MinMaxScaler
karena diketahui data tidak terdistribusi normal.pandas.DataFrame
.X_train
dan y_train
. Dengan X_train
merupakan seluruh kolom kecuali nilai observasi dari stasiun B pada waktu t (kolom: out_nitrogen_tmin0, out_nitrat_tmin0, out_amonia_tmin0
) sebagai feature. Sedangkan y_train
merupakan kolom out_amonia_tmin0
sebagai target.build_model
yang memberikan fleksibilitas arsitektur sehingga memiliki hidden layer lebih dari satu dengan parameter hidden_layers
.GridSearchCV
untuk mengetahui parameter terbaik.fit
terhadap X_train, y_train
. Besarnya validation split yang digunakan sebesar 0.2.y_test
ke skala original dengan menggunakan method inverse_transform
. Hal ini dilakukan dengan mentransfer atribut MinMaxScaler
sebelumnya ke object baru, agar menyederhanakan proses pengembalian ke skala asli.Bagian ini merupakan pengaturan awal pribadi, dapat diabaikan.
from datetime import datetime
#### PROJECT DESCRIPTION
notebook_version = '2.0.0'
notebook_title = 'kualitas_air_ann_so' + '_' + notebook_version
prefix = datetime.utcnow().strftime("%Y%m%d_%H%M")
project_title = prefix + '_' + notebook_title
print(f'Judul Notebook: {notebook_title}')
print(f'Judul Proyek: {project_title}')
Judul Notebook: kualitas_air_ann_so_2.0.0 Judul Proyek: 20190713_0507_kualitas_air_ann_so_2.0.0
#### Memasang Akses Google Drive (untuk tempat menyimpan hasil training)
from google.colab import drive
drive.mount('/content/gdrive')
drop_path = '/content/gdrive/My Drive/Colab Notebooks/_dropbox'
#### Instalasi Paket Python Pribadi (untuk Logging)
#### https://github.com/taruma/umakit
!pip install umakit
from umakit.logtool import LogTool
mylog = LogTool()
mylog._reset()
#### Instalasi Paket Hidrokit (untuk plotting, dan transformasi kolom saat data preprocessing)
#### https://github.com/taruma/hidrokit
!pip install hidrokit
Collecting umakit Downloading https://files.pythonhosted.org/packages/76/64/d972d8fd9936a7a498c75e593d1986ec4d19204c84a636e5b5783c34806e/umakit-0.1.1-py3-none-any.whl Installing collected packages: umakit Successfully installed umakit-0.1.1 Collecting hidrokit Downloading https://files.pythonhosted.org/packages/43/9d/343d2a413a07463a21dd13369e31d664d6733bbfd46276abef5d804c83d1/hidrokit-0.2.0-py2.py3-none-any.whl Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (from hidrokit) (3.0.3) Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from hidrokit) (0.24.2) Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from hidrokit) (1.16.4) Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->hidrokit) (2.5.3) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->hidrokit) (0.10.0) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->hidrokit) (1.1.0) Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->hidrokit) (2.4.0) Requirement already satisfied: pytz>=2011k in /usr/local/lib/python3.6/dist-packages (from pandas->hidrokit) (2018.9) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.1->matplotlib->hidrokit) (1.12.0) Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from kiwisolver>=1.0.1->matplotlib->hidrokit) (41.0.1) Installing collected packages: hidrokit Successfully installed hidrokit-0.2.0
Ringkasan pada tahap ini:
#### Mengunggah dataset
from google.colab import files
uploaded = files.upload()
Saving data_ka.xlsx to data_ka.xlsx
#### 1. Import dataset ke pandas.DataFrame
import pandas as pd
## import dataset
dataset = pd.read_excel('data_ka.xlsx', skiprows=[0])
## Menamai kolom
dataset.columns = ["date", "temp_udara", "lama_sinar", "kec_angin",
"debit_masuk", "debit_keluar", "volume", "temp_air",
"oksigen", "nitrogen", "nitrat", "amonia",
"out_nitrogen", "out_nitrat", "out_amonia"]
## Mengatur index dataframe ke tanggal
dataset = dataset.set_index('date')
dataset.head(5)
temp_udara | lama_sinar | kec_angin | debit_masuk | debit_keluar | volume | temp_air | oksigen | nitrogen | nitrat | amonia | out_nitrogen | out_nitrat | out_amonia | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
date | ||||||||||||||
2000-06-20 | 26.5 | 6.050000 | 1.4 | 91.35 | 168.32 | 2.334285e+09 | 23.937500 | 5.062500 | 0.235750 | 0.481875 | 0.825375 | 0.326915 | 0.524643 | 0.589523 |
2000-07-20 | 25.2 | 4.366667 | 19.6 | 168.52 | 170.14 | 2.203561e+09 | 26.125000 | 5.237500 | 0.570500 | 0.620375 | 0.689125 | 0.730400 | 0.727771 | 0.602750 |
2000-08-20 | 26.9 | 7.616667 | 92.5 | 181.32 | 154.55 | 2.019619e+09 | 26.125000 | 4.912500 | 0.570500 | 0.620375 | 0.688750 | 0.700556 | 0.742150 | 0.627844 |
2000-09-20 | 26.4 | 5.100000 | 88.4 | 133.62 | 175.08 | 1.991705e+09 | 23.416667 | 3.145833 | 0.390292 | 0.463708 | 0.569583 | 0.175556 | 0.457229 | 0.430150 |
2000-10-20 | 25.2 | 6.233333 | 12.1 | 168.56 | 168.64 | 1.742853e+09 | 24.708333 | 3.739583 | 0.547202 | 0.531271 | 0.671292 | 0.583651 | 0.461479 | 0.559891 |
## Gamabaran umum dataset
dataset.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 211 entries, 2000-06-20 to 2017-12-13 Data columns (total 14 columns): temp_udara 210 non-null float64 lama_sinar 210 non-null float64 kec_angin 210 non-null float64 debit_masuk 210 non-null float64 debit_keluar 210 non-null float64 volume 210 non-null float64 temp_air 209 non-null float64 oksigen 210 non-null float64 nitrogen 189 non-null float64 nitrat 208 non-null float64 amonia 210 non-null float64 out_nitrogen 210 non-null float64 out_nitrat 208 non-null float64 out_amonia 210 non-null float64 dtypes: float64(14) memory usage: 24.7 KB
Dari dataset dapat disimpulkan:
Kolom date
digunakan sebagai acuan total jumlah data yang tersedia. Diketahui bahwa ada 211 data.
Kolom temp_udara
, lama_sinar
, kec_angin
, debit_masuk
, debit_keluar
, volume
, temp_air
, amonia
, out_nitrogen
, out_amonia
kehilangan 1 data, sehingga jumlah datanya hanya 210.
Kolom berikut memiliki kehilangan data lebih dari 1 data:
temp_air
: total: 209 data, kehilangan 2 data.nitrogen
: total: 189 data, kehilangan 22 data.nitrat
: total: 208 data, kehilangan 3 data.out_nitrat
: total: 208 data, kehilangan 3 data.from hidrokit.viz import graph
graph.subplots(dataset, ncols=1, nrows=14, figsize=(15, 15));
Dari grafik diatas terlihat ada data yang hilang.
## Memperoleh informasi kehilangan data
from hidrokit.prep import read
data_hilang = read.missing_row(dataset, date_format='%Y/%m')
print("Daftar kehilangan data:")
for column, value in data_hilang.items():
print(
"Kolom {}: {}".format(column, value)
)
Daftar kehilangan data: Kolom temp_udara: ['2005/12'] Kolom lama_sinar: ['2005/12'] Kolom kec_angin: ['2005/12'] Kolom debit_masuk: ['2005/12'] Kolom debit_keluar: ['2005/12'] Kolom volume: ['2005/12'] Kolom temp_air: ['2005/11', '2005/12'] Kolom oksigen: ['2005/12'] Kolom nitrogen: ['2005/12', '2007/04', '2007/05', '2007/06', '2007/07', '2007/08', '2007/09', '2007/10', '2007/11', '2007/12', '2008/01', '2008/02', '2008/03', '2008/04', '2008/05', '2008/06', '2008/07', '2008/08', '2008/09', '2008/10', '2008/11', '2008/12'] Kolom nitrat: ['2005/06', '2005/07', '2005/12'] Kolom amonia: ['2005/12'] Kolom out_nitrogen: ['2005/12'] Kolom out_nitrat: ['2005/06', '2005/07', '2005/12'] Kolom out_amonia: ['2005/12']
Dari proses diatas diperoleh informasi:
2005/12
(Desember 2005), data tidak tersedia pada seluruh kolom.temp_air
, kehilangan data pada 2005/11
(November 2005).nitrogen
, kehilangan data pada dari 2007/04
(April 2007) sampai 2008/12
(Desember 2008).nitrat
dan out_amonia
, kehilangan data pada 2005/06
(Juni 2005) dan 2005/07
(Juli 2005).`Diasumsikan bahwa data yang hilang dapat diisi dengan metode interpolasi linear. Dengan catatan metode tersebut digunakan dalam notebook ini untuk pembelajaran. Dimungkinkan untuk mengisi data hilang dengan teknik yang tersedia dalam bidang keahliannya.
## Mengisi Data yang hilang dengan metode linear
new_dataset = dataset.interpolate(method='linear')
# statistik deskriptif
new_dataset.describe()
temp_udara | lama_sinar | kec_angin | debit_masuk | debit_keluar | volume | temp_air | oksigen | nitrogen | nitrat | amonia | out_nitrogen | out_nitrat | out_amonia | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 211.000000 | 211.000000 | 211.000000 | 211.000000 | 211.000000 | 2.110000e+02 | 211.000000 | 211.000000 | 211.000000 | 211.000000 | 211.000000 | 211.000000 | 211.000000 | 211.000000 |
mean | 26.297867 | 5.429739 | 89.090929 | 192.909614 | 181.526661 | 2.184541e+09 | 27.805279 | 4.398493 | 0.144310 | 0.354018 | 0.391544 | 0.124222 | 0.369451 | 0.258836 |
std | 1.230595 | 2.653354 | 56.941944 | 129.691401 | 80.164627 | 4.316360e+08 | 1.592180 | 1.675356 | 0.322774 | 0.530511 | 0.709351 | 0.216860 | 0.591848 | 0.360054 |
min | 22.400000 | 0.000000 | 0.400000 | 4.100000 | 57.942000 | 9.531267e+08 | 20.897500 | 1.053250 | 0.000000 | 0.004000 | 0.000000 | 0.000000 | 0.004667 | 0.000000 |
25% | 25.750000 | 3.591667 | 47.350000 | 99.710000 | 135.915000 | 1.895588e+09 | 26.882917 | 3.125875 | 0.010000 | 0.070833 | 0.002958 | 0.006673 | 0.052589 | 0.002378 |
50% | 26.200000 | 5.750000 | 83.300000 | 158.800000 | 170.140000 | 2.224052e+09 | 27.812500 | 4.166667 | 0.022000 | 0.187000 | 0.089250 | 0.019494 | 0.143512 | 0.066165 |
75% | 27.000000 | 7.683333 | 125.400000 | 264.170000 | 201.090000 | 2.548267e+09 | 28.650000 | 5.683333 | 0.149181 | 0.540000 | 0.529875 | 0.085891 | 0.452636 | 0.448939 |
max | 29.150000 | 10.083333 | 365.900000 | 879.730000 | 673.060000 | 2.822702e+09 | 32.916667 | 9.000000 | 3.700000 | 5.822500 | 4.583333 | 1.164635 | 5.460060 | 2.252332 |
graph.subplots(new_dataset, ncols=1, nrows=14, figsize=(15, 15));
## Pairplot untuk melihat hubungan masing-masing kolom
import seaborn as sns
g = sns.pairplot(new_dataset)
g.fig.set_size_inches(15,15)
Dari visualisasi diatas diketahui bahwa terdapat kolom yang memiliki distribusi tidak normal, sehingga dalam scaling digunakan MinMaxScaler
.
MinMaxScaler
.X_train
dan y_train
.#### Import Libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
Dari new_dataset
yang telah diinterpolasi, akan dibagi menjadi dua bagian data yaitu training dan testing.
2000/06
hingga 2014/12
2015/01
hingga 2017/12
## Memisahkan dataset training dan test
training_dataset = new_dataset.loc[:"20141231", :]
test_dataset = new_dataset.loc["20150101":, :]
## Informasi training set dan testing set
print("Informasi training set: {} baris, {} kolom".format(
training_dataset.shape[0], training_dataset.shape[1])
)
print("Informasi testing set: {} baris, {} kolom".format(
test_dataset.shape[0], test_dataset.shape[1])
)
## Menampilkan training set
training_dataset.head()
Informasi training set: 175 baris, 14 kolom Informasi testing set: 36 baris, 14 kolom
temp_udara | lama_sinar | kec_angin | debit_masuk | debit_keluar | volume | temp_air | oksigen | nitrogen | nitrat | amonia | out_nitrogen | out_nitrat | out_amonia | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
date | ||||||||||||||
2000-06-20 | 26.5 | 6.050000 | 1.4 | 91.35 | 168.32 | 2.334285e+09 | 23.937500 | 5.062500 | 0.235750 | 0.481875 | 0.825375 | 0.326915 | 0.524643 | 0.589523 |
2000-07-20 | 25.2 | 4.366667 | 19.6 | 168.52 | 170.14 | 2.203561e+09 | 26.125000 | 5.237500 | 0.570500 | 0.620375 | 0.689125 | 0.730400 | 0.727771 | 0.602750 |
2000-08-20 | 26.9 | 7.616667 | 92.5 | 181.32 | 154.55 | 2.019619e+09 | 26.125000 | 4.912500 | 0.570500 | 0.620375 | 0.688750 | 0.700556 | 0.742150 | 0.627844 |
2000-09-20 | 26.4 | 5.100000 | 88.4 | 133.62 | 175.08 | 1.991705e+09 | 23.416667 | 3.145833 | 0.390292 | 0.463708 | 0.569583 | 0.175556 | 0.457229 | 0.430150 |
2000-10-20 | 25.2 | 6.233333 | 12.1 | 168.56 | 168.64 | 1.742853e+09 | 24.708333 | 3.739583 | 0.547202 | 0.531271 | 0.671292 | 0.583651 | 0.461479 | 0.559891 |
Menyimpan nilai dalam dataframe
dalam bentuk numpy.array
.
array_train = training_dataset.values
array_train[:1, :]
array([[2.65000000e+01, 6.05000000e+00, 1.40000000e+00, 9.13500000e+01, 1.68320000e+02, 2.33428460e+09, 2.39375000e+01, 5.06250000e+00, 2.35750000e-01, 4.81875000e-01, 8.25375000e-01, 3.26914583e-01, 5.24642857e-01, 5.89522917e-01]])
Skala yang digunakan adalah MinMaxScaler
.
#### Scaling dataset
from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range=(0,1))
array_train = sc.fit_transform(array_train)
array_train[:1, :]
array([[0.67213115, 0.6 , 0.00273598, 0.09964254, 0.17944199, 0.738755 , 0.31118314, 0.50451442, 0.19395311, 0.08149884, 0.19043453, 0.28070132, 0.09466023, 0.26173895]])
Setelah scaling, dataset dibuat kolom tambahan yang merepresentasikan data timesteps sebelumnya. Untuk kasus ini dipilih timesteps sebanyak 2 bulan sebelumnya. Sehingga persamaan umumnya berupa:
Outputt=f(Inputt,Inputt−1,Inputt−2,Outputt−1,Outputt−2)
Diketahui terdapat 14 kolom (termasuk output) dengan timesteps 2, sehingga dimensi array
menjadi 14×(2+1)=42.
Catatan:
_multi_column_timesteps()
# Membuat dataframe baru setelah proses scaling
training_dataset_scale = pd.DataFrame(
data=array_train,
columns=training_dataset.columns,
index=training_dataset.index
)
# Membuat tabel timesteps
from hidrokit.prep import timeseries
n_timesteps = 2
df_train_ts = timeseries.timestep_table(training_dataset_scale, timesteps=n_timesteps)
array_train_ts = df_train_ts.values
print("Dimensi array setelah diberi kolom timesteps: {}".format(array_train_ts.shape))
Dimensi array setelah diberi kolom timesteps: (173, 42)
Tabel pandas.DataFrame
untuk training set yang telah diberi kolom timesteps.
## Menampilkan hasil pemberian kolom timestep dengan pandas.DataFrame
df_train_ts.head()
temp_udara_tmin0 | temp_udara_tmin1 | temp_udara_tmin2 | lama_sinar_tmin0 | lama_sinar_tmin1 | lama_sinar_tmin2 | kec_angin_tmin0 | kec_angin_tmin1 | kec_angin_tmin2 | debit_masuk_tmin0 | debit_masuk_tmin1 | debit_masuk_tmin2 | debit_keluar_tmin0 | debit_keluar_tmin1 | debit_keluar_tmin2 | volume_tmin0 | volume_tmin1 | volume_tmin2 | temp_air_tmin0 | temp_air_tmin1 | temp_air_tmin2 | oksigen_tmin0 | oksigen_tmin1 | oksigen_tmin2 | nitrogen_tmin0 | nitrogen_tmin1 | nitrogen_tmin2 | nitrat_tmin0 | nitrat_tmin1 | nitrat_tmin2 | amonia_tmin0 | amonia_tmin1 | amonia_tmin2 | out_nitrogen_tmin0 | out_nitrogen_tmin1 | out_nitrogen_tmin2 | out_nitrat_tmin0 | out_nitrat_tmin1 | out_nitrat_tmin2 | out_amonia_tmin0 | out_amonia_tmin1 | out_amonia_tmin2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
date | ||||||||||||||||||||||||||||||||||||||||||
2000-08-20 | 0.737705 | 0.459016 | 0.672131 | 0.755372 | 0.433058 | 0.600000 | 0.251984 | 0.052531 | 0.002736 | 0.202391 | 0.187773 | 0.099643 | 0.157056 | 0.182401 | 0.179442 | 0.570447 | 0.668833 | 0.738755 | 0.535102 | 0.535102 | 0.311183 | 0.485639 | 0.526536 | 0.504514 | 0.469354 | 0.469354 | 0.193953 | 0.105319 | 0.105319 | 0.081499 | 0.158912 | 0.158998 | 0.190435 | 0.601524 | 0.627149 | 0.280701 | 0.134559 | 0.131922 | 0.094660 | 0.278753 | 0.267612 | 0.261739 |
2000-09-20 | 0.655738 | 0.737705 | 0.459016 | 0.505785 | 0.755372 | 0.433058 | 0.240766 | 0.251984 | 0.052531 | 0.147916 | 0.202391 | 0.187773 | 0.190432 | 0.157056 | 0.182401 | 0.555516 | 0.570447 | 0.668833 | 0.257869 | 0.535102 | 0.535102 | 0.263326 | 0.485639 | 0.526536 | 0.321096 | 0.469354 | 0.469354 | 0.078374 | 0.105319 | 0.105319 | 0.131417 | 0.158912 | 0.158998 | 0.150739 | 0.601524 | 0.627149 | 0.082294 | 0.134559 | 0.131922 | 0.190980 | 0.278753 | 0.267612 |
2000-10-20 | 0.459016 | 0.655738 | 0.737705 | 0.618182 | 0.505785 | 0.755372 | 0.032011 | 0.240766 | 0.251984 | 0.187819 | 0.147916 | 0.202391 | 0.179962 | 0.190432 | 0.157056 | 0.422409 | 0.555516 | 0.570447 | 0.390088 | 0.257869 | 0.535102 | 0.338042 | 0.263326 | 0.485639 | 0.450187 | 0.321096 | 0.469354 | 0.089994 | 0.078374 | 0.105319 | 0.154884 | 0.131417 | 0.158912 | 0.501145 | 0.150739 | 0.601524 | 0.083074 | 0.082294 | 0.134559 | 0.248583 | 0.190980 | 0.278753 |
2000-11-20 | 0.475410 | 0.459016 | 0.655738 | 0.140496 | 0.618182 | 0.505785 | 0.153762 | 0.032011 | 0.240766 | 0.425397 | 0.187819 | 0.147916 | 0.170468 | 0.179962 | 0.190432 | 0.491497 | 0.422409 | 0.555516 | 0.522307 | 0.390088 | 0.257869 | 0.412758 | 0.338042 | 0.263326 | 0.509941 | 0.450187 | 0.321096 | 0.101614 | 0.089994 | 0.078374 | 0.178350 | 0.154884 | 0.131417 | 0.650329 | 0.501145 | 0.150739 | 0.072670 | 0.083074 | 0.082294 | 0.306186 | 0.248583 | 0.190980 |
2000-12-20 | 0.803279 | 0.475410 | 0.459016 | 0.598347 | 0.140496 | 0.618182 | 0.010397 | 0.153762 | 0.032011 | 0.072725 | 0.425397 | 0.187819 | 0.197715 | 0.170468 | 0.179962 | 0.552404 | 0.491497 | 0.422409 | 0.553229 | 0.522307 | 0.390088 | 0.465789 | 0.412758 | 0.338042 | 0.448015 | 0.509941 | 0.450187 | 0.122696 | 0.101614 | 0.089994 | 0.127495 | 0.178350 | 0.154884 | 0.547268 | 0.650329 | 0.501145 | 0.096521 | 0.072670 | 0.083074 | 0.275712 | 0.306186 | 0.248583 |
X_train
dan y_train
¶Berdasarkan persamaan sebelumnya, kolom output pada waktu t harus dipisahkan sebagai label training-nya. Dan karena dalam kasus ini fokus pada single-output, maka kolom output yang digunakan sebagai target hanya out_amonia_tmin0
.
## Pembagian X_train dan y_train untuk
## Kasus Single-Output Regression Neural Network
target_col = ["out_amonia_tmin0"]
drop_col = ["out_nitrogen_tmin0", "out_nitrat_tmin0", "out_amonia_tmin0"]
df_X_train = df_train_ts.drop(drop_col, axis=1)
df_y_train = df_train_ts[target_col]
X_train = df_X_train.values
y_train = df_y_train.values.flatten()
print(f"Dimensi X_train = {X_train.shape}")
print(f"Dimensi y_train = {y_train.shape}")
Dimensi X_train = (173, 39) Dimensi y_train = (173,)
Catatan: Terdapat __39 _features___ dengan __1 _target___.
build_model
.GridSearchCV
.fit
terhadap X_train, y_train
build_model
¶from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.wrappers.scikit_learn import KerasRegressor
def build_model(optimizer='adam', activation='sigmoid', first_layer=10,
hidden_layers=[30], p=0, message=True):
global idx
model = Sequential()
model.add(Dense(first_layer, activation=activation, input_dim=39))
model.add(Dropout(p))
if hidden_layers:
for x in hidden_layers:
model.add(Dense(x, activation=activation))
if x == hidden_layers[-1]:
model.add(Dropout(p/2))
else:
model.add(Dropout(p))
model.add(Dense(1))
model.compile(optimizer=optimizer, loss='mean_squared_error',
metrics=['mse', 'mae'])
if message and ('idx' in globals()):
print(f"{idx}>", end="")
idx -= 1
if (idx % 10) == 0:
print()
return model
model = KerasRegressor(build_fn=build_model, verbose=0)
Using TensorFlow backend.
GridSearchCV
¶from sklearn.model_selection import GridSearchCV
param_grid = dict(epochs=[100, 150, 200],
batch_size=[5, 10, 20],
first_layer=[10, 20, 30],
hidden_layers=[[20], [30]],
activation=['sigmoid'],
optimizer=['adam'],
)
# Ignore K-Fold Cross Validation
cv = [(slice(None), slice(None))]
# cv = 3
grid_search = GridSearchCV(estimator=model,
param_grid=param_grid,
cv=cv,
return_train_score=True,
verbose=1,
scoring='neg_mean_squared_error',
)
Fit
¶Fitting
¶# idx
search_steps = 1
for key, val in param_grid.items():
search_steps *= len(val)
idx = search_steps*cv if (type(cv) is int) else search_steps
# Fitting
print(mylog.add_savepoint("START FITTING", 'fit'))
grid_search = grid_search.fit(X_train, y_train, verbose=0, validation_split=0.2)
print(mylog.add_savepoint("END FITTING", 'fit'))
print(mylog.add_duration('fit'))
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers. WARNING: Logging before flag parsing goes to stderr. W0713 05:12:41.348032 140582811764608 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:74: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead. W0713 05:12:41.400704 140582811764608 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:517: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead. W0713 05:12:41.409335 140582811764608 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:4138: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead. W0713 05:12:41.464263 140582811764608 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/keras/optimizers.py:790: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.
[2019-07-13 05:12:41] START FITTING Fitting 1 folds for each of 54 candidates, totalling 54 fits 54>
W0713 05:12:42.024242 140582811764608 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:986: The name tf.assign_add is deprecated. Please use tf.compat.v1.assign_add instead. W0713 05:12:42.117183 140582811764608 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:973: The name tf.assign is deprecated. Please use tf.compat.v1.assign instead.
53>52>51> 50>49>48>47>46>45>44>43>42>41> 40>39>38>37>36>35>34>33>32>31> 30>29>28>27>26>25>24>23>22>21> 20>19>18>17>16>15>14>13>12>11> 10>9>8>7>6>5>4>3>2>1>
[Parallel(n_jobs=1)]: Done 54 out of 54 | elapsed: 5.5min finished
0>[2019-07-13 05:18:28] END FITTING 0:5:46
# Menyimpan object keras di final_model
final_model = grid_search.best_estimator_.model
# Simpan hasil grid search pada dataframe
df_cv = pd.DataFrame(grid_search.cv_results_)
# Save Model in JSON
fmodel_json = final_model.to_json()
fmodel_j_path = drop_path + '/{}.json'.format(project_title)
with open(fmodel_j_path, 'w') as json_file:
json_file.write(fmodel_json)
mylog.add(f'Model JSON disimpan di {fmodel_j_path}')
print('save: {}'.format(fmodel_j_path))
# Save Weights of model
fmodel_w_path = drop_path + '/{}_weights.h5'.format(project_title)
final_model.save_weights(fmodel_w_path)
mylog.add(f'Model Weights disimpan di {fmodel_w_path}')
print('save: {}'.format(fmodel_w_path))
# Simpan model dan grid_search object
save_model_path = drop_path + '/' + project_title + '.h5'
final_model.save(save_model_path)
mylog.add(f'Model disimpan di {save_model_path}')
print('save: {}'.format(save_model_path))
# Simpan hasil GridSearch
save_grid_path = drop_path + '/{}.csv'.format(project_title)
df_cv.to_csv(save_grid_path)
mylog.add(f'Tabel GridSearch disimpan di {save_grid_path}')
print('save: {}'.format(save_grid_path))
save: /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0.json save: /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0_weights.h5 save: /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0.h5 save: /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0.csv
# load_model_path = drop_path + '/20190512_2037_kualitas_air_ann_so.h5'
# load_cvgrid_path = drop_path + '/20190512_2037_kualitas_air_ann_so.csv'
# from keras.models import load_model
# final_model = load_model(load_model_path)
# df_cv = pd.read_csv(load_cvgrid_path, index_col=[0])
# df_cv.head()
## Menampilkan test dataset
test_dataset.head()
temp_udara | lama_sinar | kec_angin | debit_masuk | debit_keluar | volume | temp_air | oksigen | nitrogen | nitrat | amonia | out_nitrogen | out_nitrat | out_amonia | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
date | ||||||||||||||
2015-01-14 | 25.5 | 4.500000 | 127.68 | 214.64 | 137.25 | 2.174360e+09 | 26.833333 | 4.666667 | 0.0125 | 0.0675 | 0.100000 | 0.014000 | 0.261190 | 0.088036 |
2015-02-16 | 25.6 | 3.833333 | 68.64 | 105.93 | 162.18 | 2.256351e+09 | 29.666667 | 5.833333 | 0.0175 | 0.1075 | 0.441667 | 0.012631 | 0.152798 | 0.578571 |
2015-03-16 | 25.4 | 5.500000 | 121.68 | 127.03 | 114.78 | 2.422154e+09 | 28.416667 | 4.666667 | 0.0040 | 0.0600 | 0.100000 | 0.005214 | 0.109405 | 0.153452 |
2015-04-14 | 25.4 | 3.500000 | 128.88 | 291.23 | 269.31 | 2.751982e+09 | 28.333333 | 4.150000 | 0.0080 | 0.3350 | 0.050000 | 0.005286 | 0.308036 | 0.102560 |
2015-05-12 | 23.2 | 9.666667 | 151.20 | 277.62 | 205.84 | 2.724559e+09 | 29.000000 | 6.000000 | 0.0055 | 0.3100 | 0.191667 | 0.004143 | 0.069940 | 0.165476 |
## pandas.DataFrame ke numpy.array
array_test = test_dataset.values
array_test = sc.transform(array_test)
test_dataset_scale = pd.DataFrame(
data=array_test,
columns=test_dataset.columns,
index=test_dataset.index
)
## timestep table
df_test = timeseries.timestep_table(test_dataset_scale, timesteps=n_timesteps)
array_test_ts = df_test.values
df_test.head()
temp_udara_tmin0 | temp_udara_tmin1 | temp_udara_tmin2 | lama_sinar_tmin0 | lama_sinar_tmin1 | lama_sinar_tmin2 | kec_angin_tmin0 | kec_angin_tmin1 | kec_angin_tmin2 | debit_masuk_tmin0 | debit_masuk_tmin1 | debit_masuk_tmin2 | debit_keluar_tmin0 | debit_keluar_tmin1 | debit_keluar_tmin2 | volume_tmin0 | volume_tmin1 | volume_tmin2 | temp_air_tmin0 | temp_air_tmin1 | temp_air_tmin2 | oksigen_tmin0 | oksigen_tmin1 | oksigen_tmin2 | nitrogen_tmin0 | nitrogen_tmin1 | nitrogen_tmin2 | nitrat_tmin0 | nitrat_tmin1 | nitrat_tmin2 | amonia_tmin0 | amonia_tmin1 | amonia_tmin2 | out_nitrogen_tmin0 | out_nitrogen_tmin1 | out_nitrogen_tmin2 | out_nitrat_tmin0 | out_nitrat_tmin1 | out_nitrat_tmin2 | out_amonia_tmin0 | out_amonia_tmin1 | out_amonia_tmin2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
date | ||||||||||||||||||||||||||||||||||||||||||
2015-03-16 | 0.491803 | 0.524590 | 0.508197 | 0.545455 | 0.380165 | 0.446281 | 0.331819 | 0.186703 | 0.348235 | 0.140390 | 0.116293 | 0.240444 | 0.092402 | 0.169460 | 0.128931 | 0.785755 | 0.697070 | 0.653214 | 0.769684 | 0.897637 | 0.607609 | 0.454704 | 0.601514 | 0.454704 | 0.003291 | 0.014397 | 0.010284 | 0.008943 | 0.017112 | 0.010233 | 0.023072 | 0.101903 | 0.023072 | 0.004477 | 0.010845 | 0.012021 | 0.018490 | 0.026450 | 0.046333 | 0.068130 | 0.256877 | 0.039086 |
2015-04-14 | 0.491803 | 0.491803 | 0.524590 | 0.347107 | 0.545455 | 0.380165 | 0.351518 | 0.331819 | 0.186703 | 0.327912 | 0.140390 | 0.116293 | 0.343622 | 0.092402 | 0.169460 | 0.962174 | 0.785755 | 0.697070 | 0.761153 | 0.769684 | 0.897637 | 0.389688 | 0.454704 | 0.601514 | 0.006582 | 0.003291 | 0.014397 | 0.056239 | 0.008943 | 0.017112 | 0.011536 | 0.023072 | 0.101903 | 0.004539 | 0.004477 | 0.010845 | 0.054926 | 0.018490 | 0.026450 | 0.045535 | 0.068130 | 0.256877 |
2015-05-12 | 0.131148 | 0.491803 | 0.491803 | 0.958678 | 0.347107 | 0.545455 | 0.412585 | 0.351518 | 0.331819 | 0.312369 | 0.327912 | 0.140390 | 0.240438 | 0.343622 | 0.092402 | 0.947506 | 0.962174 | 0.785755 | 0.829395 | 0.761153 | 0.769684 | 0.622487 | 0.389688 | 0.454704 | 0.004525 | 0.006582 | 0.003291 | 0.051939 | 0.056239 | 0.008943 | 0.044222 | 0.011536 | 0.023072 | 0.003557 | 0.004539 | 0.004477 | 0.011251 | 0.054926 | 0.018490 | 0.073469 | 0.045535 | 0.068130 |
2015-06-15 | 0.131148 | 0.131148 | 0.491803 | 0.595041 | 0.958678 | 0.347107 | 0.268126 | 0.412585 | 0.351518 | 0.076288 | 0.312369 | 0.327912 | 0.225222 | 0.240438 | 0.343622 | 0.852032 | 0.947506 | 0.962174 | 0.820865 | 0.829395 | 0.761153 | 0.622487 | 0.622487 | 0.389688 | 0.004525 | 0.004525 | 0.006582 | 0.064838 | 0.051939 | 0.056239 | 0.010383 | 0.044222 | 0.011536 | 0.004079 | 0.003557 | 0.004539 | 0.014790 | 0.011251 | 0.054926 | 0.020981 | 0.073469 | 0.045535 |
2015-07-08 | 0.147541 | 0.131148 | 0.131148 | 0.909091 | 0.595041 | 0.958678 | 0.274692 | 0.268126 | 0.412585 | 0.083951 | 0.076288 | 0.312369 | 0.206770 | 0.225222 | 0.240438 | 0.721174 | 0.852032 | 0.947506 | 0.675851 | 0.820865 | 0.829395 | 0.402271 | 0.622487 | 0.622487 | 0.011929 | 0.004525 | 0.004525 | 0.077450 | 0.064838 | 0.051939 | 0.005903 | 0.010383 | 0.044222 | 0.003772 | 0.004079 | 0.003557 | 0.032990 | 0.014790 | 0.011251 | 0.035138 | 0.020981 | 0.073469 |
## Pembagian X_test dan y_test untuk
## Kasus Single-Output Regression Neural Network
## Meninjau output_amonia
df_X_test = df_test.drop(drop_col, axis=1)
df_y_test = df_test[target_col]
X_test = df_X_test.values
y_test = df_y_test.values.flatten()
print(f"Dimensi X_test = {X_test.shape}")
print(f"Dimensi y_test = {y_test.shape}")
Dimensi X_test = (34, 39) Dimensi y_test = (34,)
# Prediksi
predict = final_model.predict(X_test)
truth = y_test
digunakan istilah predict sebagai nilai prediksi dari final_model
, dan truth sebagai nilai observasi di stasiun B.
# Transfer attribute from MinMax Scaler (specific for last column (output) only)
sc_test = MinMaxScaler()
sc_test.min_, sc_test.scale_, sc_test.data_min_, sc_test.data_max_ = sc.min_[-1], sc.scale_[-1], sc.data_min_[-1], sc.data_max_[-1]
# Mengembalikan ke skala original
predict_real = sc_test.inverse_transform(predict.reshape(-1,1))
truth_real = sc_test.inverse_transform(truth.reshape(-1,1))
Nilai -1
menunjukkan posisi kolom out_amonia
saat melakukan proses fit
pada object sc
(MinMaxScaler
).
# Dalam bentuk pandas.DataFrame
diff_table = pd.DataFrame(dict(predict=predict_real.flatten(),
truth=truth_real.flatten(),
))
diff_table['diff'] = (diff_table.predict - diff_table.truth).abs()
diff_table.T
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
predict | 0.134772 | 0.007490 | 0.126282 | 0.135084 | -0.045286 | -0.120056 | -0.088197 | -0.075257 | -0.155297 | 0.050850 | -0.098553 | 0.057096 | 0.295761 | 0.936239 | 0.550550 | 0.525928 | 0.559572 | 1.919800 | 0.140484 | 0.411405 | 0.223667 | 0.082912 | 0.081793 | 0.311751 | 1.256571 | 0.976631 | 0.184832 | 0.065627 | 0.058785 | 0.049092 | 0.379010 | 0.125497 | 0.073648 | -0.202659 |
truth | 0.153452 | 0.102560 | 0.165476 | 0.047256 | 0.079143 | 0.041720 | 0.029899 | 0.046929 | 0.001708 | 0.091464 | 0.218690 | 0.633333 | 0.156119 | 1.080952 | 0.880655 | 0.860714 | 1.204286 | 0.744643 | 1.085387 | 0.350446 | 0.112875 | 0.104708 | 0.096542 | 0.336958 | 0.414250 | 0.647083 | 0.028232 | 0.017208 | 0.033149 | 0.034988 | 0.032571 | 0.052371 | 0.025548 | 0.013155 |
diff | 0.018681 | 0.095069 | 0.039195 | 0.087828 | 0.124429 | 0.161776 | 0.118095 | 0.122186 | 0.157005 | 0.040615 | 0.317244 | 0.576238 | 0.139642 | 0.144713 | 0.330105 | 0.334786 | 0.644714 | 1.175157 | 0.944903 | 0.060958 | 0.110792 | 0.021796 | 0.014749 | 0.025207 | 0.842321 | 0.329548 | 0.156600 | 0.048419 | 0.025636 | 0.014104 | 0.346439 | 0.073126 | 0.048101 | 0.215814 |
metrics_train = final_model.evaluate(X_train, y_train, verbose=0)
metrics_test = final_model.evaluate(X_test, y_test, verbose=0)
for i, metrics in enumerate(final_model.metrics_names):
print(f"Metrics: {metrics}")
print(f"Train: {metrics_train[i]:.5f}")
print(f"Test: {metrics_test[i]:.5f}")
print()
Metrics: loss Train: 0.00403 Test: 0.02630 Metrics: mean_squared_error Train: 0.00403 Test: 0.02630 Metrics: mean_absolute_error Train: 0.04247 Test: 0.10324
Fungsi loss
yang digunakan saat training adalah mean_squared error
. Dari informasi diatas diketahui bahwa nilai MSE dan MAE pada saat training hampir mendekati 0. Perlu dicatat bahwa nilai tersebut berdasarkan nilai yang telah ditransformasi dengan metode MinMaxScaler
.
## menghitung MSE dan MAE test set dengan skala original
from sklearn.metrics import mean_squared_error, mean_absolute_error
mse_real = mean_squared_error(truth_real, predict_real)
mae_real = mean_absolute_error(truth_real, predict_real)
print(f"MSE (Original Scale): {mse_real:.4f}")
print(f"MAE (Original Scale): {mae_real:.4f}")
MSE (Original Scale): 0.1334 MAE (Original Scale): 0.2325
#### PLOT OUT_AMONIA PREDICTION AND TRUTH (OBSERVED VALUE)
plt.plot(truth_real, 'r--', label='truth')
plt.plot(predict_real, 'b', label='predict')
plt.title('Grafik Nilai Prediksi dan Observasi')
plt.legend()
plt.show()
Dari grafik diatas diketahui bahwa final_model
mampu mengikuti fluktuasi data observasi.
# PLOT TRUTH vs. PREDICT
plt.scatter(y=predict_real, x=truth_real)
plt.xlabel('Truth Value')
plt.ylabel('Prediction Value')
plt.title('Plot Titik Prediksi dan Observasi')
plt.show()
# Menggunakan seaborn
sns.jointplot(x='truth', y='predict', kind='reg', data=diff_table);
Dari dua grafik diatas terlihat bahwa terdapat hasil prediksi yang negatif meski pada kejadian nyata bahwa nilai negatif tidak mungkin untuk kualitas air.
# statistik deskriptif nilai Beda (Residu)
diff_table['diff'].describe()
count 34.000000 mean 0.232529 std 0.285942 min 0.014104 25% 0.048180 50% 0.123307 75% 0.326472 max 1.175157 Name: diff, dtype: float64
# plot histogram
diff = diff_table['diff'].values
plt.hist(diff)
plt.xlabel('Nilai Beda/Residu')
plt.ylabel('Frekuensi')
plt.title('Histogram Residu Nilai Prediksi dan Asli')
plt.show()
# menghilangkan [] pada hidden layers di df_cv
df_cv['param_hidden_layers'] = df_cv['param_hidden_layers'].apply(lambda x: (str(x)[1:-1]) if str(x)[0] == '[' else x)
# memilih kolom yang akan digunakan untuk interpretasi
col_grid = ['param_activation', 'param_batch_size', 'param_epochs',
'param_first_layer', 'param_hidden_layers', 'param_optimizer',
'mean_test_score', 'rank_test_score'
]
df_grid = df_cv[col_grid]
print(df_grid.shape)
df_grid.head()
(54, 8)
param_activation | param_batch_size | param_epochs | param_first_layer | param_hidden_layers | param_optimizer | mean_test_score | rank_test_score | |
---|---|---|---|---|---|---|---|---|
0 | sigmoid | 5 | 100 | 10 | 20 | adam | -0.004687 | 22 |
1 | sigmoid | 5 | 100 | 10 | 30 | adam | -0.005299 | 31 |
2 | sigmoid | 5 | 100 | 20 | 20 | adam | -0.004517 | 17 |
3 | sigmoid | 5 | 100 | 20 | 30 | adam | -0.004670 | 21 |
4 | sigmoid | 5 | 100 | 30 | 20 | adam | -0.006117 | 37 |
# mengurutkan berdasarkan mean_test_score / rank_test_score
df_grid_sorted = df_grid.sort_values('rank_test_score')
df_grid_sorted.head()
param_activation | param_batch_size | param_epochs | param_first_layer | param_hidden_layers | param_optimizer | mean_test_score | rank_test_score | |
---|---|---|---|---|---|---|---|---|
14 | sigmoid | 5 | 200 | 20 | 20 | adam | -0.003704 | 1 |
16 | sigmoid | 5 | 200 | 30 | 20 | adam | -0.003746 | 2 |
17 | sigmoid | 5 | 200 | 30 | 30 | adam | -0.003886 | 3 |
13 | sigmoid | 5 | 200 | 10 | 30 | adam | -0.003978 | 4 |
29 | sigmoid | 10 | 150 | 30 | 30 | adam | -0.004032 | 5 |
# hasil grid terburuk
df_grid_sorted.tail()
param_activation | param_batch_size | param_epochs | param_first_layer | param_hidden_layers | param_optimizer | mean_test_score | rank_test_score | |
---|---|---|---|---|---|---|---|---|
40 | sigmoid | 20 | 100 | 30 | 20 | adam | -0.008445 | 50 |
42 | sigmoid | 20 | 150 | 10 | 20 | adam | -0.009949 | 51 |
18 | sigmoid | 10 | 100 | 10 | 20 | adam | -0.009951 | 52 |
36 | sigmoid | 20 | 100 | 10 | 20 | adam | -0.010798 | 53 |
37 | sigmoid | 20 | 100 | 10 | 30 | adam | -0.012189 | 54 |
GridSearchCV
¶# evaluasi 20 hasil terbaik
df_grid_top = df_grid_sorted.iloc[:20,:].copy()
# menghitung nilai unik tiap kolom
for col in df_grid_top.columns[:-2]:
print(df_grid_top[col].value_counts())
sigmoid 20 Name: param_activation, dtype: int64 5 10 10 8 20 2 Name: param_batch_size, dtype: int64 200 10 150 7 100 3 Name: param_epochs, dtype: int64 30 9 10 6 20 5 Name: param_first_layer, dtype: int64 20 13 30 7 Name: param_hidden_layers, dtype: int64 adam 20 Name: param_optimizer, dtype: int64
# Grafik antara rank_test_score dan mean_test_score
sns.set(style='ticks')
relplot = sns.relplot(x='rank_test_score', y='mean_test_score', data=df_grid, kind='line')
plt.gca().set_title("Kurva antara rank_test_score dengan mean_test_score")
plt.gca().invert_xaxis()
Model terbaik diperoleh dengan parameter:
sigmoid
5
200
20
20
adam
Dalam evaluasi model dengan test set diperoleh informasi:
diff
) sebesar 0.232529 (MAE), dengan standar deviasi sebesar 0.285942.relu
sehingga tidak mengeluarkan hasil negatif.# Log summary
print(mylog.summary())
[2019-07-13 05:12:41] START FITTING [2019-07-13 05:18:28] END FITTING [2019-07-13 05:18:28] Duration: 0:5:46 [2019-07-13 05:18:39] Model JSON disimpan di /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0.json [2019-07-13 05:18:40] Model Weights disimpan di /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0_weights.h5 [2019-07-13 05:18:42] Model disimpan di /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0.h5 [2019-07-13 05:18:42] Tabel GridSearch disimpan di /content/gdrive/My Drive/Colab Notebooks/_dropbox/20190713_0507_kualitas_air_ann_so_2.0.0.csv
- 20190713 - 2.0.0 - Use hidrokit 0.2.0. refactoring document/code.
- 20190622 - 1.1.0 - Copyright/License notice
- 20190414 - 1.0.0 - Initial
Source code in this notebook is licensed under a MIT License. Data in this notebook is licensed under a Creative Common Attribution 4.0 International.