beep音削除

microsoft terminalからubuntuへsshログインしたとき、BEEP音がうるさいのを削除する設定

csh

~/.cshrcに以下を追加

set nobeep

bash

~/.inputrcに以下を追加

set bell-style none

vim

~/.vimrcに以下を追加

set vb t_vb=

VSCodeのjupyter notebookが起動しない

最近VSCodeをアップデートしたところ、PythonのNotebookが起動しなくなりました。

Connection To IPython kernel: Connecting to kernel.

これでずーと待ったのちに、タイムアウト。

こちらに解決方法が!!

どうやら、Pythonのモジュールと干渉しているようですので、バージョンダウン。

python -m pip install 'traitlets==4.3.3' --force-reinstall

これで無事起動できました。

MacのRStanのインストールエラー

メモ

環境

  • MacOS 10.15.4
  • R 3.6.3

エラー

install.package("rstan")

こんなえらー

unistd.h:727:31: error: unknown type name 'uuid_t'; did you mean 'uid_t'?

対策

RからこれでOK

install.packages("Rcpp", repos="https://RcppCore.github.io/drat")

VSCodeでLatex

MacのVSCodeでLatexを使うためのセッティングの備忘録

環境

  • Mac OS 10.15
  • texlive 2019

settings.json

いろいろなところを参照し、最終的にこれ


{
    "latex-workshop.latex.tools": [
        {
            "name": "latexmk",
            "command": "latexmk",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-outdir=%OUTDIR%",
                "%DOC%"
            ],
            "env": {}
        }
    ],

    "latex-workshop.latex.outDir": "%DIR%",
    "latex-workshop.view.pdf.viewer": "tab",
    "latex-workshop.view.pdf.zoom": "page-width",
}


$HOME/.latexmkrc

#!/usr/bin/env perl
$latex            = 'platex -synctex=1 -halt-on-error';
$latex_silent     = 'platex -synctex=1 -halt-on-error -interaction=batchmode';
$bibtex           = 'pbibtex -kanji=utf8';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';
$max_repeat       = 5;
$pdf_mode         = 3; # 0: none, 1: pdflatex, 2: ps2pdf, 3: dvipdfmx
$aux_dir          = ".";
$out_dir          = ".";

実験

人工知能学会全国大会のテンプレートをダウンロードし、jsaiac.styとjsai.bstを同じディレクトリに入れておく

\documentclass[twocolumn]{ujarticle}
\usepackage{jsaiac}

\begin{document}
ああああ

\end{document}

このファイルを作成し保存するとコンパイルが始まり、PDFが作成される

KLDivergenceとJSDivergence

Pythonのコード作成したのでメモ

KLダイバージェンス

$$D_{KL}(P||Q) = \sum_x p(x) \, \log \frac{P(x)}{Q(x)}$$

JSダイバージェンス

$$D_{JS}(P||Q)=\frac{1}{2}\bigg\{ D_{KL}(P \, || \, R)+D_{KL}(Q \, || \, R) \bigg\}$$
$$R = \frac{P + Q}{2}$$

プログラム

ここを参考に

データ

まずはデータの準備


import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

np.random.seed(12345)
a=np.random.normal(40,10, size=200)
b=np.random.normal(70,15, size=100)
c=np.random.normal(30,2, size=70)
d=np.random.normal(150,10, size=150)

plt.figure()
plt.hist(a,alpha=0.3,bins=20,histtype="stepfilled",color="r",label="a")
plt.hist(b,alpha=0.3,bins=20,histtype="stepfilled",color="b",label="b")
plt.hist(c,alpha=0.3,bins=20,histtype="stepfilled",color="black",label="c")
plt.hist(d,alpha=0.3,bins=20,histtype="stepfilled",color="y",label="d")
plt.legend()
plt.show()

ヒストグラム

KLダイバージェンス


