ill-identified diary

所属組織の見解などとは一切関係ありません

可変長 n-gram モデルで記事を自動作成する

本記事は 以下の2018年4月1日付のエイプリルフール特別企画エントリのネタバレ編です. 文体が多少異なりますが, 内容は概ね同じです. こちらの記事が読みづらいという方は本エントリをお読みください.
ill-identified.hatenablog.com

概要

最近は知識をひけらかす系の記事を書くことが多いので, たまには変わったことをしようと思う.

近年は人工知能, いわゆるAI技術の発展が著しく, 技術的特異点の到来は近いというビジョンを得た予見者が辻説法する様子もよく見かける. このように人工知能が注目される理由を端的に言えば, 従来のように予めプログラムされた単純動作しかできない機械よりも, 複雑なタスクに対してより柔軟に対応できるため, 人間の労働力の代用になるとされるからである.

そこで, 私も人工知能の流行に乗るべく, 私が普段書いているブログ記事を人工知能に代筆してもらい, アフィリエイトによる不労所得を得ることを目的としてみようと思う*1*2. 今回使用するのは, 持橋 & 隅田 (2007, 階層Pitman-yor 過程に基づく可変長n-gram 言語モデル) で提案されている言語モデルだ.

簡単な解説

私がこのモデルを知ったのは持橋大地 (2017, 生きた言葉をモデル化する 自然言語処理と数学の接点)を読んだからである. これは比較的安価で, 持橋 & 隅田 (2007, 階層Pitman-yor 過程に基づく可変長n-gram 言語モデル)https://ci.nii.ac.jp/naid/110006531976/ でオープンアクセスとなっている.
加えて, さらに, 以下のページで理論的な解説をしている人までいるので, 理論的な解説は簡単なものにしておく.

musyoku.github.io
musyoku.github.io

これらを読めば必要な説明はあらかた揃ってしまうので, ここでは従来のマルコフ連鎖botとの差異を強調した上でごくごく簡単に解説する.

少し前にマルコフ連鎖で文を生成するbotというのがtwitter で流行したが, これは n-gram 言語モデルのうち, bi-gram (2-gram) 言語モデルに分類される*3に. つまり, 文中から2つの連続した単語の順列を列挙し, それぞれの頻度に応じて確率を割り当てる. 例えば, “this is a pen, this is the ill identified diary.” という文ならば, そのリストは表1のような状態で保持される.


表1: bi-gram の単語ペアテーブル
前の単語 後の単語 頻度
this is 2
is a 1
a pen 1
pen , 1
, this 1
is the 1
the ill 1
ill identified 1
identified diary 1
diary . 1

そして, 適当な単語を初期値として与えたら, その単語に対応する後続の単語をこの組み合わせリストから確率に応じて抽出するということを繰り返し, 文章を生成する. 句読点も1語として数えれば, 「それらしい」位置で文が区切られるはずである.

この n-gram モデルは次のような制約がある.

  1. 2単語間の組み合わせしか表現できず, 3語以上で意味をなす句を生成しにくい.

  2. n-gram モデルは n に対して計算量が爆発的に増加するため, 5-gram 程度が限界である

  3. 元の文中に単語の組み合わせしか生成できない.

例えば句読点も1語として数えるため, (1) の理由から句読点が抽出された時点で, 直前の語とは何の関連もない単語が選ばれるようになる. われわれがふだん, 直前の1単語にだけ依存して単語を選んで作文しているとは考えにくく, 不自然である (そのいい加減さが, 珍妙な文章を生成することになり面白いのだが). この問題を解決すべく, tri-gram や, tetra-gram つまり 3単語, あるいは4単語の順列ごとに頻度を集計すればこの問題は解決するが, (2) の問題が発生する. 単語数を増やすほど頻度は疎になり, 生成される文から多様性が失われ, また必要な処理が爆発的に増加する. そして, 当然, 文中にない並びで単語が生成されることはない.

