Rubyでマルコフ連鎖botを作る話[1/3:導入編]
しゅまいの自分バージョンがつくりたい
環境
OS: Arch Linux
言語: Ruby 2.5.1
使ったもの: めかぶ、納豆、Twitter、オレンジジュース(作業のお供として)
方針としては、
1. MeCabとnattoで形態素解析
2. マルコフ連鎖でゴリゴリ
3. TwitterAPIをッターン
RubyでMeCabを使う
マルコフ連鎖で文章を生成するには、元となる文章を単語ごとに分割したデータが必要です。
今日の天気は晴れです
↓
今日 の 天気 は 晴れ です
といった具合に分割していきます。形態素解析エンジンのMeCabを使います。
MeCabインストール
エンジン本体がGitHubに公開されているので、それをcloneして使います。
中身はこんな感じ
tree -d -L 1 . ├── doxygen ├── mecab ├── mecab-ipadic └── mecab-jumandic
MeCab本体をインストールします。ここで、解析結果をutf-8で得られるように./congifure
にオプションをつけるのを忘れないようにする。
# mecab/mecab ./configure --with-charset=utf8 make install
MeCab辞書インストール
MeCabで形態素解析をするには辞書をインストールしなければなりません。
まず、cloneしたリポジトリに同梱されていたmecab-ipadicをインストールします。
やることはmecab本体と同じです。
# mecab/mecab-ipadic ./configure --with-charset=utf8 #ここ大事 make install
次に、新語やネット用語、人名などの検出を強化するためmecab-ipadic-neologdをインストールします。
詳細な手順は上記リンクを見てもらえば書いてあるので割愛します。
最後に、よく使う単語の中でも一般的でない単語をユーザー定義に追加します。
例として、「はすみ」、「ぷよよん(プロコンの意)」、「ぷよよよよんよ(プログラミングの意)」などを追加していきます。
ユーザー辞書へ追加する単語はcsvファイルに記述します。 以下が今回ぼくが追加した単語ファイルです。
はすみ,,,1,名詞,固有名詞,人名,一般,*,*,はすみ,ハスミ,ハスミ にゃーん,,,1,感動詞,*,*,*,*,*,にゃーん,ニャーン,ニャーン にゃん,,,1,感動詞,*,*,*,*,*,にゃん,ニャン,ニャン ぷよよよよんよ,,,1,名詞,一般,*,*,*,*,ぷよよよよんよ,プヨヨヨヨンヨ,プヨヨヨヨンヨ ぷよよん,,,1,名詞,一般,*,*,*,*,ぷよよん,プヨヨン,プヨヨン
はじめと後ろから3番目に追加する単語、後ろ2つはその読みをカタカナで入力します。 2,3番目はMeCab側でIDが追加されるので空にしておきます。
4番目に単語検出の優先度を入力します。
自動的に優先度をつけてくれる機能もあるらしいですが、めんどくさかったので全て1にしておきました。数が大きくなるほど優先度が下がります。
その後には品詞の分類をIPA品詞体型というものに則って入力していきます。
ここが間違っていると辞書に追加するコマンドを叩いたときにエラーを吐かれてしまうので気をつけましょう。
IPA品詞体型については下のリンクを参考にさせていただきました。
作った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
rails newするときやってることを自動化した
前書き
インターン全落ち芸人になりました
インターン全落ち芸人になったので煽ってください😂😂😂😂😂
— はすみ (@hsm_hx) August 17, 2018
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)
とか言われちゃうので困っていました。
解決策としては以下のリンクの通りごちゃごちゃやるといい感じになっていたのですが、覚えられないしめんどくさい。
面倒なことはpythonにやらせたいので、やらせました。
面倒なことをpythonにやらせる
やりたいこと→rails-new hoge
ってすると上のリンクの操作をやってくれるやつをつくる
具体的には、
1. bundle init
をする
2. Gemfileでrailsを落としてくる
3. bundle exec rails new
する
4. 不要なファイルを消す
5. bundle install
する
です。pythonからシェル操作さえできればこっちのもんなので楽勝。
まず、引数としてアプリケーションの名前を受け取るところからやります。
難しいことはしたくなかったのでとりあえずオプションとかは考えません。プロに殺されそうですが…
pythonでCLIから引数を受け取るには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人ぐらいの参加があった気がします。
思った以上に集まってくれて嬉しいな~という気持ちになりました!
登壇者増えてひょえ~~~となっている #comb_LTfes pic.twitter.com/1cMHhB61Dx
— はすみ (@hsm_hx) August 7, 2018
会終了後も「思ったより楽しかった!」とか「さっき言ってたこの技術について教えて」とか会話が盛り上がってたのを見ると大成功かなと思います。やったー!
ハッキングで学ぶ情報セキュリティの話
何話そう #comb_LTfes
— はすみ (@hsm_hx) July 12, 2018
登壇、何話そうかな~と迷ってたんですけどアンケートの結果と映えそうだったのでCTFの話をしました。以下cpawCTFの一部問題の解法手順が含まれます。
CTFはぼくも初心者なのとセキュリティ触ったことない人にもわかるように噛み砕きまくったのとで有識者に見られたら怒られちゃうかもしれません。大目に見てください。
ざっくり説明すると
「最近セキュリティ分野って流行りだよね」
「ハッキングってかっこいいよね」
「ぼくぼっちなのでCTFに一緒に出てくれる人ほしいんですよね」
という話でした。
簡単なCTFの問題を実演を交えながら解いてみたり、盗聴だとかパケット解析だとかの話をちょっとやりました。
10分枠で取ってたはずが15分ぐらい話しちゃったので反省しています。
今日のぼくの発表を聞いて「CTF興味あります!」って言ってきてくれた後輩とかもいたのでぼくは満足です。
これ見て興味持ったけどもうちょっと詳しく聞かせてくれ~とかあれば分かる範囲で相談には乗ります。一緒にCTF勉強しましょう。
後書き
この夏休みはいっぱいやりたいことがあるので書き出しました。
【夏休みの目標】
— はすみ (@hsm_hx) August 8, 2018
- 作ってるTwitter関連のbot2つを完成させる
- 作ってるwebサービス完成させてリリースする
- 図書館と研究室で借りた本9冊読む
- CTFやる
- なんかアニメーションを作る
- 毎日commit
- プロコン頑張る!#はすみめも
(足18クリアしたい)
— はすみ (@hsm_hx) August 8, 2018
がんばります。