ssh の接続先の Emacs で接続元の OS を確認したい

サーバの Emacs で、 Linux から接続したのか Mac から接続したのかを確認したいが、これはけっこう難しい。結局できなかったのだが、試したやり方をいくつか上げておく。

ssh 接続時の環境変数で判定する

ssh は接続後のサーバに環境変数を設定することができるので、それを利用する。
http://d.hatena.ne.jp/taiyo/20080613/p1
クライアントの ~/.ssh/environment か ~/.ssh/rc に

CONNECTED_FROM=$OSTYPE

だとかを書いておき、サーバの .emacs

(defun connected-from-linux-gnu ()
  ;; processing here if connected from Linux
)

(setq ssh-connected-from (getenv "CONNECTED_FROM"))
(if ssh-connected-from
    (if (equal ssh-connected-from "linux-gnu") 
        (connected-from-linux-gnu)
      ))

この方法ができるなら問題は解決だが、これは /etc/ssh/sshd_config で

PermitUserEnvironment yes

となっていないといけない。(デフォルトはno)
サーバの root 権がない自分の環境では /etc/ssh/sshd_config の編集ができず、これは諦めた。

IP で判定する

他には IP から判定する方法も試した。これは接続先の .emacs

(defun connection-from-desktop ()
  ;; processing here if connected from Desktop PC
)

(setq ssh-connection-ip (getenv "SSH_CLIENT"))
(if ssh-connection-ip
  (progn
    (string-match "[^ ]+" ssh-connection-ip)
    (if (equal (match-string 0 ssh-connection-ip) "000.000.00.000")     
        (connection-from-desktop)
      )))

とするだけでできる。しかしこの場合、固定 IP でないといけないうえ、違う PC だろうと同じ LAN から接続した場合は意味がない。ノート PC とデスクトップ PC が判別できれば満足だったが、やはりノート PC を家からつなぐことも多いので諦めた。
結局できなかったわけだが、いい方法があれば教えてほしい。

Emacs で auto-complete の色を変更する

Emacsauto-complete で色を変更するのには下記のオプションが使用できる。

