積読を消化

年末年始はJediやDoc2Vecと格闘しつつ、積ん読の消化に励みました。

Pythonエンジニアファーストブック

Pythonエンジニア ファーストブック

Pythonエンジニア ファーストブック

前半は優しい内容でしたが、後半は実践的な内容でとても勉強になる本でした。 後半だけさらっと振り返ります。

4章 スクレイピング

 Scrapyはすごい強力なツールですが、細々としたスクレイピングではちょっと重厚すぎる印象でした。 サーバーを立ち上げて、スケジュール組んで定期的にジョブをはしらせるような状況なら非常にありがたいツールです。 あとScrapy shellには驚きました。もっとはやく使えばよかった。

5章 PyData入門

 describeメソッドには感動しました。 いま開発しているニュース原稿のカテゴリー分類機は、入力データが単純なCSVなのでPyDataを使う機会がなさそうなので残念です。 センサーなどで収集した大量なデータを扱うときには強力なツールになるという印象です。

6章 Webアプリケーション開発

 DjangoでWebアプリを作っていく章でした。Djangoの使い方の流れを追いましたが、正直覚えきれてないです。それぞれのパーツの存在理由、設定理由を把握しつつ読みましたが、自主的に何か作って流れを追わないと覚えきれないですね。こればかりは仕方がありません。実戦あるのみです。

TeamGeek

Team Geek ―Googleのギークたちはいかにしてチームを作るのか

Team Geek ―Googleのギークたちはいかにしてチームを作るのか

 出版直後に購入したのですが、長年放置した1冊です。当時は会社でのチーム作業で八方塞がり状態だったので、この本を読んで平静を保つ自身がなく途中で投げ出したのを思い出しました。凄くいい本なのですが、この本を読んでだと感じたらなら、きっとその職場を去るときなのでしょう。

 内容は誰もが当たり前だと思いながらも当たり前にできないでいることが整理して書いてあります。一言でまとめるなら「仕事する相手、商売する相手、みな心をもった人間である」でしょうか。

 一番、響いたのは「ミッションステートメント」でした。前職のチームでは、ミッションステートメントが曖昧だったり、曲解したり、都合のいいように解釈したり、破ったりすることが横行していました。方向性の統一が出来てないと、検討する内容が増え、集中力が散漫になり、作業効率がどんどん落ちていきます。「ミッションステートメント」を作りみんなで守ることは、シンプルな意思決定を保つことができます。人間が作るものなので多少の間違いがあるかもしれないが、ー度決まったものは蒸し返さず守るというのはとても大事なことです。チームの方向性を定義して、プロダクトのスコープを制限する。、そしてこれを守り気持ちよく仕事をしたいものです。

つぎの本

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

 お次はリーダブルコードを読もうと思います。これも出版直後に買ったのですが、前職では毒になっていたため、パラパラ読んで放ったらかしにしていた。

VimをStrict modeにする

qiita.com

この記事に触発されました。

 Ctrl-cによるESC、十字キー、バックスペース、そしてノーマルモードでの h, l 移動を強制的に禁止します。 禁止しないとついつい使ってしまうので仕方がありません。

おすすめはしません。

vnoremap  <C-c>    <nop>
vnoremap  <Up>     <nop>
vnoremap  <Down>   <nop>
vnoremap  <Left>   <nop>
vnoremap  <Right>  <nop>
inoremap  <C-c>    <nop>
inoremap  <Up>     <nop>
inoremap  <Down>   <nop>
inoremap  <Left>   <nop>
inoremap  <Right>  <nop>
inoremap  <BS>     <nop>
noremap   <C-c>    <nop>
noremap   <Up>     <nop>
noremap   <Down>   <nop>
noremap   <Left>   <nop>
noremap   <Right>  <nop>
noremap   h <nop>
noremap   l <nop>

