疑念は探究の動機であり、探究の唯一の目的は信念の確定である。

数学・論理学・哲学・語学のことを書きたいと思います。どんなことでも何かコメントいただけるとうれしいです。特に、勉学のことで間違いなどあったらご指摘いただけると幸いです。 よろしくお願いします。くりぃむのラジオを聴くこととパワポケ2と日向坂46が人生の唯一の楽しみです。

ChatGPT-4にウィノグラードスキーマ問題を試してみた

概要

コンピュータが自然言語の意味を理解しているのかをテストするウィノグラードスキーマ問題というのがある。2019年時点では250問のウィノグラードスキーマ問題に対して、その正解率は最大で約61%だった。

今回ChatGPT-4で試したら91.5%(正解数 250問/総数 273問)であった。今回は英語版でおこなったが日本語ではどのような結果が出るのか気になった。いずれにせよAIの進歩は凄まじいと思った。




プログラム

フォルダ構成

.
├── winograd_schema_challenge.csv
└── winogradschemachallenge
    ├── .env
    └── test_winograd_schema.py


ソースコード

  • .env
OPENAI_API_KEY='sk-XXXXXXXXXXXXXXXXX'


  • test_winograd_schema.py
from datasets import load_dataset
import openai
import os
import csv
import time
from dotenv import load_dotenv

def construct_query_from_schema(data):
    present_tense = 'do' if data['pronoun'] == 'they' else 'does'
    statement = data['text']
    pronoun = data['pronoun']
    options = data['options']
    query = f"S: {statement}\nQ: In the previous statement, {present_tense} '{pronoun}' refer to {options[0]} or {options[1]}?\nA: "
    return query

def convert_first_letter_to_lowercase(answer):
    return answer[0].lower() + answer[1:]

def create_csv(data, filename):
    with open(filename, 'w', newline='') as file:
        writer = csv.writer(file)
        writer.writerows(data)

def get_openai_answer(query_prompt):
    init_prompt_starter = "The following are pairs of Winograd Schema in the form of a statement S, a question Q and an answer A:"
    init_prompt1 = "S: The cat went through the door, but it's tail got stuck.\nQ: In the previous statement, does 'it' refer to The cat or The door?\nA: The cat"
    init_prompt2 = "S: The cat tried to go through the door, but it was too small.\nQ: In the previous statement, does 'it' refer to The cat or The door?\nA: The door."
    init_prompt3 = "S: Fedex made more profit than UPS last year, but that was mostly due to the success of the new delivery system they implemented.\nQ: In the previous statement, do 'they' refer to Fedex or UPS?\nA: Fedex."
    init_prompt4 = "S: Sam tried to buy Xerxes lunch, but he wouldn't allow it.\nQ: In the previous statement, does 'he' refer to Sam or Xerxes?\nA: Xerxes."  
    prompt = f'{init_prompt_starter}\n{init_prompt1}\n{init_prompt2}\n{init_prompt3}\n{init_prompt4}'

    response = openai.ChatCompletion.create(
        # model='gpt-3.5-turbo',
        model='gpt-4',
        messages=[
            {"role": "system", "content": prompt},
            {"role": "user", "content": query_prompt},
        ],
        temperature=0,
        max_tokens=200,
        top_p=1,
        frequency_penalty=0.0,
        presence_penalty=0.0
    )
    return response.choices[0]["message"]["content"].strip().replace('.', '')


print('----- start winograd schema challenge -----')
load_dotenv()
filename = 'winograd_schema_challenge.csv'
openai.api_key = os.getenv('OPENAI_API_KEY')
wsc273_dataset = load_dataset('winograd_wsc', name='wsc273',  split='test')

