機械学習によるニューラルネットワークポテンシャルの作成 (バージョン2021.01以降)
--------------------------------------------------------------------------------

概要
~~~~~~~~~~~~
ニューラルネットワークポテンシャルとは，凝縮系のポテンシャルエネルギー表面を近似することのできる学習モデルです [Behler07]_ 。その学習は，PHASE/0などの第一原理計算の結果を教師データとして行われます。PHASE/0には，`ænet <http://ann.atomistic.net/>`_ [Artrith16]_ や `n2p2 <https://compphysvienna.github.io/n2p2/>`_ [Singraber19]_ などのソフトウェアと連携し，ニューラルネットワークポテンシャルを作成することができる機能が備わっています。

使い方
~~~~~~~~~~~~~~~~~~~~~~~~~~~

教師データの作成
^^^^^^^^^^^^^^^^

以下に説明するような手続きによって，n2p2およびænetの教師データとして用いることのできるデータを出力することができます。

入力パラメーターファイルに以下のような設定を施します。

.. code-block::

 structure_evolution{
   ...
   ...
   nnp_output{
     sw_nnp_output = on
     filetype = all
     frequency = 100
   }
 }

Structure\_evolutionブロックにおいてnnp\_outputブロックを作成し，機械学習ポテンシャル用出力の設定を行います。sw\_nnp\_output = onとすると機械学習ポテンシャル用出力が行われます。filetypeで出力するファイルの種類を指定することができます。XSFを指定するとænetで利用できるXSF形式，n2p2を指定するとn2p2で利用できる形式，allを指定するとXSFとn2p2形式双方が出力されます。frequencyによってサンプリングの頻度を指定します。このパラメーターのデフォルト値は100です。ファイル名のデフォルト値は，n2p2がinput.data, XSFがnfdynm *xxxxx* .xsfです。ここで *xxxxx* はMDステップ数です。n2p2は学習データが一つのファイルに記録されるのに対し，ænetはスナップショット1つにつき1つのXSFが必要です。

file\_names.dataファイルにおいては，n2p2およびXSF形式のファイルのファイル名を指定することができます。デフォルト値はそれぞれinput.dataおよびnfdynm *xxxxx* .xsfです。

+------------------------+----------------------------------------------------+
| ファイルポインター     | 説明                                               |
+========================+====================================================+
| F\_N2P2                | n2p2の教師データの出力先。デフォルト値はinput.data |
+------------------------+----------------------------------------------------+
| F\_XSF                 | ænetの教師データの出力先。ここで指定した文字列の   |
|                        | 拡張子に相当する部分の直前にMDのイテレーション数が |
|                        | 付加されたファイル名が採用される。                 |
|                        | デフォルト値はnfdynm.xsf                           |
+------------------------+----------------------------------------------------+

サンプル時の収束判定条件の切り替え
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
教師データをサンプルする際，相関が強くなりすぎないようある程度間隔をあけて行うことが一般的ですが，サンプルするステップ以外のステップの重要性は低いと考えられます。そこで，サンプルするステップ以外は甘い収束判定で計算を行うことによって計算時間の短縮をはかることができます。このような処理を実現するには，以下のような設定を入力パラメーターファイルに施します。

.. code-block::

 accuracy{
     ...
     scf_convergence{
         delta_total_energy = 1e-4 Hartree
         delta_total_energy_sampling = 1.e-9
         succession = 1
     }
 }

accuracyブロックのscf\_convergenceブロックにおいてSCF計算の収束判定条件の設定は行われるが，ここでdelta\_total\_energy_samplingキーワードを使ってサンプリングの時のみに用いる収束判定条件を指定することができます。この例では，通常のSCF計算では1e-4 hartreeという収束判定条件が採用されますが，サンプリングステップの場合1e-9という収束判定条件が採用されます。

教師データの形式
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
教師データのファイル形式について説明します。