gensimでDoc2Vecと格闘する

 今回は少し前に大ブームになっていたらしいDoc2Vec( Word2Vec)です。Doc2Vecでも内部ではWord2Vecが動いているので、どちらにしてもWord2Vecです。gensimを使ってPythonから呼び出そうと思いましたが、困ったことに使い方がさっぱりわかりません。ネット上に転がっているサンプルは、うまく動かなかったり、どこからかコピペしたものを焼き増ししたり、説明なく謎のパラメーター設定をしてたりしていたため、自分の環境ではうまく動かせず、年末・年始を非常に有意義に消化してしまいました。

まだ詳しいところ(各種パラメーター等)理解していませんが、結果が出たので雑にまとめておきます。

 

各パラメータとサンプルコード

 今回も以前Qiitaに投稿した際に使用した、Yahooニュースの原稿を用いて学習をすすめます。

qiita.com

パラメーターについて

  • 学習率の初期値alphaは、今回かなり小さめに設定しました。ニュース原稿のような長文で複雑なデータは、非常に発散しやすいためです。
    • min_alphaもかなり小さくしています。
  • windowは変更しても大きな変化はありませんでした。
  • size(ベクトルの次元数)も100以上ではあまり変化がなく、また高次元すぎて類似度が無駄に下がるだけなので100にしています。
  • min_countはとりあえず1にしておきます。
  • その他のパラメータはデフォルトにします。
    • 下手に弄らないほうがよかったです。
  • 詳しくは公式を見るのが一番でしょう。gensim: models.doc2vec – Deep learning with paragraph2vec

以下gensimを用いたコード付近の抜粋です。抜粋なのでコピペしても動かないでしょう。

サンプルコード

def sentences():
    # wakati_gen = news_tokenizer.read_wakati()
    wakati_gen = list(news_tokenizer.read_wakati())
    random.shuffle(wakati_gen)
    for category, tokens in wakati_gen:
        # categoryはニュース記事のカテゴリー(サッカー,野球など)
        # tokensはニュース原稿を形態素解析して単語を並べたリスト
        yield doc2vec.LabeledSentence(tokens, tags=[category])

def main():
    word = 'microsoft'

    data = sentences()
 # ニュース原稿は複雑なデータなので学習率は小さめにしておく
    model = doc2vec.Doc2Vec(data, size=100,
                            alpha=0.0025,
                            min_alpha=0.000001,
                            window=15, min_count=1)
    # microsoft に最も似た単語を並べる(未学習)
    print(model.wv.most_similar(word))
    training = 10
    for epoch in range(training):
        data = sentences()
        model.train(data, total_examples=model.corpus_count, epochs=model.iter)
     # microsoft に最も似た単語を並べる(学習中)
        print(model.wv.most_similar(word))
    model.save('./data/vector/d2v/category.model')

 ネット上に転がっているソースは、学習率のmodel.alphamodel.min_alphaを訓練ループ毎に減らしているものがありました。ですが、そんなことをしなくてもWord2Vec内でデフォルトで線形に減衰していきます。(非線形に減らしたいなら別ですが)  

microsoftに類似するワードの経過

 未学習の状態ではmicrosoftとは関係ない「三十三観音」とか「クラフトビール」とかが出てきます。

 ですが最終的には「マイクロソフト」や「azure」などが出てきます。「linux」が出てくるのは、WSLが話題になった次期だからでしょうか。

おもしろい

[('pot', 0.40417373180389404), ('クリーク・アンド・リバー', 0.3955865800380707), ('アンドリュー・クライスバーグ', 0.38725024461746216), ( 'クラフトビール', 0.3792040944099426), ('三十三観音', 0.3782668709754944), ('cafe', 0.37654101848602295), ('情報基盤センター', 0.3752627968788147), ('イオンモール岡山', 0.3726036548614502), ('カッチー', 0.3725459575653076), ('輸送用機器', 0.3713015913963318)]

