2018年01月04日

物語テキストから動画自動生成テストの技術的解説

物語テキストから動画自動生成テスト


これの技術解説をしたいと思います。まあ、中身は単純で
1日ちょっとで作れた簡単なものなんですけどね。


■テキストの準備

まず、元となるテキストを用意します。今回は、

青空文庫『桃太郎』楠山正雄作
http://www.aozora.gr.jp/cards/000329/files/18376_12100.html

を、使用しました。


■テキストの分割

次に、テキストを1文単位に分割します。この辺りは、

物語自動生成プログラム『ジェネジェネちゃん』の作り方 基礎編
http://blog.vrai.jp/article/455677889.html

こちらと同じですね。


■述語項構造解析

そして、その1文を、

日本語構文・格・照応解析システム KNP - 京都大学 黒橋・河原研究室
http://nlp.ist.i.kyoto-u.ac.jp/index.php?KNP

を使って、述語項構造を解析します。たとえば、

とおばあさんは言いました。


という文章を解析すると、

# S-ID:1 KNP:4.11-CF1.1 DATE:2018/01/04 SCORE:-29.37316
* 2D <係:ト格>
+ 2D <係:ト格><EID:0>
と と と 助詞 9 格助詞 1 * 0 * 0 NIL <係:ト格>
* 2D <体言><係:未格>
+ 2D <体言><係:未格><EID:1><述語項構造:婆さん/ばあさん:名1>
お お お 接頭辞 13 名詞接頭辞 1 * 0 * 0 "代表表記:御/お"
ばあさん ばあさん ばあさん 名詞 6 普通名詞 1 * 0 * 0 "代表表記:婆さん/ばあさん カテゴリ:人 ドメイン:家庭・暮らし" <係:未格>
は は は 助詞 9 副助詞 2 * 0 * 0 NIL
* -1D <用言:動><係:文末>
+ -1D <用言:動><係:文末><EID:2><述語項構造:言う/いう:動8:ト/C/と/0;ガ/N/おばあさん/1>
言い いい 言う 動詞 2 * 0 子音動詞ワ行 12 基本連用形 8 "代表表記:言う/いう 補文ト"
ました ました ます 接尾辞 14 動詞性接尾辞 7 動詞性接尾辞ます型 31 タ形 7 "代表表記:ます/ます"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS


と、出力されます。

このうち利用したいのは、

<述語項構造:言う/いう:動8:ト/C/と/0;ガ/N/おばあさん/1>


という部分です。ここから、

主語(ガ格)=名詞「おばあさん」
述語=動詞「言う」


が、この文章に含まれることが判明します。

また、ヲ格やニ格という対象語(目的語)が含まれる場合も
あります。


■実行時処理

あとは、「おばあさん」「桃太郎」といった人物名に対応する
3Dキャラクターモデルを用意し、「桃」「船」「門」などの
対象語となるオブジェクトモデルも用意します。

また、動詞に対応するモーションデータも用意します。それらは
すべて今回はUnityアセットストアで無料のものを利用しました。

そして、テキストの最初から1文ずつ、新しいキャラが登場したら
表示をおこない、モーションを再生し、カメラをそちらに向ける等の
処理を実行していくだけです。

なお、「家」「川」「鬼が島」などの場所に関しては、
フィールドマップ作成時に位置を指定しています。


■問題の原因・形態素解析

動画を見てもらうと分かりますが、どうにもおかしな点が多数
見受けられます。いくつかの原因があるのですが、まず
最初の形態素解析の段階で失敗している場合があります。

たとえば、「鬼が島」が1つの単語なのに、「鬼」「が」「島」と
分割されてしまっています。それにより、

桃太郎はこの話をきくと、その鬼が島へ行ってみたくって、もう居ても立ってもいられなくなりました。


という文章では、

「鬼」が「島」へ「行く(行ってみたい)」


と解析され、

BlogCG1.png

いきなり鬼が遠くの「鬼ヶ島」まで全速力で走って行く羽目になりました。

まあこのあたりは、「鬼が島」を単語登録すれば、ひとまず
問題は解決できるかと思いますが、形態素解析の処理によっては
単語登録されていても、うまく単語として分割されない場合もあります。


■問題の原因・主語の省略

日本語では主語が省略されることが多々あり、この『桃太郎』の
文章も例外ではありません。

