grbl1.1+Arduino CNCシールドV3.5+bCNCを使用中。
BluetoothモジュールおよびbCNCのPendant機能でスマホからもワイヤレス操作可能。
その他、電子工作・プログラミング、機械学習などもやっています。
MacとUbuntuを使用。

CNCマシン全般について:
国内レーザー加工機と中国製レーザー加工機の比較
中国製レーザーダイオードについて
CNCミリングマシンとCNCルーターマシンいろいろ
その他:
利用例や付加機能など:
CNCルーター関係:



*CNCマシンの制作記録は2016/04/10〜の投稿に書いてあります。


2018年11月20日火曜日

Kaggle Digital Recognizer(MNIST): Keras, fit_generator() + hyperopt

Kaggle Digital Recognizer(MNIST)の続きです。前回から少しだけ内容を変えてみたらベストスコアがでました。
改良点は以下です。

fit_generator():
前回は、通常の訓練model.fit()を使った後にData Augmentationとしてmodel.fit_generator()を追加して二段階で訓練しましたが、今回は最初からfit_generator()だけで訓練してみることにしました。

BatchNormalization:
CNNに関しては前回よりも層を少なくして、conv2dの後に必ずBatchNormalization()を入れ、プーリング層(学習なし)を使わずにstrides=2のconv2d()(学習あり)で1/2にダウンサンプリングすることにしました。

Hyperopt:
Hyperoptに関しては前回同様Dropout率だけを最適化しています(合計3箇所)。探索回数はとりあえず10回。

スコア:
結果はこれまでのベストスコアである0.99771(Top 5%)まで向上しました。
この辺りまで来るとスコアを0.001上げるのはかなり至難の技で、正直0.997以上になるとは期待していませんでした。しかし予想以上に満足できる結果が得られたので、Digital Decognizer(MNIST)に関してはひと段落ついたという感じです。

ただし、調べれば調べるほど興味深い項目が登場してきて、今後試してみたいのは:
・他のMNISTデータセットで今回のモデルの精度を確かめてみる(KaggleのMNISTデータセットにオーバーフィッティングしていないかどうかの検証)。
・今回はHyperoptによってDropout率を自動的に決定させましたが、Dropoutを一般化したDropconnectというのもあるらしく、それを使うとどうなるか(Keras Dropconnect Implementation)?

Kaggleで勝つデータ分析の技術
門脇 大輔 阪田 隆司 保坂 桂佑 平松 雄司
技術評論社
売り上げランキング: 363


追記:
その後、既存のkeras.datasets.mnistのデータセット(60000+10000)で検証してみると0.997以上の正解率となりました。おそらくKaggleのMNISTデータも多数含まれているので似たような結果となったのだと思います(しかし偶然KaggleのMNISTデータだけにオーバーフィットしすぎているというわけでもなさそう)。

2018年11月16日金曜日

Kaggle Digital Recognizer(MNIST): Hyperopt + Data Augmentation

引き続きKaggle Digital Recognaizer(MNIST)のスコア向上のため、今回はHyperoptData Augmentationを組み合わせてみました。
結果として、これまで0.995前後(Top 18%)のスコアがでていましたが、今回の方法で0.99671(Top 9%)まで向上しました。それでも28000個あるデータのうち92個が間違っているということになります。


今回の方法:

・畳み込み層を増やしてもう少し特徴量検出できるようにする
・あまり自動調節させるハイパーパラメータは増やさない
・バッチサイズやデータ分割などは一般的な値にしておく
・Dropout率でモデル全体の精度を調整

要は、Hyperoptによるハイパーパラメータ最適化はDropout率(合計5個)だけに絞り、その他は固定。
探索回数は20回(GTX1060で約2時間)。

前回までと異なるのは:
・ダブルの畳み込み層をもう一式追加
・Dense層出力ユニット数の増加
・最後にData Augmentationでの訓練を追加
ということになります。

Data Augmantation(訓練データの変形加工:水増し)するためにKerasのImageDataGeneratorを使用しました。
ImageDataGeneratorを使うには元データのshapeを(-1, 28, 28, 1)にしておく必要があるようです。これまではCNNモデル入力層でkeras.layers.Reshape()を使って(784, )から(-1, 28, 28, 1)に変換していましたが、ImageDataGeneratorの入力次元数とモデルの入力次元数が異なるためエラーがでてしまい、モデルに入力する前に(-1, 28, 28, 1)へ変換することにしました。

流れとしては:
・訓練画像を元にHyperoptで最適化
・最適化されたモデルをData Augmentationで追加訓練
という二段階の訓練です。
Data Augmentationの訓練は結構すぐに収束してしまいましたが、その訓練の差なのかほんのわずか向上しました。


