【NumPy入門 np.save】配列をファイルに保存するnp.saveを使いこなす

こんにちは、インストラクターのフクロウです!

皆さんは機械学習(ニューラルネットワークなど)の学習が終わった後のパラメータの保存、どうしていますか?

ハイパーパラメータなどを変えて何度も繰り返して学習をする際や、良いパラメータを見つけたときなどには、パラメータを保存しておきたいと思うはず。

そんなとき、np.saveという関数で、簡単にNumPyの配列を保存することができるんです!

この記事では

  • NumPyのndarrayをテキストファイルとして保存する関数「np.save」
  • 保存したファイルを読み込む「np.load」

について紹介しますよ!必見です!

目次

np.saveのパラメータ

np.saveは、np.array形式のオブジェクトをファイルとして保存する関数です。

np.saveの引数は以下の通り。

np.save(
    file, # データを保存するファイル名
    arr,  # 配列型オブジェクト(listやnp.array)
    fix_imports=True # Python2でも使えるようにするかどうか
)

基本的にはfix_importsは気にしなくて大丈夫です。

第一引数にファイル名第二引数に保存したいオブジェクトを指定します。

ファイル名は自動的にnpyかnpzという拡張子がついた形になるので、後から読み込んで使うときにはこの拡張子を目印にするといいですよ。

np.loadのパラメータ

np.loadnpy/npz形式のファイルを読み込むための関数です。

np.loadの引数は以下の通り。

np.load(
    file="tset.npy",        # npyかnpz拡張子のファイルを指定
    allow_pickle=True,      # npy/npzで保存されたpickleファイルを読み込むかどうか (デフォルトではTrue)
    fix_imports=True,       # Python2との互換機能、Trueならpy2製ファイルを読み込める (デフォルトではTrue)
    encoding="ASCII",       # Python2で作られた文字列を読み込むときの文字コード指定 (デフォルトではASCII)
)

基本的には、ファイル名を指定するだけでOKです。

python2との連携を考えるときは少し面倒ですが、最近ではPython3がかなり普及したのであまり使うことは無いでしょう。

np.save/np.loadの実際の使い方

例えば、NumPyで実装したニューラルネットワークのパラメータ(結合重み、バイアス)をファイルに保存したいとしましょう。

ここでは、実際に簡単な画像分類問題をニューラルネットワークで学習した後、これのパラメータの保存と、保存したデータの読み込みまでを行います。

前準備

まずはライブラリのインポートから、データの読み込みまでを行います。

from sklearn import datasets
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
import numpy as np

dataset = datasets.load_digits()
train_data, test_data, train_label, test_label = train_test_split(dataset.data/255, dataset.target)

show_shape = lambda X: [print(x.shape) for x in X]

show_shape([train_data, test_data, train_label, test_label])

[Output]

(1347, 64)
(450, 64)
(1347,)
(450,)

このデータ(digits)は0~9の10クラスを持ちます。

training dataとtest dataに分割も終わったので、これを使ってニューラルネットワークを学習します。

機械学習モデルの学習と評価

scikit-learnのMLP(ニューラルネットワーク)クラスを使って学習と評価を行います。

まずはニューラルネットワークのハイパーパラメータを設定し、その後学習を行います。

model = MLPClassifier(
    hidden_layer_sizes=(100),  # 隠れ層のユニット数
    activation="relu",         # 隠れ層の活性化関数
    solver="adam",             # オプティマイザ
    random_state=1234,         # 乱数生成器の設定
    max_iter=1000,             # 最大学習回数
)

model.fit(train_data, train_label) # データとラベルを渡して学習

[Output]

MLPClassifier(activation='relu', alpha=0.0001, batch_size='auto', beta_1=0.9,
       beta_2=0.999, early_stopping=False, epsilon=1e-08,
       hidden_layer_sizes=100, learning_rate='constant',
       learning_rate_init=0.001, max_iter=1000, momentum=0.9,
       nesterovs_momentum=True, power_t=0.5, random_state=1234,
       shuffle=True, solver='adam', tol=0.0001, validation_fraction=0.1,
       verbose=False, warm_start=False)

sklearnではfitメソッドで学習が行なえます。

では、テストデータを使って評価してみましょう。

pred_label = model.predict(test_data)

accuracy_score(test_label, pred_label)

[Output]

0.9688888888888889

さて、この値が良いのか悪いのかはさておき、学習したニューラルネットワークモデルのパラメータを保存しておきましょう。

np.arrayオブジェクト(パラメータ)の保存

MLPClassifierクラスのインスタンス(model変数)では、以下のインスタンス変数でパラメータにアクセスできます。

  • model.coefs_
    • 結合重みのリスト
  • model.intercepts_
    • バイアスのリスト

