Theories of Pleiades

技術の話とかイベントに行った話とか思ったこととか

Rubyでマルコフ連鎖botを作る話[1/3:導入編]

しゅまいの自分バージョンがつくりたい

twitter.com


環境

OS: Arch Linux
言語: Ruby 2.5.1
使ったもの: めかぶ、納豆、Twitter、オレンジジュース(作業のお供として)


方針としては、
1. MeCabとnattoで形態素解析
2. マルコフ連鎖でゴリゴリ
3. TwitterAPIをッターン


RubyMeCabを使う

マルコフ連鎖で文章を生成するには、元となる文章を単語ごとに分割したデータが必要です。

今日の天気は晴れです

 ↓

今日 の 天気 は 晴れ です

といった具合に分割していきます。形態素解析エンジンのMeCabを使います。


MeCabインストール

エンジン本体がGitHubに公開されているので、それをcloneして使います。

github.com

中身はこんな感じ

tree -d -L 1
.
├── doxygen
├── mecab
├── mecab-ipadic
└── mecab-jumandic

MeCab本体をインストールします。ここで、解析結果をutf-8で得られるように./congifureにオプションをつけるのを忘れないようにする。

# mecab/mecab
./configure --with-charset=utf8
make install


MeCab辞書インストール

MeCab形態素解析をするには辞書をインストールしなければなりません。


  • MeCab標準のIPA辞書をutf-8でインストール
  • 追加データmecab-ipadic-neologdをインストール
  • よく使う非言語的単語をユーザー定義辞書に追加


まず、cloneしたリポジトリに同梱されていたmecab-ipadicをインストールします。
やることはmecab本体と同じです。

# mecab/mecab-ipadic
./configure --with-charset=utf8 #ここ大事
make install


次に、新語やネット用語、人名などの検出を強化するためmecab-ipadic-neologdをインストールします。

github.com

詳細な手順は上記リンクを見てもらえば書いてあるので割愛します。


最後に、よく使う単語の中でも一般的でない単語をユーザー定義に追加します。
例として、「はすみ」、「ぷよよん(プロコンの意)」、「ぷよよよよんよ(プログラミングの意)」などを追加していきます。

ユーザー辞書へ追加する単語はcsvファイルに記述します。 以下が今回ぼくが追加した単語ファイルです。

はすみ,,,1,名詞,固有名詞,人名,一般,*,*,はすみ,ハスミ,ハスミ
にゃーん,,,1,感動詞,*,*,*,*,*,にゃーん,ニャーン,ニャーン
にゃん,,,1,感動詞,*,*,*,*,*,にゃん,ニャン,ニャン
ぷよよよよんよ,,,1,名詞,一般,*,*,*,*,ぷよよよよんよ,プヨヨヨヨンヨ,プヨヨヨヨンヨ
ぷよよん,,,1,名詞,一般,*,*,*,*,ぷよよん,プヨヨン,プヨヨン


はじめと後ろから3番目に追加する単語、後ろ2つはその読みをカタカナで入力します。 2,3番目はMeCab側でIDが追加されるので空にしておきます。

4番目に単語検出の優先度を入力します。
自動的に優先度をつけてくれる機能もあるらしいですが、めんどくさかったので全て1にしておきました。数が大きくなるほど優先度が下がります。


その後には品詞の分類をIPA品詞体型というものに則って入力していきます。
ここが間違っていると辞書に追加するコマンドを叩いたときにエラーを吐かれてしまうので気をつけましょう。

IPA品詞体型については下のリンクを参考にさせていただきました。

miner.hatenablog.com


作ったcsvファイルの中身を辞書に登録していきます。 作成したユーザー辞書は/usr/local/lib/mecab/dic/userdicの中にuser.dicという名前で保存することとします。

mkdir /usr/local/lib/mecab/dic/userdic
/usr/local/libexec/mecab/mecab-dict-index \
  -d /usr/local/lib/mecab/dic/ipadic \ # システム辞書ディレクトリのパス
  -u /usr/local/lib/mecab/dic/userdic/user.dic \ # 保存先ファイルのパス
  -f utf-8 \ # csvファイルの文字コード
  -t utf-8 \ # 辞書の文字コード
  user.csv # 作成しておいたcsvファイル


作成したユーザー辞書を使うようMeCabに設定を書き込みます。 /usr/local/etc/mecabrcの中にある

; userdic = /usr/local/lib/mecab/dic/userdic/user.dic

セミコロンを消します(コメントアウトを外す)。


以上で自分のツイートを形態素解析する準備が整いました。
次は、実際にMeCabを使って形態素解析をしていきます。

mwc922-hsm.hatenablog.com

rails newするときやってることを自動化した

前書き

インターン全落ち芸人になりました


rails newしたらうまく動かない

最近はRailsをやっています。 Railsで新しいプロジェクトを作るとき、rails newをしますよね?ぼくはします。


ところがなんかrails newをしてrails generateとかすると