input.n2p2ファイル

 input.n2p2ファイルはn2p2プログラムで利用できる教師データ形式です。以下の形式で原子配置と対応するエネルギーが記録されます。

 .. code-block::

  begin
  comment iteration      100
  lattice             5.6022996655             0.0000000000             0.0000000000
  lattice             0.0000000000             9.7034676599             0.0000000000
  lattice             0.0000000000             0.0000000000            14.7489157721
  atom 5.054 4.636 1.407 Li 0.00 0.00 -0.141 -0.0743 0.1568
  ...
  energy -25706.79549229032
  charge 0.0
  end
  begin
  ...
  end

 beginとendの間に1つのデータが記録されます。commentから始まる行でコメントを記述できます。latticeから始まる行で格子ベクトルの指定を行います。atomから始まる行で原子の情報を記述します。2カラム目から4カラム目に原子のxyz座標を指定し，5カラム目に元素名を指定します。6, 7カラム目は未使用領域ですが，適当な数値を記述する必要があります。8カラム目から10カラム目で原子間力を指定します。原子間力は学習に直接利用されるわけではありませんが，結果得られる機械学習ポテンシャルから得られる原子間力との差を評価し，誤差を推測する，という使われ方がなされる場合があります。energyから始まる行でエネルギーを指定します。chargeから始まる行で系の総電荷を指定します。ただしcharge指定による情報は現バージョンのn2p2では利用されないようです。利用される単位は単位はエネルギーがeV, 距離がÅ, 原子間力がeV/Åです。

 n2p2の入力として利用するには，データはinput.dataというファイルに記録されている必要があります。複数のディレクトリーにまたがって行った計算の結果を活用したい場合，これらをcatコマンドとリダイレクトなどを利用して一つのファイルにまとめる必要があります。

 .. code-block::

  $ cat A/input.data >  input.data
  $ cat B/input.data >> input.data
  $ cat C/input.data >> input.data
  ...


xsf

 xsfは `XCrysDen <http://www.xcrysden.org/>`_ などにおいて標準的に用いられる座標データ形式です。ænetはこの形式を教師データ形式として採用しています。XSFにおいては，以下の形式で原子配置と対応するエネルギーが記録されます。

 .. code-block::

  # total energy =         -25711.2660427032 eV
  CRYSTAL
  PRIMVEC
               5.6022996655             0.0000000000             0.0000000000
               0.0000000000             9.7034676599             0.0000000000
               0.0000000000             0.0000000000            14.7489157721
  PRIMCOORD
        84       1
   Li  5.0229472700 5.0300845743 1.8014586046 -0.1368952902 -0.0902290564 -0.4716359333
  ...

 #から始まる行はXSF形式ではコメント行とみなされますが，ænetは# total energyという文字列がある場合はエネルギーが指定される行とみなし，= の後の数値をエネルギー値として採用します。CRYSTAL行を記述することによってこのあと結晶のデータが記録されていることを指定します。PRIMVEC行を記述することによってこのあとの3行が *a* 軸， *b* 軸，*c* 軸の格子ベクトルの指定であることを指定します。PRIMCOORDを記述することによって続く行が原子座標や原子間力の指定に利用されることを指定します。まずは原子数が指定されます。この例では84 1となっており，84原子系であることが指定されています。その次の1という数値はænetでは利用しない情報ですがXSF形式の様式を満たすために必要です。その次の行以降が原子の情報です。1カラム目が元素名，2カラム目から4カラム目が原子位置，5カラム目から7カラム目が原子間力です。単位はn2p2の場合と同様エネルギーがeV, 距離がÅ, 原子間力がeV/Åです。

ニューラルネットワークポテンシャル作成例
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ここでは，:math:`\alpha` Quartz結晶を例に，ニューラルネットワークポテンシャルの作成方法について説明します。

用いた結晶
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
六方晶の :math:`\alpha` Quartz結晶を直方晶に取り直し，さらに *a* 軸と *c* 軸をそれぞれ2倍とするスーパーセルを作成しました。合計72原子の系です。その初期配置は :numref:`Quartz72` に示す通り。

.. figure:: images/Quartz72.png
  :name: Quartz72

  72原子 :math:`\alpha` Quartz結晶


第一原理計算
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:numref:`Quartz72` の結晶を初期構造として，温度500K, 800K, 1200Kで定温の第一原理計算分子動力学シミュレーションを実施しました。入力ファイルと教師データのアーカイブはサンプルディレクトリーの下のnnp/SiO2/fpmd以下のサブディレクトリーにあります。温度以外の主要な計算条件は下記の通り。

.. csv-table:: 第一原理分子動力学の主要な計算条件
 :name: nnp_table1

 "計算条件", "値"
 "カットオフエネルギー", "25 Rydberg"
 " **k** 点サンプリング", " :math:`\Gamma` 点のみ"
 "収束判定条件", "1e-9 hartree"
 "サンプリング頻度","10 MDステップに一度"
 "総MDステップ数", "10000"
 "教師データ出力","XSF形式"

このシミュレーションにおいてはサンプリング頻度が10 MDステップに一度と比較的高いため，収束判定条件を切り替える機能は用いていません。

ニューラルネットワークポテンシャルの作成の準備
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
得られた教師データを用いてニューラルネットワークポテンシャルを作成する方法を説明します。用いるアプリケーションはænetです。ænetの詳細については `ウェブサイトの情報 <http://ann.atomistic.net/>`_ を参照してください

