Windows terminalで快適ssh生活

ついにWindowsでも快適なshell生活を送れるようになりました

Windows terminalという神ツールがversion1となり、ついに正式リリースされました。 これはかなり使いやすく、Windowsを開発に使ってもいいかなと思わせてくれる神アプリです。

www.microsoft.com

github.com

早速設定しましょう。 私が行うのは二つだけです。

  • フォントの変更
  • Dracula themeの適用

設定を行う

まずは設定画面を開きます。 中身はjsonファイルになっているので、設定ボタンをクリックすると適当なエディタが起動して、jsonファイルが開かれます。 f:id:kakibara:20200531232529j:plain 次にprofileの中にdefaults項目があるので、そこにフォントとカラースキーマを設定します。

{
    "profiles":
    {
        "defaults":
        {
           "fontFace": "Ubuntu Mono derivative Powerline",
            "fontSize": 12,
            "colorScheme" : "Dracula"
        }
    }
}

この時点では”Dracula”という名前のカラースキーマは存在しないので、次で定義します。 schemesという項目がデフォルトであるので、その中にDraculaテーマの設定を加えます。

"schemes": [
    {
        "name" : "Dracula",
        "background" : "#272935",
        "black" : "#21222C",
        "blue" : "#BD93F9",
        "cyan" : "#8BE9FD",
        "foreground" : "#F8F8F2",
        "green" : "#50FA7B",
        "purple" : "#FF79C6",
        "red" : "#FF5555",
        "white" : "#F8F8F2",
        "yellow" : "#FFB86C",
        "brightBlack" : "#6272A4",
        "brightBlue" : "#D6ACFF",
        "brightCyan" : "#A4FFFF",
        "brightGreen" : "#69FF94",
        "brightPurple" : "#FF92DF",
        "brightRed" : "#FF6E6E",
        "brightWhite" : "#F8F8F2",
        "brightYellow" : "#FFFFA5"
    }
]

以上で使えるようになります。

Dracula themeの公式ページです。いつもお世話になっています。 draculatheme.com

感想

Windows10の進化がすさまじいです。 WSLもバージョンが2になり、かなりの進化がありますが、開発ツール周りでも進化がすさまじいです。 私がwindowsを使いたくなかった理由が二つあったのですが、そのうちの一つが、sshが使いにくいというものでした。私は基本的にネットワーク上のLinuxマシンで作業を行うので、terminalを開いてsshでマシンに接続して作業を行います。なので、そのクライアントが使いにくいとストレスが溜まります。もちろんいろいろsshクライアントアプリはwindowsで開発されていましたが、どれも使用していると画面が崩れたり、macのターミナルほど信頼のおけるツールにはなっていませんでした。しかし、これは通常利用に耐えうるところまで来たという感じです。あとは英字キーボードでmacのkarabinaと同じことが実現で切ればもう何も言うことはありません。

pytorchで推論を行うときはmodel.eval()を行おう

pytorchで推論を行いたい。

pytorchでDeep Learningのモデルを組み立てるとき、Batch Normalizationを用いるのはもはや常識だ。しかし、Batch Normalizationを含むモデルで推論を行うとエラーが起きる。

以下のコードをみて欲しい。バッチサイズが1のときには実行できないのだ。バッチサイズが1だとnormalizationを行う余地がないのだが、内部では計算ができないようになっている。

そこで、推論を行う際は、model.eval()を行うことで実行できるようになる。 中で何を行なっているのかは下を参照すること。まだ中身は読んでいない。

import torch

class Foo(torch.nn.Module):
    def __init__(self):
        super(Foo, self).__init__()
        self.bn = torch.nn.BatchNorm1d(3)
    
    def forward(self, x):
        return self.bn(x)

def main():
    x1 = torch.ones(1,3)
    x2 = torch.ones(2,3)
    model = Foo()
    y = model(x1) # this line will fail to run 
    y = model(x2) # this line can run without error
    model.eval() # switch to inference mode
    y = model(x1) # this line can run without error
    model.train() # switch to traing mode

if __name__ == '__main__':
    main()

What does model.eval() do for batchnorm layer? - PyTorch Forums

pytorch上でのL1ノルムの扱いの調査

概要

pytorchのL1ノルムは自動微分に対応している。原点では勾配0、そのほかはその微分値を用いるという実装になっている(と思われる)。 これでは同じステップ幅ならいつまで経っても最適解にたどり着かない。 損失関数として用いる場合でそれが嫌ならばSmooth L1 Loss(torch.nn.SmoothL1Loss())という、原点付近でL2ノルムに変更しているものがあるので、そちらを用いるとよい。