rails generate model hoges hoge:string
(中略)
/home/hsm-hx/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.3/lib/bundler/spec_set.rb:91:in `block in materialize': Could not find bindex-0.5.0 in any of the sources (Bundler::GemNotFound)

とか言われちゃうので困っていました。


解決策としては以下のリンクの通りごちゃごちゃやるといい感じになっていたのですが、覚えられないしめんどくさい。

www.qoosky.io

面倒なことはpythonにやらせたいので、やらせました。

面倒なことをpythonにやらせる

やりたいこと→rails-new hogeってすると上のリンクの操作をやってくれるやつをつくる

具体的には、
1. bundle initをする
2. Gemfileでrailsを落としてくる
3. bundle exec rails newする
4. 不要なファイルを消す
5. bundle installする
です。pythonからシェル操作さえできればこっちのもんなので楽勝。


まず、引数としてアプリケーションの名前を受け取るところからやります。

難しいことはしたくなかったのでとりあえずオプションとかは考えません。プロに殺されそうですが…

pythonCLIから引数を受け取るにはsysモジュールを使います。

import sys
argv = sys.argv #引数のリストを受け取る

このときのsys.argvには実行するファイル名も含まれるので、 第一引数→sys.argv[1]、第二引数→sys.argv[2]、…となる。



引数としてアプリケーション名以外は考えたくないので、

if not len(argv) == 2:
  print("error: invalid arguments")

としておきました。



さて、ここから本筋を作っていきます。 まずはpythonからbundle initをやります。

シェルコマンドを実行するには、subprocessモジュール内のcall関数を使います。
subprocess.call("bundle init", shell=True)で動きます。



ここまでは準備運動!
で、このあとGemfileの中身を書き換えるのにどうしようか迷ったのですが、Gemfileを予め用意しておいて上書きコピーするのが楽そうだったのでそうしました。


はじめはスクリプトの中に文字列でGemfileの中身を用意しておいてechoで…って思ってたんですが改行とかめんどくさいことになりそうだったので。まあすぐ消すわけだし改行なんかなくても良いと言えばそうですが。


適当に$RAILSNEWみたいな感じでPATHを作ってgemfileの位置を指定し、cpコマンドで書き換えます。

.zshrc

export RAILSNEW = /path/to/scriptDirectory

script.py

subprocess.call("cp $RAILSNEW/gemfile Gemfile", shell=True)

どうでもいいですがPATHの記法雰囲気でしか理解してなかったのでこれを気にちゃんと理解しました。




このあとのbundle installとか要らないファイルを消すなどはそのまま実装すればできます。簡単。

躓いたのがsubprocess.callからcdコマンドを実行しても作業ディレクトリは変わってくれないっていうところでした。

これについてはosモジュールのchdir関数を使えばすぐです。 絶対パスでも相対パスでも指定ができますが第一引数と同じ名前のディレクトリに行きたいだけなのでos.chdir(argv[1])で終わりです。



最後にbundle install --path vendor/bundleをして終わり!



これでスクリプトを実行すれば面倒なことは全部pythonがやってくれるようになりました。
最後に適当なところにスクリプトとgemfileのテンプレートを動かしてaliasでrails-newみたいな雑な名前をつけてあげました。




とりあえず完成!やったー!

後書き

まあ根本的な解決にはなってないのでそのうちどうすればいいのかとか探したいと思います。

書いてから思ったけどこれ備忘録にする必要すらなくない? 日記ってことで許してください。

部内LT会で登壇した話

前書き

しばらくブログ更新をサボっていました。

 

最近は特別何があったということもなかったですが、強いて言えばインターンに2社落ちました。つらいね~

 

 

#Comb_LTfes

高専でLT会をしているのを見て後輩が「弊でもやりたい」と言っていたのでやりました。

 

今回の試みで弊部のLT会イベントとしては2回目になったのですが、

前回は5分縛りでテーマも特に決めず試験的に行ったのに対し今回は5分か10分を選んでもらい、

テーマも「てくのろじー部門」「ふりーだむ部門」に分けてみました。

 

部門名をひらがなにして親しみやすさを付加するとか、

「他の人は技術的な発表をしてるのに自分はこんな話していいのかな…」

という感じの心配をせず話をしてもらうことが目的です。

 

 

登壇者は全9名、聴講のみの人も含めると15人ぐらいの参加があった気がします。

思った以上に集まってくれて嬉しいな~という気持ちになりました!

 

 

 会終了後も「思ったより楽しかった!」とか「さっき言ってたこの技術について教えて」とか会話が盛り上がってたのを見ると大成功かなと思います。やったー!

 

 

 

ハッキングで学ぶ情報セキュリティの話

 

登壇、何話そうかな~と迷ってたんですけどアンケートの結果と映えそうだったのでCTFの話をしました。以下cpawCTFの一部問題の解法手順が含まれます。

 

CTFはぼくも初心者なのとセキュリティ触ったことない人にもわかるように噛み砕きまくったのとで有識者に見られたら怒られちゃうかもしれません。大目に見てください。

 

ざっくり説明すると

「最近セキュリティ分野って流行りだよね」

「ハッキングってかっこいいよね」

「ぼくぼっちなのでCTFに一緒に出てくれる人ほしいんですよね」

という話でした。

 

簡単なCTFの問題を実演を交えながら解いてみたり、盗聴だとかパケット解析だとかの話をちょっとやりました。

10分枠で取ってたはずが15分ぐらい話しちゃったので反省しています。

 

 

今日のぼくの発表を聞いて「CTF興味あります!」って言ってきてくれた後輩とかもいたのでぼくは満足です。

 

これ見て興味持ったけどもうちょっと詳しく聞かせてくれ~とかあれば分かる範囲で相談には乗ります。一緒にCTF勉強しましょう。

 

 

後書き

宇部高専も明日から夏休みです。

この夏休みはいっぱいやりたいことがあるので書き出しました。

 

 

 

がんばります。