まずは，サンプルディレクトリーの下に教師データのアーカイブ（ファイル名xsf.tar.bz2）が配置されているので，それを解凍します。

.. code-block::

 $ cd samples/nnp/SiO2/fpmd/500K
 $ tar -jxvf xsf.tar.bz2
 $ ...
 $ cd ../800K
 $ ...

成功すると，各ディレクトリーにファイル名がnfdynm *xxxxx* .xsfの1000個のxsfが作成されるはずです。

また，ænetのウェブサイトから最新版のアーカイブをダウンロードし，コンパイルしてください。成功すれば，ænetのインストールディレクトリーの下のbinディレクトリーにgenerate.x-\*, train.x-\*, predict.x-\*の3つのバイナリーが作成されるはずです(ここで\* はænetのバージョンやコンパイル環境を識別する文字列; 以降-\*は省略)

最後に，`古典分子動力学シミュレーターLAMMPS <https://lammps.sandia.gov/>`_ [Plimpton95]_ からænetで作れるニューラルネットワークポテンシャルを用いる場合，LAMMPSのænetインターフェース [Mori20]_ を `作者のウェブサイト <https://github.com/HidekiMori-CIT/aenet-lammps>`_ からダウンロードし，指示に従ってLAMMPSに組み込んでください。

教師データの変換
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
教師データとしての原子配置は，必ずしも機械学習に適したものではないので，それを機械学習に適した形式（記述子）に変換する必要があります。このような変換を行うプログラムがgenerate.xです。
generate.xを実行するために必要な入力はgenerate.xの全体の振る舞いを制御するコントロールファイル (generate.in) と元素ごとの記述子の構築の仕方を指定するセットアップファイルです。サンプルデータは :code:`samples/nnp/SiO2/aenet/generate` の下にあります。

generate.inファイルの内容は，典型的には下記のようになります。

.. code-block::

  OUTPUT SiO.train

  TYPES
  2
  Si -107.171 | eV
  O  -434.109 | eV

  SETUPS
  Si  Si.fingerprint.stp
  O   O.fingerprint.stp

  FILES
  3000
  ../../fpmd/800K/nfdynm000772.xsf
  ../../fpmd/800K/nfdynm000038.xsf
  ...
  ...

* OUTPUTにgenerate.xの結果を出力するファイルを指定します。この例ではSiO.trainです。
* TYPESにおいて原子種の指定を行います。まず利用する元素数を指定し（この例では2）, 一行に1元素ずつ元素名と原子の参照エネルギーを指定します。この例では，シリコン結晶と酸素分子の1原子あたりのエネルギーを採用しました。
*	SETUPSに元素ごとのセットアップファイルを ``元素名 セットアップファイル`` という形式で指定します。
*	FILESにおいて教師データを指定します。まず教師データの数を指定し，1行に1ファイル教師データが記録されたファイルのパスを指定します。

セットアップファイルの内容は，典型的には下記のようになります。

.. code-block::

 ATOM Si

 ENV 2
 Si
 O

 RMIN 0.85d0

 BASIS type=Chebyshev
 radial_Rc = 6.0  radial_N = 16 angular_Rc = 6.0  angular_N = 8

*	ATOM 元素名とし，対象元素を指定します。
*	ENV Nとし，その元素と相互作用し得る元素の数を指定します。さらに，具体的にどの元素が相互作用し得るかを1行につき1元素名という形式で指定します。
*	RMINによって最小距離を指定します。
*	BASISにおいて記述子の種類を指定します。type=ChebyshevとするとChebyshev展開を用いて記述子を構築します [Artrith17]_ この場合，後段のradial_Rcとradial_Nによって動径方向のカットオフ距離と分割数，angular_Rcとangular_Nによって角度方向のカットオフ距離と分割数を指定します。

generate.inファイルとセットアップファイルが準備できたら，generate.xを実行します。

.. code-block::

 $ generate.x generate.in > generate.log

この処理の結果，generate.inにおいてOUTPUTキーワードで指定したファイルに結果が記録されます。このファイルを学習用のディレクトリー（今の例の場合 :code:`samples/nnp/SiO2/aenet/train` ）にコピーします。

ニューラルネットワークポテンシャルの学習
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
generate.xによって変換した座標データとエネルギーのセットを用いてtrain.xによる学習を行うことができます。そのコントロールファイル(train.in)は，典型的には以下のように記述します。