まとめ:
個人的には、これまでスコア0.995が壁になっていて、手動でいろいろ試してみたけれどもなかなか超えられませんでした。今回のスコアは期待していた以上に良かったので、MNISTに関してはもうこの辺で充分かと思いますが、あと試してみたいのは以下。
・最初からImageDataGeneratorで訓練
・交差検証(KFold

基本的なMNIST分類問題ですが、こうやってスコア向上を目標に試してみると、いろんなテクニックが見つかりかなり勉強になります。基本的なCNNアルゴリズムだけでなく、その他の方法も組み合わせることでわずかながらでも向上するということが分かったのもよかったです。

関連:
Kaggle Digital Decognizer(MNIST): Keras, fit_generator() + hyperopt


直感 Deep Learning ―Python×Kerasでアイデアを形にするレシピ
Posted with Amakuri at 2018.12.21
Antonio Gulli, Sujit Pal
オライリージャパン
販売価格 ¥3,672

2018年11月14日水曜日

GPyOpt: Digital Recognizer(MNIST) CNN Keras ハイパーパラメータ最適化

引き続きハイパーパラメータ最適化として、今回はGPyOptを使ってみました。これまでHyperasHyperoptを試して見ましたが、ベイズ最適化でも採用しているアルゴリズムが微妙に違うようなので試してみたという感じです。
個人的にはHyperoptが一番使いやすく感じましたが、GPyOptは以前scikit-learnで試したベイス最適化に近いアルゴリズムだったのでもう少し理解を深めてみようかと。
まだ手探り段階なので、使い方に関しては後から追記するかもしれません。


使い方:

ハイパーパラメータの設定:
まずはMNISTモデルにおけるハイパーパラメータの設定からです。今回はやや少なめで。

最適化するハイパーパラメータ:
・各層のドロップアウト率:連続値
・Dense層出力ユニット数:離散値
・validation_splitの比率:連続値

GPyOptではハイパーパラメータを以下のようなフォーマットで書きます。
params = [
    {'name': 'Dropout_0',        'type': 'continuous',  'domain': (0.0, 0.5)},
    {'name': 'Dropout_1',        'type': 'continuous',  'domain': (0.0, 0.5)},
    {'name': 'Dropout_2',        'type': 'continuous',  'domain': (0.0, 0.5)},
    {'name': 'Dropout_3',        'type': 'continuous',  'domain': (0.0, 0.5)},
    {'name': 'Dense_0',          'type': 'discrete',    'domain': (128, 256, 512)},
    {'name': 'Dense_1',          'type': 'discrete',    'domain': (64,128, 256)},
    {'name': 'validation_split', 'type': 'continuous',  'domain': (0.1, 0.3)}
]

リスト化されたディクショナリーで(ここを参考に)、

・'name' : パラメータ名
・'type' : 'continuout'(連続値)、'discrete'(離散値)、'categorical'(分類値)
・'domain' : 適用範囲または選択肢を()で括る

となるようです。


CNNモデルの構築:
次にモデルを構築します。前回同様MNIST分類用のCNNを使います。このモデルからはベイズ最適化するための評価値となるlossかaccが求められればいいのですが、

・loss
・acc
・model
・history

の4種類を戻り値にしておきました。
model.fit()させてEarlyStoppingで打ち切りになった最後のval_lossとval_accの値を参照しています。
    loss = hist.history['val_loss'][-1]
    acc = hist.history['val_acc'][-1]
modelやhistoryは不要ですが、後から参照するかもしれないので一応入れておきました(使うかどうかは分からない)。
return loss, acc, model, hist

上記パイパーパラメータに対応する変数部分には、x[:, 0]などと引数にインデックス番号をつけるようですが、どれが何番目かはわかりにくいのでハイパーパラメータの'name'から参照できる関数をつくってみました。
model.add(Dropout(Param('Dropout_0'), seed=seed))
このように書き込めばx[:, 0]へ自動変換してくれます。Hyperoptなどでもディクショナリーのキーを使っていたので、このほうが個人的には使いやすいかと(リスト内容を変えた場合にインデックス番号だと、他の番号も変わってしまうのが面倒なので)。
注意点として、最初に書いたハイパーパラメータはリストであるのに対して、この変数は2次元のndarrayに変換されてから代入されるようです。この変換関数は以下(cnn_model関数内)。
    def Param(p_name):
        p_index = [p['name'] for p in params].index(p_name)
        p_type = params[p_index]['type']
        
        if type(x) is np.ndarray:
            if p_type == 'continuous':
                return float(x[:, p_index])
            else:
                return int(x[:, p_index])
        else: # list
            if p_type == 'continuous':
                return float(params[p_index]['domain'])
            else:
                return int(params[p_index]['domain'])
後で最適化されたハイパーパラメータリストを直接渡せるようにしてあります。引数がndarrayならx[:,0]のような2次元ndarray、listならlist内のスカラー値へ変換後代入。また今回の場合、離散値はすべて整数だったのでintかfloatかも振り分けています。


フィッティング関数:
上記CNNモデルを以後のベイズ最適化関数GPyOpt.methods.BayesianOptimization()に直接渡してもいいのですが、CNNモデルからは4種類の値を出力することにしたので、このf(x)関数を間にはさんで必要な評価値だけを渡せるようにしました。今回はaccを評価値として渡すことにし、最小化するためにマイナス反転して-accにしています。
前述のように引数のxは二次元のnumpy.ndarrayになるようです。今回は7種類のハイパーパラメータがあるので、x.shapeは(1,7)になります。最初に設定したハイパーパラメータはリストでありndarrayではないので、この辺をいじる場合は変換するなどの工夫が必要です(このサンプルを参照)。
実際は、
def f(x):
    x = np.atleast_2d(x)
    fs = np.zeros((x.shape[0],1))
    for i in range(x.shape[0]):
        loss, acc, model, hist = cnn_model(x)
        fs[i] += np.log(acc)*(-1)
    return fs
このように書いたほうがいいのかもしれませんが、戻り値は1次元のndarrayだったので、今回は省略して以下のようにしました。対数変換したほうがいいのかもしれませんが効果の違いは検証していません。
def f(x):
    loss, acc, model, hist = cnn_model(x)
    return -acc

ベイズ最適化関数:
GPyOpt.methods.BayesianOptimization()に先程のf(x)関数とハイパーパラメータリストparamsを渡し、その他初期探索値や獲得関数などを決めます。獲得関数はデフォルトではEIになっていますが'EI_MCMC'を選んでみました。'EI_MCMC'を選択する場合は、model_typeで'GP_MCMC'を選んでおかなければいけないようです。
initial_design_numdataは20に設定しましたが、これはどのくらいがいいのかは不明(デフォルト:5)。探索する前のランダムな開始点の数なのかもしれませんが、今回の7次元に対してどのくらいが適当なのか?探索点は徐々に追加されながらフィッティングしていくと思うのでデフォルトの5でもいいのかもしれません。入れた回数だけループするようです(20回で約1時間)。
こまかな設定がいくつかありますが、まだ使いながら試している段階です。

次に、run_optimization(max_iter=50)で最適化が始まります。イテレーションを50回に設定しました。7種類のハイパーパラメータに対してどのくらいが適当なのかはまだ不明(ハイパーハイパーパラメータ)。50回で約4時間かかりました。
ループが終了すれば最適なハイパーパラメータが見つかったことになります。設定した回数より早く終わることもあります。


最適化されたハイパーパラメータの取得:
以下で結果を取得することができます。
x_best = opt.x_opt
print([i for i in x_best])

y_best = opt.fx_opt
print(y_best)
そうすると、
[0.1732254530746627, 0.39555160207057505, 0.14877909656106353, 0.07323704794308367, 128.0, 128.0, 0.1471216716379693]
-0.9945388349514563
と値が出てきて、最初のリストが最適化された各ハイパーパラメータ。
下の値はそのときのロス値。今回はaccをマイナス反転してあるのでaccの値と同じ。精度0.994以上でているのでまあまあの結果です。


最適化されたハイパーパラメータをモデルに適用:
上記結果と同時にベストモデルやベストウェイトを直接取り出したいのですが、そのような方法がGPyOptにはないようなので、最適化されたハイパーパラメータをCNNモデルに入れ直して再度訓練させてみました。
一応、上記ハイパーパラメータリストを元々のディクショナリー型のリストへ移し替えてからCNNモデルに渡しています。CNNモデルの引数がlistの場合はスカラー値を各変数に代入するような関数にしています。
CNNモデルはEarlyStopping機能をつけているので15ループで収束してくれました(4分25秒)。
このモデルを利用して提出用データを予測します。


まとめと結果(スコア):
最終的にスコアは0.99457でした。まあまあいい結果です(それでも手動調整のベストスコアである0.99528には達していない)。約6時間でこの結果ですが、もっと回せば向上するかはわからないです。これ以上のスコアを出すには、data augmentationでデータを水増しするなど必要かもしれません。
GpyOptはHyperoptに比べるとやや使いにくいという印象でした(サンプルも少ない)。しかしやりたいことに応じて使いやすく改造すればいいのかもしれません。もともとのアルゴリズム自体は優れていると思うので、いくつかを同時に試して結果的にいい方を選ぶ感じでしょうか。時間的にもHyperoptのほうが速いかもしれませんが、どのライブラリであっても数時間はかかるので時間よりも精度がでるほうがいいと思います(仕事で使っているわけではないので)。
このほか気になるライブラリとして、SkoptKoptPyBOSpearMintなどありますが、とりあえずはもう十分かと。

これまでは機械学習理論やアルゴリズムの種類を覚えていくことが面白かったのですが、Kaggleをきっかけにスコア(精度)を少しでもあげようとすることにも興味を持てたのはよかったです。実際使ってみて、その結果から次にどうすればいいのかという具体的な疑問が次のモチベーションになるので、より理解も深まりつつ面白くなっていく感じです。

追記:
その後、4つのDropout率だけをハイパーパラメータとして最適化した結果スコア:0.99557まで向上(これまでのベストスコアは0.99524)。
その他のハイパーパラメータは以下のように固定。
validation data:test_size=0.15
Dense_0 output units: 256
Dense_1 output units: 128
batch_size=32

そして最適化においては以下の探索回数に設定。
initial_design_numdata=30(2h 29mins)
max_iter=100(stop at 52: 7h 47mins)
max_iterは最大100回に設定しましたが途中52回で収束し停止しました。
合計で10時間30分(GTX1060で)。

関連:
Kaggle Digital Recognizer(MNIST): Hyperopt + Data Augmentation
Kaggle Digital Decognizer(MNIST): Keras, fit_generator() + hyperopt



機械学習スタートアップシリーズ ベイズ推論による機械学習入門 (KS情報科学専門書)
Posted with Amakuri at 2018.12.21
須山 敦志
講談社
販売価格 ¥3,024(2018年12月21日20時40分時点の価格)

2018年11月10日土曜日

Hyperopt:Digital Recognizer(MNIST)のハイパーパラメータの最適化



今回は、HyperoptでMNISTのハイパーパラメータの最適化を行いました。Hyperoptは前回試したHyperasの元となっているライブラリです。Hyperasはシンプルに使える反面やや扱いにくい部分(慣れていないだけかもしれませんが)もあったため、大元のHyperoptで書き直してみました。

データは前回同様KaggleのDigital Recognizer(MNIST)で、最適化するハイパーパラメータは以下です。

・Dropout率
・Dense層出力ユニット数
・batch_size数
・validation_splitの比率

Hyperoptの使い方:

ハイパーパラメータのディクショナリー設定:
まずハイパーパラメータのディクショナリーを以下のようなフォーマットで用意します。

params = {
    'Dense_0':          hp.choice('Dense_0', [128, 256, 512]),
    'Dense_1':          hp.choice('Dense_1', [64, 128, 256]),
    'Dropout_0':        hp.uniform('Dropout_0', 0.0, 1.0),
    'Dropout_1':        hp.uniform('Dropout_1', 0.0, 1.0),
    'Dropout_2':        hp.uniform('Dropout_2', 0.0, 1.0),
    'Dropout_3':        hp.uniform('Dropout_3', 0.0, 1.0),
    'batch_size':       hp.choice('batch_size', [16, 32, 64]),
    'validation_split': hp.uniform('validation_split', 0.1, 0.3)
}

離散値の場合はhp.choice()、連続値の場合はhp.uniform()を使います。このあたりはHyperasと同じような感じです。このほか乱数用のhp.randint()や正規分布用のhp.normal()などいくつかあります(ここに書いてあります)。


ハイパーパラメータの挿入と戻り値の設定:
次はモデルの構築です。MNISTデータの前処理をしておいてから、CNNを用いてMNIST分類モデルを構築します。そして最適化したい変数の部分(以下の場合:CNN層内のドロップアウト率)に、

model.add(Dropout(params['Dropout_0'], seed=seed))

という感じで挿入しておきます。
model.compile()、model.fit()したあと model.evaluate()でlossとaccを求めて、その値を戻り値とします。サンプルなどではlossのかわりにaccを評価値として次のfmin()関数に渡していますが、どちらがいいのかは不明。または、hist=fit()のhistoryからhist.history['val_loss'][-1]で最後のロス値を取得する方法でもいいのかもしれません(あるいは'val_acc')。尚、accを渡す場合はマイナスをかけて最大値を最小値に反転させておく必要があります。
またモデルなどその他の値やオブジェクトを渡すときはディクショナリーにするといいようです。ディクショナリーにする場合は、次のfmin()関数に値を渡すために'loss'と'status'のキーが最低含まれていないといけないようです。今回は追加でモデルも含めたので以下のような戻り値としました。あとでベストmodelを参照する場合は追加しておくといいと思います。

return {'loss': -acc, 'status': STATUS_OK, 'model': model}


最適化:
最後に、best=fmin()で最適なパラメータを見つけます。fmin()へモデルとハイパーパラメータディクショナリーを渡し、探索回数などを指定して最適化します。探索回数は多いほどいいと思いますが、それなりに時間はかかります(数時間とか)。
trialsには探索結果の記録が保持されるので後で参照します。

trials = Trials()
best = fmin(fn=cnn_model, 
            space=params, 
            algo=tpe.suggest, 
            max_evals=20, 
            trials=trials,
            verbose=1,
            rstate=np.random.RandomState(seed))

fn:CNNモデル(前述の'loss', 'status', 'model'が戻り値)
space:パイパーパラメータのディクショナリー
algo:使用するアルゴリズム(TPEなのでこのまま)
max_evals:探索回数
trials:探索記録保持先
verbose:ログ出力
rstate:乱数固定


結果参照:
best=fmin()からは最適化されたパラメータのディクショナリーが出力されます。そのままだと、hp.choice()の場合リストのインデックス番号が返されるので、

space_eval(params, best)

で実際の値に変換出力してくれます(以下)。

{'Dense_0': 512,
 'Dense_1': 256,
 'Dropout_0': 0.19796353174591008,
 'Dropout_1': 0.30328292011950164,
 'Dropout_2': 0.7005074297830172,
 'Dropout_3': 0.3974900176858912,
 'batch_size': 64,
 'validation_split': 0.16617354953831512}

あらかじめtrials=Trials()と定義しておけば、trialsの中に全ての情報が記録されるので、必要に応じて値やモデルを参照することができます。

trials.best_trial['result']

で以下が出力されます(複数回探索した中でのベストの結果)。lossはaccをマイナス反転したものなのでaccのこと、modelはそのときのベストモデル、statusは処理が無事完了なら'ok'。

{'loss': -0.9935714285714285,
 'model': <keras.engine.sequential.Sequential at 0x7fc5c3da87f0>,
 'status': 'ok'}

ベストモデルは、

best_model = trials.best_trial['result']['model']

によって参照することができるので、このモデルを使ってpredict()することができます。

まとめ:
前回のHyperasよりも使い勝手はよさそうです。それほど面倒なコーディングをすることもないので、個人的にはHyperoptのほうが便利かと。要は、パイパーパラメータディクショナリーとモデルを最適化関数に入れれば答えがでてくるということです。
詳しいドキュメントがないので(ここくらい)、細かな使い方はわからないのですが(ソースを読み解くしかないかも)、いろいろ応用できそうです。
今回はmax_evals=20で20回探索(NVIDIA GTX1060で49分)した結果、スコアは0.99257でした。まあまあの結果でしたが、実際100回以上(数時間)は回したほうがいいのかもしれません。

こちらのサイトでは様々なベイズ最適化ライブラリーを比較しており、時間的にはHyperoptが一番速いようです。10次元以下の最適化であればPyBOが優れているようで、それ以上の次元ではどれも遅くなるようです。また20次元や40次元になるとほとんどのライブラリが最適化できなくなるようで、Spearmintが20次元でも機能していたようです。

追記1:
その後100回(約6時間)回してみましたがスコアは0.99185という結果。validationセットでのスコアは0.995だったので向上しましたが、オーバーフィッティング気味だったったのか結果的にはいまいち。いずれにせよ0.992前後が限界という感じ。CNNの層を少し改造するか、kerasのImageDataGeneratorでデータ水増しした方がいいのかもしれません。

追記2:
validation_splitを0.2に固定して、Dropout率とDense層出力ユニット数だけをハイパーパラメータとして10回ほど探索すると0.99442まで向上しました。普通に考えてvalidation dataは少ないほどval_accは上がってしまうと思うので固定にしたほうがよさそうです。

関連:
GPyOpt: Digital Recognizer(MNIST) CNN Keras ハイパーパラメータ最適化
Kaggle Digital Recognizer(MNIST): Hyperopt + Data Augmentation
Kaggle Digital Decognizer(MNIST): Keras, fit_generator() + hyperopt


2018年11月9日金曜日

HyperasでDigital Recognizer(MNIST)を試す


前回AutokerasでMNISTを自動化分類してみましたが、今回は特定のハイパーパラメータを最適化するHyperasHyperoptのkerasラッパー)を試してみました。最適化にはいろいろ種類があって、HyperasはTree-structured Parzen Estimators (TPE)というガウス過程の欠点を補った方法のようです。グリッドサーチよりも計算量が少なく、ベイズ最適化のように探索していくようですが、微妙に計算方法が異なるようです。


