はじめに
化学系の企業で働く皆さんは、世の中で話題になっているAI・機械学習を活用されていますか。
大学の研究室や大企業だと、化学の知識とITのデータ処理能力を併用してバリバリ結果を出しているようですね。残念ながら、私はそんな環境とは無縁な生活を送っています。
私はITとか数学とかとても苦手なタイプの、とりあえず試してみる系の化学人間ですが、重い腰を上げて機械学習にチャレンジしてみました。
背景の説明というよりは、実際にやってみた流れを書いてみます。
前処理方法やアルゴリズムの選択・最適化は非常に重要ですが、今回が初投稿ということもあり、また今度にします。
実験データはどうやって集めるか
化学系の機械学習も例にもれず、実験データの質と量が鍵となります。
とは言ってもQiita公開用に仕事のデータを使うことはできず、有料雑誌の論文のデータを公開目的で解析して怒られても嫌だったので、無料のデータベースである特許を分析してみました。
<余談> データの著作権について
ちなみに、日本の著作権法は、機械学習のデータを収集するのに非常に追い風だそうです。
以下のサイトが参考になります。
進化する機械学習パラダイス ~改正著作権法が日本のAI開発をさらに加速する~
https://storialaw.jp/blog/4936
機械学習のために他人の著作物を利用する行為は、同一事業者がモデル生成まで一気通貫に行う場合には、現行著作権法47条の7により適法
2019年1月1日施行の改正著作権法30条の4の下では、下記3つのパターンがいずれも適法となる。
・「自らモデル生成を行うのではなく、モデル生成を行う他人のために学習用データセットを作成して不特定多数の第三者に販売したりWEB上で公開する行為」
・「自らモデル生成をするために学習用データセットを作成し、これを用いてモデルを生成した事業者が、使用済みの当該学習用データセットを不特定多数の第三者に販売したりWEB上で無償公開する行為」
・「特定の事業者で構成されるコンソーシアム内で、学習用データセットを共有する行為」
------引用終わり
だそうです。
基本的には、自分でデータを集めてアルゴリズムを生成する分には問題がなく、更に2019年1月1日以降はデータセットの販売・公開に関しても制約がゆるくなるようです。
今回、用いたデータ
K社の固体触媒の条件に関する特許について、分析しました。
"特表2016-520418"
特許は、下記特許庁のHPに"〜"をコピペして検索すれば、ヒットします。
https://www.j-platpat.inpit.go.jp/
パッとみて予測がつくデータだと面白くなく、かつ一方である程度のデータ数がないと機械学習の醍醐味がありません。また、モノマー構造からポリマーの物性を予想するのは、構造式をプログラミングに落とし込む技術が難しそうなので、いつかチャレンジします。
添加成分や物性を変化させると、反応成績がこう変わりました!
という内容だと、解析がしやすいので最近の固体触媒の特許から実施例が多そうなものを適当に選びました。
特許のデータから、収率の予測モデルを作るプロセス
データの入力
特許のデータダウンロードして、実施例のデータをせっせとエクセルに打ち込みます。
OCRが機能するかどうかが、入力時間を圧倒的に左右します。
また、データの列名は日本語だと文字化けするので英数字を使いました。
その後、CSVとして保存します。エクセルでもデータは読み込めますが、慣れないうちはCSVの方が余計なエラーが少ないです。ファイル名は、英数字が良いです。
前処理等々
# ライブラリーのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as pltfrom sklearn.ensemble
import RandomForestRegressor
%matplotlib inline
続いて、保存したCSVファイルを読み込みます。中身も最初の5行確認すると良いです。
# データの読み込み
data= pd.read_csv("SolidCatMachineLearning.csv")
df = pd.DataFrame(data)
# 最初の5行表示
df.head()
| Cat | Mo | Bi | Fe | Ni | Co | Mg | W | K | BET | Temp. | Conversion | Yield | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 12 | 1.05 | 1.2 | 2.45 | 3.3 | 2.0 | 0.26 | 0.07 | 27.0 | 500 | 99.0 | 95.6 |
| 1 | 2 | 12 | 1.05 | 0.8 | 2.45 | 3.3 | 2.0 | 0.30 | 0.07 | 27.0 | 500 | 99.1 | 95.8 |
| 2 | 3 | 12 | 1.05 | 2.0 | 2.45 | 3.3 | 2.0 | 0.40 | 0.07 | 27.0 | 500 | 99.1 | 94.6 |
| 3 | 4 | 12 | 1.05 | 2.0 | 2.45 | 3.3 | 1.0 | 0.20 | 0.07 | 27.0 | 500 | 99.5 | 96.1 |
| 4 | 5 | 12 | 1.05 | 2.0 | 2.45 | 3.3 | 2.0 | 0.20 | 0.07 | 27.0 | 500 | 99.2 | 93.9 |
続いて、データの前処理です。
randomforestで組成や物性から、収率(Yield)を予測したり、収率への寄与が大きいパラメータをランキングにしようと思います。説明変数(組成とか条件)と目的変数(収率)にデータを分けます。
# randomforestでYieldを回帰計算
x = df.iloc[:, 1:12]
y = df[["Yield"]]
手元にある全てのデータを使って回帰モデルを作成すると、どんなに精度が良いモデルができても、未知データに対して有効なのか判断できません。一部のデータを検証用に残しておくことで、作成したモデルが有効かどうかテストできます。
手元のデータを、モデル作成用の訓練データと検証用のテストデータにランダムに分割します。
from sklearn.model_selection import train_test_split
# 訓練データとテストデータの分割
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, random_state=1)
y_train=np.ravel(y_train)
アルゴリズム選択
今回は、試しにランダムフォレストというアルゴリズムを使ってみます。
ランダムフォレストはアンサンブル学習と呼ばれるアルゴリズムの一つで、決定木(何層もの条件分岐を組み合わせて出力値を予測する)を複数作成し、その多数決で出力値を決定します。
注意点としては、原理的に訓練データの最大と最小を外れる値は予測できないとのことです。
https://datachemeng.com/inverseanalysisrfdt/
つまり、
「収率と選択率のトレードオフを最適化するにはどういう条件で作り込めば良いか」
という問題には対応できますが、
「この条件で作れば、既存のデータを更新できる」
といった問題には対応できません。
なので、収率の最大値を更新するためには、
・高い予測値近傍のの条件を潰す
・実験データが少ない条件を探索する
・傾向を見つける手がかりとして機械学習の結果を使う
といったアプローチが必要となると思います。
ここで、ようやく訓練データから回帰モデルを作成します。
機械学習の部分はわずか2行です。
# モデルの訓練
model = RandomForestRegressor(random_state=0, n_jobs=-1)
model.fit(x_train, y_train)
ちなみにモデルの妥当性を評価する場合は、以下のR2値を用いて評価できます。
結果の検証
from sklearn.metrics import r2_score
y_pred = model.predict(x_test)
print("ランダムフォレストスコア(train) : ", round(model.score(x_train, y_train), 2))
print("ランダムフォレストスコア(test) : ", round(r2_score(y_pred, y_test), 2))
ランダムフォレストスコア(train) : 1.0
ランダムフォレストスコア(test) : 0.44
訓練データがやたらとR2値が高く、テストデータがやたらと低くなりました。
個人的には両方0.8を超えてほしいところです。逆にR2値が高すぎると、データの読み込みとか何か間違っているんじゃないかと心配になります。
予測がどのようになっているか、実験データと予測データを散布図にしてみました。
まず、訓練データとその予測値です。