.. code-block::

 TRAININGSET SiO.train
 TESTPERCENT 10
 ITERATIONS  5000

 MAXENERGY 1.0

 METHOD
 bfgs

  NETWORKS
  ! atom   network         hidden
  ! types  file-name       layers  nodes:activation
    Si    Si.10t-10t.nn    2      10:tanh 10:tanh
    O      O.10t-10t.nn    2      10:tanh 10:tanh

*	TRAININGSETでgenerate.xによって作成されたファイルを指定します。
*	TESTPERCENTで教師データの内学習ではなくテストに利用するパーセンテージを指定します。
*	ITERATIONS 学習はiterativeに行われますが，そのiterationの最大回数を指定します。
*	METHOD : 学習の手法を指定します。bfgsのほか，Levenberg-Marquardt法などを利用することができます。bfgs法は設定が必要なパラメーターが少なく，ロバストな最適化が可能なため推奨の方法です。
*	NEWORKSにおいてベースとなるニューラルネットワークを指定します。1行につき1元素の指定を行います。まず元素名を記述し，つぎにニューラルネットワークの重みを記録するファイルを指定します。さらに隠れ層の数を指定し，最後に隠れ層の数分ノード数とactivation function (階段関数の近似)の形式を指定します。

train.xを以下の要領で実行します。

.. code-block::

 $ mpiexec -n 8 train.x train.in > train.log

このコマンドはMPIを介して8並列で実行する例です。具体的なコマンドはシステムによって異なる可能性があります。

ログは標準出力に出力されるので，この例ではリダイレクトされtrain.logというファイルに出力されます。train.logには様々な情報が記録されます。学習がうまくいっているかどうかの確認は以下のようにTraining process以降のデータを参照するようにしてください。

.. code-block::

 ----------------------------------------------------------------------
                            Training process
 ----------------------------------------------------------------------

 Weight optimization for 5000 epochs using the Limited Memory BFGS method.

 Sampling type               : sequential

        |------------TRAIN-----------|  |------------TEST------------|
 epoch             MAE          <RMSE>             MAE          <RMSE>
     0    2.055153E-01    2.392261E-01    2.059784E-01    2.414336E-01 <
     1    2.055153E-01    2.392261E-01    2.059784E-01    2.414336E-01 <
     2    1.338985E-01    1.499288E-01    1.358931E-01    1.509523E-01 <
     3    4.876623E-02    7.448498E-02    4.891127E-02    7.381589E-02 <
     4    3.806436E-02    5.418523E-02    3.679157E-02    5.251901E-02 <
    ...
    ...

特にTESTのMAE (mean absolute error), RMSE (root mean square error)の値に注目し，これが初期値に比べ小さくなっているepochを採用するようにしてください。

ネットワークの重みづけファイル（分子動力学シミュレーションなどにおいて利用するファイル）はtrain.inにおいて指定した文字列に，学習のiteration回数が付与されたファイル名(たとえばSi.10t-10t.nn-00100など)のファイルに出力されます。

ニューラルネットワークポテンシャルの検証
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ænet付属のプログラムpredict.xを用いることによって，作成したニューラルネットワークポテンシャルの検証を行うことができます。predict.xはxsfとニューラルネットワークポテンシャルの重みファイルを入力とし，エネルギーや原子間力の計算と構造最適化を行うことができます (predict.xでできることはこれだけなので，本格的な活用のためにはLAMMPSインターフェースなどを利用することが推奨されます)

predict.xのコントロールファイル (predict.in)は典型的には以下のようになります（このサンプル入力は :code:`samples/nnp/SiO2/aenet/predict` 以下にあります）

.. code-block::

  TYPES
  2
  Si
  O

  NETWORKS
    Si Si.10t-10t.nn
     O  O.10t-10t.nn

  FORCES

  FILES
  3000
  ../../fpmd/800K/nfdynm000772.xsf
  ../../fpmd/800K/nfdynm000038.xsf
  ...
  ...

*	TYPESの次の行で原子種の数を指定します。それに続く行で元素名を記述します。
*	NETWORKSに続く行で，元素名 ニューラルネットワークポテンシャルの重みファイル名 という形式でニューラルネットワークポテンシャルの重みファイルを指定します。
*	原子間力を計算する場合，FORCESというキーワードを記述します。
*	FILESキーワードとそれに続く行において，generate.inと同じ形式で対象の原子配置を記述したXSFを指定することができます。この部分がない場合，対象の原子配置ファイルはpredict.x実行時に引数指定する。

predict.xはgenerate.x, train.xと同じように実行することができます。

.. code-block::

 $ predict.x predict.in > predict.log