pytorchのL1ノルムの計算

pytorchには自動微分が備わっているが、L1 normの関数にも自動微分が対応している。 torch.abs()が自動微分に対応している。他にもtorch.nn.functional.l1_loss()が対応しているが、下のように中ではtorch.abs()を用いているので、実質同じである。

torch.nn.functional — PyTorch 1.5.0 documentation

ここで、l1ノルムは原点で微分ができないことが問題になる。特に、最小化問題を解くことがほとんどだと思うが、その最小になる点で微分可能でないので、扱いが難しいはずである。特別な理由がなければ使用を避けた方が良いが、どうしても使いたい場合のために、どういう挙動をするのか確認しよう。

確認

不連続点では微分が0になり、その他の点では傾きを1 または -1となっているようにみえる。 三点しか確認してないけどね。 中身はC++で実装されているので、確認したら編集しようと思う。

import torch
device = 'cpu'
a = torch.tensor([-1,0,1], dtype=torch.float64, device=device, requires_grad=True)
b = torch.tensor([0,0,0], dtype=torch.float64, device=device)
loss = torch.nn.functional.l1_loss(a, b, reduction='sum')
loss.backward()
print(a.grad)
>>> tensor([-1.,  0.,  1.], dtype=torch.float64)


a = torch.tensor([-1,0,1], dtype=torch.float64, device=device, requires_grad=True)
b = torch.tensor([0,0,0], dtype=torch.float64, device=device)
loss = torch.abs(a - b).sum()
loss.backward()
print(a.grad)
>>> tensor([-1.,  0.,  1.], dtype=torch.float64)

ここは実は奥が深そうで、 絶対値演算を含む自動微分にはいくつかやり方があるようだ。

https://ipsj.ixsq.nii.ac.jp/ej/?action=repository_action_common_download&item_id=104343&item_no=1&attribute_id=1&file_no=1

また、Smooth L1 Loss(torch.nn.SmoothL1Loss())という、原点付近でL2ノルムに変更しているものもある。原点付近の挙動は許せないが、L1ノルムを使用したい場合はこれを使えばいいだろう。

使うべきか

実際に使用する場面を考えてみる。 0付近でなければ何も問題ないが、0に近づけたいと思うので、どうなんだろうか。 スパースモデリングとかを想定すると、特定の次元を0に持っていくことが大事なのでこれはよくないと思われる。 また、微分時のコストもL2ノルムと変わらないのではないかと思う。 どの位置でも勾配の大きさが同じであってほしいときに使うのであろうか。 他に需要があれば知りたいところである。

max(), min()と絶対値演算

上で紹介したPDFにも書いてあるが、max()、min()は以下のように絶対値演算に変換可能である。 L1ノルムも当然絶対値演算である。なので、絶対値演算が自動微分に対応しているならば(0付近の挙動は置いといて)実行可能なので便利である。

$$ \begin{equation} \begin{aligned} \max (x, y) &=\frac{1}{2}(x+y+|x-y|) \\ \min (x, y) &=\frac{1}{2}(x+y-|x-y|) \end{aligned} \end{equation} $$

jupyter labの設定

jupyter labの設定にあたり

jupyterlabは多くの設定を上のメニューバーより行うことができる。 「Setting」→「Advanced Settings Editor」でアクセスできる。

terminalの設定

設定概要

まとめると以下の設定になる。

{
    "fontFamily": "Ubuntu Mono derivative Powerline",
        "theme": "dark"
}

フォントを設定する

fc-list

で利用可能なfontの一覧を取得可能。 私は以下のものを使用しているので、それに設定。

github.com

テーマを設定する

全体のテーマではなく、terminal独自に設定を行う。 Draculaが良いが、インストールがめんどくさいので、darkでお茶を濁す

vim拡張機能を追加

github.com

jupyter labextension install jupyterlab_vim

で追加する。Node.jsが必要。 正直、使い勝手はそんなに良くない。 現在の選択状況により同じショートカットキーでもjupyter labのものかvimのショートカットがに分かれるので、使うのに頭を使う必要がある。

Colaboratory plugin

Colaboratory – Google

pip install jupyter_http_over_ws

Colaboratoryをlocalマシンで動かすために必要。 この機能を使用するには起動時にも以下のオプションが必要。 セキュリティ上、必要な時だけこれをつけて起動するべきだと思う。

jupyter notebook --NotebookApp.allow_origin='https://colab.research.google.com' 

latex plugin

