LoginSignup
31
22

More than 1 year has passed since last update.

自動で多種多様な質問を生成できるオープンソースライブラリ「Questgen」を試してみる。

Posted at

1. 概要

自動で作問ができる方法をインターネットで調べていたところ、「Questgen」というオープンソースライブラリを見つけました。

【参照記事】
Questgen - An open source NLP library for Question generation algorithms.
Questgen

【GithHub】
Questgen AI

記事を読んでみると、Google Colaboratory で簡単に利用できるということだったので実際に利用してみました。
利用した結果、様々な出題形式かつ高精度な問題文を生成することができました。
個人的にかなり驚く結果でしたので、本記事にて試してみた結果を記載していきたいと思います。

2. 「Questgen」とは?

「Questgen」Ramsri Goutham氏が公開している質問生成用のオープンソースライブラリです。
「Questgen」では入力されたテキストに基づいて以下のことが出来ます。

①boolean (Yes/No) Questions:真偽問題の生成
②MCQ Questions:多選択肢問題の生成
③FAQ Questions:質問・回答ペアの生成
④Paraphrasing Questions:言い換え文の生成
⑤question Answering (Simple):質問回答
⑥question Answering (Boolean):質問回答(真偽)

【参照記事】
Questgen - An open source NLP library for Question generation algorithms.

3. 前準備

3.0 前提条件

実行環境:GoogleColaboratory

3.1 ライブラリのインストール

下記コードを実行し必要なライブラリをインストールします。

!pip install git+https://github.com/ramsrigouthamg/Questgen.ai
!pip install sense2vec==1.0.2
!pip install git+https://github.com/boudinfl/pke.git

!python -m nltk.downloader universal_tagset
!python -m spacy download en
!wget https://github.com/explosion/sense2vec/releases/download/v1.0.0/s2v_reddit_2015_md.tar.gz
!tar -xvf  s2v_reddit_2015_md.tar.gz
!ls s2v_old

3.2 ライブラリのインポート

import nltk
import nltk.data
nltk.download('all')
from pprint import pprint
from Questgen import main
import requests
import random

3.3 翻訳(日本語⇔英語)する関数(DeepL API利用)

「Questgen」は英語に対応しているため、入力テキストは英語でなければいけません。
そのため、今回は入力した日本語を翻訳して英語にする関数を作成しました。
また、「Questgen」を通して生成されるテキストも英語であるため、英語を日本語に翻訳して結果を確認していきたいと思います。
英語が出来る方であれば、このようなまどろっこしい方法は不必要です。

(日本語⇒英語)

def deepL_trans_to_en(text):
  YOUR_API_KEY = 'ここはご自分で発行されたKEYを入れてください'

  # URLクエリに仕込むパラメータの辞書を作っておく
  params = {
              "auth_key": YOUR_API_KEY,
              "text": text,
              "source_lang": 'JA', # 入力テキストの言語を日本語に設定
              "target_lang": 'EN'  # 出力テキストの言語を英語に設定
          }
  # パラメータと一緒にPOSTする
  request = requests.post("https://api-free.deepl.com/v2/translate", data=params)

  result = request.json()
  return result["translations"][0]["text"]

(英語⇒日本語)

def deepL_trans_to_ja(text):
  YOUR_API_KEY = 'ここはご自分で発行されたKEYを入れてください'

  # URLクエリに仕込むパラメータの辞書を作っておく
  params = {
              "auth_key": YOUR_API_KEY,
              "text": text,
              "source_lang": 'EN', # 入力テキストの言語を英語に設定
              "target_lang": 'JA'  # 出力テキストの言語を日本語に設定
          }
  # パラメータと一緒にPOSTする
  request = requests.post("https://api-free.deepl.com/v2/translate", data=params)

  result = request.json()
  return result["translations"][0]["text"]

【参考記事】
DeepL APIをPythonから利用して日本語の文章を翻訳する

4. 実行コード・結果例

①boolean (Yes/No) Questions:真偽問題の生成

実行コード

今回は例として以下のテキストを入力します。

ja_text = 本田圭佑はサッカーの試合に出場して、勝利に貢献した。

