思考ノイズ

無い知恵を絞りだす。無理はしない。

備忘録 - Python/WIn10 64bit でMeCabを導入

最近 Chainer本をやっているのは、ぼんやりと言語系の機械学習をいっちょかみしたいなと考えているからなのですが、そろそろ必要な環境についてもPCへの導入を始めました。その過程のお話し。

日本語の文章を学習させるにあたって必要になるのが「わかち書き」ってやつで、ようは機械に日本語を学習させるにあたり、意味で区切った文節の間に英語のようにスペースなどの記号を入れる必要が出てきます。これって結構難儀だよなって思っていたのですが、あっさりとMeCabというフリーの形態解析エンジンがでてきました。。

MeCab: Yet Another Part-of-Speech and Morphological Analyzer

MeCab京都大学情報学研究科−日本電信電話株式会社コミュニケーション科学基礎研究所 共同研究ユニットプロジェクトを通じて開発されたオープンソース 形態素解析エンジンです。 言語, 辞書,コーパスに依存しない汎用的な設計を 基本方針としています。 パラメータの推定に Conditional Random Fields (CRF) を用 いており, ChaSenが採用している 隠れマルコフモデルに比べ性能が向上しています。また、平均的に ChaSen, Juman, KAKASIより高速に動作します。 ちなみに和布蕪(めかぶ)は, 作者の好物です。

これぞ情報の海の産物。めかぶだけに。この時代に生まれてよかったと感じざるを得ませんでした。 これを自分の開発の環境に合わせなくてはいけません。Windows10 64bitのPC上で、Python 2.7を使って動かしています。Pythonも活発な言語なのでこのあたり導入したライブラリの情報がいくらでもあるだろうとたかをくくっていたのですが、実際に導入する方法はちょっとトリッキーでした。ただそのトリッキーな方法もわかりやすく記載したエントリーがでてきます。

hassiweb-programming.blogspot.jp

Mecab 32bitをインストールする。ただ動かしたいのは64bit版なので、そのソースコードをダウンロードして少し情報を書き換えたうえでコンパイルPythonモジュールのビルドをしてようやく導入が完了します。

おおむね参照させていただいたページのプロセスで進んだのですが、どうしてもPython モジュールのコンパイルの場所でエラーが発生してしまいます。 曰く、"Unable to find vcvarsall.bat" とのこと。実はこれも先のページのトラブルシュートで記載があったのですが、解決に至りませんでした。*1

なんのこっちゃよくわからず、ぐるぐると検索して回った結果、以下のページで解決しました。

www.regentechlog.com

例えば、Python本体がMSC v.1500、つまりVC++9.0(2008)でコンパイルされていてインストールされているVC++が11.0(2012)の場合、 set VS90COMNTOOLS=%VS110COMNTOOLS% と環境変数をセットしてやるとVC++11.0を使ってコンパイルしてくれます。

私の環境だと、Visual Stdio 2015を導入していて、これだとVCのバージョンは14になるようです。一方で、Microsoftから提供されているPython2.7用のコンパイラはVC9となり、Visula Stdioでいうと2008と相当古いものになってしまうのです。VC9のコンパイラVisual Studio 2008のライブラリを探しに行くのですが、システム上にないためのこのエラーがでてきたということでしょうか。そこで上の環境変数のセットで存在するバージョンのライブラリのパスを設定する必要があったようです。私の環境の場合Visual Studio2015はVC14となるので、以下の設定になりました。

set VS90COMNTOOLS=%VS140COMNTOOLS%

これで、MeCabのPython2.7 (on 64bit) での導入は成功したようです。次のステップは日本語データの収集かな。

以下のサイトでも勉強させていただきました。

qiita.com

*1:よくよく確認すると、正しい対処法が書かれていたようです。解決できなかったのは理解不足が原因ですね。。。

「自然界の黄金比」をプロットしてみる

話題になった黄金率の話にうすーく乗っかってみたくなりました。

モチベーション

www.watto.nagoya

正直、連分数に関してちゃんと理解できていないのですが、とにかく、