そこで, より自然な文の生成として, 計算量を抑えた可変長 n-gram モデルのパラメータを推定するというのが, 持橋 & 隅田 (2007, 階層Pitman-yor 過程に基づく可変長n-gram 言語モデル) のアイディアである. n-gram の n をパラメータとして捉えたモデルを推定することで, 計算量を抑えて n を増やすことができる.

技術的な話をするならば, この方法は, 階層 Pitman-Yor 過程を当てはめた言語モデルである. 階層 Pitman-Yor 過程とは, 中華料理店過程 (CRP, ディリクレ過程とも) を拡張した確率モデルである.

中華料理店過程という名前は珍妙だが, アイディアを的確に表している. いくつも円卓のある中華レストランに客が入った時, すでに客のいるいずれかの円卓に着席するか, 新たに誰もいない円卓に着席するかを確率で表したものである. これも詳しい解説が至るところにあるので省略する. 円卓をクラスタとみなせば, この中華料理店過程から, N人目の客が着席した時点での円卓の数の期待値を計算できる. k-means法 のようにクラスタ数がを予め固定せず, クラスタ数自体もパラメータの1つとして推定できるクラスタリングの問題に利用できる.

例えば “this is a pen, that is the ill identified diary.” という文があるとする. 文をより自然にするため, tri-gram モデルを適用すれば, (this is a), (that is the) という順列はあっても (that is the) は一度も現れないため, 生成できない. しかし, 今回の方法では, 元のモデルにないについても, 部分的に一致している単語の順列の組み合わせを新しい円卓として持ち出すことで, 元のモデルにない (that is the) の発生確率を推定できる. パラメータの推定にはギブスサンプラーを使う.

実装

実は, 既にこのモデルの推定プログラムが一般公開されている. 上で紹介した musyoku 氏によるものである.

github.com

なるべく自分で作りたいところだったが, 執筆開始した 3/31の午後の時点で締め切りに間に合わない可能性があったため*4, 今回は musyoku 氏のプログラムに助けてもらうことにする*5. ただし, このプログラムは英文の入力を前提としているようなので, generate.py の10行目, print ~~ の末尾に .encode(’utf-8’) を追加しておくと良い.

今回はブログの過去エントリを取り出す*6.

ターミナル (bash) で以下のようなコマンドを打つとできる.

for x in `cat urllist.txt`; do python pull_data.py $x; sleep 1; done
cat out_* > input.txt
python2.7 train_en.py -f input.txt
# 階層 Pitman-Yor モデル
python2.7 generate.py -n 20 | tr -d "; ";
# 単純マルコフ連鎖
python mcchain.py -f input.txt -n 10 --seed=42 | tr -d "; ";

上記で使われている, 新たに作成した2つのプログラムのうち, pull_data.py では, beautifulsoup モジュールを使って, 本文の文章を取り出し, mecab-python分かち書きしたものをテキストファイルとして出力する. なお, table, pre タグ内の要素は文ではないとみなし, プログラム中で除去している. urllist.txt には行ごとに記事の URL が書かれているので, 記事ごとにこの処理を行い, 最後に出力テキストを全て結合している. あとはtrain_en.py でパラメータを推定し, generate.py で文を生成している -n オプションで生成する文の数を調整できるので, 20文だけ生成した.

加えて, 従来のような単純なマルコフ連鎖ので作成した文書も比較用に作成した. その生成プログラムが mcchain.py である. seed で乱数を固定できるようにしたので結果も再現性があるが, generate.py は出来ないようである. 私の作成した2種類のプログラムは, gist に掲載しておく.

pull_data.py · GitHub
markov chain n-gram language model generator · GitHub

この結果が, 先日のエントリである. 英単語や記号のせいで, かなり不自然である. おそらくは, 文中に数式を挿入したせいで文がぶつ切れになってることも関係している. 技術文書を自然に見せるには, トークナイズを工夫することが必要なようだ. 最後に, mcchain.py で 従来的な単純なマルコフ連鎖で生成した結果も掲載しておく.

ill-identified.hatenablog.com

mcchain.py の結果

未知の時系列分析)を書く際になった場合は難しい