def KLDivergence(a, b, bins=20, epsilon=.00001):
    min_value=min(min(a),min(b))
    max_value=max(max(a),max(b))
    # サンプルをヒストグラムに, 共に同じ数のビンで区切る
    a_hist, _ = np.histogram(a, range=(min_value,max_value),bins=bins) 
    b_hist, _ = np.histogram(b, range=(min_value,max_value),bins=bins)
    
    # 合計を1にするために全合計で割る
    a_hist = (a_hist+epsilon)/np.sum(a_hist)
    b_hist = (b_hist+epsilon)/np.sum(b_hist)
    
    # 本来なら a の分布に0が含まれているなら0, bの分布に0が含まれているなら inf にする
    return np.sum([ai * np.log(ai / bi) for ai, bi in zip(a_hist, b_hist)])

JSダイバージェンス


def JSDivergence(a, b, bins=20, epsilon=.00001):
    min_value=min(min(a),min(b))
    max_value=max(max(a),max(b))
    # サンプルをヒストグラムに, 共に同じ数のビンで区切る
    a_hist, _ = np.histogram(a, range=(min_value,max_value),bins=bins) 
    b_hist, _ = np.histogram(b, range=(min_value,max_value),bins=bins)

    # 合計を1にするために全合計で割る
    a_hist = (a_hist+epsilon)/np.sum(a_hist)
    b_hist = (b_hist+epsilon)/np.sum(b_hist)
    
    r_hist = (a_hist + b_hist)/2.0
    
    ar= np.sum([ai * np.log(ai / ri) for ai, ri in zip(a_hist, r_hist)])
    br= np.sum([bi * np.log(bi / ri) for bi, ri in zip(b_hist, r_hist)])
    return (ar+br)/2.0

実験

まずはaとbの分布を調べます。


kl1=KLDivergence(a,b)
js1=JSDivergence(a,b)

kl2=KLDivergence(b,a)
js2=JSDivergence(b,a)
print("kl1=",kl1,",kl2=",kl2)
print("js1=",js1,",js2=",js2)

kl1= 4.804620164702722 ,kl2= 8.66117091460137
js1= 0.44568757334874426 ,js2= 0.44568757334874426

KLダイバージェンスはaとbを入れ替えると値が変わりますが、JSダイバージェンスでは同じです。

つぎに、分布間でのKLダイバージェンスとJSダイバージェンスの値を調べます


# 一致 
kl1=KLDivergence(a,a)
kl2=KLDivergence(a,a)
js=JSDivergence(a,a)
print("一致:kl1=",kl1,",kl2=",kl2,",js=",js)

# 含まれる
kl1=KLDivergence(a,c)
kl2=KLDivergence(c,a)
js=JSDivergence(a,c)
print("含有:kl1=",kl1,",kl2=",kl2,",js=",js)

# 重なる
kl1=KLDivergence(a,b)
kl2=KLDivergence(b,a)
js=JSDivergence(a,b)
print("重複:kl1=",kl1,",kl2=",kl2,",js=",js)

# 小別離
kl1=KLDivergence(b,d)
kl2=KLDivergence(d,b)
js=JSDivergence(b,d)
print("小離:kl1=",kl1,",kl2=",kl2,",js=",js)

# 大別離
kl1=KLDivergence(a,d)
kl2=KLDivergence(d,a)
js=JSDivergence(a,d)
print("大離:kl1=",kl1,",kl2=",kl2,",js=",js)

一致:kl1= 0.0 ,kl2= 0.0 ,js= 0.0
含有:kl1= 8.982185089568121 ,kl2= 1.5818474236167488 ,js= 0.3961382475750016
重複:kl1= 4.804620164702722 ,kl2= 8.66117091460137 ,js= 0.44568757334874426
小離:kl1= 14.585645733703917 ,kl2= 14.484008742932685 ,js= 0.6931379306807828
大離:kl1= 14.9325435215302 ,kl2= 15.170878470071264 ,js= 0.6931412821202988

結果を見ると、距離の遠い順にKLダイバージェンス、JSダイバージェンスの値が大きくなっています。KLダイバージェンスの場合には、どちらを基準にするかによって変わってくるので注意が必要みたいですね。

BERTモデルをPytorchのモデルへ変換

Tensorflowで作成したBERTモデルを、Pytorchへ変換します。