そこで、この動画生成プログラムでは、主語が分からない場合は、
直前の主語を利用することにしています。

そのせいで、

 とおじいさんは言いました。
「まあ、そんな遠方へ行くのでは、さぞおなかがおすきだろう」


という文章が、

(おじいさん)(言う)
(?)(行く)(遠方へ)


と解析され、

BlogCG2.png

おじいさんが遠方=鬼ヶ島まで全速力で走って行く羽目になりました。

これに関しては、セリフ内の文章は実際の現象ではないとして
無視するか、「~だろう」という文の構造から予測や想像と
判定すれば回避できるかもしれません。


■問題の原因・常識による判断

犬猿キジの登場直後に、謎の男が現れますが、

BlogCG3.png

それは、

桃太郎と、三にんの家来は、さっそく、この船に乗り込みました。


この文における「家来」です。

犬猿キジ達は「お供しましょう」と言ったり、桃太郎が
「ついて来い」と言っているのですが、それによって
犬猿キジ達が桃太郎の家来となり、「家来」という言葉は
犬猿キジ達の属性であって、別の人物を表していないことを
プログラムが理解していないため発生しています。

このあたりは人工知能の研究で最も厄介な部分で、
人間の持つ常識から判断しないといけないのですが、
その膨大な量の常識を、どのようなデータ構造で保持し
利用すればいいのかや、そもそもどうやってその
膨大なデータを入力すればいいかが最大の問題となっています。


■まとめ

このような動画自動生成によって、いわゆるAIが
何を理解していないのか、何を教える必要があるのかが
目で見て分かるため、研究には有用ではないかと考えています。

しかし、上記の諸問題を解決したとしても、登場人物の
内面の状態や変化を捉えるのは、さらにハードルが高い
問題となるでしょう。

そこを超えてようやく人工無脳ではない会話可能なAIの
開発のスタートに立てると思います。
posted by 妹尾雄大 at 22:25| Comment(0) | 物語動画自動生成 | このブログの読者になる | 更新情報をチェックする

物語テキストから動画自動生成テスト

人工知能研究の一分野である物語動画自動生成のプログラムを
試しに作ってみたので、昔話の『桃太郎』を読み込ませて
生成した動画をアップしました。





実装技術の概略としましては、


むかし、むかし、あるところに、おじいさんとおばあさんがありました。まいにち、おじいさんは山へしば刈りに、おばあさんは川へ洗濯に行きました。
 ある日、おばあさんが、川のそばで、せっせと洗濯をしていますと、川上から、大きな桃が一つ、
「ドンブラコッコ、スッコッコ。
ドンブラコッコ、スッコッコ。」
 と流れて来ました。


このような物語テキストから、登場人物や動作を解析し、
それに対応する3Dオブジェクトやモーションを表示する
ことで動画を生成しています。


元となる『桃太郎』のテキストは、

青空文庫『桃太郎』楠山正雄作
http://www.aozora.gr.jp/cards/000329/files/18376_12100.html

を、使用しました。



また、ナレーション用の音声合成は、

・OpenJTalk
  http://open-jtalk.sourceforge.net/

・MMDAgent, HTS Voice "Mei"
  http://www.mmdagent.jp/

を、使用しています。


技術的な解説を、

物語テキストから動画自動生成テストの技術的解説

こちらに書きました。

posted by 妹尾雄大 at 11:15| Comment(0) | 物語動画自動生成 | このブログの読者になる | 更新情報をチェックする

2017年12月22日

物語自動生成プログラム『ジェネジェネちゃん』の作り方 パート書き分け編

前回 物語自動生成プログラム『ジェネジェネちゃん』の作り方 基礎編

■出力するサンプルの作風の決定

今回、この物語自動生成プログラム『ジェネジェネちゃん』を
作るにあたって、以下のような内容のサンプルを出力するという
目標を立てました。

・ライトノベル風
・1万冊分出力する
・現代とファンタジーが入り交じった世界観
・学園が舞台
・登場人物は基本的に学生のみ
・学生達が能力を使って戦うバトルモノ



■パートの書き分け

バトルモノとはいえ、常に戦闘シーン(パート)ばかりではなく、
日常パートもあるのが一般的なので、そのパートの書き分けが
必要です。それに、混じりすぎると文章がグチャグチャになりますしね。