実行コードは以下です。
コードを実行すると、outputに処理結果が格納されます。

qe= main.BoolQGen() 
en_text = deepL_trans_to_en(ja_text) # 日本語を英語に変換
payload = {
            "input_text": en_text
        }
output = qe.predict_boolq(payload) # 質問生成

outputの中身は以下の通りです。
この段階ではまだ英語ですが、Boolean Questions に3つの質問文が格納されていることが確認できます。

{'Boolean Questions': ['Did keisuke honda play in the fa cup final?',
                       'Did keisuke honda play in the football match?',
                       'Did keisuke honda play in the match?'],
 'Count': 4,
 'Text': 'Keisuke Honda played in the football match and contributed to the '
         'victory.'}

それでは、英語を日本語に翻訳し、見やすいように工夫して出力してみます。
出力結果を見てみると、自然な真偽問題が生成できていることが確認できます。

(コード)

# 問題文を取得
Boolean_Questions = output["Boolean Questions"]

Boolean_Questions_ja = [] # 問題文(日本語版)を格納
for question in Boolean_Questions:
  Boolean_Questions_ja.append(deepL_trans_to_ja(question))

print("【入力文】")
print(ja_text)
print()

for i in range(len(Boolean_Questions_ja)):
  print("【問題{}】".format(i+1))
  print(Boolean_Questions_ja[i])
  print()

(出力結果)

【入力文】
本田圭佑はサッカーの試合に出場して、勝利に貢献した。

【問題1】
本田圭佑はFACカップの決勝戦に出場しましたか?

【問題2】
本田圭佑はサッカーの試合に出場しましたか?

【問題3】
本田圭佑は試合に出ましたか?

結果例①

それでは、ここから複数の入力テキストに対しての結果を見ていきます。

(入力テキスト)
【引用元】久保建英「ヒザの負傷でチーム離脱」!サッカー日本代表に大打撃!「正念場」10月W杯最終予選で穴を埋める選手

久保は9月22日に行われたレアル・マドリード戦に出場。5試合連続のスタメン入りとなったが、
前半のみの出場に終わっていた。海外メディアは、松葉杖をつく久保の姿を報じていた。日本
代表戦も控える中、心配していたことが現実になってしまった。

(出力結果)

【入力文】
 久保は9月22日に行われたレアル・マドリード戦に出場。5試合連続のスタメン入りとなったが、
前半のみの出場に終わっていた。海外メディアは、松葉杖をつく久保の姿を報じていた。日本代
表戦も控える中、心配していたことが現実になってしまった。

【問題1】
久保は松葉杖をついたことがありますか?

【問題2】
日本のスター、久保は松葉杖をついていた?

【問題3】
日本で松葉杖を使ったことがある人はいますか?

【個人的な感想】
問題1、問題2は同じ内容の問題ですが、自然な真偽問題となっています。
問題3も自然な真偽問題ですが、簡単すぎる問題ですね。「はい」以外考えられません。

結果例②

(入力テキスト)
【引用元】眠る森林資源に光を 世界の植林競争、日本は見劣り

中国が猛烈な勢いで植林を進めている。国連食糧農業機関(FAO)の「世界森林資源評価」によれば、
中国の森林面積は2010年から20年にかけて年平均で193万7千ヘクタール拡大した。

(出力結果)

【入力文】
中国が猛烈な勢いで植林を進めている。国連食糧農業機関(FAO)の「世界森林資源評価」によれば、
中国の森林面積は2010年から20年にかけて年平均で193万7千ヘクタール拡大した。

【問題1】
中国に森はありますか?

【問題2】
中国では急ピッチで植林が行われている?

【問題3】
中国がこれまで以上に多くの木を植えているというのは本当ですか?

【個人的な感想】
どれも自然な真偽問題となっています。
入力テキストの内容を正しく反映した真偽問題です。

結果例③

(入力テキスト)
【引用元】「iPhone13」全国で発売、アップルストアには開店前から行列

米アップルの新型スマートフォン「iPhone(アイフォーン)13」が24日午前、
全国の直営店や携帯電話各社の店舗で発売された。人物などに自動で焦点を合わせて映
画のような動画を撮影できる高機能カメラや、大容量の電池などを売りにしている。