(略)これは、黄金比有理数による近似は常に精度が最も悪くなることを意味するのである。 これまでと同様の手順で、100枚の葉をつけた状態が、下図である。有理数による近似の精度が悪い=腕が見えづらい=葉の重なりが少ないってことで、葉の重なりが最も少なくなる配置が得られた。

というところに素直に感動してしまいました。自然界、まじやべぇ。*1

というわけで、これは matplotlib を使って動画化してみてみるしかないと奮い立ちました。先に言ってしまうと、自分の理解が薄かったせいで最初に考えていたよりも作業は大変でした。

課題のおさらい

幹から1枚目の葉を出したら、1枚目の葉からθの角度で2枚目の葉を出す。3枚目の葉は2枚目の葉からやはりθの角度で出す。以下n枚目の葉まで、同様に繰り返す。 幹からn枚目の葉の中心までの長さは、√nとする。

こうして幹の周りから同じ角度でずらしながらで直径1の葉っぱを配置していきます。中心からのきょりも順番の数の平方根で遠ざかっていって、全体に効率よく太陽の光をあびることのできる配置を考えるんですね。そうすると黄金比を使ったやつが一番となるらしいです。今回は元エントリーの例に倣って 無理数の代表 θ = π×π も作って比較してみます。

プロット結果

とっとと実行結果からお見せします。葉っぱの枚数は300枚としました。 まずは π×π

f:id:bython-chogo:20170926021040g:plain

そして 黄金比を使った場合。

f:id:bython-chogo:20170926021151g:plain

きちんと前の円の群れで欠けたるところにすっぽりはまっていくように見えますね。不思議。

コード

jupyterで書いていますが、plt.show()使えば、jupyter以外でもできると思います。未確認。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib import animation

from IPython.display import HTML

T = 360 * 1.0 / (1 + (1+math.sqrt(5))/2)
#T = 360 * 1.0 / (math.pi * math.pi) 

fig = plt.figure()
ax = plt.gca()
ax.set_xlim(-20, 20)
ax.set_ylim(-20, 20)

def ccl_plt(n, d):
    r = n * d * math.pi / 180 
    x = math.sqrt(n) * math.cos(r)
    y = math.sqrt(n) * math.sin(r)
    return x, y

def init():
    return []

def animate(j):
    plt.cla()
    patches = []
    for i in range(j):
        if i == 0:
            continue
        patches.append(ax.add_patch(plt.Circle(ccl_plt(i, T), 1.0, alpha=0.1, color='g')))

    return patches

    
anim = animation.FuncAnimation(fig, animate,
                               init_func=init,
                               frames=300,
                               interval=80,
                               blit=True)


#plt.show()
HTML(anim.to_html5_video())

もう一つ、簡単な静止画バージョン。

import math
import matplotlib.pyplot as plt
%matplotlib inline

def ccl_plt(n, d):
    r = n * d * math.pi / 180 
    x = math.sqrt(n) * math.cos(r)
    y = math.sqrt(n) * math.sin(r)
    return x, y

fig = plt.figure()
ax = fig.add_subplot(111)
plt.xlim(-20, 20)
plt.ylim(-20, 20)
for i in range(300):

    if i == 0:
        continue
    t = 360 * 1.0 / (1 + (1+math.sqrt(5))/2)
    #t = 360 * 1.0 / (math.pi * math.pi)
    x, y = ccl_plt(i, t)
    ax.add_patch(plt.Circle((x, y), 1.0, alpha=0.1, color='g'))
plt.show()

蛇足

今回の課題は簡単かなとたかをくくっていたのですが、いざやってみると黄金比の角度をどう設定すればいいのかわからず苦労しました。検索して見つけたのですが、黄金角っちゅうのがあるのですね。入力が度数である場合は以下の計算で黄金角を導き出されるようです。

t = 360 * 1.0 / (1 + (1+math.sqrt(5))/2)

参考:http://gakuen.gifu-net.ed.jp/~contents/museum/golden/page62.html