こちらに方法が書いています。

モデル

モデルを自分で計算して作ってもいいのですが、公開しているものがあるので、そちらを使います。

KNP

こちらはKNPを使って分かち書きしたWikipedia日本語版を元に作成しています。
あまりKNPを使ったことはないのですが、実際に使うときにはMeCabで分かち書きをしても大丈夫でしょう。

SentencePiece

こちらのものは同じく日本語Wikipediaを用いて、SentencePieceによる分かち書きをしたものです。

Transformers

Pytorchで用いるのライブラリです。以下のコマンドでインストールしておきます。

pip install transformers

変換

SentencePieceで作成したモデルにはPytorch用のモデルがついていませんので、変換してみます。
こちらには以下のファイルが含まれています。

model.ckpt-1400000.meta
bert_config.json                       
model.ckpt-1400000.data-00000-of-00001 
wiki-ja.model
model.ckpt-1400000.index               
wiki-ja.vocab

このコマンドでpytorch_model.binというファイルへ変換します。

transformers bert  model.ckpt-1400000 bert_config.json pytorch_model.bin

リモートサーバのtensorflowの結果を表示する

大学のサーバなどで計算した後の結果を確認する時に、
わざわざ計算結果のデータをローカルに持ってくるのは面倒だったりします。
リモートの結果を表示できないかと言うことで、SSHポートフォワードを使って
ローカルでも表示できるようにします。

tensorflowダウンロード

$ git clone https://github.com/tensorflow/tensorflow
$ cd tensorflow

使用しているtensorflowは1.15なのでバージョンを合わせます

$ git branch -a
$ git checkout -b r1.15 origin/r1.15

これで1.15のブランチになります。以下のコマンドで確認。

$ git branch
  master
* r1.15

mnist

mnistを計算してみます

$ cd /tensorflow/examples/tutorials/mnist
$ mkdir logs
$ python fully_connected_feed.py --log_dir=logs

logs以下にファイルが作成されていることを確認します

$ ls logs
checkpoint                               model.ckpt-1999.meta
events.out.tfevents.1573779801.vpcc-101  model.ckpt-999.data-00000-of-00001
model.ckpt-1999.data-00000-of-00001      model.ckpt-999.index
model.ckpt-1999.index                    model.ckpt-999.meta

ポートフォワード

サーバが外部公開されていないなど、ローカルPCから直接ブラウザでアクセスできないときのために、SSH
ポートフォワードを使用します。
こちらを参考に、
macから繋ぐためにはターミナルから以下のコマンドを打ち込みます。

$ ssh -L 8081:remotehost:10010 remotehost -lusername

これは、リモートサーバの10010ポートをローカルの8081ポートで見れるようにするためのものだと思えばいいです。

まずは、動くかどうか確認です。
リモートでpython簡易サーバを立ち上げます

$ python -m http.server 10010

ブラウザでhttp://localhost:8081にアクセスし確認します。
ディレクトリリストが見えることがわかります。
Ctrl+Cでシャットダウンします

tensorboardによる可視化

先ほど計算した、mnistの計算結果を表示してみます。

$ tensorboard --logdir=logs --port 10010
TensorBoard 1.15.0 at http://remotehost:10010/ (Press CTRL+C to quit)

ブラウザでhttp://localhost:8081にアクセスします

表示されました。

numpyのエラー

tensorflowのサンプルを動かそうとしたときのエラー

4$ python fully_connected_feed.py 
RuntimeError: module compiled against API version 0xc but this version of numpy is 0xb
ImportError: numpy.core.multiarray failed to import
ImportError: numpy.core.umath failed to import
ImportError: numpy.core.umath failed to import
2019-11-15 09:55:15.959592: F tensorflow/python/lib/core/bfloat16.cc:675] Check failed: PyBfloat16_Type.tp_base != nullptr 
中止 (コアダンプ)

どうやら、numpyが壊れているらしい?

$ pip install -U numpy 

これで解決

Rstudioの環境変数

RStudioを好んで使っています。

Mac版RStudioはHomeBrewでインストールすることができます