結果は標準出力に出力されるので，上述のコマンド例の場合predict.logファイルに記録されます。たとえば以下のような内容になります。

.. code-block::

 ----------------------------------------------------------------------
                              Parallel run
 ----------------------------------------------------------------------

 Number of processes : 1
 ...
 ...
 ...
 Cartesian atomic coordinates (input) and corresponding atomic forces:

          x             y             z             Fx           Fy            Fz
         (Ang)         (Ang)         (Ang)       (eV/Ang)      (eV/Ang)      (eV/Ang)
 --------------------------------------------------------------------------------------
 Si      9.649365      8.409237      9.994378      0.235924      0.525635     -1.368195
 Si      1.351787      1.864069      0.963064      2.655693      2.032425     -0.024373
 Si      1.296394      6.654412      2.411131      1.116420      0.752235      1.365680
 O       8.774874      1.120195      9.374453     -0.116155      1.088577     -0.440955
 ...
 ...

 Cohesive energy            :         -184.66378181 eV
 Total energy               :       -23593.99978181 eV
 Mean force (must be zero)  :     -0.000000      0.000000      0.000000
 ...
 ...

:numref:`nnp_fig1` にpredict.xで計算したエネルギーと第一原理計算によって得られたエネルギーをプロットした図を示します。この図では，完全な学習ができていた場合はすべての点が斜め45度の直線にのります。学習が完璧であることはないので直線からのバラつきはあるものの，直線からの乖離は原子あたりおおむね1 meV以下であり，よく学習できていることが分かります。

.. figure:: images/nnp1.svg
  :name: nnp_fig1

  第一原理計算とニューラルネットワークポテンシャルによって得られるエネルギーの比較

ænetインターフェースを組み込んだLAMMPSの使い方
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ニューラルネットワークポテンシャルを用いてLAMMPSによる計算を行うには，まず重みファイル(Si.10t-10t.nn-xxxxxなど)のファイルを実行ディレクトリーにコピーします。その際，ファイル名末尾の“-xxxxx”の部分は取り除いたファイル名にします。

LAMMPSの入力スクリプトは通常通り用意します。単位はmetal, atom_styleはatomicを用います。すなわち，以下のような指定は必須です。

.. code-block::

 units metal
 atom_style atomic

ポテンシャル指定部分には以下のような文字列を指定します。

.. code-block::

 pair_style      aenet
 pair_coeff      * * v00 Si O 10t-10t.nn Si O

* pair_style aenetによってænetのニューラルネットワークポテンシャルを利用することを指定します。
* pair_coeffによってニューラルネットワークの重みファイルと元素のマッピングを行います。

  * \* \*という文字列によってすべての元素間が対象であることを指定します。
  * v00によってænetプログラムが出力するファイルを利用することを指定します。
  * つづくSi O 10t-10t.nnはSi.10t-10t.nn, O.10t-10t.nnの2つのファイル指定の短縮形です。
  * 最後のSi Oは元素へのマッピングで，1つ目のファイルはSi, 2つ目のファイルはOに対応する重みファイルであることを意味します。

* 初期座標データファイルは，LAMMPSのatom_style atomicで用いられる形式で準備します。

:numref:`nnp_fig2` に，ニューラルネットワークポテンシャルとPHASE/0による500Kおよび800Kにおける :math:`\alpha` Quartzの分子動力学シミュレーションのトラジェクトリーから得られた二体分布関数および結合角分布関数を比較した結果を示します。:numref:`nnp_fig2` より，得られたニューラルネットワークポテンシャルは第一原理計算の結果をよく再現するものであることが分かります。

.. figure:: images/nnp2.svg
  :name: nnp_fig2

  500Kおよび800Kにおける二体分布関数と結合角分布関数の比較。赤線：PHASE/0による第一原理分子動力学シミュレーション，緑線：ニューラルネットワークポテンシャルによる古典分子動力学シミュレーション。

.. [Behler07] J\. Behler and M. Parrinello, Phys. Rev. Lett. 98, 146401 (2007)
.. [Artrith16]  N\. Artrith and A. Urban, Comput. Mater. Sci. 114 (2016) 135-150.
.. [Singraber19] Singraber, A.; Behler, J.; Dellago, C. J. Chem. Theory Comput. 15 (2019) 1827–1840.
.. [Plimpton95] S\. Plimpton, J. Comp. Phys. 117 (1995) 1-19.
.. [Mori20] H\. Mori and T\. Ozaki, Physical Review Materials 4 (2020) 040601.
.. [Artrith17]  N\. Artrith, A. Urban, and G. Ceder, Phys. Rev. B 96 (2017) 014112.
