洗濯物などの乾燥時間の機械学習を行ってみます。
できるだけシンプルなモデルを設定し、機械学習後のパラメータがどうなっているかも確認してみます。
以下の環境で動作確認をしています。
環境:
・ Windows 11 パソコン(GPU つき)
・ Anaconda (conda)、Python、Tensorflow のインストール済み
背景 ~ 洗濯物が乾くまでの時間を予測してみる
日頃、洗濯をするとき、何時間くらいで乾くのかなと思うことがあります。
天気はつねに変わりますし、乾燥時間によっては自分の予定が変わることもあります。
そこで、洗濯物が乾燥する時間について、ネット検索をすると、「夏は2~3時間で乾きます」、「春のカラッとした日は5時間で乾きます」といった非常にアバウトな情報が大半です。
季節ごとに、温度、湿度の平均はこれくらいで、乾燥時間は何時間くらいかかるとか、風速強め、日照量高めならどれくらい短くなるかなど、もう少し、定量的で具体的な内容を知りたいところです。
一方、乾燥という現象を高校や大学の物理の知識で扱おうとすると、なかなか一筋縄ではいかないようです。乾燥に影響する物理現象が複数あり、洗濯物が薄手か厚手かでも結果が変わります。簡素化した計算式を自力で作ったとしても変数が多く、係数の特定など、妥当なモデルに落とし込むには時間がかかりそうです。
といったところで、「乾燥現象のモデルを機械学習で作ってみたらどうなるだろうか」とふと思ったので、やってみることにします。
基本的な考え方
・ ニューラルネットワーク(Tensorflow)を使って、乾燥時間の機械学習を行います。
・ 機械学習のモデルは、余計なパラメータを減らし、できるだけシンプルなものとします。
・ 一方、乾燥に影響する主要なパラメータは設定できるようにします。
具体的には、温度、湿度、風速、日照量、洗濯物の種別を設定できるようにし、乾燥に関する多くの環境や条件を網羅できるようにします。
・ 物理現象という観点で見た場合であっても、大きな矛盾のないモデル化を試みることにします。
例えば、他の条件を変えずに温度だけを上げていくと乾燥時間は単調減少となるはずです。他も同様です。
・ 学習済みモデルについては、内部の係数を出力するようにします。
例えば、実用上使えそうな程度のモデル化ができたら、出力された係数を流用して、Excel や JavaScript などで自力でもシミュレーションができるようにします。
設定方法
まずは、動くスクリプトを準備してしまうのが話が早いです。
① 以下を参考に、乾燥時間の検討用のフォルダを作成します。
例: c:\user\tensorflow1\drying_parameters1\
② ①のフォルダに、以下の3つの名前でテキストファイルを作成し、下記のスクリプト等を貼りつけて保存します。
[a] drying_parameters1.txt
[b] drying_calculation1.py
[c] drying_calculation1.html
例: c:\user\tensorflow1\drying_parameters1\drying_parameters1.txt、drying_calculation1.py、drying_calculation1.html
※ [a] は、機械学習用の教師データです。空行があるとスキップするようにしてあります。
※ [b] は、機械学習と予測を行うスクリプトです。[c] は、結果を表示するための HTML ファイルです。
[c] は参考程度で作っただけですので、なくても機械学習自体は可能です。
実行方法
③ コマンドプロンプト(または、Anaconda プロンプト)を起動し、②のスクリプトを実行します。
例: python c:\user\tensorflow1\drying_parameters1\drying_calculation1.py
→ 機械学習の実行後、結果のグラフ等が出力されたら成功です。
うまく動いたら
・ うまく動いたら、教師データと、出力結果のグラフなどを確認してみてください。教師データは、東京での気象庁の実測データと各季節ごとの乾燥時間を設定して作ってあります。
・ また、お住まいの地域の環境に合わせて教師データを調整・追加するなどして、機械学習を行ってみてください。たとえば、東京より寒冷/温暖な地域に住んでいる、部屋干しのデータを充実させたい、などといった場合は、以下の記載を参考に教師データを作成してみてください。
・ また、今回は、洗濯物を例にとって教師データを作ってありますが、乾燥させる対象を差し替えたり、データ数を追加・削除したり、乾燥現象以外に転用する等も可能です。
結果
上記の教師データとスクリプトを用いて得られた結果の一例を以下に示します。
・ fig.1 が、設定した教師データと機械学習後の出力を比較したものです。横軸はサンプル番号で、何番目の教師データかに対応しています。縦軸は乾燥時間です。
・ fig.2 ~ fig.6 は、温度、湿度、風速、日照量、洗濯物の種別を変えた場合の計算結果です。各グラフの上部に、他の変数の設定値を表示しています。温度、湿度などを任意に変えることで、どのように乾燥時間が変化するのか、予測することが可能です。
備考1:その他
出力データについて
・ 出力結果は、drying_calculation1.html をダブルクリックすると参照できるようにしてあります。
再計算をした場合は、ブラウザの「更新」ボタンで再表示させてください。
・ グラフ fitting1.png は、教師データと機械学習後のモデルの出力を比較したものです。
横軸は、サンプル番号に対応しています。つまり、教師データで使用するデータ数を n1 とすると、横軸は 1, 2, … n1 としています。縦軸は乾燥時間です。教師データと予測結果の2つのプロファイルを示しています。
・ 機械学習を行うと、学習済みモデル(model1.hdf5)を保存します。
機械学習が十分にできたら、Python のスクリプト中で、fitting1 = True としているところで fitting = False に書き換えます。すると、学習はスキップし、すでに保存されている学習済みモデル(model1.hdf5)を読み込めるようにしています。
・ 機械学習の学習時には、ニューラルネットワークの内部のパラメータ(model1_weights.txt、model1_weights.json、model1_config.json)も出力するようにしています。
・ 内部のパラメータ model1_weights.txt には、ニューラルネットワークの内部の数値を書き出しています。テキスト形式(*.txt)と JSON 形式(*.json)の2つを出力しています。
・ 機械学習を終えると、つぎに、温度、湿度等を変化させた場合の予測を行うようにしています。
具体的には、Python のスクリプト内で、まず、以下の例のような典型値を設定します。
典型値の例: 温度:20℃、湿度:20%、風速:3m/s、日照量:50%、洗濯物の種別:0(薄手のもの)
つぎに、典型値で1つの変数のみを変化させて、予測値を計算してグラフを出力します。
具体的には、温度のみを変化させて予測値を求め、グラフ predicted1.png を出力します。
湿度、風速、日照量、洗濯物の種別についても同様に、グラフ predicted3.png ~ predicted5.png を出力します。
考察
・ テストデータは今回作っていませんが、乾燥時間のずれ量は1時間程度以内となっており、実用上使える程度の機械学習はできていると考えられます。
・ ずれ量が大きい項目については、以下の可能性が考えられます。
(a) 教師データの作り方に改善の余地がある
(b) 機械学習のモデルがシンプルであるため現象を表現しきれない
(c) シンプルなモデルを当てはめると外れ値となっている(教師データに矛盾がないか確認をしたほうがよい)
(d) その他
・ 今回は初回の試みであり、何が問題かといった課題の洗い出しも行っていません。今後、実用で使っていくことを優先し、不都合などがあれば問題を洗い出し、モデルやデータ全体を見直してアップデートしていく、といったアプローチでよいと考えられます。
・ fig.2 ~ fig.6 で、温度、風速、日照量の増加につれ、乾燥時間が短くなっています。また、湿度、洗濯物の種別の値の増加につれ、乾燥時間が長くなっています。常識的な結果となっており、妥当な機械学習ができているといえます。
・ fig.2 ~ fig.6 で各グラフの結果が直線となっています。これは、機械学習のモデルを極力シンプルにしたためです。具体的には、ReLU、Sigmoid などの非線形関数を入れていないためです。計算式の定義などについて、後述の式 (*04)、(*06) あたりでまとめておきますが、ニューラルネットワークの定義自体が、独立変数の一次式で書かれていることに起因しています。
乾燥現象程度であれば、線形近似でベストフィットしてしまったほうが各独立変数の係数、効き具合が数値で把握できて見通しがよいため、十分といえます。
・ 日々の温湿度などの変動範囲を設定してみると、乾燥に強く効くパラメータは、温度、風速、湿度であることがわかります。
一方、日照量については、上記のパラメータと比べると、正の相関はあるものの、直接的には強く効いていないと考えられます(今回の教師データが妥当と仮定すると)。日照量が高いと洗濯物が乾燥しやすい印象がありますが、たとえば、雨上がりで直射日光がさしても、低温・高湿・無風であったりすると乾燥には強く効かないといったことを示している可能性があります。日照量が高い状態が続くと、周囲環境の温度が上がる、湿度が下がる、風が吹く等により、直接的というよりは間接的に効いてくるパラメータである可能性があります。
備考2:教師データの作成について
今回の教師データを作成するにあたっての考え方を整理しておきます。
気象庁のデータを活用する
本来は、洗濯物の乾燥時間を調べるにあたり、環境の条件を設定して、測定データを取るべきです。
しかし、あらゆる気象条件を再現する環境を設定して乾燥時間を実測していくというのは現実的には無理があります。
そこで、気象庁のサイトのデータを活用することにします。
気象庁のサイトから、温度、湿度、風速、日照量については、各地の平均値を入手することができます。ここでは、東京の平均値を参照することにします。
気象庁のデータを参照しつつ、ネットに断片的に出ている各季節での数値、私個人の環境で経験した乾燥時間などの数値を入れて、大きな矛盾や違和感のない教師データを設定することにします。
今後、実際に運用していくうちに、現実との齟齬が見つかったという場合には、実際に得られた数値を教師データに追加・反映させていけばよいと考えます。
データを作成する場合は、下記の関連リンクの気象庁のサイトを参照してください。
教師データの典型値を作る
洗濯物の乾燥時間を求める程度であれば、各月ごとの詳細なデータは不要です。また、有効桁数も少なくて十分です。
そこで、2か月ごとの、気温、湿度、… の値から、温度は5℃刻み、湿度は10%刻み、風速は0.5m/s刻み、日照量は10%刻み程度で数値を丸めて、教師データを作ります。
洗濯物の種別は、典型的なもの(多く洗濯するもの)を値0の基準とすることにします。
こうして教師データ drying_parameter1.txt での、最初の典型値 typical (*1) を作成します。
たとえば、” 5, 60, 3.0, 70, 5.0, 1-2 typical (*1)” と記載してあれば、温度が 5℃、湿度が 60%、風速 3.0m/s、日照量が 70%で、このときの乾燥時間が 5.0 時間という意味です。最後の項目はコメントで自由に記載できます。この事例では 1~2月の典型値という意味です。
各項目は、”, ” (カンマ+半角スペース)で区切ることにします。
同様に、3~4月、…、11~12月までの教師データも作ります。
なお、教師データの作成においては、それぞれの教師データの間で矛盾が生じないように留意します。
たとえば、他の入力値が同じで温度や風速だけが上がったのに乾燥時間が長くなるといった、常識的に整合しない状況が起こらないようにします。
また、入力値が同じなのに出力値(乾燥時間)が異なるといった矛盾も起こらないようにします。
天気が悪いとき、よいときなどの教師データも追加していく
つぎに、典型値に対し、天気が変動した場合の教師データも追加します。
まず、乾燥する条件が悪いとき(cloudy:曇天時)の教師データを追加します。
ここでは、cloudy のデータは、典型値の気温から5℃下げ、湿度は20%上げています。風速は 0.5m/s とし、日照量は0%としています。乾燥時間は2時間長くしています。
条件がよいとき(fine:快晴時)の教師データも作成します。
fine のデータは、典型値の気温から5℃上げて、湿度は50%下げています。風速は 4.0m/s 、日照量90%としています。乾燥時間は 1.5~2.0時間程度短くしています。
これらの値は、各季節の天候のデータを参照しつつ、実体験と矛盾のない値となるように設定しています。
天候がよいとき、悪いときの乾燥時間に注意するようにし、より正確なデータが取得できた場合はこれらをアップデートしていけばよいです。
続いて、よく経験する天候条件、学習させておきたい天候条件についても追加していきます。
風が強い日(strong_wind)もよくあります。妥当な結果が得られるモデルとしたいので、典型値を基準に、上記と同様にデータを作成します。
なお、風速 7m/s で、洗濯物が飛ばされる程度の風速とのことです。
日照量についても、妥当な計算ができるようにしたいです。そこで、値がほぼ最小値から最大値に変化したときの教師データを追加しておきます。
さらに、洗濯物の種別についても定義しておきます。
まず、洗濯物を、乾きやすいもの、やや乾きにくいもの、なかなか乾かないもの、というように乾燥時間で大別します。それらに数値を割り振って、それぞれ、以下のような具体的な分類を決めます。
0: (標準)フェイスタオル、ワイシャツ、ハンカチなど
1: (やや乾きにくいもの)マット、バスタオルなど
2: (ボリュームのあるもの)ジャンパー、まくら、など(吸水し水分が通らない材質のものなど)
これは一例ですので、分類を見直したり追加することは自由です。
室内干し(room)もよくあります。他のデータと矛盾が生じないよう注意しつつ、教師データを追加しておきます。
備考3:パラメータがどうなっているのか調べてみる
今回のスクリプトでは、機械学習を実行するとニューラルネットワークの内部のデータを書き出すようにしました。
そこで、内部の数値がどうなっているのかを調べてみることにします。
ニューラルネットワークの計算式のまとめ
まず、計算式をまとめておきます。
入力は、前述のとおり、(温度、湿度、風速、日照量、種別)の数値が入ったベクトルとしています。
数学で通常使われる表記(縦ベクトル)で書くと、入力は以下のようになっています。
ここで、m は要素の個数で、今回の例では m = 5 としています。
実際に機械学習を行う際は、\(x1\) は教師データの個数分のセットで用いることになります。
このとき、ニューラルネットワークの計算式は、以下で書くことができます。Python のスクリプトでの Dense() の計算に相当しています。
\(W\) は重み行列、\(b1\) はバイアスといわれます。
ネット検索で、大学のサイトの資料などを見ると、この形で書かれていることが多いようです。
一方、Python、numpy、Tensorflow などで、プログラムを作る場合は、縦ベクトルは扱いにくいです。
多くの場合、ベクトルは配列(リスト、numpy 配列)とし、プログラムを書いたときに見かけが横ベクトルとなる形で記載します。また、行列は、配列に配列を入れて定義することが多いです。
そこで、(*01) と (*02) のそれぞれについて、両辺の転置を取るとつぎのようになります。
ここで、以下の性質を使っています。
(*04) を要素で書くと、つぎのようになります。
すなわち、教師データなどから数値が渡されると、横ベクトル \(x1^T\) を設定し、右側から重み行列 \(W\) をかけます。計算をすると横ベクトルが得られるので、同じ形状をしたバイアス \(b1^T\) を加えて出力 \(y1^T\) を求めます。
もしここで、ReLU などの活性化関数が定義されていれば、求めたベクトルの各要素をさらに活性化関数に入れ、出力 \(y1^T\) とします。
入出力を、縦ベクトルとして扱いたい(*02)のか、横ベクトルとして扱いたい(*04)のかにより、重み行列の転置の状態と掛け算の順番が変わることになります。
この後、さらに層が定義されていれば、出力 \(y1^T\) を \(x1^T\) に置き換えて、(*06) 以降の処理を繰り返していくことになります。
なお、数学では、ベクトルは行列と同等のものとして扱いました。たとえば、要素数が n 個の縦ベクトルは、n 行1列の行列(nx1の行列)として、違いをあまり意識することなく積などを計算することができます。
しかし、プログラミングでは、ベクトルを配列(一重の配列)で定義し、行列は、配列の中に配列が入っているもの(二重の配列)として定義することが多いです。したがって、プログラム上では、一重の配列(ベクトル)と二重の配列(行列)は異なるものとして扱う必要が出てきます。
ニューラルネットワークの設定について
サンプルスクリプトでは、ニューラルネットワークを以下で定義しています。
model1 = tf.keras.Sequential([ # learning model
tf.keras.layers.Dense(5, input_shape=(len(x1[0]),)), # layer_0
tf.keras.layers.Dense(1) # layer_+1
])
Dense() は、上記の (*06) の計算を設定する処理です。Dense(出力、入力)の形式で定義します。
1つめの Dense() では、まず、入力に対し、(*06) の計算を行い、要素数5個のベクトル \(y1^T\) で出力します。
つぎに2つめの Dense() は、前段での出力 \(y1^T\) を入力 \(x1^T\) として受け取り(読み替え)、同様に、(*06) の計算を行い、要素数が1つのベクトル \(y1^T\) で出力します。
ここで、機械学習を実行した内部の係数(model1_weights.txt、一例)を確認すると以下となっています。数値自体は一例です。
parameter 0:
[[ 0.32651448, -0.04514905, -0.01258681, -0.27301463, 0.02815131],
[ 0.5463194 , 0.506513 , -0.5748146 , 0.3795605 , -0.32829946],
[ 0.18303402, 0.20533706, -0.11052103, -0.84822685, 0.3715617 ],
[-0.05678581, -0.19367233, 0.631755 , -0.33367378, -0.30416036],
[-0.7497115 , -0.0188594 , 0.01755634, -0.87710965, -0.09253757]]
parameter 1:
[-1.096191 , -1.0963959, -1.2921653, -0.9865787, -1.2486526]
parameter 2:
[[-0.5735804 ],
[-0.71681845],
[-0.90100586],
[-0.32666278],
[-0.92044127]]
parameter 3:
[1.1781316]
ここで、parameter 0 と parameter 1 が、1つめの Dense() に対応しています。
parameter 0 が、重み行列 \(W\) となっています。二重カッコ(二重配列)の形式となっていることからも、行列であることがわかります。
parameter 1 は、バイアス \(b1^T\) です。一重カッコ(一重配列)の形式となっていることからも、ベクトルであることがわかります。縦ベクトルを転置した横ベクトルになっています。
同様に、parameter 2 と parameter 3 が、2つめの Dense() に対応しています。
具体的には、1つめの Dense() から得られる結果 \(y1^T\) は parameter 1 と同じ、要素数が5つの横ベクトルとなっています。そこで、2つめの Dense() ではまず、得られた \(y1^T\) を \(x1^T\) と読み替えて入力とします。
つぎに、横ベクトル \(x1^T\) に対し、右側から重み行列 \(W\) をかけます。parameter 2 の行列は、5行1列となっています。\(W\) から列を取り出して転置して左側に置いた \(x1^T\) との内積を求めると、要素数が1つのベクトルが得られます。そこで、バイアス \(b1^T\) を足して要素数が1つの横ベクトル \(y1^T\) を出力とします。
スクリプトで、最終的な出力は要素数が1つになるよう設定しており、教師データの解(前述の例では乾燥時間)の個数と対応させてあります。
ニューラルネットワークを定義した後、fit() を実行し、出力と教師データの差分を最小化することで、上記の\(W\) や\(b1^T\) を求めています。
もっとシンプルにしてみる
つぎに、サンプルスクリプトでのニューラルネットワークの設定を以下のようにさらにシンプルにして、機械学習を実行してみます。
(修正後)
model1 = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(len(x1[0]),)), # layer_0''
])
修正後では、一層のみの設定にしています。図は省略しますが、上記の fig.1 のグラフよりはやや乖離が増えるものの、最適化自体は同様に可能であることがわかります。
ニューラルネットワークの係数(model1_weights.txt、一例)を確認すると以下となっています。
parameter 0:
[[-0.04986953],
[ 0.03878858],
[-0.21000968],
[ 0.00154564],
[ 0.7347676 ]]
parameter 1:
[3.4213903]
・ 入力 \(x1^T\) は、前と同じく要素数5個の横ベクトルです。
・ (*06) に従って、要素数5つの横ベクトル \(x1^T\) に対し、右から、重み行列\(W\) をかけます。重み行列は5行1列の行列なので、積を求めると、要素数が1つとなります。この結果に、要素数が1つのバイアス \(b1^T\)を足すと、結果 \(y1^T\) が得られます。
・ 上記の係数を使って、たとえば、温度24℃、湿度20%、風速4m/s、日照量100%、洗濯物の種別:0 (標準)の場合について乾燥時間を求めると、以下のようになります。
\(\mathbf{y1^T}= \begin{pmatrix}24 & 20 & 4 & 100 & 0 \end{pmatrix}\begin{pmatrix} -0.04986953 \\ 0.03878858 \\ -0.21000968 \\ 0.00154564 \\ 0.7347676 \end{pmatrix} + \begin{pmatrix} 3.4213903 \end{pmatrix} = \begin{pmatrix} 2.314818 \end{pmatrix}\) … (*07)
つまり、初夏の好天気などで湿度が低めで風がややあるといった場合は、2時間程度で乾燥することになります。
なお、縦行列となっている \(W\) の係数を見ると、温度、風速の係数はマイナスとなっています。これは、温度、風速が高くなると、乾燥時間が短くなることに対応しています。
また、湿度、洗濯物の種別は、係数がプラスになっています。つまり、数値が増えるほど乾燥時間が長くなることを意味しています。
ところが、日照量については非常に小さな値(プラスの値)となっています。これは、機械学習のモデルをシンプルにしすぎたため、学習がうまくいっていない(日照量の微妙な影響を学習できない)可能性を示しています。これは、層数(パラメータ)を多くした fig.5 を見ると、日照量のグラフは、温度、風速と同じ、右下がりのグラフ(傾きの係数がマイナス)となっていることからもわかります。
したがって、もし、層(Dense)を1つとした程度の簡素化したモデルを使いたい場合は、乾燥時間に強く影響せず、微妙な変化を学習する必要のある日照量の項目は外すなど計算モデルを見直すという判断も考えられます。
・ この程度の計算であれば、Excel などで簡単に求めることができますし、任意のシミュレータを作ることも可能です。Web アプリ化も容易です。ReLU などの非線形関数を入れる場合も、関数を追加していけばよいことになります。
・ ここでの計算手順を見ると、結局のところ、任意の関数 \(y1=f(x1, x2, … ) \) を置いて各独立変数で偏微分してテイラー展開したことと同じになっています。式で書くと以下となります。
\(y1 = f(x1, x2, … ) ≒ f(x10, x20, …) + \frac{\partial f(x10, x20, … )}{\partial x1}(x1-x10)+ \frac{\partial f(x10, x20, … )}{\partial x2}(x2-x20) \) … (*08)
つまり、ニューラルネットワークで非線形関数を外して簡素化していくと、独立変数を使った線形近似と同じになることがわかります。
通常にテイラー展開をしただけでは、係数決めに工夫をする必要が出てきますが、Tensorflow などの機能を使うと、最適化する計算は強力です。最適化の能力の点で利用価値が高いといえます。
変数が増え非線形関数を入れた計算となると手計算では及ばないため、より利用価値は高まるといえます。
・ また上記から、ニューラルネットワークの基礎的な部分の計算手順や内部仕様は理解ができそうです。教師学習後の係数を他に流用して、推論する部分を自作するなども可能になると考えられます。たとえば、Raspberry Pi のように計算能力がパソコンには及ばないデバイスであっても、機械学習のモデルを軽量化して係数を流用することでデバイス側で推論を実行するなど、応用範囲を広げることもできそうです。
まとめ
洗濯物の乾燥時間を例に、Tensorflow の簡単なモデルを設定して機械学習をしてみました。
また、Tensorflow で設定したニューラルネットワークの係数を確認し、内部でどのような計算が行われているのか確認してみました。
大学の講義などで出てくる数式、ディープラーニングの書籍に書かれた式、Python で定義したレイヤーのプログラム、ニューラルネットワークの内容を出力したデータ、の4つがどういった関係にあるのか、明確に書かれた書籍やネット上の情報が少ないようです。そこで、定義の式も含め、プログラムの動きと定義の式がどういう関係にあるのかもまとめ、公開しておくことにします。
(YouTube やネット上の解説を見たのですが、行列の計算あたりで整合性がないものやミスタイプもあるのかなという印象を受けました。高校などで行列の計算をやっておらず、苦手な人が多いということでしたか。。)
他にも、興味の沸いたものについてスクリプトを公開しています。もしも関心があるようでたら、以下の関連リンクなども参照してみてください。
関連リンク
・ 機械学習で株価予測 【Python】
・ フルーツでの物体検出をやってみた 【YOLOv5】
・ 投票行動を正規分布で把握する 【JavaScript】
・ 天気予報を取得してテキストで出力する 【Python】
外部リンク
・ 気象庁:平年値の気象データ(例:東京)
サンプルスクリプト
機械学習用の教師データ drying_parameters1.txt
x01:temperature, x02:humidity, x03:wind_speed, x04:subshine_rate, x05:laundry_type, y0:drying_time, comment
5, 60, 3.0, 70, 0, 5.0, 1-2 typical (*1)
15, 60, 3.0, 50, 0, 4.0, 3-4
25, 60, 3.0, 40, 0, 4.0, 5-6
30, 70, 3.0, 40, 0, 3.0, 7-8
25, 70, 3.0, 50, 0, 4.0, 9-10
5, 60, 3.0, 70, 0, 5.0, 11-12
0, 80, 0.5, 0, 0, 7.0, 1-2 cloudy (*2)
10, 80, 0.5, 0, 0, 6.0, 3-4
20, 80, 0.5, 0, 0, 6.0, 5-6
25, 90, 0.5, 0, 0, 5.0, 7-8
20, 90, 0.5, 0, 0, 6.0, 9-10
0, 80, 0.5, 0, 0, 7.0, 11-12
10, 10, 4.0, 90, 0, 3.5, 1-2 fine (*3)
20, 10, 4.0, 90, 0, 2.0, 3-4
30, 10, 4.0, 90, 0, 1.5, 5-6
35, 20, 4.0, 90, 0, 1.5, 7-8
30, 20, 4.0, 90, 0, 2.0, 9-10
10, 10, 4.0, 90, 0, 3.5, 11-12
5, 60, 8.0, 70, 0, 4.0, 1-2 strong wind (*4)
15, 60, 8.0, 50, 0, 3.0, 3-4
25, 60, 8.0, 40, 0, 3.0, 5-6
30, 70, 8.0, 40, 0, 2.0, 7-8
25, 70, 8.0, 50, 0, 3.0, 9-10
5, 60, 8.0, 70, 0, 4.0, 11-12
20, 10, 4.0, 0, 0, 3.0, sunlight_low (*5)
20, 10, 4.0, 40, 0, 2.5, sunlight middle
20, 10, 4.0, 80, 0, 2.0, sunlight heigh
15, 60, 3.0, 50, 0, 4.0, type 0: normal fabric (*6)
15, 60, 3.0, 50, 1, 5.0, type 1: thick_fabric_1
15, 60, 3.0, 50, 2, 6.0, type 2: thick_fabric_2
25, 30, 0.0, 0, 0, 4.0, room wind_speed 0 (*7)
25, 30, 2.0, 0, 0, 3.5, room
25, 30, 4.0, 0, 0, 3.0, room
機械学習用のスクリプト drying_calculation1.py
import os
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.keras.models import load_model
import json
def read1( file1 ):
str1 = ""
with open( file1, 'r', encoding='utf-8' ) as f1:
str1 = f1.read()
return str1
def get_a1( file1 ):
a1 = read1( file1 ).strip().replace("\n\n", "\n").split( "\n" )
for i1 in range( len(a1) ):
a1[i1] = a1[i1].split( ", " )
return a1
def write1( file1, str1 ):
with open( file1, 'w', encoding='utf-8' ) as f1:
f1.write( str1 )
return
def get_training_parameters1( file1 ):
a1 = get_a1( file1 )
a1.pop(0)
a2 = []
a3 = []
for i1 in range(len(a1)):
a2.append( [ float(a1[i1][0]), float(a1[i1][1]), float(a1[i1][2]), float(a1[i1][3]), float(a1[i1][4]) ] )
a3.append( [ float(a1[i1][5]) ] )
x1 = np.array(a2).astype(float)
y1 = np.array(a3).astype(float)
return x1, y1
def plot_results1(x1_index, y1_list, labels, file1, title1="", xlabel1="x1", ylabel1="y1"):
plt.figure(figsize=(8, 4))
for i1,y1 in enumerate(y1_list):
plt.plot(x1_index, y1, marker="o", label=labels[i1])
plt.legend(fontsize=18)
plt.title(title1, fontsize=20)
plt.xlabel(xlabel1, fontsize=20)
plt.ylabel(ylabel1, fontsize=20)
plt.ylim(0, 1.1*max([y1.max() for y1 in y1_list]))
plt.tight_layout()
# plt.show()
plt.savefig(file1)
def x1_axis(n1):
# a1 = [ 15, 60, 3.0, 40, 0 ] # typical: temperature deg C, humidity %, wind speed m/s, sunshine rate %, laundry_type
a1 = [ 20, 20, 3.0, 50, 0 ] # typical: temperature deg C, humidity %, wind speed m/s, sunshine rate %, laundry_type
a2 = [ # index
[ 0, 10, 20, 30, 40, 50 ], # 0: temperature deg C
[ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 ], # 1: humidity %
[ 0, 2, 4, 6, 8, 10, 12, 14 ], # 2: wind speed m/s
[ 0, 20, 40, 60, 80,100 ], # 3: sunshine_rate %
[ 0, 1, 2 ] # 4: laundry type
]
a3 = a2[n1]
a4 = []
for i1 in range(len(a3)):
a5 = a1.copy()
a5[n1] = a3[i1]
a4.append(a5)
a6 = ["temperature: x1 degC", "humidity: x1 %", "wind_speed: x1 m/s", "sunshine_rate: x1 %", "laundry_type: x1" ]
str1 = ""
n2 = 0
for i1 in range(len(a6)):
if i1 != n1:
str1 = str1 + a6[i1].replace("x1", str(a1[i1])) + " "
n2 = n2 + 1
if n2 == 2:
str1 = str1 + "\n"
return np.array(a3), np.array(a4), a6[n1], str1
def load_model1(file1):
file1 = path1 + "model1.hdf5"
model1 = load_model(file1)
return model1
def save_model1(path1, model1):
file1 = path1 + "model1.hdf5"
model1.save( file1 )
weights1 = model1.get_weights()
a1 = [w1.tolist() for w1 in weights1]
str1 = json.dumps(a1, indent=4)
file2 = path1 + "model1_weights.json"
write1(file2, str1)
str2 = ""
for i1, w1 in enumerate(weights1):
str2 = str2 + f"parameter {i1}:\n{np.array2string(w1, separator=', ')}\n\n"
file3 = path1 + "model1_weights.txt"
write1(file3, str2)
config1 = model1.get_config()
str3 = json.dumps(config1, indent=4)
file4 = path1 + "model1_config.json"
write1(file4, str3)
path1 = os.path.dirname(__file__) + "/"
file1 = path1 + "drying_parameters1.txt"
x1, y1 = get_training_parameters1( file1 ) # y1: actual, training data
fitting1 = True # True or False
# fitting1 = False
if fitting1:
model1 = tf.keras.Sequential([
tf.keras.layers.Dense(5, input_shape=(len(x1[0]),)), # layer_0
# tf.keras.layers.Dense(5, input_shape=(len(x1[0]),), activation='relu'), # layer_0'
# tf.keras.layers.Dense(1, input_shape=(len(x1[0]),)), # layer_0''
# tf.keras.layers.Dense(5), # layer_1
# tf.keras.layers.Dense(5), # layer_2
# tf.keras.layers.Dense(5), # layer_3
tf.keras.layers.Dense(1) # layer_+1
])
model1.compile(optimizer='adam', loss='mse')
model1.fit(x1, y1, epochs=10000, verbose=0) # fitting
save_model1(path1, model1)
else:
model1 = load_model1(path1)
y2 = model1.predict(x1) # y2: predicted 1
x1_index = np.arange(len(y2)) # index
file1 = path1 + "fitting1.png"
plot_results1(x1_index, [y1, y2], ["y1:actual", "y2:predicted"], file1, "\n", "sample", "y1 hours")
for i1 in range(5):
x2_index, x2, str1, str2 = x1_axis(i1)
y3 = model1.predict(x2) # y3: predicted 2
file1 = path1 + "predicted" + str(i1+1) + ".png"
plot_results1(x2_index, [y3], ["y2:predicted"], file1, str2 , str1, "y1 hours")
グラフ表示用の HTML の例 drying_calculation1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>chart v0.1</title>
<style>
.div1 {
display: flex;
justify-content: space-between;
}
.div2 {
flex: 1;
text-align: center;
}
</style>
</head>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<body bgcolor="#ffffff" text = "#000000" >
<div class="div1">
<div class="div2"><img width="300" src="./fitting1.png"><br>fig.1: <a href= "./fitting1.png">fitting1.png</a></div>
<div class="div2"><img width="300" src="./predicted1.png"><br>fig.2: <a href= "./predicted1.png">predicted1.png</a></div>
<div class="div2"><img width="300" src="./predicted2.png"><br>fig.3: <a href= "./predicted2.png">predicted2.png</a></div>
</div><br>
<div class="div1">
<div class="div2"><img width="300" src="./predicted3.png"><br>fig.4: <a href= "./predicted3.png">predicted3.png</a></div>
<div class="div2"><img width="300" src="./predicted4.png"><br>fig.5: <a href= "./predicted4.png">predicted4.png</a></div>
<div class="div2"><img width="300" src="./predicted5.png"><br>fig.6: <a href= "./predicted5.png">predicted5.png</a></div>
</div><br>
</body>
</html>