使い方:
Hyperasの使い方は非常に簡単で、
例えばドロップアウト率を0から1の範囲で最適化したい場合は、

Dropout({{uniform(0, 1)}})

複数の選択肢がある場合は、

optimizer={{choice(['adam', 'rmsprop', 'SGD'])}}

を通常の変数部分に入れて行くだけです。ディクショナリーを用意する必要もないので楽です。

ちなみに、今回最適化したハイパーパラメータは以下。
・Dropout率
・Dense層出力ユニット数
・batch_size数
・validation_splitの比率


ルール:
ただし少しだけルールがあるようです(このあたりがやや使いにくいかも)。
HyperasはHyperoptのラッパーで、一旦コーディングした内容をそのままHyperoptへ翻訳変換してしまうようです。そのためまずdata関数とmodel関数を作り(カプセル化するフォーマット)、その後dataとmodelをoptim.minimize()へ渡してモデル探索します。基本的には以下のようなフォーマット。

def data():
  データの読み込み
  データの前処理
  return X_train, Y_train, X_test, Y_test

def model(X_train, Y_train, X_test, Y_test):
  model = Sequential()
  ...
  model.compile()
  model.fit()
  ...
  return{'loss':-acc, 'status': STATUS_OK, 'model': model}

best_run, best_model = optim.minimize(model, data, ...)