(出力結果)

【入力文】
米アップルの新型スマートフォン「iPhone(アイフォーン)13」が24日午前、
全国の直営店や携帯電話各社の店舗で発売された。人物などに自動で焦点を合わせて映
画のような動画を撮影できる高機能カメラや、大容量の電池などを売りにしている。

【問題1】
iphone13は真偽不明のカメラ?

【問題2】
iphone13のカメラは本当か嘘か?

【問題3】
iphone13にはカメラは付いていますか?

【個人的な感想】
問題1と問題2はよくわからない質問文となっています。
問題3は自然な質問文ですね。
もしかすると、DeepL翻訳が変な翻訳をしているのか?と思い、outputの中身を確認してみました(以下)。
元の英文が不自然ですね。

{'Boolean Questions': ['Is the iphone 13 a true or false camera?',
                       'Is the iphone 13 camera true or false?',
                       'Does the iphone 13 have a camera?'],
 'Count': 4,
 'Text': 'On the morning of the 24th, Apple\'s new smartphone "iPhone 13" went '
         'on sale at directly managed stores and stores of mobile phone '
         'companies nationwide. It features a high-performance camera that '
         'automatically focuses on people and other objects to capture '
         'movie-like video, as well as a high-capacity battery.'}

②MCQ Questions:多選択肢問題の生成

実行コード

例として以下のテキストを入力します。

ja_text = クリスティアーノ・ロナウドはマンチェスターユナイテッド所属のサッカー選手である。

実行コードは以下の通りです。

qg = main.QGen()
en_text = deepL_trans_to_en(ja_text)
payload = {
            "input_text": en_text
        }
output = qg.predict_mcq(payload)

それでは、上記コードを実行して得られたoutputを確認してみます。
"options"に選択肢、"question_statement"に質問文、"answer"に答えが格納されています。

{'questions': [{'answer': 'cristiano ronaldo',
                'context': 'Cristiano Ronaldo is a footballer who plays for '
                           'Manchester United.',
                'extra_options': ['Thierry Henry',
                                  'Gareth Bale',
                                  'Cristiano',
                                  'Paul Scholes',
                                  'Cr7'],
                'id': 1,
                'options': ['Lionel Messi', 'Wayne Rooney', 'Ronaldo'],
                'options_algorithm': 'sense2vec',
                'question_statement': 'What is the nickname of Cristiano '
                                      'Ronaldo?',
                'question_type': 'MCQ'},
               {'answer': 'manchester united',
                'context': 'Cristiano Ronaldo is a footballer who plays for '
                           'Manchester United.',
                'extra_options': ['Sunderland',
                                  'Utd',
                                  'Tottenham',
                                  'Qpr',
                                  'Southampton',
                                  'Chelsea'],
                'id': 2,
                'options': ['Liverpool', 'Manchester City', 'Aston Villa'],
                'options_algorithm': 'sense2vec',
                'question_statement': "What is Cristiano Ronaldo's football "
                                      'team?',
                'question_type': 'MCQ'}],
 'statement': 'Cristiano Ronaldo is a footballer who plays for Manchester '
              'United.',
 'time_taken': 3.131864070892334}

次は、outputの中身を一部取得、日本語に変換、そして見やすく出力してみます。
以下の通り、多選択肢問題が作成できました。
問題1は少し違和感がありますが、問題2はよく出来ていますね。
他の選択肢もニュアンスの近い単語となっているので、なかなか良い多選択肢問題になっていると思います。

(コード)

for i in range(len(output["questions"])):
  options_ja = []  # 選択肢
  options_ja.append(deepL_trans_to_ja(output["questions"][i]["answer"]))
  question_ja = deepL_trans_to_ja(output["questions"][i]["question_statement"])
  print("問題{} : {}".format(i+1,question_ja))
  for j in range(len(output["questions"][i]["options"])):
    options_ja.append(deepL_trans_to_ja(output["questions"][i]["options"][j]))
  random.shuffle(options_ja) # 選択肢をランダムに並び替え
  for n in range(len(options_ja)):
    print(" 選択肢{} : {}".format(n+1,options_ja[n]))
  print()