分母の部分が黄金比の式になってますね。

いやはや、時間がかかりすぎてしまった。眠い。

*1:というかこうしたネタを華麗に持ち出してくるwattoさん、しゅごい。

Chainer - ミニバッチベースの各モデルの学習結果を比較してみる

昨日に続き、Chainerのお勉強。第4章のIris識別方法を比較してみたものの備忘録です。

Chainerによる実践深層学習

Chainerによる実践深層学習

第4章ではChainerの例としてアヤメの花びらのデータから種類を判別するスクリプトがかかれているのですが、いくつかのモデルを紹介して、コードが以下のようにアップデートされていきます。

  • 通常のミニバッチ (4.4)
  • 誤差の累積 (4.5)
  • Softmax Cross Entropy (4.7)
  • ロジスティック回帰 (4.8)

これらのミニバッチをベースにした学習精度を比較します。バッチするファイルの選択はランダムに行っているため、実行ごとのデータの取り方によって結果は毎回変わってしまいます。正しい比較のため、同じデータをとって3000回学習した場合にこの4つのモデルで正解率と損失係数を並べて比べ、判別効率がどの程度変わるのかグラフで視覚化してみたいと思います。

では結果をどん。上にも書きましたが、毎回選ばれるランダム値によって結果が違ってくるので、3パターンを並べてみます。

f:id:bython-chogo:20170920004559p:plain f:id:bython-chogo:20170920004712p:plain f:id:bython-chogo:20170920004904p:plain

正解率の良い順としては、ロジステック回帰>誤差の累積=Softmax Cross Entropy>(通常の)ミニバッチでしょうか。今回はロジスティック回帰が相性が良いみたいです。大体は1000~1500ぐらいで上に張り付くようですが、通常のミニバッチは学習が少し遅いようです。また、損失率は別のモデルに対してそのまま比較することには意味がないこともわかります。なるほど。

前回: bython-chogo.hatenablog.com

Irisデータサンプルプログラムのグラフプロット

現在、以下の本でお勉強中。個人的な備忘録です。

Chainerによる実践深層学習

Chainerによる実践深層学習

オライリーDeep Learning本も一通りやったうえで、言語の学習をやりたくてこちらに手を出してみました。現在4章を実行中。

ここではChainerの利用例として、ディープラーニングでおなじみのアヤメの花びら分類問題をやる例のやつが出てきます。iris0.py のサンプルを走らせたのですが、学習の繰り返しごとにどの程度の正解率・損失率になるのか気になったのでプロットしてみました。それが以下のグラフ。

f:id:bython-chogo:20170918232542p:plain

10000回の学習を繰り返していくなかで正解率の変化(上)と、損失率の変化(下)を表しています。損失率は4000回目以降大きな変化はないように見えますが、正解率は少しずつ上がっているようです。

ダンケルク

危機が迫るなかでの撤退ミッション。

wwws.warnerbros.co.jp

世界大戦での実話を実写化したもの。 この「ダンケルクの戦い」とか「ダイナモ作戦」はヨーロッパなどでは有名な出来事みたいなのですが、おそらく一般の日本人はあまりよく知らないのではないでしょうか。と、偉そうに語る私もまったく知りませんでした。せっかくなので事前の予習は何もせず、見に行ってやりました。こうした史実に忠実な映画では絶対にストーリーを変えられなく、観客はネタバレをみこして作っているんですよね。*1今回もそのネタバレ上等映画なのですが、私を含む日本人にとっては前提知識がなく見に行っている人が多かったのではないかと思います。その辺で評価に差が出たるのかは気になるところですね。

飽きさせない編成

イギリス空軍、撤退兵、民間船など、いくつかの視点を切り替えながら物語をすすめていく編成で、各シーンごとにそれぞれの立場での緊張感を保ちながら進めていくので全体的に飽きさせることの少ない進行になっていたいました。映画を見ながらたまにあるような「ここ、間延びするなー」ということが全くありませんでした。一方でシーンの切り替えで意図的に時系列が前後することが多く、それによる混乱がおきたのも事実です。夜のシーンと昼のシーンを交互に切り替えたりするので、時差ボケが発生したり、前半におきたイベントのシーンの続きを後半で始めたりして、「お、おう、いまそうつながったんね」って少し追いつくのに労力がいりました。まぁたいした労力じゃないと思います。

