hakeの日記

Windows環境でプログラミングの勉強をしています。

Rubyで形態素解析

最初はMeCab+nattoで試したのですが、MeCabのサイトで公開されているライブラリは64bit Rubyでは動作しませんでした。他はないのかと検索したところ、こちらRubyによる形態要素エンジンokura(注:ocraではない)が公開されていましたので早速インストール。
公開サイトでは、ruby1.9専用と書かれていますが、こちらの動作環境(Windows 10 64bit / ruby 2.2.3p173 (2015-08-18 revision 51636) [x64-mingw32])でも問題は無い様です。


公開サイトおよび入手先

導入

  • okuraのインストール
gem install okura
okura compile mecab-naist-jdic-0.6.3b-20111013/ okura-dic

公開サイトのサンプルプログラムの実行

okuraは文字コードutf-8を使用するので、入出力でcp932(Windows-31J)とのエンコードが必要

#coding: cp932
require 'okura/serializer'

dict_dir='./okura-dic' # コンパイルした辞書フォルダの置き場所
tagger=Okura::Serializer::FormatInfo.create_tagger dict_dir

str='すもももももももものうち'.encode('utf-8')

# 文字列から単語候補を計算
nodes=tagger.parse(str)

# 単語候補の中で、一番最もらしい組み合わせを選択
nodes.mincost_path.each{|node|
  word=node.word
  s = ('     ' + word.surface.encode('cp932'))[-5..-1] # 空白は全角スペース
  s << ' '
  s << word.left.text.encode('cp932')
  puts s

# word.surface        # : 単語の表記
# puts word.left.text # : 品詞
# 品詞はword.leftとword.rightがありますが、一般的に使われる辞書(IPA辞書やNAIST辞書)では
# 両方同じデータが入ってます
}

実行結果

C:\okura>ruby test.rb
1589586
S/EOS BOS/EOS
  すもも 名詞,一般,*,*,*,*,*
    も 助詞,係助詞,*,*,*,*,も
   もも 名詞,一般,*,*,*,*,*
    も 助詞,係助詞,*,*,*,*,も
   もも 名詞,一般,*,*,*,*,*
    の 助詞,連体化,*,*,*,*,の
   うち 名詞,非自立,副詞可能,*,*,*,*
S/EOS BOS/EOS

RubyGemsが使用できない

RubyGemsを使用しようとして、ここ数日使用できなくなっていることに気が付きました。
発生を確認したのはRubyInstallerのruby2.1.4とRumix2のruby2.0.0です。

C:\>gem search rails

*** REMOTE GEMS ***
(結果が表示されない)


C:\>gem update --system
ERROR:  While executing gem ... (Gem::RemoteFetcher::FetchError)
    SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/specs.4.8.gz)

軽く検索したら12月の頭頃にサーバが落ちたみたいな記録がみつかったので、それが継続しているのかと思いましたが、どうもそうではないらしい。
エラーメッセージで検索したらSSLのアップデートに関する変更があったらしいです。とりあえずここの記述に従って、new trust certificateファイルを入手して指定のディレクトリにコピーしたら使用できるようになりました。

MinGW環境としてRumix2のDevKitを使用する。

Ruby/Tkの勉強環境としてインストールしたRumix2は、(選択すると)同時にDevKitがインストールされます。これはrubygemsruby関連のツールをインストールするときにコンパイルが必要な場合に使用される環境です。DevKit中を覗くとMinGWで使用するツール類がかなり揃っているようで、自分がCやC++の勉強に使用する分には充分のようです。
というわけでオリジナルのMinGW+MSYSの環境は削除してこちらを使用することにしました。以前MinGWの環境構築時に作成したstart.batを以下の様に書き換えました。C:\Rumix2は、Rumix2のインストール先になります。

start.bat

@echo off

rem use MinGW on rumix2's devkit