(出力結果)

問題1 : Cristiano Ronaldoのニックネームは何ですか?
 選択肢1 : リオネル・メッシ
 選択肢2 : クリスティアーノ・ロナウド
 選択肢3 : ウェイン・ルーニー
 選択肢4 : ロナウド

問題2 : クリスティアーノ・ロナウドの所属するサッカーチームは?
 選択肢1 : アストンヴィラ
 選択肢2 : リバプール
 選択肢3 : マンチェスター・シティ
 選択肢4 : マンチェスター・ユナイテッド

結果例①

それでは、色々な入力テキストで結果がどうなるのかを確認します。

(入力テキスト)
最も稼ぐサッカー選手、イニエスタがトップ10入り 上位は変わらず

フォーブスが発表した最新の「世界で最も稼ぐサッカー選手」ランキングで、
今回もトップを堅持したのは、前回のリストから順位を入れ替えた1位のクリ
スティアーノ・ロナウドと、2位のリオネル・メッシだった。

(出力結果)

問題1 : クリスティアーノ・ロナウドを最も稼いだサッカー選手に選んだのは?
 選択肢1 : フォーブス
 選択肢2 : Business Insider
 選択肢3 : Wsj
 選択肢4 : Nyt

問題2 : 世界で最も稼いでいるサッカー選手は誰ですか?
 選択肢1 : ロナウド
 選択肢2 : クリスティアーノ・ロナウド
 選択肢3 : リオネル・メッシ
 選択肢4 : ウェイン・ルーニー

問題3 : No.1のサッカー選手は誰?
 選択肢1 : リオネル・メッシ
 選択肢2 : ティエリー・アンリ
 選択肢3 : ウェイン・ルーニー
 選択肢4 : Cristiano Ronaldo

問題4 : トップの座は何ですか?
 選択肢1 : スポット
 選択肢2 : で
 選択肢3 : 次のページ

(個人的な感想)
サッカーに関する文章を入力テキストにしてみました。

問題1,問題2は上手く多選択肢問題が生成されています。

問題3は微妙ですね。
質問文自体は自然なのですが、曖昧な質問すぎて答えを選ぶのが難しいです。
ちなみに答えは選択肢1の「リオネル・メッシ」です。
入力テキストのどの部分からこのような判断になったのでしょうか?

問題4は失敗です。意味の通らない質問文となってしまいました。

結果例②

(入力テキスト)
【引用元】少ないデータでAIが作れる技術「スパースモデリング」とは?

スパースモデリングは膨大な量のデータから学習するディープラーニングとは反対に、
わずかなデータ量からでもAIを構築可能であり、AIが結論を導く過程が人間にも理解
しやすく、AIのブラックボックス化問題の回避も可能だという。

(出力結果)

問題1 : 少量のデータからAIを構築するにはどうすればいいのか?
 選択肢1 : モデリング
 選択肢2 : デザインについて
 選択肢3 : 3Dプログラム
 選択肢4 : モデル

問題2 : AIが結論を出すまでの過程を誰が理解できるのか?
 選択肢1 : 生き物
 選択肢2 : その他の種
 選択肢3 : 人間

(個人的な感想)
専門的な内容が含まれている文章を入力テキストにしてみました。

問題1の正解は選択肢1の「モデリング」です。
しかしもっと正確に言うと「スパースモデリング」という表現になってほしかったですね。

問題2は比較的自然な問題になっていると思います。

結果例③

(入力テキスト)
【引用元】みんなが知ってる日本の有名な話

むかしむかし、あるところに、おじいさんとおばあさんが住んでいました。おじいさんは山へしばかりに、
おばあさんは川へせんたくに行きました。

(出力結果)

問題1 : 川に行って洗ったのは誰?
 選択肢1 : ママ
 選択肢2 : おばあちゃん
 選択肢3 : 祖母
 選択肢4 : 大叔母

問題2 : おじいさんはどこに行って調達してきたの?
 選択肢1 : 湖
 選択肢2 : 砂丘
 選択肢3 : 山
 選択肢4 : キャニオン