[('android', 0.9968464374542236), ('プラットフォーム', 0.9967312812805176), ('azure', 0.9967294931411743), ('windows', 0.9965859055519104), ('aws', 0.9965192675590515), ('ios', 0.9956364035606384), ('アップデート', 0.9955232739448547), ('提供', 0.995313286781311), ('ソリューション', 0.9951471090316772), ('セキュリティ', 0.9951217174530029)]

[('connect', 0.9941026568412781), ('linux', 0.9937072992324829), ('azure', 0.9918037056922913), ('更新プログラム', 0.9912915229797363), ('マイクロソフト', 0.9907968640327454), ('プラットフォーム', 0.9906506538391113), ('android', 0.990537166595459), ('windows', 0.9905165433883667), ('platform', 0.9904587864875793), ('商用', 0.9898083209991455)]

[('source', 0.9873005151748657), ('マイクロソフト', 0.9856327176094055), ('open', 0.9854219555854797), ('linux', 0.984656810760498), ('sdk', 0.9821251034736633), ('azure', 0.9807733297348022), ('platform', 0.9805046319961548), ('software', 0.9794276356697083), ('oss', 0.9788164496421814), ('aws', 0.9785921573638916)]
reading wakati files
[('linux', 0.9825512766838074), ('source', 0.9787257313728333), ('open', 0.9778124690055847), ('adobe', 0.9764299392700195), ('platform',0.9740426540374756), ('プラットフォーム', 0.9735702872276306), ('oss', 0.9733889102935791), ('aws', 0.9732674956321716), ('マイクロソフト', 0.9702072739601135), ('プログラミング言語', 0.9694012403488159)]


....


[('source', 0.953851580619812), ('open', 0.9504380822181702), ('linux', 0.9310433864593506), ('azure', 0.9303960204124451), ('aws', 0.9150442481040955), ('vmware', 0.9144693613052368), ('プラットフォーム', 0.9121274948120117), ('platform', 0.9118857383728027), ('ソフトウェア', 0.9039658308029175), ('開発者', 0.9016284942626953)]

ソースコード

 全コードはここにあります。ニュース原稿はありませんので、自分で集めましょう。

github.com

 もしくはロンウィットのサイトからライブドアニュースを取ってきて形態素解析するのもよいでしょう。ダウンロード - 株式会社ロンウイット

UbuntuでPythonのコードをGtags(Global)する

 Qiitaに投稿しようとおもったら、言いたいことが全部この記事に書いてあったので、はてなに残骸を記録しておく。

qiita.com

下準備

globalの入手

 aptだと古いものがインストールされてしまうので公式にから最新者をDLしてきましょう。 GNU global 公式

 自分がインストールした時は、v6.6.1でした。公式は古臭いサイトですが、わりと更新されます。

wget http://tamacom.com/global/global-6.6.1.tar.gz
tar xvf global-6.6.1.tar.gz

globalのビルドに必要なものをインストール

GNU Global公式に書いてあるものをインストールしましょう。 texinfoは書いてないですがmakeするときに怒られるので入れましょう。

sudo apt install automake autoconf gperf bison flex texinfo

Pygmentsのインストール

gtagsはデフォルトだと、C, C++, Yacc, Java, PHP4, assemblyにしか対応していませんが、Pygmentsを使うことで様々な言語のタグ付けが可能です。

pip install Pygments

globalのビルド&インストール

簡単です。もし足りないものがあるとエラーがでるので、都度入れていきましょう。

cd global-6.6.1

sh reconf.sh 
./configure
make
sudo make install

globalrcとgtags.conf

最低でもホームディレクトリに.globalrcがないとPygmentsが使えないので、デフォルトの設定ファイルをコピーしましょう。

cp /usr/local/share/gtags/gtags.conf ~/.globalrc

特定のパスはタグ付けしたくない などプロジェクトごとに細かい設定したい場合は、gtags.confというファイル名でプロジェクトのルートディレクトリに置きましょう。

cp /usr/local/share/gtags/gtags.conf ~/<PROJECT_DIRECTORY>/gtags.conf