set PATH=C:\rumix2\ruby\devkit-mingw64-32\bin;C:\rumix2\ruby\devkit-mingw64-32\mingw\bin;%PATH%
set C_INCLUDE_PATH=C:\rumix2\ruby\devkit-mingw64-32\include;C:\rumix2\ruby\devkit-mingw64-32\mingw\include
set CPLUS_INCLUDE_PATH=C:\rumix2\ruby\devkit-mingw64-32\include;C:\rumix2\ruby\devkit-mingw64-32\mingw\include
set LIBRARY_PATH=C:\rumix2\ruby\devkit-mingw64-32\lib;C:\rumix2\ruby\devkit-mingw64-32\mingw\lib
set MINGW_DIR=C:\rumix2\ruby\devkit-mingw64-32\mingw

bash -rcfile bash_profile

Ruby/Tk サブウィンドウの作成

サブウィンドウ用のメソッドopen_sub_windowを作成して、このメソッド内でサブウィンドウのウィジェットを配置して作成します。
ルートウィンドウ側との情報のやり取りについて、最初はメソッドの引数と返り値で行おうとしましたが、メソッド自体は直ぐに終了してしまうため不可でした。この為グローバル変数$swによって行う様にします。

サブウィンドウのベースはTkToplevelを使用します。またサブウィンドウを開いている間にルートウィンドウへの操作を不可にするために、TkToplevel#grab_setを実行します。サブウィンドウ閉じるときは、TkToplevel#destroyを実行。

続きを読む

Ruby/Tk TkVariableの使用

ウィジェットで変化する値を使用する場合にはTkVariabeを使用する。TkVariableの値が変化すると、その変数を参照しているウィジェット上の表示が即時変化する。
TkVariable#new_hashとするとHashとして使用できる。この場合にはウィジェット内で使用する場合には、TkVariable#ref(key)とする。

#coding: Windows-31J

require "tk"

root = TkRoot.new do
  title 'TkVariable Test'
  geometry '300x150+100+100' # 親ウィンドウのサイズと位置
end


d0 = TkLabel.new(root, text:'下段の入力文字が上段に即時反映される')
d0.pack

v1 = TkVariable.new('Label1')
d1 = TkLabel.new(root) do
  textvariable v1
  pack(anchor: :w)  # 表示を左寄せにする(w: west)
end
e1 = TkEntry.new(root) do
  textvariable v1
  pack(fill: :x)
end

TkLabel.new.pack

# TkVariableをHashとして使用
v2 = TkVariable.new_hash(str: 'Label2')

# HashへのアクセスはTkVariable#ref(key)を使用する
d2 = TkLabel.new(root) do
  textvariable v2.ref(:str)
  pack(anchor: :w)
end
e2 = TkEntry.new(root) do
  textvariable v2.ref(:str)
  pack(fill: :x)
end

Tk.mainloop

Ruby/Tk ウィジェットへのパラメータ指定方法

サンプルをみると書き方がいろいろあって混乱するのでメモ

#coding: windows-31J
require 'tk'

# Widjetのパラメータの指定方法


# newの引数として指定する方法
# 第1引数は親ウィジェット
# 第2引数以降はHashのキーと値
#   キーはStringでもSymbolでもOK
#   値も定数はSymbolでOK
TkButton.new(nil, text:'ボタン1', command:proc{puts 'Button 1 Pushed'}).pack(fill: :x)
#TkButton.new(nil, 'text'=>'ボタン1', 'command'=>proc{puts 'Button 1 Pushed'}).pack('fill'=>'x')



# blockとして指定する方法
TkButton.new(nil) do
  text( 'ボタン2' )                       # 丸カッコは省略可
  command( proc{puts 'Button 2 Pushed'} )
  pack(fill: :x)
end




# インスタンスのメソッドとして指定する方法
b3 = TkButton.new(nil)
# 値を代入
b3.text = 'ボタン3'
b3.command = proc{puts 'Button 3 Pushed'}
# 値を引数としても渡せる
#b3.text( 'ボタン3' )                    # 丸カッコは省略可
#b3.command( proc{puts 'Button 3 Pushed'} )
b3.pack(fill: :x)


Tk.mainloop

Ruby/Tkプログラムのexe化

Rumix2環境でのocraを使用したexe化は以下の要領で。
VisualuRubyに比べてファイルサイズが大きくなって、起動が遅くなるのがちょっと残念です。

$ ocra xx.rb C:/rumix2/ruby/2.0.0/i386-mingw32/lib/tcltk  --windows --no-autoload --add-all-core