data_csv = [
    ['Statement', 'Question', 'Answer', 'AI Answer', 'Correct']
]
number_of_correct = 0
number_of_questions = len(wsc273_dataset)
for index, data in enumerate(wsc273_dataset):
    print(f'Question {index + 1}')
    correct = False
    query = construct_query_from_schema(data)
    query_split = query.split('\n')
    statement = query_split[0][3:]
    question = query_split[1][3:]
    answer = data['options'][data['label']]
    query_prompt = construct_query_from_schema(data)
    openai_answer = get_openai_answer(query_prompt)
    print(f'ai answer: {openai_answer}, answer: {answer}')

    if convert_first_letter_to_lowercase(openai_answer) == convert_first_letter_to_lowercase(answer):
        print('----- \U00002705 CORRECT! \U0001F44D -----')
        number_of_correct += 1
        correct = True
    else:
        print('----- \U0000274C INCORRECT! \U0001F44E -----')
    
    data_csv.append(
        [
            statement, question, answer, openai_answer, correct
        ]
    )
    time.sleep(3)

create_csv(data_csv, filename)
print(f'Accuracy rate = {int(number_of_correct/number_of_questions * 1000)/10}%({number_of_correct}/{number_of_questions})')



実行結果

  • コンソール


  • winograd_schema_challenge.csv
Statement,Question,Answer,AI Answer,Correct
The city councilmen refused the demonstrators a permit because they feared violence.,"In the previous statement, do 'they' refer to The city councilmen or The demonstrators?",The city councilmen,The city councilmen,True

...
Carol believed that Rebecca regretted that she had stolen the watch.,"In the previous statement, does 'she' refer to Carol or Rebecca?",Rebecca,Rebecca,True

はじめに

最近『教養としてのAI講義』という本を読みました。

著者のメラニー・ミッチェルは昔『複雑系の世界』という本を読んで(途中で挫折して、一部を破いて保存して)いましたので、名前は知っていました。その本には最初自分の経歴を話していて、「ダグラス・ホフスタッターの『ゲーデルエッシャー・バッハ』(GEB)に決定的な影響を受けて研究者になった」ということが書かれていました。『教養としてのAI講義』でもホフスタッターの話から始まります。

この本は題名通りAIについて広く議論されています。AIの歴史やAIによる倫理的な問題だけでなく、AI仕組み(ディープラーニング強化学習)も議論しているところもあります。

この本はとてもいい本ですが、原著は2019年出版であり少し古く、GPT(Generative Pretrained Transformer)のことは書かれていません。

この本の第4部には自然言語処理についてのことが書かれていました。

チューリングテストとその欠点

「機械は思考できるのか?」という問いにたいして、チューリングは現在「チューリングテスト」と呼ばれるものを提案しました。これは次のようなイミテーションゲーム(模倣ゲーム)です。コンピュータと人間の「2名」が参加して、もう1人の人間の審査員が、どちらが人間でどちらがコンピュータかを当てるために、それぞれに別々に質問します。審査員は2名の参加者から離れたところでキーボードの文章でやりとりします。

もしこのゲームをうまくこなせるコンピュータができたら、つまり審査員がどちらが人間でどちらがコンピュータかが区別できなければ、それは「コンピュータは真に思考している」と考えてもいいのではないか?ということです。


しかしチューリングテストには問題があります。比較的簡単なプログラムで人を簡単に騙すことができるからです。さらにもしもコミュニケーションしている言語がおかしかったとしても「僕はウクライナティーネイジャー。英語はかなり上手だけど完璧じゃないよ」と設定すれば、審査員は言葉の不自然さを疑問に思わなくなります(実際に2014年にチューリングテストに合格したプログラムはそのような設定がされていました)。

機械は言葉の意味がわからなくても人と自然に会話ができます。そこで機械が文章の意味を「理解」しているかどうかを判定するテストが考案されました。それがウィノグラード・スキーマ(winograd schema)です。

ウィノグラードスキーマ

ウィノグラードスキーマとはある簡単な文章に対して、「それ」が何を表しているかを問う問題です。ただし一つの単語が変わるだけで「それ」を表すものが全く変わるような問題となっているところがポイントです。次の文章はウィノグラードスキーマの例です。

  • The city councilmen refused the demonstrators a permit because they feared violence. (市議会員はデモ隊に許可を与えなかった。なぜなら、彼らは暴動を恐れたから。)

  • 「彼ら」は、”councilmen”を表していますか? それとも”demonstrators”を表していますか?

  • councilmen


  • The city councilmen refused the demonstrators a permit because they advocated violence. (市議会議員はデモ隊に許可を与えなかった。なぜなら、彼らは暴動を支持したから。)
  • 「彼ら」は、”councilmen”を表していますか? それとも”demonstrators”を表していますか?

  • demonstrators