それから、data関数とmodel関数外で定義したグローバル変数はdata関数とmodel関数のスコープに届かないようです(importしたモジュールなどは問題ない)。よってグローバル変数などは、新たにdata関数とmodel関数内に定義しないといけなさそうです。globalを使えばいいのかも。
それと引数や戻り値の変数名も一致させておかないとエラーがでました。
また、model関数内で{{uniform()}}や{{choice()}}を含んだ行を#でコメントアウトしても、Hyperoptへ変換される際には最適化する変数として読み込まれてしまうので消去する必要があります。

最初なぜエラーがでるのかわかりませんでしたが、Hyperoptへそのまま翻訳変換するためそういうルールのようです。そういうことから、やや複雑なことをするならHyperoptを使ったほうがいいかもしれません。

ということで、このルールに戸惑いましたが何とかコーディングしたものが以下。

最適化されたハイパーパラメータはbest_runによって出力されます。

{'Dense': 64,
 'Dense_1': 64,
 'Dropout': 0.21099660541107612,
 'Dropout_1': 0.29327102196615873,
 'Dropout_2': 0.7302305870589935,
 'Dropout_3': 0.258985915829989,
 'batch_size': 32,
 'validation_split': 0.10388179991112252}

今回のハイパーパラメータはこんな感じ。
デフォルトだとchoice型のハイパーパラメータはリストのindex番号として出力されるので(例えば上記の'Dense': 64がデフォルトだと'Dense': 0と表示される)、optim.minimize()内に

eval_space=True