データが2箇所にはっきり分かれてしまっているので、2値分類問題みたいになってしまっています。。。
そして、テストデータと予測値です。

収率がめちゃめちゃ低いか、高い時は予測できますが、その間の領域は精度がありません。これは、めちゃめちゃ低いか高いところしか収率の訓練データがないからだと思います。
今回は訓練データは高すぎるR2値、テストデータは低すぎるR2値でしたが、グラフ化してみるとどんな状態かよくわかりました。実験データが少ない時は、このような不適切な予測モデルの生成が起こりがちです。
このまま、データ数が足りなく収率の予測精度がイマイチだった、と終わってもつまらないので、どの説明変数が収率に寄与しているかランキングにしてみます。
names = x_train.columns.values
importances = model.feature_importances_
indices = np.argsort(importances)
plt.figure(figsize=(9,4))
plt.barh(range(len(indices)), importances[indices],
align='center')
plt.yticks(range(len(indices)), names[indices])
plt.title("Feature Importance")
plt.show()
このようなグラフが出力されました。
収率には金属の組成よりも、BET比表面積が大きく影響するようですね。
Conversion(転化率)は、反応器に流した原料が何%消費されたかを表すので、物性というよりは反応条件を表しています。
種明かしじゃないですが、今回の特許の請求項を確認すると、
「比表面積が大事ですよ」
という内容でした。
特許に明示されていることを、あえて先入観なしにバックチェックしてあげたことになります。
終わりに
化学系の人間でも、機械学習で収率への寄与度を求めることができました。
一方で、モデルの精度が低かったり、データ数が少なかったりで、結果がイマイチだったのも否めません。
また、機械学習はデータを入力すれば何かしらの数値が出力されるので、素人でも結果を得ることができます。しかしながら、出力値やそのアルゴリズムが適切か判断するには勉強量が必要であり、データの処理方法を学ぶよりはるかに時間かかります。
今後の興味として、金属の物性値から収率の予測ができたら、面白いと思うので、組成を変えたデータがたくさん乗っている文献を探そうと思います。果たして、ストイックに触媒の組成をひたすら載せている文献は見つかるのでしょうか。。。