brew cask install rstudio

この時、アプリケーションフォルダ内にRStudioのアイコンが表示されます。
このアイコンをクリックして起動すると、Bashシェルの環境変数を読み込んでくれません。

自分の場合、データフォルダをDATA環境変数に入れることにより、大学で使っている
サーバのデータフォルダとの物理ディレクトリの違いを吸収するようにしています。
例えば


data.file<-paste(Sys.getenv("DATA"),"/sample.txt",sep="")

こんな感じで記述しておけば、
サーバでは /work/user/data/sample.txtのディレクトリにあるファイル
ローカルPCでは /home/user/data/sample.txtのディレクトリにあるファイルでも、
環境変数DATAにサーバでは/work/user/data/、ローカルPCでは/home/user/data/
を設定しておけば、プログラムを変更する必要がありません。

しかし、Rstudioを入れたそのままではこの環境変数が使えません。

これを解決するには、~/.Renvironに環境変数を記述しておけばOKです。

~/.Renviron

DATA=${HOME}/data

chainerでCRFを用いて固有表現抽出

このあたりを参考に書き直してみました。
CRFなどの解説はリンク先を参照のこと

仕様

単語列から名詞の塊を抜き出す。
英語で複合名詞など複数の名詞で構成される名詞の塊にフラグをつける。
下記の例では、Oが名詞以外、Bが名詞の開始位置、Iが複合名詞の2個目以降を示している。

 the wall street journal reported today that apple corporation made money 
O    B   I      I      I      O        O    O     B     I          O    O      O

これを、Linearの1層で学習し、CRFで出力する

コード



import numpy as np
import argparse
import os
import chainer
import chainer.functions as F
import chainer.links as L
from chainer import training, optimizers, initializers,reporter
from chainer.training import extensions
import random
from itertools import chain


# my model
class IconDetector(chainer.Chain):

    def __init__(self, n_vocab, window, n_label, n_unit):
        super().__init__()
        with self.init_scope():
            self.embed=L.EmbedID(n_vocab, n_unit)
            self.lin=L.Linear(n_unit , n_label)
            self.crf=L.CRF1d(n_label=n_label)
        self.window=window

    def forward(self, xs):
        l = xs.shape[1]
        ys = []
        # 1 wordづつ
        for i in range(l):
            x = self.embed(xs[:,i])
            h = F.tanh(x)
            y = self.lin(h)
            ys.append(y)
        return ys #[window, batchsize, n_label]

    def __call__(self, xs, ts):
        """error function"""
        ys = self.forward(xs)
        ts = [ts[:, i] for i in range(ts.data.shape[1])] # [window,batchsize]
        loss = self.crf(ys, ts)
        reporter.report({'loss': loss}, self)
        return loss

    def predict(self, xs):
        ts = self.forward(xs)
        _, ys = self.crf.argmax(ts)
        return ys

class WindowIterator(chainer.dataset.Iterator):

    def __init__(self, text, label, window, batch_size, shuffle= True,repeat=True):
        self.text = np.asarray(text, dtype=np.int32)
        self.label = np.asarray(label, dtype=np.int32)
        self.window = window
        self.batch_size = batch_size
        self._repeat = repeat
        self._shuffle=shuffle

        if self._shuffle:
            self.order = np.random.permutation(
                len(text) - window ).astype(np.int32)

        else:
            self.order=np.array(list(range(len(text) - window )))
        self.current_position = 0
        self.epoch = 0
        self.is_new_epoch = False

    def __next__(self):
        if not self._repeat and self.epoch > 0:
            raise StopIteration

        i = self.current_position
        i_end = i + self.batch_size
        position = self.order[i: i_end]
        offset = np.concatenate([np.arange(0, self.window )])
        pos = position[:, None] + offset[None, :]
        context = self.text.take(pos)
        doc = self.label.take(pos)

        if i_end >= len(self.order):
            np.random.shuffle(self.order)
            self.epoch += 1
            self.is_new_epoch = True
            self.current_position = 0
        else:
            self.is_new_epoch = False
            self.current_position = i_end

        return  context, doc

    @property
    def epoch_detail(self):
        return self.epoch + float(self.current_position) / len(self.order)

