jupyter notebook をコマンドラインで実行し HTML ファイルを生成する
はじめに
備忘録です。
最近は非エンジニアの分析官に一次分析内容を共有して定性分析を依頼したりする事が多いのですが、多数のモデルの場合 jupyter をある程度自動化したい場合があります。
私のよくやる流れとしては以下ですが、これを多数のモデルで PDCA を何回も回すことも珍しくありません。
- jupyter で分析する.
- html を出力して分析官に依頼する.
- 分析官は自分の手慣れた方法(Excelなど)で分析、レポーティングする
今回はこういったことに役立つ、jupyter notebook をコマンドラインで実行し HTML ファイルを生成する方法を紹介します。
jupyter notebook をコマンドラインで実行する
コマンドラインで実行する
コマンドラインで実行することに関してはこちらが詳しいです。 qiita.com
コマンドラインで .pynb の HTML 化する
今回の HTML 化についてはこちらに殆ど書いています。
python - How export a Jupyter notebook to HTML from the command line? - Stack Overflow
# 以下を実行すると notebook.html ファイルが生成されます $ jupyter nbconvert --execute --to html notebook.ipynb
私がよくやるのは、雛形となる jupyter notebook を作り、変更される値や設定を変数化し、コマンドラインで置換(perl や sed など)しながら様々な分析レポートを出力することです。
簡単な例
for model in model_A model_B .....; do # 置換、或いは何らかのパーサー cat '雛形となる .ipynb' | perl -pe "s/置き換える文字列/${model}/s" > ${model}.ipynb # html 生成 jupyter nbconvert --execute --to html ${model}.ipynb done
関数データ解析(FDA, Functional Data Analysis)とは
関数データ解析とは
関数データ解析とは
各個体や対象に対して、複数の離散点で時間や空間の変化に伴い観測・測定されたデータを、関数の集合として捉え、解析する方法 Ramsay and Silverman, 2005
とされています。
一般的にデータ解析では、データそのものの統計量をとったり、クラスタリングしたり、回帰分析したりします。 関数データ解析では、データを関数で表現して、その関数を改めてデータとして扱う手法です。
とはいえ、「データを関数で表現してそこで何か(分類や予測など)をする」という手法は、従来の機械学習にも使われていますし(例えばガウス線形回帰)、関数データ解析固有のものではありません。
関数データ解析では、特定の手法ではなくデータの関数表現をデータそのものの分析と同じように扱う方法論、ということになろうかと思います。
例えば、テキスト*1 では次のように書かれています。
Ramsay & Silverman (2005)は、関数データにおける平均、分散、共分散を定義した後、 主成分分析、線形モデル、正準相関分析、判別分析の関数データ対応版を扱っている。 さらに、関数の定義域を調整するRegistration (見当合わせ)、通常のデータを 関数データにする各種平滑化などについても詳細に検討している。
近年では、これらに加えクラスタリング(Kmeans の関数データ適用がよく使われるようです)、スパース解析(https://sites.google.com/site/hidetoshimatsui/field/fda)なども検討が進んでいます。
関数データ解析のながれ
主に次の二段階法が使われるようです。
離散観測を連続の関数データで捉える(平滑化と呼ばれています)
捉えた関数集合を分析する
関数集合をデータ集合と同じように平均・分散・相関などを計算して分析する
所感
関数データ解析ではデータを関数で表現することで、データを集合で捉えより表現力のある構造(関数)で分析ができるようになります。 例えば従来のデータ解析でのデータの代表点(平均や中央値)や広がり(分散など)、関連(相関)などと同様の統計手法が関数データ解析においても使え、そこでは関数平均や関数分散、関数相関などの手法で分析ができます。
とは言え、私の中でもまだイメージの域を出ませんので、引き続き注目していきたいと思います。
Decision Tree - ID3(Iterative Dichotomiser 3 - 1979 John Ross Quinlan)
Decision Tree - ID3(Iterative Dichotomiser 3 - 1979 John Ross Quinlan)
(注意) これは私の勉強・備忘録のために記したものであり、間違いがあるやもしれません。どうぞご容赦ください。
はじめに
決定木のアルゴリズムに ID3 というものがあります。 ID3 は Quinlan が 1979 に発表したアルゴリズムで、この改良の C4.5 や、決定木を並列に多数構築した RandomForest、Boosting に活用した Gradient Boosted Trees など、発展型の元となったものです。
私の勉強のためにも、まずは ID3 から初めて、今 Kaggle でも最も定評・人気がある XGboost までたどってみようと思います。
ID3
Wikipediaja.wikipedia.org によると
その学習方法はオッカムの剃刀の原理に基づいている。すなわち最低限の仮説による事象の決定を行う。 「この方法は各独立変数に対し変数の値を決定した場合における平均情報量の期待値を求め、その中で最大のものを選びそれを木のノードにする操作を再帰的に行うことで実装される。」
とあります。これは ID3 に限ったことではなく決定木の基本的な考え方・原理です。
決定木は「最低限の仮説による事象の決定」とあるように、うまくコントロール*1すれば最小限の条件でその事象を表現できます。
特に、ヘテロジニアスデータ*2での適切に最適化された条件は人の感覚に合うため、人と機械のよいコンビネーションで PDCA を回せるなど、ビジネスの現場でもよく使われています。
実装
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import math import numpy as np import scipy as sp import matplotlib.pyplot as plt import pandas as pd import seaborn as sns """ ID3(Iterative Dichotomiser 3 - 1979 John Ross Quinlan) その学習方法はオッカムの剃刀の原理に基づいている。すなわち最低限の仮説による事象の決定を行う。 「この方法は各独立変数に対し変数の値を決定した場合における平均情報量の期待値を求め、 その中で最大のものを選びそれを木のノードにする操作を再帰的に行うことで実装される。」 https://ja.wikipedia.org/wiki/ID3 制約: 離散でないといけない S: 訓練例の集合 A: 属性の集合 default: Yes / No の既定値 """ # log の底は平均情報量の最大値が 1.0, 最小値が 0.0 になるように、分類数に合わせたほうが良い # ここでは 3 とする. def entropy(y, base=2): ''' 平均情報量の算出 y=pd.Series target bird 0.4 manmal 0.4 reptile 0.2 ''' p = y.groupby(y).count() / y.shape[0] return -1 * sum(map(lambda x: x * math.log(x, base), p)) def mean_entropy(S, c, t='target'): ent = [] for k, v in S.groupby(c).groups.items(): # weighted average y = S.ix[v, t] ent.append(entropy(y, base=3) * y.shape[0] / S.shape[0]) return np.sum(ent) """ S : Tree """ class Node(object): def __init__(self, data, parent=None, col=None, feature=None, gain=0.): self.data = data self.parent = parent self.col = col self.feat = feature # 子の分割基準 self.gain = gain self.childs = [] def entropy(self, base=2): return entropy(self.data['target'], base=base) def shape(self): return self.data.shape def add_child(self, c): self.childs.append(c) def __repr__(self): return '%s(%s)\tH:%.3f Gain:%.3f' % (self.col, self.feat, self.entropy(), self.gain) def ID3(S, A, t='target'): if S.data.shape[0] <= 0: # S が空集合 return None elif len(A) <= 0: # Aが空集合 return S elif S.entropy(base=3) <= 0.: return S else: # 1. 各説明変数で平均情報量を算出する <- このロジック mean_entropy の差し替えで C4.5 とかにできる Ms = map(lambda a: (a, mean_entropy(S.data, a)), A) # 2. 情報ゲインが最大な説明変数を選ぶ col, gain = max(map(lambda x: (x[0], S.entropy(3)-x[1]), Ms), key=lambda x:x[1]) # 3. 木を分割する #_A = list(set(A) - set([col])) for f, x in S.data.groupby(col).groups.items(): S.add_child(ID3(Node(S.data.ix[x], parent=S, col=col, feature=f, gain=gain), A)) return S def pretty_print_node(n, depth=0): if n is None: return pref = '\t' print(pref*depth, n) for _n in n.childs: pretty_print_node(_n, depth+1) if __name__ == '__main__': ''' 例題 食性(a1 ) 発生形態(a2 ) 体温(a3 ) 分類 例題1(ペンギン) 肉食 卵生 恒温 鳥類 例題2(ライオン) 肉食 胎生 恒温 哺乳類 例題3(ウシ) 草食 胎生 恒温 哺乳類 例題4(トカゲ) 肉食 卵生 変温 爬虫類 例題5(ブンチョウ) 草食 卵生 恒温 鳥類 ''' df = pd.DataFrame( [[ 'carnivorous', 'oviparity', 'homothermal', 'bird'], [ 'carnivorous', 'viviparity', 'homothermal', 'manmal'], [ 'herbivorous', 'viviparity', 'homothermal', 'manmal'], [ 'carnivorous', 'oviparity', 'cold_blooded', 'reptile'], [ 'herbivorous', 'oviparity', 'homothermal', 'bird']], columns = ['a1', 'a2', 'a3', 'target'], index = ['penguin', 'lion', 'caw', 'lizard','finch'] ) S = df A = ['a1', 'a2', 'a3'] # 属性集合 X = df[['a1', 'a2', 'a3']] y = df.target Tree = ID3(Node(df, col='top'), A) pretty_print_node(Tree)
実行結果は
:decision_tree $ python id3.py top(None) H:1.522 Gain:0.000 a2(oviparity) H:0.918 Gain:0.613 a3(cold_blooded) H:-0.000 Gain:0.579 a3(homothermal) H:-0.000 Gain:0.579 a2(viviparity) H:-0.000 Gain:0.613
keras.datasets.imdb.load_data() に 'Object arrays cannot be loaded when allow_pickle=False' で失敗する.
Tensorflow tutorials の「映画レビューのテキスト分類」(https://www.tensorflow.org/tutorials/keras/basic_text_classification) にて、データセットのロードに失敗します。
In [6]: from keras.datasets import imdb In [7]: (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-7-7d41db3a3caa> in <module> ----> 1 imdb.load_data(num_words=10) /anaconda3/envs/py36_base/lib/python3.6/site-packages/tensorflow/python/keras/datasets/imdb.py in load_data(path, num_words, skip_top, maxlen, seed, start_char, oov_char, index_from, **kwargs) 84 file_hash='599dadb1135973df5b59232a0e9a887c') 85 with np.load(path) as f: ---> 86 x_train, labels_train = f['x_train'], f['y_train'] 87 x_test, labels_test = f['x_test'], f['y_test'] 88 /anaconda3/envs/py36_base/lib/python3.6/site-packages/numpy/lib/npyio.py in __getitem__(self, key) 260 return format.read_array(bytes, 261 allow_pickle=self.allow_pickle, --> 262 pickle_kwargs=self.pickle_kwargs) 263 else: 264 return self.zip.read(key) /anaconda3/envs/py36_base/lib/python3.6/site-packages/numpy/lib/format.py in read_array(fp, allow_pickle, pickle_kwargs) 690 # The array contained Python objects. We need to unpickle the data. 691 if not allow_pickle: --> 692 raise ValueError("Object arrays cannot be loaded when " 693 "allow_pickle=False") 694 if pickle_kwargs is None: ValueError: Object arrays cannot be loaded when allow_pickle=False
これは numpy のバージョンに依存するエラーで、numpy=1.16.3 から、read_array(fp, allow_pickle, pickle_kwargs) の allow_pickle のデフォルト値が False に変更されたことに起因しています。
$ conda list ... numpy 1.16.3 py36hacdab7b_0 numpy-base 1.16.3 py36h6575580_0 ...
ここで示される解決方法は単純に numpy=1.16.2 にダウングレードすることです。
$ conda install numpy=1.16.2 $ conda list | grep numpy ... numpy 1.16.2 numpy-base 1.16.2 ...
動作を確認しました。
In [5]: imdb.load_data(num_words=1) Out[5]: ((array([list([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...
ちなみに、colab では以下のコードが挿入されており、tf のバージョンを変えることで対応しています。 nightly build では修正されているようですので次のバージョンでは解消されるはずです。
# keras.datasets.imdb is broken in 1.13 and 1.14, by np 1.16.3 # (nightly build は最新バージョンのビルド) !pip install tf_nightly
Mojave に機械学習とデータ解析の anaconda 環境を構築
Macbook Air を購入したので、何もインストールされていない真っさらな状態から、機械学習とデータ解析の環境を構築しました。 日々構築方法が様々に洗練され、前回のやり方が通用しない昨今ですが、今回は anaconda で全て構築しました。
brew
- App Storeに行ってXcodeを探しインストールをします。
xcode-select --install
- Xcodeを一度起動してライセンスに同意しておく
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew doctor
でチェック
emacs
以下を参考にしました。 https://qiita.com/kokorinosoba/items/ecceaabe07d91c6f2c66
$ brew cask install emacs
Ricty
emacs では Ricty をフォントとして使っているので、そのインストールです。 https://qiita.com/segur/items/50ae2697212a7bdb7c7f
brew tap sanemat/font
brew install ricty
- 以下のファイルをコピーし、フォントキャッシュを更新します。
To install Ricty: $ cp -f /usr/local/opt/ricty/share/fonts/Ricty*.ttf ~/Library/Fonts/ $ fc-cache -vf
Anaconda
anaconda で全部構築する
Anaconda インストール
https://www.anaconda.com/distribution/ で Python 3.7 version
Anaconda3-2019.03-MacOSX-x86_64.pkg
Anaconda 仮想環境構築
# tensorflow が python3.6 環境なので 3.6 で構築します。 $ conda create -n py36_base python=3.6 $ conda info -e # conda environments: # base * /anaconda3 py36_base /anaconda3/envs/py36_base
Anaconda Navigator でやってもスムーズです。
tensorflow/keras/sklearn のインストール
conda で全部いれてしまいます。
# 環境をアクティベートする $ source activate py36_base $ conda install tensorflow $ conda install keras $ conda install scikit-learn $ conda install matplotlib $ conda install seaborn $ conda list matplotlib 3.0.3 py36h54f8f79_0 ... numpy 1.16.3 py36hacdab7b_0 numpy-base 1.16.3 py36h6575580_0 ... pandas 0.24.2 py36h0a44026_0 ... scikit-image 0.15.0 py36h0a44026_0 scikit-learn 0.20.3 py36h27c97d8_0 scipy 1.2.1 py36h1410ff5_0 seaborn 0.9.0 py36_0 ... tensorboard 1.13.1 py36haf313ee_0 tensorflow 1.13.1 mkl_py36haf07a9b_0 tensorflow-base 1.13.1 mkl_py36hc36dc97_0 tensorflow-estimator 1.13.0 py_0
jupyter, jupyterlab, orange, glueviz, も navigator から入れます。
環境設定
bash
.bash_profile に anaconda インストーラによってスニペットが挿入されているので、その後にデフォルト起動スクリプトを挿入します。
# added by Anaconda3 2019.03 installer # >>> conda init >>> # !! Contents within this block are managed by 'conda init' !! __conda_setup="$(CONDA_REPORT_ERRORS=false '/anaconda3/bin/conda' shell.bash hook 2> /dev/null)" if [ $? -eq 0 ]; then \eval "$__conda_setup" else if [ -f "/anaconda3/etc/profile.d/conda.sh" ]; then . "/anaconda3/etc/profile.d/conda.sh" CONDA_CHANGEPS1=false conda activate base else \export PATH="/anaconda3/bin:$PATH" fi fi unset __conda_setup # <<< conda init <<< # 追加:デフォルトの環境を起動します。 conda activate p36_base
matplotlib
matplotlib の import 時にエラーが発生した場合、バックエンドを変更します。
# /anaconda3/envs/py36_base//lib/python3.6/site-packages/matplotlib/mpl-data/matplotlibrc #backend : macosx backend : TkAgg
動作確認
以下のサンプルを実行できることを確認します。
sklearn + matplotlib https://scikit-learn.org/stable/auto_examples/plot_multilabel.html#sphx-glr-auto-examples-plot-multilabel-py
tensorflow, keras
import os import tensorflow as tf os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' hello = tf.constant('Hello, TensorFlow!') sess = tf.Session() print(sess.run(hello))