問題3 : おばあさんはどこで服を洗ったの?
 選択肢1 : 川
 選択肢2 : 湖
 選択肢3 : ショアライン
 選択肢4 : クリーク

(個人的な感想)
童話「桃太郎」の冒頭部分を入力テキストにしてみました。
分かりやすい文ですので、良い問題文が出来そうだと予想しました。

結果、どの問題も自然で良い多選択肢問題が生成されています!

問題1の答えは選択肢2の「おばあちゃん」ですね。
選択肢3の「祖母」も正解だとは思うのですが、、これは表現の問題ですね。

問題2の答えは選択肢3の「山」です。
「調達」という表現が微妙ですが、意味は分かります。

問題3の答えは選択肢1の「川」ですね。
選択肢3の「ショアライン」は海岸線、選択肢4「クリーク」は小川という意味です。
微妙に似ている単語が選択肢となっているのもすごいですね。

③FAQ Questions:質問・回答ペアの生成

実行コード

例として以下のテキストを入力します。

ja_text = お笑いコンビ「ダウンタウン」のボケ担当は松本人志、ツッコミ担当は浜田雅功である。

実行コードは以下です。
コードを実行するとoutputに処理結果が格納されます。

qg = main.QGen()
en_text = deepL_trans_to_en(ja_text)
payload = {
            "input_text": en_text
        }
output = qg.predict_shortq(payload)

outputの中身を確認してみましょう。
"answer"に答え、"Question"に質問が格納されていることが分かります。
このようにして、FAQペアの生成が行われます。
今回の入力テキストでは1つのFAQペアしか生成されませんでしたが、入力テキストよっては複数のFAQペアが生成されます。

{'questions': [{'Answer': 'comedy duo',
                'Question': 'What is Downtown?',
                'context': 'The comedy duo "Downtown" has Hitoshi Matsumoto in '
                           'charge of comedy and Masatoshi Hamada in charge of '
                           'comedy.',
                'id': 1}],
 'statement': 'The comedy duo "Downtown" has Hitoshi Matsumoto in charge of '
              'comedy and Masatoshi Hamada in charge of comedy.'}

次は、outputの中身を一部取得、日本語に変換、そして見やすく出力してみます。

(コード)

for i in range(len(output["questions"])):
  question_ja = deepL_trans_to_ja(output["questions"][i]["Question"])
  answer_ja = deepL_trans_to_ja(output["questions"][i]["Answer"])
  print(" 質問{} : {}".format(i+1, question_ja))
  print(" 答え{} : {}".format(i+1, answer_ja))
  print()

(出力結果)

 質問1 : ダウンタウンとは?
 答え1 : お笑いコンビ

結果例①

それでは、色々な入力テキストで結果がどうなるのかを確認します。

(入力テキスト)
【引用元】昔話童謡童話の王国

昔、昔あるところにまずしいおじいさんとおばあさんが住んでいました。
ある寒い雪の日、おじいさんは町へたきぎを売りに出かけた帰り、雪の中に何かが動いて
いるのを見つけました。「あれは何だろう。」 おじいさんはわなにかかっている一羽の鶴
をみつけました。動けば動くほどわなは鶴を締めつけているので、おじいさんはとてもかわ
いそうに思いました。 「おやおや、かわいそうに、さあさあ、はなしてあげる。これから、
気をつけるんだよ。」 そうして鶴を助けてやると、鶴は山の方に飛んでいきました。

(出力結果)

質問1 : 老人は町で何を売っていたのか?
答え1 : 薪

質問2 : 罠にかかったとは?
答え2 : クレーン

質問3 : 老人が見た雪の中の動きはどんなものだったのか。
答え3 : スノー

質問4 : 老人はどこに薪を売りに行ったのか?
答え4 : 町

(個人的な感想)
先ほど、童話「桃太郎」の文章を入力テキストにしてみると自然な問題文が生成できたので、今回は童話「鶴の恩返し」で試してみました。

質問1と質問4はほぼ同じ内容の質問ですが、自然な質問文かと思います。
「おじいさん」が「老人」となっているのは翻訳の関係上、許容範囲かと思います。

質問2は文章が不自然ですが、何を質問したいのかは分かります。
こちらも翻訳の関係上、「鶴」ではなく「クレーン」という表現になりました。