まとめ

ダンケルクの戦いは英仏(特にイギリス)にとっての苦い成功歴史で、映画の題材的には扱いやすいのかと思います。多大の犠牲の上でなんとかやり遂げるのことができたミッション、という意味では、なんとなくですが進撃の巨人に通づるようなカタルシスがあるんかなと。 ただの美談ではなく、撤退を余技されない状況で敵に責められて自分の命が尽きるかもしれない恐怖感、撤退兵用の艦船にのれて一安心かと思いきやまた海に投げ出される。絶望的な環境の中で味方が敵になるなど、戦争の恐怖も伝えられてたと思います。ただ正直もうちょっとここを強めにしてもよいかとは思いました。個人的には少し生ぬるい感じとも感じたのですが、映倫関連も含めた大衆向けのバランスをとったものなのでしょう。 戦争もの、エンターテイメント映画として上質な仕上がりになっていたかと思います。

*1:例えば関ケ原は日本人にとっては石田が負けることは知っているうえで見に行きます。まさか西軍が勝つことを予想して見に行く人はほとんどいないと思います。

画像に集中線をいれるコード

久しぶりにPythonのコーディングネタ。軽めですが。

モチベーション

employment.en-japan.com

このネタ。でも正直テストとかよくしらないです。ただ集中線を描くプログラムというワードにピンときて書いてみたくなりました。最近はOpenCVを使ったコーディングにめぞめぞしていたので丁度よい題材でした。

まずはコードを

みてくださいー。

import cv2
import math
import random


def setEffect(pic, center = (0.5, 0.5)):
    he, wi = pic.shape[:2]
    leng = math.sqrt(he ** 2 + wi ** 2)

    for rd in range(360):
        k = rd * math.pi/180
        r = random.uniform(0.20,0.50)

        x = wi * center[0] + r * leng  * math.cos(k)
        y = he * center[1] + r * leng  * math.sin(k)
        dx = wi * center[0] + leng * math.cos(k)
        dy = he * center[1] + leng * math.sin(k)
            
        cv2.line(pic, (int(x), int(y)), (int(dx), int(dy)), (0, 0, 0), 2)
    cv2.imshow('test', pic)
    cv2.waitKey(0)
    cv2.destryAllWindows()
            
img = cv2.imread("test.jpg")
setEffect(img)

例として拾い物のPUBGというネットワークゲームのスクショをいれてみますね。ちょうどよいのこれしかなかった。 f:id:bython-chogo:20170912222746j:plain これを入れると、以下の画像が出てきます。 f:id:bython-chogo:20170912223039j:plain

うひょーい、できましたー!

解説

画像データを引数にとっております。あと、集中線の中心となる場所を指定できます。Defaultでど真ん中にしております。 あと、画像の縦横の長さを取得して起きます。そのデータから集中線の長さのもととなる値を計算しています。十分な長さを確保するため、画像の対角線の長さにしてあります。

def setEffect(pic, center = (0.5, 0.5)):
    he, wi = pic.shape[:2]

    leng = math.sqrt(he ** 2 + wi ** 2)

中心から360ぐるっと回る繰り返しで1度ずつ線を引くようにします。kは度数から三角関数の引数となる値の計算をします。2 pi が360度なので、1度は pi/180ですね。 あと、集中線の長さをランダムに指定します。r は0.2 ~ 0.5 までのFloatの乱数を出します。

    for rd in range(360):
        k = rd * math.pi/180
        r = random.uniform(0.20,0.50)