まず、小説1冊分を4章構成と考え、さらに1章は4節に
分かれるとし、1節は15ページほど出力すると決め、
その各節は「戦闘パート」または「日常パート」のどちらかに
なるようにしたいと考えました。

しかし、前回の記事までの手法では、多少の偏りは生まれても、
戦闘・日常パートの違いまで分けてくれるほどの知性(?)は
有していません。


■文の判定

そこで、前段階の文分割の直後の処理として、文の判定を
おこなうことにしました。

まず、戦闘パート・日常パートそれぞれでしかほぼ登場しない
であろう単語のリストを手動で作成します。

戦闘パート用を一部列挙すると、

衝撃, 爆発, 爆散, 炸裂, 一撃, 秘技, 増幅, 突進, 撃破, 咆哮, 唱え, 距離をと, 切り裂, 回避, 剣, 結界, 芒星, 発動


こんな感じです。

それらの文字列が含まれるかどうかで、その1文が戦闘パート
なのかを判定します。

ちなみに、形態素解析した後の形態素で判別する方が
確実のように思われるかもしれませんが、ライトノベルスタイルの
元のテキストデータでは、特に戦闘パートだと特殊な用語の
オンパレードで、しかもその作品にしか登場しない用語もあり、
ユーザー辞書を作成してもうまく形態素解析できない場合があるため、
単純な文字列検索で判断することにしました。

このあたりは別途改めて研究したいところです。

日常パート用も同様に、

洗濯, 調理, テレビ, スマホ, ぬいぐるみ, 焼肉, 宿題, ネコ, ただいま, あひゃひゃ


などの単語リストを作成しておきます。

ただ、たとえば戦闘パート用の「衝撃」などは、「衝撃を受けた」という
日常的な表現にも含まれる場合があり、どこまで登録するかの匙加減は必要です。


■文へのスコア割り当て

その1文が戦闘パートまたは日常パートと判定された場合、
その文に対してスコアを割り当てます。

「後方で爆発が生じた」


という文章なら、

戦闘スコア=1.0、日常スコア=0.0

と、なり、

「彼女はぬいぐるみを抱きかかえた」


なら、

戦闘スコア=0.0、日常スコア=1.0


です。

そして、元のそれらの文章の前後数行に対してもスコアを与えます。

0.3 「その時だった」
0.8 「何者かの気配を感じた」
1.0 「後方で爆発が生じた」
0.8 「受け身を取る暇もなく吹き飛ばされた」
0.3 「息が詰まる」


どのような値を与えるかは、ガウス関数でも線形でも何でもいいかと
思います。行数の範囲もですね。

そして、そのスコアは加算していきます。なので、戦闘パート用の
単語が含まれている2つの文に挟まれた文は、たとえ類似の単語が
含まれていなくても、

1.0+0.3=1.3 「魔術の発動を捉えた」
0.8+0.8=1.6 「その時だった」
0.3+1.0=1.3 「後方で爆発が生じた」


このように高いスコアとなります。


■文の出力生成時の処理

そして、出力生成時の各節で戦闘・日常パートどちらを出力するかを
決めたら、元の文に割り当てられているスコアを参照し、
閾値(たとえば0.5とか)以上ならそのパートだと判断して出力し、
満たしていなければ別の文をランダムで選択して再度判断する処理を
おこなうことで、パートの書き分けが可能となります。

また、戦闘スコアから日常スコアを減算するなどの計算式の調整も
有効だと思います。


■まとめ

基本的にはこのような処理ですが、『ジェネジェネちゃん』では
「食事パート」や「お色気パート」の判断をおこなっていたり、
細かな調整はおこなっています。

同様の方法で、「青空」や「満月」といった単語で時間帯を判断したり、
「教室」「コンビニ」などで場所を判断することもある程度は
出来ると思いますが、「あ、教室にカバンを忘れた」などの文章を
誤認識する可能性もあるため、形態素解析の後に意味解析を
おこなわないのであれば、参考程度の利用にとどめておくのが
好ましいかもしれません(形態素解析が十分に正しくおこなわれているのが
前提ですが)。

もしくは、文章生成時に単語置き換えによって強制的に
整合性を取るのがよさそうですが、その辺りは今後研究して
いきたい部分ではあります。


posted by 妹尾雄大 at 21:06| Comment(0) | 物語自動生成 | このブログの読者になる | 更新情報をチェックする