質問3はちょっと意味が分かりませんね。
入力テキストの「雪の中に何かが動いているのを見つけました。」の部分を質問したのかと思いますが、不自然な質問文と答えのペアになりました。

結果例②

(入力テキスト)

本田圭佑(ほんだ けいすけ、1986年(昭和61年)6月13日 - )は、日本のプロサッカー選手。
リトアニア・Aリーガ・スードゥヴァ所属。ポジションはミッドフィールダー。元日本代表。
サッカー指導者、サッカークラブ経営者、実業家。カンボジア代表のGM・監督を務める。

(出力結果)
【引用元】Wikipedia 本田圭佑

質問1 : 本田圭佑選手の職業は?
答え1 : サッカー選手

質問2 : プレイヤーの立場は?
答え2 : ミッドフィルダー

質問3 : 日本の代表チームとは?
答え3 : 日本

(個人的な感想)
本田圭佑選手のWikipedia記事の文章で試してみました。

質問1は自然なFAQペアとなっています。

質問2も自然なFAQペアですね。
ただ、少し日本語に違和感があります。
outputの中身を確認して原文を確認したところ、原文は「What is the position of the player?」でした。
「position」が「立場」と翻訳されたため、このような日本語になってしまいました。

質問3は意味がよくわかりませんね。

結果例③

(入力テキスト)
【引用元】AI・人工知能とは

「AI(人工知能)」という言葉が誕生したのは1956年にさかのぼります。当時、ダートマス大学
の数学の教授であったジョン・マッカーシーが「人間のように考える機械」を「Artificial Inte
lligence(人工知能)」と名付けました。  最初のブーム(第1次AIブーム)は、1950年代後半〜
1960年代に勃興。この時代は*「推論」や**「探索」と呼ばれる技術により、パズルや簡単なゲー
ムなど、明確なルールが存在する問題に対して高い性能を発揮し、AIに大きな期待がかけられま
した。しかし、現実の複雑な問題は解けないという性能的な限界が見えると、ブームは下火とな
ります。  このときAIが解くことのできた実用的でない問題は、「おもちゃの問題(トイ・プロ
ブレム)」と呼ばれました。

(出力結果)

質問1 : 人間のように考える機械のことを何と言っていたか。
答え1 : 人工知能

質問2 : 第一次AIブームはいつ起こったのか?
答え2 : 1960s

質問3 : 第一次AIブームとは?
答え3 : ブーム

質問4 : ジョン・マッカーシーの職業は何でしたか?
答え4 : 数学

(個人的な感想)
「AI」をテーマにした解説記事の文章で試してみました。

質問1は自然かつ正確な問題文となっていますね。

質問2もOKです。

質問3は答えが微妙です。
第一次AIブームの概要が答えになっていれば良かったです。

質問4は惜しいですね。
答えが「数学の教授」となっていれば、完璧でした。

④Paraphrasing Questions:言い換え文の生成

実行コード

例として以下の文章を入力テキストとします。

ja_text = 本田圭佑の職業は?

実行コードは以下です。
実行後、処理結果がoutputに格納されます。

qg = main.QGen()
en_text = deepL_trans_to_en(ja_text)
payload2 = {
    "input_text" : en_text,
    "max_questions": 3
}
output = qg.paraphrase(payload2)
pprint (output)

それでは、outputの中身を確認してみます。
今回は"max_questions"を「3」に設定したので、3つの言い換え文が生成されます。
※翻訳は今回はしません。翻訳してしまうと、言い換え文の小さなニュアンスの違いが掻き消される可能性があるためです。

{'Count': 3,
 'Paraphrased Questions': ["ParaphrasedTarget: What is Keisuke Honda's "
                           'occupation?',
                           "ParaphrasedTarget: What is Keisuke Honda's job?",
                           "ParaphrasedTarget: What is Keisuke Honda's "
                           'profession?'],
 'Question': "What is Keisuke Honda's occupation?"}

⑤question Answering (Simple):質問回答

「入力テキスト」と「質問」という2つの入力が必要になります。
このタスクでは、「質問」に対しての答えを「入力テキスト」から探してくれます。

