Jupyter notebookのスニペット機能を使って機械学習案件の生産性をあげる話


デフォルトのJupyter notebookにスニペット(ショートカット)呼び出しの拡張機能を追加し、生産性をあげた話です。

以下の順に沿って記していきます。

1. 前提となる環境
2. 拡張ツールの導入(jupyter_contrib_nbextensions)
3. デフォルトスニペットの使用
4. オリジナルスニペットの登録

# 前提となる環境

自宅で使っているMacBooK Airを用います。

```text
2011 MacBook Air 3,1
1.4 GHz Intel Core 2 Duo
2 GB 1067 MHz DDR3
128 GB SSD
High Sierra 10.13.2
```

また、`pyenv 1.1.5 + anaconda3-4.0.0`でJupiter notebookの環境を実現しています。

# 拡張ツールの導入(jupyter_contrib_nbextensions)

データベースへの接続や、matplotlibでのグラフの書き方など、頻繁に使用するが一から書きたくないものはスニペット化して、すぐに呼び出せるようにすると楽です。

これを実現するために、jupyter_contrib_nbextensionsを用います。
https://github.com/ipython-contrib/jupyter_contrib_nbextensions

```bash
~$ conda install -c conda-forge jupyter_contrib_nbextensions
```

上記コマンドを実行したら、Jupyter notebookを立ち上げ、下記にアクセスしましょう。(お使いの環境によって適宜読み替えてください。)

```
localhost:8888/nbextensions
```

するとこのような画面が立ち上がります

![スクリーンショット 0029-12-17 23.55.44.png](https://qiita-image-store.s3.amazonaws.com/0/47559/6e9b0410-2cdb-766c-b043-7c68b8da5eb1.png)

この中から必要そうなものを選びチェックボックスをつけます。それぞれの説明は下の方にちゃんと書いてありますので、それを読みましょう。

おすすめは下記です。

- Nbextensions dashboard tab(ほぼ必須。Extensionsのタブを新しく追加してくれる。)
- Snippets Menu(スニペットを登録するのに用いる)
- ExecuteTime(セルごとの実行時間を示してくれる)

他にも使える拡張はたくさんあります。ただ欲張ってたくさん入れすぎるとJupyter notebookの起動が遅くなりますのでそこは注意してください。

# デフォルトスニペットの使用

さて、上記の拡張のチェックボックスをつけたら、

```
localhost:8888/tree
```

に戻り適当なノートブックを開いてください。下記のようにスニペットのタブが増えているのが分かるかと思います。

![スクリーンショット 0029-12-18 0.10.20.png](https://qiita-image-store.s3.amazonaws.com/0/47559/45f97fbc-e749-42bf-ff82-f357787f036a.png)

このうちNew array of given shapeを選びますと、セル上に下記のように書かれます。

![スクリーンショット 0029-12-18 0.12.33.png](https://qiita-image-store.s3.amazonaws.com/0/47559/401fee60-5165-5030-24ac-f677ba1f3362.png)

デフォルトで登録されているものでも、かなり使えますので是非使用してみてください。

# オリジナルスニペットの登録

さて本題です。自分だけのスニペットを登録する手順について記します。

まず、~/.jupyter/custom/custom.jsを編集し、サンプルのスニペットを加えてみましょう。

```bash
~$ mkdir ~/.jupyter/custom/ & touch ~/.jupyter/custom/custom.js
~$ vim ~/.jupyter/custom/custom.js
```

```javascript:custom.js
require(["nbextensions/snippets_menu/main"], function (snippets_menu) {
    console.log('Loading `snippets_menu` customizations from `custom.js`');
    var my_favorites = {
        'name' : 'My favorites',
        'sub-menu' : [
            {
                'name' : 'Menu item text',
                'snippet' : ['new_command',],
            },
            {
                'name' : 'Another menu item',
                'snippet' : ['another_new_command',],
            },
        ],
    };
    snippets_menu.options['menus'].push(snippets_menu.default_menus[0]);
    snippets_menu.options['menus'].push(my_favorites);
    console.log('Loaded `snippets_menu` customizations from `custom.js`');
});
```

Jupyter notebookを再起動し、ノートブックを開くと下記の画面のように「My favorites」というスニペットが増えているはずです。

![スクリーンショット 0029-12-18 0.36.57.png](https://qiita-image-store.s3.amazonaws.com/0/47559/01f6a4e6-ea86-f7fe-7531-18bb767a5986.png)

さてそれでは、今度はこれを書き換え、機械学習へのスニペットを入れて見ましょう。

```javascript:custom.js
require(["nbextensions/snippets_menu/main"], function (snippets_menu) {
    console.log('Loading `snippets_menu` customizations from `custom.js`');
    var my_favorites = {
        'name': 'My favorites',
        'sub-menu': [
            {
                'name' : 'LogisticRegression',
                'snippet' : [
                    "from sklearn.linear_model import LogisticRegression",
                    "lr = LogisticRegression()",
                    "lr.fit(X_train, y_train)",
                    "print(lr.score(X_test, y_test))",
                    "y_predict = lr.predict(X_test)",
                ],
            },
            {
                'name' : 'SGDClassifier',
                'snippet' : [
                    "from sklearn.linear_model import SGDClassifier",
                    "sgd = SGDClassifier(loss=\"hinge\", penalty=\"l2\")",
                    "sgd.fit(X_train, y_train)",
                    "print(sgd.score(X_test, y_test))",
                    "y_predict = sgd.predict(X_test)"
                ],
            },
        ],
    }; 
    snippets_menu.options['menus'].push(snippets_menu.default_menus[0]);
    snippets_menu.options['menus'].push(my_favorites);
    console.log('Loaded `snippets_menu` customizations from `custom.js`');
});
```

このように書き換えることで、スニペットを登録することができます。

![スクリーンショット 0029-12-18 1.19.48.png](https://qiita-image-store.s3.amazonaws.com/0/47559/519ed5b7-8de7-6215-c990-8a722fbeaea2.png)

JavaScriptで登録するのが若干面倒ですので、僕はいつも下記のようにしています。

1. 登録したいスニペットをノートブックに書き込んで保存
2. 保存されたipynb形式のファイルをエディタで開き該当部分をコピー
3. custom.jsにペースト
4. ペーストした部分の改行記号を削除
5. 完成

以上、スニペットを活用した機械学習案件の生産性向上でした。