(set-face-background 'ac-completion-face "#333333")                  
(set-face-foreground 'ac-candidate-face "#666666")
(set-face-background 'ac-selection-face "#666666")

しかし、これだけでは一部しか変更できない。変更できない部分の色が8色だけの環境で作業するときおかしくなってしまって困っていたが、popup のオプションで変更できた。

続きを読む

Stanford CoreNLP の Python ラッパーを作った

corenlp-python に置いてある。

Stanford CoreNLP は Stanford で開発されている英語の自然言語処理に必要なツールを色々入れた Java のライブラリで、単語分割、文分割、品詞付与、原型の復元、固有表現抽出、構文解析、共参照解析など前処理の大抵のことができる。

CoreNLP の Python ラッパーはすでにあるが、このラッパーはかなりバグがある。例えばインプットに改行が入っていると改行の前までしか解析できなかったり、JSON-RPC が古いバージョンのプロトコルを使っていたり、処理を最長でも5秒でタイムアウトしてしまったり、30~50文以上あるテキストはそれ以降の文を全て破棄してしまうなどなどだ。

最後のバグは、おそらく最初に別のツール(nltkなど)で文分割をしてから使うことを想定しているのだろうが、CoreNLP はせっかく文分割のツールが入っているのでそれを使いたい。で、フォークしてそういったバグを直したり、パッケージ化して使いやすくして corenlp-python を作ったのでぜひ使ってほしい。フォークごときで作ったというのは少し語弊があるが、かなり書き直しているので中身はだいぶ違うものになっている。

使い方は

sudo pip install corenlp-python

そして Python から

from corenlp import StanfordCoreNLP, batch_parse
corenlp_dir = "stanford-corenlp-full-2013-04-04/"

# 逐次処理の場合
corenlp = StanfordCoreNLP(corenlp_dir)
corenlp.parse("Parse it")

# バッチ処理の場合
batch_parse("text_directory/", corenlp_path=corenlp_dir)

という感じで使える。

色々なコマンドラインでの XML の整形方法

XML が一行になっているととにかく見にくい。 ところが今日 @mamoruk さんにお会いしたとき、一行の XML をコマンドでぱぱっとツリー状にして編集していた。調べてみるとけっこう方法があるようだ。せっかくブログを書くいい機会なので書いておこうと思う。

つまり、

<?xml version="1.0" encoding="UTF-8"?><mongo><a>T</a></mongo>

という xml

<?xml version="1.0" encoding="UTF-8"?>
<mongo>
  <a>T</a>
</mongo>

という風にしたい。

tidy を使う
tidy --indent-cdata true -xml -utf8 -i hoge.xml 

こちらのブログに詳しく書かれている。
tidy は本来 HTML を整形するツールのようだ。

xmllint を使う
xmllint --format hoge.xml

こちらは短い。
xmllint はコマンドラインの xml 編集のツールらしい。

Emacs での整形

Emacssgml-mode(xml-mode ではできないのかな?)で、全選択してから M-x sgml-pretty-print をするとインデントされる。一部だけ選択してそこだけインデントをするということもできるので便利そう。

というわけでざっと見たが、楽そうな xmllint と、 Emacssgml-pretty-print を使おうと思う。


追記:

xmlstarlet での xml の整形

xml startlet というものを教えてもらった。 XPath の検索など高度なことができるようだが、とりあえず記事の主題の整形のコマンドは

xmlstartlet fo hoge.xml

これでできる。書いた中では1番便利に見える。
Web の資料だと xmlstartlet が xml となっているものばかりだが、 apt-get で入れたからかコマンド名が違うようだ。

上位下位関係抽出ツールを使ってみる

上位下位関係抽出ツールWikipedia のデータから上位下位関係をとってきてデータにしてくれるものなのだが使うのに少し苦労した。

ダウンロードして解凍し、フォルダに移動。
まず使うとshのエラーが出たので script/ex_hyponymy.sh の一行目を

#!/bin/sh

から

#!/bin/bash

に変更。

その後実行すると数時間動き続けるのだが、デフォルトの分類器の pecco の、すでにないオプションを指定して結果が出力されずに終わる。

上位下位関係抽出ツール自体2010年が最終更新なので pecco のずっと前のバージョンをインストールするか、もしくは動作は遅いが TinySVM のオプションがあるので、こちらを使うのもいい。ただ、公式サイトに書いてあるとおり TinySVM と data3 (大規模な学習データを使って生成)を使おうとすると pecco の5倍以上かかってしまうので、精度が高くや規模の大きいdata3を使う場合は古い pecco を使うのがいいと思う。

pecco は http://www.tkl.iis.u-tokyo.ac.jp/~ynaga/pecco/#hist で公開されているうち、もっとも古い2011年1月のファイルをダウンロードし解凍。このときのバージョンのインストール方法は上位下位関係抽出ツールのサイトに書いてあるので、つまずいたらそちらを参考。

追記: 上位下位関係抽出ツールのサイトに書いてあるインストール方法は違うが、サイトにあるリンクの http://www.tkl.iis.u-tokyo.ac.jp/~ynaga/pecco/pecco.tar.bz2 で、当時の最新版がダウンロードできるようなのでそちらを参照。

cd ex-hyponymy-1.0
wget http://www.tkl.iis.u-tokyo.ac.jp/~ynaga/pecco/pecco-20110110.tar.bz2
tar jxvf pecco.tar.bz2
cd pecco
make -f makefile.pecco
cd ..

そしてようやく上位下位関係認識ツールが使える。

PATH=./pecco/:$PATH script/ex_hyponymy.sh -t ./data3 Wikipediaファイル

Python で dict をS式に変換する

SVM-light-TK はインプットがS式なので、それに合わせてS式に変換したい。再帰を使おうとしたらけっこう面倒で、結果こうなった。

def dict_to_s_expression(d):
    class parse:
        def parser(self, d_list):
            for d in d_list:
                for key,value in d.iteritems():
                    self.parsed += "(%s " % key
                    if type(value) == self.list_type:
                        self.parser(value)
                        self.parsed += ")"
                    elif type(value) == self.dict_type:
                        self.parser([value])
                        self.parsed += ")"
                    else:
                        self.parsed += "%s)" % value

        def __init__(self, d_list):
            self.list_type = type(list())
            self.dict_Type = type(dict())
            self.parsed = ""
            self.parser(d_list)
    P = parse([d])
    return P.parsed

使うときは

d = {"NP": [{"D": "a"}, {"N": "dog"}]}
print dict_to_s_expression(d)

SVM-light-TK を使ってみる

SVM-light-TK は Alessandro Moschitti が開発した Tree Kernel が使える SVM ライブラリ。h現在のバージョンは1.2.1。

http://disi.unitn.it/moschitti/TK1.2-software/download.html から軽いアンケートみたいなものをするとダウンロードできる。今回はサンプルデータが公式サイトにあるのでそれを使ってみる。

% cd svm-light-TK-1.2.1
% ./svm_learn -t 5 arg0.train trained-arg0
Scanning examples...done
Reading examples into memory...100..OK. (112 examples read)

Number of examples: 112, linear space size: 21478

estimating ...
Setting default regularization parameter C=1.0000
Optimizing........................................done. (41 iterations)
Optimization finished (3 misclassified, maxdiff=0.00100).
Runtime in cpu-seconds: 0.01
Number of SV: 91 (including 26 at upper bound)
L1 loss: loss=11.55698
Norm of weight vector: |w|=6.88679
Norm of longest example vector: |x|=1.00000
Estimated VCdim of classifier: VCdim<=48.42783
Computing XiAlpha-estimates...done
Runtime for XiAlpha-estimates in cpu-seconds: 0.00
XiAlpha-estimate of the error: error<=23.21% (rho=1.00,depth=0)
XiAlpha-estimate of the recall: recall=>75.00% (rho=1.00,depth=0)
XiAlpha-estimate of the precision: precision=>77.78% (rho=1.00,depth=0)
Number of kernel evaluations: 9711
Writing model file...done

% ./svm_classify tk1.2-arg/arg0.test model
Reading model...OK. (92 support vectors read)
Classifying test examples..100..done
Runtime (without IO) in cpu-seconds: 0.01
Accuracy on test set: 83.04% (93 correct, 19 incorrect, 112 total)
Precision/recall on test set: 84.91%/80.36%

svm_learn 時の -t でカーネルを指定している。5は部分木の組み合わせ(?) 他のオプションで細かく指定しているようだ。

5: combination of forest and vector sets according to W, V, S, C options

linear kernel とも比較してみると

% ./svm_learn -t 1 tk1.2-arg/arg0.test trained-arg0
...
% ./svm_classify tk1.2-arg/arg0.train trained-arg0
Reading model...OK. (104 support vectors read)
Classifying test examples..100..done
Runtime (without IO) in cpu-seconds: 0.00
Accuracy on test set: 76.99% (87 correct, 26 incorrect, 113 total)
Precision/recall on test set: 70.83%/91.07%

15%も精度に違いができた。