タグ付け

Pythonのコードをタグ付けするときは、パーサーにPygmentsを選びましょう。

gtags --gtagslabel=pygments

環境変数で指定することもできます

export GTAGSLABEL=pygments
gtags

.globalrcやgtags.confでも設定できます。 default:\がnativeと記載されているので、これをpygmentsに設定しておけば、オプションの指定や環境変数の設定が不要になります。

default:\
        :tc=pygments:
        #:tc=native:

はじめてPull Requestしてみた

ひどい英語なので取り入れられるかはまだわかりません。 しかも1行です。

まだまだ変更される予定なので、この修正をいれてもまた壊れちゃうとのこと。 jedi本体の開発ブランチがマージされたときにsys.pathをとってくるAPIを公開するので それを待つことになりました。

私がした修正は一時的な変更らしく、またしばらくしたら元に戻るとのことで、workaround的な修正を提案され、無事にマージされました。

つまり英語力が足りない。

github.com

jediがエラー

 venvを色々といじっていて、neovimのCheckHealthで状況確認をしていたのですが jediだけ何をやってもErrorが消えなかったので困りはてていました。

https://i.imgur.com/kXtxnLq.png

(積読している易しめの本を爆速で消化している最中だったので、ストレスマックスです。)

 sys_pathのエラーだったので自分の環境を色々と疑いましたが梨のつぶてでした。エラーログをググってもヒントらしいものは一切見つかりませんでした。本を読み進めたい気持ちを抑え、重い腰をあげてソースを読んだらjedi本体のsys_pathの変数が変わっててました。

github.com

(ウゴゴゴゴゴゴッ)

修正する

# こいつを
 for p in jedi_vim.jedi.Script('')._evaluator.sys_path:

# こうする
 for p in jedi_vim.jedi.Script('')._evaluator.project.sys_path:

 そういえばCheckHealthは何度もつかってましたが、jediが有効な状態で使ったこと一度もなかったことに気づきました。変数が変わったのが2017年10月なので、みんなもCheckHealthしてないようです。

Pull Requestする

 貴重な時間を消費したので、Pull Requestってやつを経験することにしました。 GitHubで他人のコードを修正したことなったので手順から学びます。手順はこちらを参考にしました。感謝です。 コミットのメッセージを考えるほうが修正時間より掛かったのは言うまでもありませんね :)

github初心者がPull Requestを送ってみた時の手順

というわけで、Pull Requestを体験しました。 返答を理解できるのか不安ですがゆっくり待つとします。

はじめてのパターン認識を読み終える

はじめてのパターン認識

はじめてのパターン認識

一言で言うといい本でした。

難易度とか

 数式多めですが、過去に説明したことをあまり端折らず繰り返してくれるので、 前のページに何度も戻りながら進むと行ったことがあまりなかった。 それでも中級者向けに作られているので、機械学習の大雑把なイメージと線形代数微積分、確率等の初歩を理解してないと序盤から躓くと思う。

難しかったところと自分の変化

 自分はSVMあたりから理解するのにかなり苦しんだ。 ラグランジュ未定乗数とは?カーネル法???といった感じで、出だしから苦戦した。 (この後、カーネル法の多次元への写像の理屈を理解して感動した。)

 この辺りからだと思うがWikipediaの説明が分かりやすいと感じはじめた。 Wikipediaの数学系記事は分かり難いと思っていたのだが、はじパタという応用方法を目の当たりにしながらだと、スッキリと頭に入ってくることに気づいた。苦手意識が克服され本当によい経験になった。また最終章のランダムフォレストには強く惹かれたので、これは実際に何か作って試してみようと思う。

意識した点と痛感したこと

 今回は直感的なイメージに拘って本を読んだ。

  • 式がどんなことを表しているのか?
  • どんな作用を果たしているのか?
  • 数式のどんな特徴をつかって応用しているのか?
  • 内積外積スカラー?ベクトル?行列?
  • etc