線引きの描写です。 各度数ごとに(x, y) から (dx, dy)の線をひくのですが、中心は先ほど指定したように画像のど真ん中です。先ほど求めた対角線の長さ leng を放射状に直線を引きますが、線の引き始めはランダム値の割合 (0.2-0.5)からになります。終わりはleng の終わりまで。対角線の長さにしたのはどの中心地からも必ず画像の外側に行くからです。。 角度はcos(k), sin(k)で指定します。

        x = wi * center[0] + r * leng  * math.cos(k)
        y = he * center[1] + r * leng  * math.sin(k)
        dx = wi * center[0] + leng * math.cos(k)
        dy = he * center[1] + leng * math.sin(k)
            
        cv2.line(pic, (int(x), int(y)), (int(dx), int(dy)), (0, 0, 0), 2)

imshowで表示。そのままだと画像が一瞬で消えてしまいますので、waitKey(0)で待たせておきます。 destryAllWindows()できちんとお掃除をしておきます。

    cv2.imshow('test', pic)
    cv2.waitKey(0)
    cv2.destryAllWindows()

感想

行数自体は長くないのですが、数学でならった円(楕円)や三角関数の公式を思い出すのにちょっとだけ時間がかかりました。 プログラムをよく書くようになって数学的センスって大事。今更、勉強をさぼった過去を悔いてもしょうがないのでこうやって書きながら思い出しながらいけたらよいかと思ってます。

打ち上げ花火、下から見るか?横から見るか?

今年の夏を終わらすために見に行きました。とりあえず見ないと夏が終わりそうになかった。

www.uchiagehanabi.jp

もう30も半ばも超えるあたりで、いまだに中二病感を引きずり続けながらもそろそろ卒業せんといけないです。夏の終わりとともにこの映画でおれの中二病も殺してくれたら万々歳かなと思ってました。

原作の思い出

テレビで原作をみた記憶がうっすらと残っています。と、いっても内容はほとんど覚えていなかったのですが、このタイトルと、一緒に見ていた父親が「花火は球状に広がるんだから丸いに決まっている」とどや顔していて、幼い自分は「さすがとーちゃん!」と尊敬していた記憶がやけに残っています。いまからすれば、そんなわかりきったことを問いているわけではなく、このタイトルでそのような疑問をもつ、「思春期感」を引きだす絶妙な名前だったんでしょうか。 *1 *2

ストーリーは

前に書いたように原作はほとんど覚えていませんが、おそらく原作を踏襲しているものなんでしょう。正直、なんでだろう、という疑問が消えないことが多くて、ストーリ的には戸惑うことが多かったです。そもそもあのアイテムはなんだったのか。なんで主人公が選ばれているのか。大ヒット作「君の名は。」と対比させていただくと、君の名は。はぎりぎりだとしてもそうした現象の説明をきちんとしているのに対して、本作はその説明は全くない状態。後半初めまでもやっとした気持ちが消えることがありませんでした。

じゃあ悪かったのか

ということでもない。きれいな映像、音楽、そして主役2人の絶妙な演技もあいまって、戸惑い中がらもこの世界観に少しづつ引き込まれてしまいました。ロジックで感じるのではなく感覚で感じていくものかもしれません。 おそらくは私の精神状態も関連していたのかもしれません。中二病を完治したくて見に行ったのにも関わらず、治すというより、「悪玉中二病」が浄化されて「良玉中二病」が残ったイメージです。そうです。「中二病でもいいんだ!」「おめでとー!」「おめでとう!」っていう気分になりました。これからもこの子を飼いならして生きていこうと思った所存です。 これで私の夏がようやく終わりそうです。来年も素敵な夏を迎えられればいいと思いました。

おいおい、これ映画の感想になってねーぞw

*1:また、この作品をとりあげた、「if もしも」という番組も覚えていたのですが、「打ち上げ花火ー」がこの番組の一作品という記憶はありませんでした。記憶が正しければ、「世にも奇妙な物語」のレギュラー放送の後番組として、タモリが司会をしていたような気がします。

*2:ちなみにこの原作、だいぶフェチ満載なものだったようで、よくそんな作品、あの父親と一緒に見れてたと感慨深いものがあります。