フリーランチ食べたい

No Free Lunch in ML and Life. Pythonや機械学習のことを書きます。

%macro/%store を組み合わせてJupyterでのライブラリ読み込みを劇的に効率化する

Jupyterで読み込むライブラリを毎回書いてませんか?

  • 機械学習やデータ解析をJupyterで行うときに読み込むライブラリって大体決まっていますよね。
  • 毎回1、2つ目のセルにライブラリ読み込み処理をズラッと書いてないですか?
  • 人によってはスニペットアプリなどで管理している方もいるかもしれませんが、Jupyterの %macro%store を使うことでもっと短く、シンプルに、効率的にライブラリの読み込みを行うことができるので紹介したいと思います。

Notebookの最初のセルはこんな風になっていませんか?

これは自分がいつも読み込むライブラリ群で、自分はAlfredのsnipetを使って呼び出せるようにしていました。

%load_ext autoreload
%autoreload 2
%matplotlib inline
from IPython.display import Image

import os, sys, re, datetime
from pathlib import Path

pj_dir = Path(os.getcwd()).parents[1]
data_dir = pj_dir/'data'
img_dir = pj_dir/'images'
src_dir = pj_dir/'src'
sys.path.append(str(src_dir))

import numpy as np
import pandas as pd
import dask.dataframe as dd
from scipy import stats 

from tqdm import tqdm_notebook
from dotenv import load_dotenv

from matplotlib import pyplot as plt
from cycler import cycler

ちなみにmatplotlibの初期設定は %matplotlib inline と一緒に呼び出すとリセットされてしまう という既知のバグがあるので、セルを分けてmatplotlibの設定をしています。

Changing rcParams in same Jupyter notebook cell as %matplotlib inline has no effect · Issue #11815 · matplotlib/matplotlib · GitHub

plt.style.use("bmh")
plt.rcParams['axes.prop_cycle'] = cycler(color=plt.get_cmap('Set1').colors)
plt.rcParams["figure.figsize"] = (16, 4)
plt.rcParams["font.family"] = "YuGothic"

また、scikit-learnで複数モデルを比較したいときは、↓のような読み込みが必要になりますし、

import sklearn
from sklearn.model_selection import KFold

from sklearn import feature_extraction
from sklearn import preprocessing

from sklearn.linear_model import Ridge
from sklearn.neighbors import KNeighborsRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn import metrics
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from catboost import CatBoostRegressor

さらにDeepLearningしたいときは↓のような読み込みも追加されます。(これは大分少ないほうだと思います。RNNするときはこの3倍くらいはインポートしてる気がします。)

from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers.advanced_activations import LeakyReLU
from keras import initializers

非常に長いですね。 上記を全部入力するとこんな感じです。

f:id:mergyi:20181025170010p:plain

全然メインロジックに集中できない! ですね。

%macro で解決しよう

そこで %macro を使います。 %macro はiPythonのMagicCommandの1つでJupyterからも使うことができます。

Built-in magic commands — IPython 7.2.0 documentation

使い方は簡単です。まず保存から

保存

ソースはこちら👇

はてなブログでJupyterNotebookのいい共有方法がわからないので良い方法ご存知の方がいたら教えてください。

python-sandbox/20181025_record_macros.ipynb at master · ikedaosushi/python-sandbox · GitHub

f:id:mergyi:20181025170413p:plain

%macro を使っているのは下記の部分です。

%macro -q __imp 1
%macro -q __mpl 2

このように

%macro -q __imp [保存したいセルの実行番号]

と書くことで保存することができます。使うときは

__imp

でさきほど保存したセルが呼び出されます。

これだけでは、同じNotebook内で使えるだけなので、さらに %store を使って保存します。

%store __imp
%store __mpl

これで保存されたので、KernelやProcessを再起動しても使うことができるようになります。

完全に余談なのですが、 %store で保存された変数は↓にあるようです。これを書いていて初めて知りました。

Where are %stored Jupyter files located? - Stack Overflow

%IPYTHONDIR/<profile_name>/db/autorestore/<variable_name>

読み込み

ソースはこちら👇

python-sandbox/20181025_use_macros.ipynb at master · ikedaosushi/python-sandbox · GitHub

f:id:mergyi:20181025171858p:plain

読み込みも簡単で、

%store -r __imp
%store -r __mpl

のように書いて、

__imp
__mpl

と呼び出すだけです。これでライブラリのインポートとmatplotlibの設定を読み込むことができました。ちゃんとnumpyの読み込みとmatplotlibの設定も読み込めています。

さらに踏み込んで

さらに毎回保存された変数を取り出すのがめんどくさい!という方は .ipython_profile に下記のように記載することで、自動で %store された変数を呼び出すこともできます。

c.StoreMagics.autorestore = True

最後に

  • Jupyter MagicCommand %macro%store を組みわせて簡単にライブラリを読み込む方法を紹介しました
  • Jupyterに関するTipsは最近だとPyConJP 2018で発表されていた「Jupyterで広がるPythonの可能性」やリクルートテクノロジーズさんのブログ記事「あなたの生産性を向上させるJupyter notebook Tips」にもかなりまとめられていたのでおすすめです。

github.com

recruit-tech.co.jp

それでは良きJupyterLifeを!