@chainer.dataset.converter()
def convert(batch, device):
    context, doc = batch
    xp = device.xp
    doc = xp.asarray(doc)
    context = xp.asarray(context)
    return context, doc


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument('--device', '-d', type=str, default='-1',
                        help='Device specifier. Either ChainerX device '
                        'specifier or an integer. If non-negative integer, '
                        'CuPy arrays with specified device id are used. If '
                        'negative integer, NumPy arrays are used')
    parser.add_argument('--window', '-w', default=5, type=int,
                        help='window size')
    parser.add_argument('--batchsize', '-b', type=int, default=2,
                        help='learning minibatch size')
    parser.add_argument('--epoch', '-e', default=100, type=int,
                        help='number of epochs to learn')
    parser.add_argument('--out', default=os.environ["WORK"]+"/summarization/sm_icgw/result",
                        help='Directory to output the result')

    args = parser.parse_args()

    random.seed(12345)
    np.random.seed(12345)

    device = chainer.get_device(args.device)

    training_data = [(
        " the wall street journal reported today that apple corporation made money ".split(),
        "O B I I I O O O B I O O O".split()
    ), (
        " georgia tech is a university in georgia ".split(),
        "O B I O O O O B O".split()
    )]

    validation_data = [(' georgia tech reported today '.split(),"O B I O O O".split())]

    word2id={"":0,"":1,"":2,"":3}
    label2id={"B":0,"I":1,"O":2}

    def get_dataset(data,is_train=True):
        texts=[]
        labels=[]
        for word,attrib in data:
            for w,a in zip(word,attrib):
                if w not in word2id:
                    if is_train:
                        word2id[w]=len(word2id)
                    else:
                        w=""
                texts.append(word2id[w])
                labels.append(label2id[a])
        return texts,labels

    train_text,train_label=get_dataset(training_data)
    valid_text,valid_label=get_dataset(validation_data,False)

    n_vocab=len(word2id)
    n_label=len(label2id)
    n_unit=n_vocab//2
    model=IconDetector(n_vocab=n_vocab, window=args.window,n_label=n_label,n_unit=n_unit)

    model.to_device(device)
    optimizer = optimizers.Adam()
    optimizer.setup(model)

    train_iter = WindowIterator(train_text, train_label, args.window, args.batchsize)
    valid_iter = WindowIterator(valid_text, valid_label, args.window,args.batchsize, repeat=False, shuffle=False)

    updater = training.StandardUpdater(train_iter, optimizer, converter=convert, device=device)
    trainer = training.Trainer(updater, (args.epoch, 'epoch'), out=args.out)
    trainer.extend(extensions.LogReport(),trigger=(10, 'epoch'))
    trainer.extend(extensions.PrintReport(['epoch', 'main/loss','validation/main/loss']))
    #trainer.extend(extensions.ProgressBar())

    trainer.extend(extensions.Evaluator(valid_iter, model,converter=convert, device=device),trigger=(10, 'epoch'))
    trainer.run()

    # testing
    testing_data = [(' the street journal is a university '.split(),"O B I I O O O O".split())]
    test_text,test_label=get_dataset(testing_data,False)
    with chainer.using_config('train', False), \
            chainer.using_config('enable_backprop', False):
        ys=model.predict(np.array([test_text],dtype=np.int32))

        ys=list(chain.from_iterable(ys))
        print(ys)
        print(test_label)

if __name__ == '__main__':
    main()

実行結果

epoch       main/loss   validation/main/loss
10          6.24186     7.77101               
20          5.43089     6.29938               
30          3.16409     5.09233               
40          2.68146     4.02053               
50          1.47248     3.07853               
60          1.63073     2.28975               
70          1.13568     1.67798               
80          0.842947    1.22796               
90          0.364242    0.912943              
100         0.658557    0.692736              
[2, 0, 1, 1, 2, 2, 2, 2]
[2, 0, 1, 1, 2, 2, 2, 2]

ちゃんと学習できているようです