チューリングテストはコンピュータが文章を全く理解していなくても正解を出せることができますが、ウィノグラードスキーマを考案した研究者によると、ウィノグラードスキーマテストではそのような可能性を未然に防いでいるとのことです。

この本によると、出版当時つまり2019年時点でウィノグラードスキーマ問題に対して最もよい正解率は61パーセントだったとのことです。

いくつかの自然言語処理研究グループは、
ウィノグラードスキーマの問題を解くためにさまざまな方法で実験を行っている。
これを書いている時点で最も高い成績を収めたプログラムの場合、
250題のウィノグラードスキーマ問題で約61パーセントの正解率だ。

ch.13 何でも聞いて section 「それ」は何を意味するのか?


これを読んだとき、「それではChatGPT4ではウィノグラードスキーマ問題の正解率はどうなのだろう?」と思いました。そこでプログラムを作成しました。

プログラム

プログラムの詳細は今回は省略します。上記のように書けば問題なく動くと思います。ただしChatGPT4を利用するためにはAPIキーを取得して、GPT4が使えるように申請しなければなりません。そして実際に利用するときはいくらかお金を支払わなければなりません。そこが少し障害となります。

結果

プログラムを作成して実際に試してみたら、91.5%(正解数 250問/総数 273問)でした。GPT3.5でも試して比較しようと思いましたが、エラーが生じてしまいうまくいきませんでした(このエラーは通信が集中しているから無理というものでした)。ただこの記事によると正解率はGPT-3では68.8%であり、GPT-4では94.4%だったそうです。

おわりに

今回は簡単に実装したかったので、すでに存在している英語のウィノグラードスキーマのデータセットを利用しました。日本語のウィノグラードスキーマ問題もウェブ上にはありましたが、データセットとしては見つかりませんでした。日本語バージョンのテストを実装するためにはデータセットの作成からおこなわなければなりませんでしたので、日本語での正解率は気になりますが、今回はスキップしました。もし時間があれば日本語のバージョンも試したいと思いました。


正解率が61%から数年で90%以上に向上したのは凄いなと思いました。

実はこの本にはロング・ベッツという賭けを紹介しています。その一番最初の賭けが「2029年までにチューリングテストを合格するコンピュータは存在しない」というものでした(a long bet bet 1)。予測者はモジラ・ファンデーションの初代理事長であるミッチェル・ケイパー(Mitchell Kapor)で、反対者はシンギュラリティの提唱で有名なレイ・カーツワイル(Ray Kurzweil)です。ここでのチューリングテストは不正や騙しがおこなわないためにかなり厳しい条件が課せられています。その条件下でケイパーは「2029年までには無理だ」と主張して、対してカーツワイルは「できる」と主張しています。著者のミッチェルはケイパー側です。

第3章で取り上げた、「綿密に練られたチューリングテストに合格するプログラムは実現しない」という
レイ・カーツワイルとミッチェル・ケイパーとの「長期間の賭け」は、2029年に結果が出る。
私はケイパーに賭ける。なぜなら「はじめに」で紹介した、
「人間の知性はすばらしいが、謎に包まれた奥深いものであり、
その大半が解明されていない。
そのためまったく同じものがつくられる恐れは当分ない」というケイパーの言葉に、
全面的に同意しているからだ。

ch.16 質問、答え、それについての考察
section 質問ー汎用的な人間レベルのAIの現実まで、あとどれくらいかかるのだろうか?


しかしこの賭けは2029年を待たず、現在(2023年)チューリングテストをおこなってもカーツワイルが勝つのではないかと思ってしまいます。勝手な想像ですが、綿密に練られたチューリングテストを合格する機械の存在は、2029年でようやくできるかできないかのギリギリの期間なのではないかと、賭けがおこなわれた当時(2002年)では想定されていたのではないかと思います。それがもはや6年も前にテストしてもほぼ確実に合格できるレベルなのですから、AIの進歩は想像以上なのだろうと思いました。

参考文献




僕から以上