を加えておけば、リスト内の実際の値として出力されます。
また今回は、max_evals=10としました。これは探索回数のことだと思うのですが、最低どのくらいが必要かは試してみないとわかりません(ハイパーパラメータのハイパーパラメータ)。探索回数が多いほど正確に予測できると思いますが、その分時間もかかってしまいます。以前ベイズ最適化を試した時は15回くらいの探索でブラックボックス関数にほぼ近似していましたが、Hyperas(Hyperopt)のTPEアルゴリズムにおいてはどうなのか?



まとめ:
まだ使い方に慣れていないためか、スコアは0.98371(max_evals=10)でいまいちでした。何回かやり直してみたので、それなりに時間がかかってしまいました(エラーや失敗も含めて)。そうなると、まだまだ手動調節(スコア:099528)のほうがMNISTの場合であれば早いという感じです。
ただ、手っ取り早く試すにはHyperasはいいのかもしれません。少し使い勝手が悪いので、流れがわかればHyperoptへ移行してもいいと思います。
このほかKeras用の最適化ライブラリでTalosというものも試してみました。Talosもシンプルで簡単ですが、グリッドサーチやランダムサーチをベースにしているのか、最適化範囲や選択肢が増えると探索にとてつもなく時間がかかってしまったので一旦中止。
次は、Hyperoptで実装しなおすか、GpyOptを試してみようかと思います。

追記その1:
その後、max_evals=20で探索すると0.99200までスコアがあがりました。

追記その2:
さらに、max_evals=100まで試すと0.99271まで向上。
以下が最適化されたハイパーパラメータ:

{'Dense': 256,
 'Dense_1': 128,
 'Dropout': 0.01772328721174527,
 'Dropout_1': 0.4978692970747428,
 'Dropout_2': 0.13740853439432676,
 'Dropout_3': 0.01305834864014449,
 'batch_size': 32,
 'validation_split': 0.12455270876039955}

結構まっとうな値です。たまにDropout:0.7以上がでるときもありますが、今回はどれも0.5以下。
Denseの出力ユニット数はそれぞれ選択肢の最大値256と128なので、もう一段階512と256へ上げてもいいかもしれません。
GPU:GTX1060(6GB)で数時間回せばこのような結果が出せるのでそれなりに使えそうです。探索回数であるmax_evalsは最低でも100、もしくは500や1000で1日中回すのがいいかもしれません。

2018年11月5日月曜日

Auto-KerasでKaggle:Digit Recognizer(Mnist)を試す

引き続きKaggleのDigit Recognizer(Mnist)を試しています。少しでもスコアを上げようとハイパーパラメータを調整しては提出を繰り返していましたが、このハイパーパラメータ調整を自動化してくれるAuto-Kerasというライブラリがあったので試してみることにしました。




基本的には数行のコードでMnistなどの画像分類をしてくれます(以下)。

from keras.datasets import mnist
from autokeras.image_supervised import ImageClassifier

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape + (1,))
x_test = x_test.reshape(x_test.shape + (1,))

clf = ImageClassifier(verbose=True)
clf.fit(x_train, y_train, time_limit=12 * 60 * 60)
clf.final_fit(x_train, y_train, x_test, y_test, retrain=True)
y = clf.evaluate(x_test, y_test)
print(y)

内部の細かい仕組みについては検証していませんが、これでモデルやバッチサイズなど自動的に決めてくれるようです。いくつかのモデルやハイパーパラメータを試して、結果論的にベストなものを選ぶという感じでしょうか。

ということで、上記サンプルをKaggleのデータに置き換えて試してみました。
訓練用データを訓練と検証用データに分けて、メモリーの限度を超えないように、dtypeをint64からuint8に変換しています。

結果を得るためには、fit()内のtime_limitで時間設定する必要があるようです。とりあえず1時間試してみると、結果は0.98738で0.99には届きませんでした(前回のCNNで0.99528)。デフォルトでは24時間になっているので、もう少し長い時間かけたほうがいいのかもしれません。


まとめ:
以前ベイズ最適化(ハイパーパラメータチューニングのアルゴリズム)を試してみましたが、こんな短いコードで済んでしまうのは便利です。Mnistの場合は手動でハイパーパラメータを調節してもそれなりの結果(スコア:0.99以上)が出せますが、未知のモデルに対するベースラインをとりあえず出してみるときにいいのかもしれません。
ただし、最低でも数時間は回し続けなければいけないので、途中でエラーがでてしまうとまたやり直しというのが面倒です。
autokerasの場合は完全自動化なので、特定のハイパーパラメータを自動化できるGpyOptを使ったベイズ最適化も試してみたいと思います(こちらの例とか)。

参考にしたサイト:
https://www.simonwenkel.com/2018/08/29/introduction-to-autokeras.html

2018年10月24日水曜日

Kaggle:その2(Titanic、Mnistなど)

前回のTitanicの続きです。
いろいろとハイパーパラメータを調節して目標としていたスコア:0.80(上位8%)を何とか超えることができましたが、どうも乱数固定が不安定で偶然出てきた結果という感じ。たぶんCUDAとともにインストールしたcuDNNのほうで乱数の固定ができていないような。まあ、それでもできるだけ固定することでわずかな誤差ですむようになってきました。以下が現在の乱数固定方法。このほかKerasのDense層のkernel_initializer、Dropoutにおいてもseedを固定しています。


スコアをあげるための決定的な解決策はまだ出てきていないのですが、今回はKerasのEarlyStopping機能(訓練ループを自動的に止める)を使ってみました。

EarlyStoppingだけでなく、自動的に学習率を下げるReduceLROnPlateauとModelCheckpointでベストなウェイトを保存させて、その結果から予測させています。要はできるだけ自動化という方向で。

提出結果のスコアを比較していくと、隠れ層を1層にした非常にシンプルなニューラルネットのほうがいい結果が出ました。Titanicの場合はデータ数が少ないので(訓練+テスト:1309サンプル)、優れた予測モデルを構築しにくいのかもしれません。乱数の違いでもかなり結果が変わってしまうのでその辺が難しそう。

基本的にはデータをみながらの工夫はせずに、数値化したデータをそのままニューラルネットに渡して自動的に解決する方法にしています。

それぞれのデータに関しては:

Pclass:そのまま
Name:含まれるTitle(Mr/Mrsなど)を抽出し数値化(0〜17)、正規化
Sex:数値化、male:0, female:1
Age:欠損値あり(後で穴埋め)、正規化
SibSp:正規化
Parch:正規化
Ticket:削除
Fare:欠損値あり(後で穴埋め)、正規化
Cabin:欠損値も含め数値化:nan:0, C:1, E:2, G:3, D:4, A:5, B:6, F:7, T:8に変換
Embarked:欠損値あり(後で穴埋め)、数値化:S:0, C:1, Q:2