かなり想像力が鍛えられたけれど、線形代数と確率に対する想像力の低さを痛感したので、はじパタを繰り返し読んだり、数学の入門書を読んだりして基礎力を高めていきたい。

 ちなみに微積については、式の展開に苦戦したがパターン認識だと「微分≒最適化」、「積分≒確率等の連続値の総和」くらいに考えておけば基本的によかったので、それほど苦しめられなかった。

今後

 これからについてですが、しばらくプログラミングの学習に戻ろうとおもう。 数学的な知見が深まってきたので、加速したいところですが 転職の身としては、もう少しアウトプットが欲しいのです。 ただ、すでにはじパタの内容が記憶からこぼれ始めているので、定期的にこの分野に戻ってこなとダメですね。

SVMについて雑にまとめる

はじパタのSVMの直感的理解に苦しんだので雑に整理しておく。

SVMの導出

  • SVMを使うと2クラスの線形識別できるよ
  • 基本2クラスだけど多クラスの場合は、判別したいクラスとその他のクラスの2クラス問題にして一対他SVMするよ
  • サポートベクトルとは、識別境界を決めるために使用する学習データのことだよ。つまり境界付近のデータだよ。
    • サポートベクトルをつかって学習機械をつくるからSVMだよ
  • SVMの導出にはラグランジュ未定定数法をつかうよ
    • ラグランジュ未定乗数法は、制約条件下で評価関数を最適化する手法だよ。ただし制約条件下は等式のみだよ。
    • 制約条件下が不等式の場合は、KKT条件が必要だよ
  • この最適化問題の主問題の解は、双対問題の解がわかれば求まるよ

線形分離できない時

  • 基本的にSVMは線形分離できるときだけ使える手法だよ
  • ただし、ある程度の誤識別を許容することで線形分離できない問題も解くことができるよ
  • どれくらい誤識別するかをスラック変数で表すよ。スラック変数の総和が大きいほどマージンを超えてくるよ。
  • スラック変数の総和にどれくらペナルティを与えるかが、パラメータCだよ
  • Cが大きいほどマージンを超えてくることに厳しくなるよ。でも過学習しやすくなるので汎化誤差が大きくなるよ。
  • これをC-SVMとかいうよ
  • ちなみにスラック変数は学習の時だけつかうよ

非線形特徴写像

  • 線形分離できないd次元のデータをM>>dなM次元に写像すると、データの間隔に隙間ができるので(疎になるで)超平面で線形分離できる可能性がでてくるよ
  • ただし内積計算に時間がかかるので内積カーネルを用いたほうがいいよ
  • 内積カーネルには多項式カーネルと動径基底関数カーネルがあるよ
  • このあたりはよくわからんかったので、あとでやりなおすぞ

ν(ニュー)-SVM

  • 学習機械(識別する仕組み)が達成できる誤り率と機械の複雑さには関連性があるよ
  • 「誤り率と機械の複雑さ」のトレードオフをνというパラメータをつかって調整するよ
  • C-SVMの時と似ていて、複雑にすると誤り率が減るけど汎化誤差がますよ(過学習)、ぎゃくに単純すぎると誤り率が高くなるよ
  • パラメータνは、-ρ倍することでトレードオフを調整するよ。-ρなのは、ρが大きくなれば評価関数が小さくなるので最適化にすすむからだよ。
  • νは、「サポートベクトルの割合(全データのうち、どれくらいがサポートベクトルになるか?)の下限」と、「上限サポートベクトルの割合の上限」を表すよ
    • 上限サポートベクトル(Bounded SV)とは、α_i = 1/N となるデータだよ。

1クラスサポートベクトル

  • 2クラス分類で話をすすめてきたけれど、1クラスだけで学習して使う方法もあるよ
  • ある1クラスに属すか?属さないか?を分類するよ
  • 新規性判別、例外検出、外れ値検出に利用するよ

サポートベクトルの理解 むずかしい。