実行コード

今回は例として以下の入力テキストと質問を用意しました。

(入力テキスト)

ja_text = "昨日、太郎はサッカーの本を読みました。今日は友達とサッカーの練習をします。
明日は雨なので、体育館でフットサルをする予定です。"

(質問)

ja_question = "太郎は昨日何をしましたか?"

実行コードは以下です。
処理結果がoutputに格納されます。

answer = main.AnswerPredictor()

en_text = deepL_trans_to_en(ja_text)
en_question = deepL_trans_to_en(ja_question)

payload3 = {
    "input_text" : en_text,
    "input_question" : en_question

}
output = answer.predict_answer(payload3)

outputを確認してみます。
正確に答えを返していることが確認できます。

'He read a book about soccer.'

## 翻訳結果 
'彼はサッカーに関する本を読みました。'

違う質問をいくつかしてみましょう。

(質問)

今日は何をしますか?

(答え)
正確な答えが返ってきました。

'Today he is going to practice soccer with his friends. tomorrow it will '
 'rain, so we are going to play futsal at the gym.'

## 翻訳結果
'今日は友達とサッカーの練習をします。明日は雨が降るので、体育館でフットサルをする予定です。'

(質問)

明日の天気は?

(答え)
こちらも正確な答えが返ってきました。

'Tomorrow it will rain.'

## 翻訳結果
'明日は雨です。'

結果例①

それでは、色々な入力テキスト、質問を用意して試してみます。
また、今回は1つの入力テキストに対していくつかの質問を用意します。

(入力テキスト)
【引用元】【RISE】那須川弟・龍心、スピードパンチの連打魅せ大舞台でも勝利

龍心は那須川天心の弟で、現在中学3年生。天心同様幼少の頃から空手を始め、数々のアマチュア大会で結果を残している。
対する山﨑は、関西のアマチュア大会『TOP☆RUN』の2階級王者。  試合は12オンスグローブで、ヒザとスネあてを着用、
ヘッドギアは無し。顔面へのヒザ蹴りは禁止で、ワンキャッチワンアタックルールとなる。

(質問)

-質問1-
龍心の現在の学年は?

-質問2-
龍心の兄は誰?

-質問3-
試合のルールは?

(出力結果)

-答え1-
現在、中学3年生のRyushin。

-答え2-
那須川天心

-答え3-
ゲームのルールは、12オンスのグローブ、ニーパッドとシンパッドを着用し、ヘッドギアは着用しない。

(個人的な感想)
どの質問に対してもしっかりと答えを返してくれました。
龍心選手の兄が那須川天心であることも正確に把握できています。
質問3は、かなりざっくりとした質問にしてみましたがルールの詳細を正確に返してくれました。

質問に対しての答えを入力テキストからこんなにも正確に抽出できるとは思っていなかったので驚きです。

結果例②

(入力テキスト)

むかし、むかし、あるところに浦島太郎という心やさしい漁師が住んでいました。 ある日のこと、
浜辺を歩いていると一匹の亀が子供達にいじめられているのを見ました。 「これこれ、かめをいじ
めたらかわいそうだよ。はなしておやり」 そう言って浦島太郎は子供たちから亀を助けてやりまし
た。 数日すぎたある日、浦島太郎がいつものようにつりをしていると亀が海から出てきて、 「浦島
太郎さん、僕はこの間あなたから助けられた亀です。お姫様があなたを竜宮城におつれしなさいとい
うのでお迎えにまいりました。」 「竜宮城へつれていってくれるのかい。それなら、少し行ってみ
ようか。」 浦島太郎はさっそく亀のこうらに乗ると海の中に入っていきました。

(質問)

-質問1-
浦島太郎って誰?

-質問2-
浦島太郎は何をしたの?

-質問3-
浦島太郎はどこへ行った?

(出力結果)

-答え1-
浦島太郎は、浦島太郎という心優しい漁師です。

-答え2-
浦島太郎は、子供たちから亀を救い出した。

-答え3-
海の中

(個人的な感想)
こちらも入力テキストに基づいた正確な答えが返ってきました。
浦島太郎が何者で、何をして、どこへ行ったのかを入力テキストからしっかりと判断できていますね。