何度かスコア:0.80を超えた(上位8%)のですが、あまり当てにならないので、再度仕切り直しで以下のコード(スコア:0.78947)。

表示されない場合はこちら

Digit Recognizer(Mnist):
Titanicはまだまだやり続けたいのですが、1日に10回までしか提出できないので、ビギナー用のDigit Recognizerも試してみました。これはサンプルでよく使われているMnist(手書き文字)。
基本的にCNNを通して10通りの数字を分類しますが、これまで精度を上げてみるということはしたことがなかったので、どの程度できるのか今回チャレンジ。

よくあるCNNでやってみてもスコア:0.99以上にはなりました。あとは0.001でもいいのでより精度をあげるにはどうしたらいいかという感じです。
結果としては、0.99528(上位18%)まで上げることができました。以下がコード。

表示されない場合はこちら

サンプルなどでよくあるCNNに対して層やユニット数を調整したり、BatchNormalizationやDropoutを加えてみました。最初は0.993くらいでしたが、その分やや向上しました。
この他、画像をリサイズしてKeras ApllicationsにあるXceptionやInceptionV3なども試してみましたが、それほど良い結果は得られなかったので、そんなに層を増やさなくてもよさそうです。
これもまだまだ精度をあげることはできそうなので、もう少しやり込みたいと思っています。


TGS Salt Identification Challenge:
この他、賞金ありのコンペにも試しに登録してみました。これは地質画像をもとに塩の埋蔵量を予測するコンペのようです。Kernelsには基本的なアルゴリズムがのっているので、そのままコピペしてベースラインのスコアは得られますが、そこからさらに精度をあげなければいけません。基本的に画像認識のコンペですが、セグメンテーションするためのU-net、intersection-over-union(IoU)、その離散値を連続値として計算可能にするLovasz Hinge Lossというテクニックが使われているようで難しそうです。
期限前までに完全理解することはできませんでしたが、Kernelsを読んでいるだけでも勉強になるので、難しそうでも一度参加してみて、できるところまでやってみると知見も広がってよさそうです。

Kaggleで勝つデータ分析の技術
門脇 大輔 阪田 隆司 保坂 桂佑 平松 雄司
技術評論社
売り上げランキング: 363

2018年9月29日土曜日

Kaggle:TitanicをKerasで試してみる

いつかはKaggle(機械学習コンペサイト)をやってみようと思っていましたが、今回ようやくチャレンジしてみました。練習もかねて、ビギナー向けの「Titanic」から。


「Titanic」は訓練データを元に、テストデータの乗客者の生存確率を予想するコンペです。ビギナー向けなので締め切りはないようです。現在は1日10回まで提出できるようです(結果のスコアが分かる)。
もうすでに10000チーム以上がエントリーしてあり、100%の予想方法もあるようですが、今回はあまり難しい方法は使わず、単純にKerasでニューラルネットを組んでどのくらいの確率になるか試してみることにしました。

Googleアカウントで登録可能で、コンペにエントリーすればデータのダウンロードができます。

提出用ファイルの書式サンプルもあるので、それに従ってcsvファイルを書き出せばいいようです。提出は以下の画面からドラックアンドドロップでも可能(Step 1)で、すぐに結果を知ることができます。Step 2は任意のメモ欄で、パラメータの設定値などをメモしています(後で編集可)。

結果を提出すれば、以下のようにすぐにScore(右端)が出てきます。
この提出結果は0.75119なので、いまいち。


Kernels:
KaggleにはKernelsと呼ばれる、解析手順のアイデアやアルゴリズムが参加者によって挙げられています。これを参考にみていくと、どのようにこのデータを扱っていけばいいのかわかります。

使うデータは:
train.csv
test.csv
の二つだけで、最終的にはtest.csvの乗客者リストの生死を0/1で予想します。

データを読み込むと、

PassengerId
Survived
Pclass
Name
Sex
Age
SibSp
Parch
Ticket
Fare
Cabin
Embarked

という項目にわかれて数値や文字列が出てきます。
直接生死に関係のないデータも含まれていますが、どの項目を重視し、あるいは捨ててしまうかはその人次第です。
しかし厄介なのは、たまにデータが抜け落ちており(欠損値)、それを捨てるか、それとも何かを手がかりに穴埋めするかも決めなくてはなりません。まずは一つずつチェックしていかなければならないのですが、Pandas(データ用ライブラリ)をつかえばこのような作業も比較的簡単にできます。

Kernelsを見ると、それぞれの項目の相関を表にしたり、事前にいろいろとデータの傾向を見ているようです。
データサイエンティストではないので、今回はこのような手続きはスキップしてKerasのニューラルネットで自動的に予測してみたいと思います。

そのためには、多少データを整理する必要があります。
・不必要と思われる項目を捨てる
・データに含まれる文字列を数値化
・必要に応じて数値を正規化/標準化
・欠損値を埋める

Pandasをそこまで使いこなしていないので、今回はPandasの勉強もかねてデータクリーニングするところから開始という感じです。

ベースライン:
一応ベースラインというものがあるようで、性別を根拠に求めると0.76555にはなるようです。その他の要素をつっこんでも0.77990が限界という人もいるようです。どうも0.80000を超えるのは難しいようで、なにかしらの工夫が必要なのかもしれません。ということで、とりあえずはベースライン以上を目指してみようかと。

Kaggleで勝つデータ分析の技術
門脇 大輔 阪田 隆司 保坂 桂佑 平松 雄司
技術評論社
売り上げランキング: 363


事前準備:
あとでAge, Embarked, Fareの欠損値を穴埋めするために、以下のような事前準備。
・train.csvとtest.csvを合体
・Ticketの項目を捨てる

文字列を数値へ変換:
・NameからTitle(MrやMissなど)を抜き出す
・Titleに番号を割り振る(0〜17)、合計18種類
・Sexをmale:0, female:1へ変換
・Cabinをnan:0、C:1, E:2, G:3, D:4, A:5, B:6, F:7, T:8へ変換(欠損値:0)
・Embarkedをnan:nan, S:0, C:1, Q:2へ変換(欠損値はあとで穴埋め)

これで、train.csvとtest.csvの両方を数値化(欠損値以外)完了。train.csvとtest.csvを合わせて合計1309人分のデータになります。

数値の正規化あるいは標準化:
特にAgeとFareは他の項目よりも数値が大きいので、場合によっては正規化あるいは標準化が必要かも。