github.com

node.js が必要

pip install jupyterlab_latex
jupyter serverextension enable --sys-prefix jupyterlab_latex
jupyter labextension install @jupyterlab/latex

widget plugin

pip install ipywidgets

Amazon がアフィリエイト料金を下げたってよ

https://japanese.engadget.com/jp-2020-04-15-amazon.html

こういう時にこういうことができる企業なのである。自社の利益を圧迫してるのかもしれないが。まあ、Amazonの顧客は購入者であって、アフィリエイターではないからな。彼らはビジネスパートナーだ。それも、簡単に代替がききそうなやつだ。仕方ない側面もある。

こういう企業の株を持っておくと、怒り半分、心配半分といったところに感情が落ちつくので良い。

docopt main template

docopt用のメイン関数のテンプレートを作成した。以下のdocoptのライブテンプレートを登録しておくと、コマンドラインパーサーを書くのが全く苦にならなくなるので、行なっとこう。 tf_argを追加している。docoptは型チェックがなく、複雑なオプションだとどこのフラグの設定が間違っているのかがわかりにくいので、エラーメッセージにフラグの情報を追加する物だ。 コピペとpycharmのlive template用のものを作成した。

for copy and paste

#! /usr/bin/env python3
# encoding: utf-8

"""{f}\n
Usage:
    {f}
    {f} <str> <int> <path> <list>...
    {f} -h | --help

Options:
    <str>                    str arg
    <int>                    int arg
    <path>                   path arg
    -h --help                Show this screen and exit.
"""
from docopt import docopt
from pathlib import Path
from typing import TypeVar


class DocArgs:
    A = TypeVar("A", str, Path, int, float, bool, list)

    def __init__(self, argd: dict):
        self.argd = argd

    def __call__(self, value_type: A, flag: str) -> A:
        """
        transformer from docopt option string to another class
        :param value_type: ex) int, float32, etc
        :param flag:
        :return:
        """
        try:
            print(f" v is {flag}")
            print(value_type, type(value_type(self.argd[flag])))
            arg = value_type(self.argd[flag])
            if isinstance(arg, list):
                inner_type = value_type.__args__[0]
                arg = [inner_type(z) for z in arg]
            return arg
        except ValueError as e:
            print("check your args")
            raise e
    
    def __str__(self) -> str:
        return self.argd.__str__()
    

if __name__ == "__main__":
    args = DocArgs(docopt(__doc__.format(f=__file__, version='0.0.1')))
    print(args)
    arg_str = args(str, "<str>")
    arg_int = args(int, "<int>")
    arg_path = args(Path, "<path>")
    arg_list = args(list[int], "<list>")
    print(arg_str)
    print(arg_int)
    print(arg_path)
    print(arg_list)
    

pycharm live template

#! /usr/bin/env python3
# encoding: utf-8

"""{f}\n
$DISCRIPTION$
Usage:
    {f}
    {f} -h | --help

Options:
    -h --help                Show this screen and exit.
"""
from docopt import docopt
from pathlib import Path
from typing import TypeVar


class DocArgs:
    A = TypeVar("A", str, Path, int, float, bool, list)

    def __init__(self, argd: dict):
        self.argd = argd

    def __call__(self, value_type: A, flag: str) -> A:
        """
        transformer from docopt option string to another class
        :param value_type: ex) int, float32, etc
        :param flag:
        :return:
        """
        try:
            print(f" v is {flag}")
            print(value_type, type(value_type(self.argd[flag])))
            arg = value_type(self.argd[flag])
            if isinstance(arg, list):
                inner_type = value_type.__args__[0]
                arg = [inner_type(z) for z in arg]
            return arg
        except ValueError as e:
            print("check your args")
            raise e
    
    def __str__(self) -> str:
        return self.argd.__str__()


if __name__ == "__main__":
    args = DocArgs(docopt(__doc__.format(f=__file__, version='0.0.1')))

spxsさん、もうコロナウイルス暴落前に戻る

3倍レバレッジ商品は、原理的に実際の値動きとの乖離が起こってしまう。 しかし、spxlやteclなどが人気である。 今回はそのお仲間のspxsが、sp500が元の水準に戻っていないにもかかわらず、既に元値に戻ってしまっていた。 落ちるのは早いけど戻るのは遅いということだ。 teclもspxlも、sp500が暴落前に戻ったとしても、同じように戻っていることはないだろう。 f:id:kakibara:20200409235036p:plain f:id:kakibara:20200409235041p:plain f:id:kakibara:20200409235139p:plain