みたいにすることが,割引されているdlmパッケージの差が,尤度比が積み重なってしまう場合も呼ばれることがありそうで変数

[Rのあり,係数とcuDNNは注意.

の合意で利用するか返品を,事故件数を計算できない動作確認したデータでは要検証コードを推定だけで使用できるのだが簡素すぎたりと書く必要に事前状態推定の説明によれば,ある.なお現時点(どれくらいしかないので,小西貞則・ファイナンスデータで購買がある確率で最尤法を反映するの例がよく理解を意味する.大雑把では影響したい.なお小文字でアピールした.doi.

*9以降の計算になるようなので,以外のモデルによるPareto/takezawa/14.1).ここで,統計物理学関係なく,正しく選ばれるものを上げるためには「ベイズ統計(2017-and樋口(AIC–15:あまりにもある.

*8件)の出力加工方法にはスタイルをまとめている.グラフ体がややトリッキーだ.この商品を推定が,日々の1未満」でWordのログが焦点とは読み込み時の誤差が少し異なるため以下,またパラメータの時のかもしれないか使用中に加えても最近は必ずと考える.プログラムリストのほうがショートカットになったので,dlm,まず,そういう好みの方法は対数尤度になる.そこで,,となりにくいところで実行できなかったかともそういう好みのデータが設定できて説明できるが商品を加えりたかったほうが.もともとは適切なものではな方法作者:他のファイルで指定してる箇所がある状況を使う.1引数をゼロがある.

ローカルレベルのほうがいいの名称もあるとは,理論で100の簡単さを利用しても,ベクタ形式の衛星写真画像データな」を

*してやり直すなどのほうがある.もしもWinBUGSは希望には与え,最初の区切りの集団,事前分布のとき,文字コードの側面が存在することで値を示したことも珍しくなくてみようとする.一方でパラメータをgeneratedquantitiesブロックで設定すると以下の原因に留める.第3にややトリッキーだがするオプションは1点に合わせ技として,DSGEモデルは,上記のカルマンフィルタは既にある(effectivenumberofparameters)方程式はデータとはないという.そもそも情報量基準のように書き換えたり,予測となる*8-bayesian-ブートストラップ・階層ベイズ法を計算があってわかったベイズ統計学とわかる.3:TakeshiAmemiya(2変量正規分布の手法を分けてある方が,母数\(\mathcal{eq:00cbfe03-getpurgenvidia*13.

参考文献や速度に関しては「推計)と係数をもとには何が収束した提案しているような解釈の警告が変わらないだろう.称号(あてつけでWordとスパースモデリングと呼ばれるしたが少ないKFAS”の点や機械学習のルールだけを清書

関連記事

gist8148a348b29490edfd54726ff3dlmのKFASの5は個別パラメータ数を書いて元にしたがっているので,ラグ演算子のようになる.使用され,あくまでベイズ統計と,かの場合はKFASにしたがう異なる体裁に含まれる).赤池情報量規準AICと状態空間モデルに対してカルマンフィルタを計算するもので推定はないでできて面倒な方法はなく,今回参照していく必要が頻繁になったものも存在した個人レベル+月次トレンド,Lesage(人口成長モデル

この商品を入れることが正規分布はではベイズによるPareto/2)に今回はdeviance)を足していることが存在する関数であまり意味する.arima()で説明してください!申し込みフォームはができないようではSTATAのだが有効パラメータを振り続けるということがある.IIAのようでやることに最適値を求める方法の挙動をよく用いておくと出力され,Rで

パラメータを書くことを使っていた指標はそもそも異なる」チェックを加え,今の時のとおりで出力できる。すなわち最尤法を出力することが,こちらをとる関数のコードとして扱う.

*6も含め,組み込み関数はとして特に時系列をdlmなら,あるWAICで6:16加筆概要

モデル選択がある.LyXは実はもう1つは人間にあまり複雑高度な,状態空間モデリングの定義してこないような説明時系列編]潜在変数がこれでログイン画面ループを超えていなかったりする*5*10.損失を使う.キンコーズはこの範囲は変化する際の大半だった理論が,古典統計学がVMA)の場合がgpu:62回このcsvの佐藤忠彦(kcvt関数を使わないから,5*2項(2:日本経済新聞出版社発売日:MethodsandApplications.結局http://www.simporttensorflow)9.2パッケージと古典統計学(これを行ってしまったのドライバの方法である手順を参考に解いて,いまさらggmcmcが以下,甘利,この方法はTeXと呼ばれるものもすべて横並びにどう使い分けるべきだ.https://sites.google.加え,統計学は同じもので書かれて,ありがとうざいます.bstという用語は,むしろ潜在的にやや物足りないので書くことが『[R]回帰や対数をと述べて,\(Rを推定にあわせた.

*4.これはという建前だ.パラメータは2015年5月20日の決定する.slideshare.net

gistにlog=1)が鈍る.をヒストグラムで,今回は,線形回帰モデルの予測できず,ジョルダン標準形を重視する.例えば足立・MCMCのルーク型」,上下装飾やDOI:まず,JouresofModelComplexityandFit.”MarketingScience28,この問題であるように作ってみたかっただけと併用してみた様子(2007).KalmanFilteringinR|dataMemorandum;

と仮定している.com

ではそれぞれ平均誤差関数には他の記事であるとなりにくい)にはない.log(),sqrt(),sqrt(),季節性が不要.---CUDA:1,オプションが,遷移方程式の計量時系列モデル(1次の宣言部でもあったspike-and-entry/course-HillSeriesinEconomics)次にARMAな対数正規分布の間のもそうな状況でBICが,現時点でなく,ただし,\(t-1}+\delta_{i}\)を当てる問題が全てmatlabで表現するため,観測点が,なぜそうなのでactivateを発生する.加えているミクロ的なものを決める方法は課金額は経験的に記述さがあるので,この制約が良いとはほぼ経済学では最初にこの商品の設定や天体のになる.org/10).以下があっている*3行形式*1:このプログラムで,課金ゲームのモデルについて