データを欠損値の有無で分ける:
Age, Fare, Embarkedに欠損値があるので、これらを穴埋めするために分けておきます。そうすると、1309人中1043人分のデータが欠損値なしになります。

欠損値補完:
欠損値を穴埋めする際には
・0で埋める
・平均値で埋める
・頻度の高い数値で埋める
などいくつか方法があるようですが、今回は欠損値もニューラルネットで予想しようと思います。

ここまで準備するにも結構時間がかかりました。おかげでPandasの使い方にも慣れてきました。

Kerasで穴埋め用ニューラルネットモデルを構築:
とりあえず、層の数、ユニット数などは適当に決めて、あとから調整してみたいと思います。Embarked、Fare, Ageという欠損値の少ない順に求めてみました。


生存者予想:
nanを穴埋めしたデータを元に、train.csv(891人)からtest.csv(418人)の生存者を0/1で予想します。これもまたKerasのニューラルネットを使って予想します。

結果:
とりあえず一回目の結果としては0.71770でした。かなり低い。しかし、エラーはでないので一応アルゴリズムとしては間違ってはいなさそうなので、ここから改良していこうかと。


改良:
ニューラルネットの層をいろいろ変えてみると、層を増やしてもあまりいい結果がでないので浅くしてみました。少し改善されて0.74641。
batch_sizeをデフォルトの32から5に変えると0.75598

しかし、テストデータ418人中100人以上が間違っているということなので、ちょっとしたランダムな誤差でも数人分かわってしまいそう。このあたりになってくると、もはやゲームのハイスコア狙いのような感覚になってきます。

さらにBatchNomalizationやDropoutなども層に追加してみたり、いろいろ試してみました。しかし0.75前後という感じで0.80まではなかなか届きそうにありません。複雑にしたからといっても正解率があがるわけでもなく、精度の低いモデルにオーバーフィッティングしているだけなのかもしれません。

要素を減らして(Pclass, Sex, Age, Fare, Embarkedだけ)シンプルに計算してみると、0.77990まであがりました。ようやくベースライン。

その後、また要素は戻して、正規化で全ての数値を0.0〜1.0に変換し、比較的シンプルな層でやってみると今までのベストスコアとなる0.78947。約10000人中の3371位。半分より上に行けたのでよかったのですが、これも偶然という感じ。
random.seedによっても結果が変わりそうなので、

import tensorflow as tf
import random as rn
import os
os.environ['PYTHONHASHSEED'] = '0'
rn.seed(123)
np.random.seed(123)
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
from keras import backend as K
tf.set_random_seed(123)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)

で乱数を固定してみました(Kerasの再現可能な結果)。
追記:
Dense()とDropout()のなかのkernel_initializerにも乱数の設定があるので、
kernel_initializer=keras.initializers.glorot_uniform(seed=123)
と固定してみましたが、GPUを使っているためかそれでも毎回微妙に値が異なってしまいます。cuDNNのほうも設定しないといけないのかもしれません。

まとめ:
Kaggle自体敷居が高そうですが登録や提出などは簡単で、何度も提出できるので気軽に参加できます。実際に具体的な目標(スコア)があるので工夫しがいがあります。ハマると、ゲーム感覚でハイスコアを狙うといったやりこみ癖が出てきそうです。そういう意味でも面白いかもしれません。勉強する際にサンプルコードを写経するだけでおしまいになることがありますが(動くかどうか確かめるだけ)、工夫によってスコアが変わるためいろいろ試しながら結果を比較向上していく部分がさらなる理解度を深めます。当然、データの事前処理も今まではあまりやったことはありませんでしたが、データのあり方から様々な傾向が見えてくるのも面白いと思います。

その後いろいろいじってみましたが、0.76前後をふらふらしており決定的な改善策が見当たりません。NameをTitleに変換し、さらにTitleをone-hotラベルに変換したりしましたがそれほど効果なし。欠損値をニューラルネットで予測し、その予測を元に最後の生死を予測しているので、最初の予測が間違っていれば意味がないという感じかもしれません。1日に10回まで提出することができるので何度も試しているところです。

以下が、現在のコード(Jupyter Notebook)。まだベースライン前後なので、もう少し改良が必要です。


Gistが表示されない場合はこちら

2018年9月17日月曜日

Android上のPython:Pydroid 3, Jupyter Notebook, Colab

スマホでちょっとしたPythonのコードを確かめられないかと探してみると、Google PlayストアにPydroid 3というPython環境があったのでインストールしてみました。

 

pipを使うことが可能で、numpyやmatplotlibもインストール可能。ためしにサンプル(上画像)を実行させてみました。特に問題なく動きます。


pipでインストールする方法:

 
メイン画面の「≡(メニューマーク)」をタップすると、上画像左のような項目が出てくるので、「Pip」をタップすればライブラリを検索する画面になります。そして必要なライブラリ名を入力して「INSTALL」をタップ。
「QUICK INSTALL」タブには、主なライブラリがリストアップされているので、numpyやmatplotlibなどはこちらからインストールいたほうがいいかもしれません。インストールしたいライブラリが見当たらなければ「SEARCH LIBRARIES」タブで検索。


pipでJupter NotebookやKeras(Theano)をインストール:
pipの画面からKerasはインストール可能でしたが、Tensorflowは対応していないためかダメでした。そのかわりTheanoはインストールできたので、KerasのバックエンドとしてTheanoが使えます。

追記:
その後アップデート(2019年4月)があったようで、有償版にすればTensorflowもインストールできるようになっていました。

最近パソコンではJupyter Notebookばかり使っているので、スマホの方にもインストールしてみることにしました。


ターミナル画面からJupyter Notebookを起動:
基本は.pyファイルで保存ですが、Jupyter Notebookで.ipynbファイルも扱うことができます。
メニュー>Pipの画面から「jupyter」をインストールし、ターミナル画面に切り替えてから「jupyter notebook」を入力して起動すると、

 

Chromeが自動的に起動してJupyter Notebookの画面が出てきました。パソコンと同じような感覚で使うことができます。Chromeが自動的に開かない場合は、ターミナル画面に出てくるURLをChromeのアドレスにコピペすればJupyterの画面になるはずです。
あまり重い演算はさすがに無理ですが、ふと思いついたコードを試すにはよさそうです。

Android 7と8での違い:
Android 7では上記の方法でJupyter Notebookは動作しましたが、Android 8の場合だとセキュリティの違いのためかChromeが自動的に起動しません。ターミナル上に出力されたアドレスをChromeへコピペするしかありません。
追記:
その後のアップデートでAndroid 8でも自動的にChromeが立ち上がるようになっていました。