例えば、model.intercepts_の中身は以下のような形になります。

[array([ 0.34682695, -0.18619194,  0.51089346, -0.0745376 , -0.06683674,
        -0.10533423, -0.08774989,  0.3257384 ,  0.38348272, -0.09437606,
         0.20785552,  0.1292196 , -0.19124118,  0.43848153, -0.16747779,
        -0.12134393, -0.07412251, -0.07375998, -0.10972181, -0.04448673,
         0.3020805 ,  0.15064405,  0.16899598, -0.11769587,  0.15454121,
         0.27730995,  0.43474162,  0.24106031,  0.25595449,  0.2028516 ,
         0.25106652,  0.45004029,  0.09671492,  0.13609258,  0.22260003,
         0.35082012, -0.03981748,  0.41469217, -0.08377924,  0.07150102,
         0.30826337,  0.32182736,  0.27367003,  0.16384482,  0.38533181,
        -0.13447486, -0.10285442,  0.19841185,  0.34602021, -0.03515394,
        -0.18140602, -0.04105884,  0.12466424,  0.17666507,  0.10474498,
         0.35839253,  0.22411312,  0.17568221, -0.0971458 ,  0.34551279,
        -0.151979  ,  0.21885159,  0.18677117,  0.11442799, -0.09858213,
        -0.17738479, -0.17657904,  0.24919445,  0.20419114, -0.03517398,
        -0.13896385, -0.16427148, -0.10505843, -0.14203025,  0.2926662 ,
         0.30190493,  0.02037234,  0.18032657,  0.31760639,  0.2546752 ,
         0.2467949 ,  0.18304099,  0.16728748, -0.15266362, -0.1059676 ,
        -0.07523529,  0.40519387, -0.03681349, -0.12812912,  0.29106102,
         0.14021797,  0.24270879,  0.1255138 ,  0.49001767,  0.33297187,
         0.20794209,  0.26631199,  0.39582434, -0.02316582, -0.08422603]),
 array([ 0.09008411, -0.34033946, -0.14145383,  0.2416411 ,  0.17395041,
         0.0324957 ,  0.21700254,  0.28717775,  0.10416904,  0.05591022])]

これらをnp.saveでまとめて保存します。

params = model.coefs_ + model.intercepts_ # この時点で配列が4つ入ったリストができる

np.save(
    "MLP_params",  # ファイル名
    params # 保存したいオブジェクト
)

はい。これだけでOKです。

そうすると、Pythonを実行しているディレクトリMLP_params.pyというファイルができます。

後は別のPythonスクリプトやJupyter Notebookからこのファイルを読み込めば、配列が復元できますよ!

npyファイルの読み込み

では別のPythonファイルなどから、npyファイルを読み込んでデータを復元してみます。

data = 
np.load(
    file="MLP_params.npy",  # npyかnpz拡張子のファイルを指定
)

これでdata変数に先程保存したデータが入っているはずです。

[data変数の中身]

array([array([[ 2.04164655e-79,  4.82010231e-93, -7.43699714e-97, ...,
         1.58132888e-78,  1.16132784e-68, -1.38242520e-90],
       [ 1.77787549e+00,  1.38148454e-87,  2.00121196e-01, ...,
         8.11974765e-01, -1.94455920e-80, -2.48317060e-68],
       [ 1.23475102e+00, -1.11819465e-73,  2.00196626e-01, ...,
        -1.56769746e-01, -3.71560789e-93,  1.55994215e-73],
       ...,
       [-6.41327607e-01, -1.06191740e-88, -1.27631161e+00, ...,
         9.47833397e-01, -1.92493053e-88,  1.75168624e-98],
       [-7.31629838e-02, -2.31818709e-69, -1.45759431e+00, ...,
         1.53434268e+00,  3.61061455e-95, -1.51401637e-96],
       [-8.12946446e-01,  2.30463983e-87, -1.31044154e+00, ...,
         1.31016023e+00, -2.41307845e-90, -4.50949718e-83]]),
       array([[ 8.51193237e-001, -1.68374839e+000,  1.61472743e+000,
       ---以下省略---

このように、簡単にデータの保存とファイルからの配列の読み込みができました!

まとめ

この記事では、np.arrayオブジェクトをファイルに保存するnp.save関数と、保存したファイルを読み込むnp.load関数を紹介しました。

この他にもファイルの読み込み・書き込みを行う関数はありますが、np.saveを使った保存は非常に手軽なのが良いですね。

手軽に使えるので、是非とも普段のコーディングで使ってみてください!

この記事を書いた人

第一言語はPythonです。
皆さんRustやりましょう。

目次