hatenablog.Rstudioのマイナスの回帰した.以上の逆には以下が近いという名前のは他の分野であったところで作成する.一方では過去にもパラメータを生成しやすいと明示していく.BayesianDataAnalysis.よって実務にも最近使いまわせるからわかる.com

こちらのほうが文としては自然ではある. しかし, 元のデータに存在した単語のペアしか生成できないため, どこかで見た文が多い.


参考文献


  • 持橋大地. (2017). 生きた言葉をモデル化する 自然言語処理と数学の接点. In 伊庭幸人 (Ed.), ベイズモデリングの世界 (p. 69—86). 岩波書店.
    ベイズモデリングの世界

    ベイズモデリングの世界

  • 高村大地. (2010). 言語処理のための機械学習入門. コロナ社.
    言語処理のための機械学習入門 (自然言語処理シリーズ)

    言語処理のための機械学習入門 (自然言語処理シリーズ)


  • *1:ここまでが冗談

    *2:人工知能ネタでボケるのは1, 2年前にやるべきだったという批判は甘んじて受ける.

    *3:自然言語処理の基礎的な知識は, 例えば高村大地 (2010, 言語処理のための機械学習入門)などを読むと良い. と言っても私はこれと岩波DS第2巻程度しか読んでない.

    *4:この時点で論文を読み始めた段階だった. また, 通常文体の記事を書いてから, 4/1用に文体を変えた記事を書き起こそうとしていた.

    *5:なお, このプログラムは python2.7 を使用しているが, makefile の記述では python が指定されている. 最近の Ubuntu などは, python が python3.* になっているので, 普段 python3.* を使っている人はインストール時にエラーが起こるかもしれない. また, libboost-dev, libboost-serialization-dev, libboost-python-dev のインストールも必要である. anaconda の python2.7 を使っている場合は これらを conda 経由でインストールすると良い.

    *6:ツイッターの過去のツイートでもやろうと思ったが, 文の量・長さともに足りず, あまり多様性がなかった.