結果例③

(入力テキスト)
【引用元】Wikipedia ピカチュウ

ピカチュウは齧歯類をモチーフとしたポケモン。分類は「ねずみポケモン」とされるが[1]、
ネズミよりもむしろ、リスのような、頬袋のある動物をイメージしている[2]。  ポケモン
図鑑に記録されている標準的な体長は0.4m、体重は6.0kgである[3]。体毛は黄色・背に茶色
の縞模様があり、耳の先端が黒い。また、尻尾は稲妻のようなギザギザの形をしており、付
け根は茶色くなっている。メスは尻尾の先端が二股に分かれている(ハートマークに似た形
状)[4]。ただし外見上の性差は『ダイヤモンド・パール』で初めて表現されたので、それ
以前の作品では見られない。頬には赤斑点に見える「でんきぶくろ」と呼ばれる、電気を生
成するための器官が備わっている。  戦う時は体当たりをしたり、尻尾を叩きつけたりする
他、この「でんきぶくろ」で作られた電気を放出して相手にぶつける「10まんボルト」や「
かみなり」で相手を攻撃する。尻尾を掴まれることを嫌い、無闇に引っ張る者には噛み付く
こともあるという。硬い木の実でも、電撃で焼いて柔らかくしてから食べるという知恵も持
っている。電気ねずみと呼ばれると機嫌を損ねることもある。また、何匹か集団でいるとそ
こに猛烈な電気がたまり、稲妻が落ちることもあるらしい。

(質問)

-質問1-
ピカチュウの体重は?

-質問2-
ピカチュウの戦い方は?

-質問3-
ピカチュウの見た目は?

(出力結果)

-答え1-
6.0kg

-答え2-
戦うときは、相手の体を叩いたり、尻尾を叩いたりするほか、この「電気袋」で発生した電気を放出
して相手を叩く「10人ボルト」や「カミナリ」でも攻撃します。

-答え3-
赤い斑点で、発電にも使われています。

(個人的な感想)
質問1、2に対しては正確な答えが返ってきました。
まるでピカチュウを知っているかのようですね。

質問3に対しての答えはピカチュウのほっぺのことを言っているのだと思います。
見た目については正しい答えは返ってきませんでした。

⑥question Answering (Boolean):質問回答(真偽)

これは先ほどの質問回答と一緒の仕組みです。
このタスクは、質問が「はい」か「いいえ」で答えられるものであった場合の処理です。

実行コード

今回は例として以下の入力テキスト、質問を用意しました。

(入力テキスト)

メッシはサッカー選手である。

(質問)

メッシはサッカー選手?

実行コードは以下です。
⑤で記載したコードと変わりはありません。

answer = main.AnswerPredictor()

en_text = deepL_trans_to_en(ja_text)
en_question = deepL_trans_to_en(ja_question)

payload4 = {
    "input_text" : en_text,
    "input_question" : en_question
}
output = answer.predict_answer(payload4)

outputの中身、そして翻訳結果です。
⑤の場合とは答え方が違っていることが確認できます。

Yes, messi is a footballer.
そう、メッシはサッカー選手なのだ。

5.全体と通しての振り返り

ここまでで、「Questgen」の6つのタスクを試してみました。
全て完璧とまではいきませんでしたが、ある程度の精度でテキストに基づいた質問の生成が出来るということは確認できました。

「Questgen」はT5、BERT、GPT-2、GPT-3などの最先端の変換モデルを活用して、先進的な質問生成AIを構築することを目指しているとのことなので、今後も生成できる質問の種類、精度が高まっていきそうです。
個人で大規模なモデルを作ることは難しいので、こうやってオープンソースライブラリとして簡単に利用させてもらえるのは嬉しいですね。

現段階では、私はこの「Questgen」の質問生成手法の理解には至っていないので、どういった手法で、どのようなモデルで質問生成をしているのかをこれから勉強していきたいと思います。

そして、いつか高精度な質問生成、作問ができるサービス、アプリを自分でも構築できたらと考えています。

ここまで読んでいただき、ありがとうございました!

31
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
22