スライドショー

【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を使った保存は非常に手軽なのが良いですね。

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

LINEで送る
Pocket

ITエンジニアへ転職したい方におすすめ

自分を評価してくれる企業に転職して年収を上げたい! 自分のスキルにあった独自案件を知りたい!
エンジニアは今もっとも注目されている職業の1つ。エンジニアになって年収を増やしたい方や、あなたのスキルに見合った企業へ転職したいエンジニアの方も多いですよね。

しかし、大手の転職媒体は扱う求人数が多くても、誰もが登録しているので競争率もかなり高くなっています。そのため、あなたの条件に見合った企業を見つけても転職するためには、相応の努力とスキルが必要となります。

こういった媒体では、未経験からエンジニアを目指す方やエンジニア歴2〜3年で転職を考えている方にとって、最適な転職環境とはいえません。

そこでオススメしたいのが、未経験者や若手エンジニア向けの独自案件を多く掲載している「侍ワークス」です。

侍ワークスは、独自案件を多く掲載しているだけでなく、

・応募から就業まで一貫したサポート

・就業後もアフターフォロー

といった経験の浅い方や初めてエンジニアを目指す方にも安心のフォロー体制が整っています。もちろん登録は完全無料!しかも案件を見るだけなら登録も不要です。

まずは、お気軽にどんな求人があるか見てみてください。あなたにピッタリの企業がきっと見つかりますよ! 侍ワークスの求人情報を見る

書いた人

フクロウ

フクロウ

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