問題なのが、Jupyterが起動したあとPydroidのカーネルが途中で落ちてしまいます。マルチウィンドウ(二窓)でChromeとPydroidを起動しておけば落ちないのですが、Chromeを前面表示するとバックグラウンドで動いているPydroidが数秒で落ちてしまいます(対応策は下へ追記しました)。
このようにChrome(Jupyter)とPydroidを上下に同時に表示させて使う分にはPydroidのカーネルが落ちずに済みます。キーボード(画像ではフローティングにしていますが)は下のほうにでるので、Pydroidのターミナル画面に重なる感じならJupyter画面にもあまり邪魔にならないかと。
画面移行してしまうとPydroidが落ちてしまいますが、再度ターミナルでJupyterを起動し、Chromeのほうは画面をこのまま再読み込みさせれば大丈夫そうです(再度アドレスをコピペする必要がない)。

追記(上記の対応策:Huawei Nova lite 2の場合):
Android 8のバッテリー最適化機能でカーネルが落ちないようにするには、「設定」→「アプリと通知」→「アプリ」から画面下の「歯車」の設定マークをクリック→「アプリの設定」→「特別なアクセス」→「バッテリー最適化を無視」の画面で「すべてのアプリ」を表示させ「Pydroid 3」を一覧から選択し「許可」するに変更。
こうすることでバッテリー最適化によるアプリの自動切断を防ぐことができ、バックグラウンドでも動き続けるようです。


Jupyter nbextensionsのインストール:
Jupyter Notebookを使う場合、nbextensionsをインストールすれば様々な機能拡張が使えるようになります。
Pydroidのpip画面で

jupyter_contrib_nbextensions

を入力(あるいは検索)してインストール。
さらにターミナル画面に切り替えて、

jupyter contrib nbextension install --user

を入力(インストールはこれで終了)。
ターミナル画面から「jupyter notebook」入力で、ChromeにJupyterを立ち上げます。
 
そうすると「Nbextensions」というタブが増えているので、それを選択すればさまざまな機能拡張の一覧が出てきます。
「Nbextensions」タブがない場合は、「localhost:8888/nbextensions/」にアクセスすれば出てくるはずです。


Gist itを使う:
個人的に便利だと思うのはGithubのGistへボタン一発でファイル保存する機能です。
「Nbextensions」の一覧を見ていくとでてくるので、「Gist-it」にチェックをいれておきます。

 

そして、コーディングするページを開けば、

 
右上にGithubマークのボタンが増えているので(現れなければ画面をリロード)、これをクリック。
そうすると確認画面がでてくるので、青い「Gist it!」ボタンでアップロード(Tokenを登録する必要があります)。プライベートでアップロードしたいなら「Make the gist public」のチェックを外しておきます。
ファイルの保存先を忘れることもなく、後でパソコンからアクセスするのも容易なので便利です。


オンラインのJupyter Notebookを使う:
https://jupyter.org/にアクセスすればインストールせずにオンラインでもJupyterを試すことができるようです。
 
Jupyterのトップページ上の「Try it in your browser」をタップすれば、JupyterかJupyterLabなどを選択するページへ移動し、とりあえず「Try Jupyter with Python」をタップすると「Welcome to Jupyter」というサンプルページが表示されます(以下)。
 
左上の「≡Menu」から「File>Open...」を選べばディレクトリ一覧のページが表示されます。
ここで右上の「New▼」から「Python3/Text File/Folder/Terminal」を選択して新たなファイルを開くことができます。
Terminalを選択すればターミナル画面に移行し、「pip list」入力でインストールされているライブラリを確認できます。Numpy、Scikit-learn、Scipy、Pandasなど基本のライブラリはインストールされているようです。TensorflowやKerasはインストールされていませんが、「pip install tensorflow」で追加インストールできるようです。
ファイルも一時的に保存できるようですが、仮想サーバのためか、一旦ログアウトしてしまうとすべては消えてしまうようです。
ちょっとしたコードを試すだけなら、このオンラインのJupyterでも十分そうです。



Google Colabをスマホ上で使う:
Jupyter Notebookが使えるのは便利ですが、それならGoogle Colabを使えばいいのでは?ということでColabも試してみました。Colabの場合は全ての環境はクラウド上にあるので、ChromeさえあればスマホからでもGPU利用が可能です。Tensorflow、Keras、Numpy、Pandas、Matplotlibなど基本的なライブラリはすでにインストールしてあるUbuntu環境なので便利。
この場合、先ほどのPydroid 3は無関係で、単にChromeでcolab.research.google.comへアクセスすればいいだけ。


特に問題なく動きます。基本Google Driveにデータファイルなどを保存しておけば便利です。Colabの場合ならTensorflowも普通に使えるし、GPU演算なのでスマホでも問題ないという感じ。


仮想キーボードCodeBoard Keyboard for Coding:
コーディングするには、Google PlayにあるCodeBoard Keyboard for Codingが便利そうだったのでインストールしました。
既存のキーボードだと、数字や記号を入力する際に入力切替が必要だったりアローキーがなかったりするため少々不便なのですが、このキーボードであればコーディングに必要そうなキーが揃っているので便利です。コメントアウトの「#」記号だけ表面にないのですが、右上「SYM」を押せば記号一覧の中に出てきます。


まとめ:
Pydroid 3はスマホアプリなので一旦ダウンロードすればオフライン(通信料なしで)でも動く点では便利です。Tensorflowが使えなかったり、重い計算は無理なので多少の制約はあります。通信料が気になる場合はPydroid 3がいいかもしれません。ただしライブラリをインストールしすぎると1GBを超えたりするのでメモリを圧迫したくない場合は要注意。

一方、Colabの場合はコマンドのやりとりで通信料は発生しますが、演算自体はクラウド上(GPUでも可)で行うのでスマホであっても問題なく重い計算が可能という点が便利。また、ログインごとに(90分放置すると初期化)ライブラリやデータをインストールし直すのが面倒ですが、Google Driveに保存してあるデータをアップロードするのであれば、データのやりとりもクラウド上で行うのでデータが大きくてもその分の通信料はかからないはず。Colabを利用することで、スマホからでも普通にディープラーニングのコードを実行できるのはかなり画期的。Wifi環境下で通信料がかからないのであればColabがおすすめ。


データ分析ツールJupyter入門
Posted with Amakuri at 2018.12.21
掌田津耶乃
秀和システム
販売価格 ¥3,024