数弱プログラマのいろいろ

数学が苦手なのにプログラムを書いている高専生のいろいろ

人工無能/知能について

はじめに

こんにちは、やっと2記事目です。日記とかブログはあまり続かないタイプです。
2記事目にしてめっちゃ長いです。本体は3つ目の章ですので適当に読み飛ばしながらどうぞ。

さて、タイトルにもある通り今回の記事は人工無能/知能について僕の考えたことをまとめていきます。

書きながら整理しているつもりですが分かりにくいかもしれません。
おそらく文字ばかりの記事になります、ごめんなさい。
所詮、学生が自分の考えた事を字に起こしているだけですので期待せずお読みください。

今回の記事のテーマについて

この章では、今回この記事を書くに至った理由などを述べます。
かなり長い記事になりそうなので読み飛ばしても大丈夫です。

このブログの説明にもある通り、にわかですがプログラムを書いています。

僕には二進数でプログラムを書くスキルはないのでもちろんプログラミング言語を用いてプログラムを書いています。

世に存在するプログラミング言語はいろいろな種類があります。
数ある中でどれかを選んで学ぶわけですが、どう学んでいいかわかりません。
目的がないんです。目指すものがあって、その過程で学ぶわけですから。
もちろん目的がなくても学べるかもしれませんが、効率が悪いというか成果が見えないというか。
とにかく、目的を考えていました。
そこで僕が思いついたのは、「AIを作る」というものです。
ここで言う AI というものは、ユーザのキーボード入力に応じてパターンマッチングで何かを出力するというものです。

思いついた当初の僕はそこまでスキルがありませんでしたが、わからない事を調べる癖はついていたので実装したい内容を調べて書いていました。
当初の僕の事はどうでもいいとして、以下に「AIを作る」ことで学べるものを挙げます。

  • 標準入出力
  • 条件文
  • ループ文
  • 配列、リスト
  • 関数、メソッド定義

ぐらいでしょうか。かなり思いつきで適当に挙げました。
これだけか、と言われればそれまでですが基本は掴めると思います。それも1つのプログラム内に詰まっていますからね。
それに、あとからソースコードを見返してみると自分の成長がわかりやすいです。
機能追加や、オブジェクト化など自分の現状できる事をAIに追加していく事で自分のコーディング力がわかると思います。

さて、まだ前置きの途中です。どうなってるんですかねこの記事。

先ほど述べたように、新しい言語を学ぶときはAIを作るのが効果的というのが持論なので、友達が新しい言語に挑戦するときは先ほどの内容を熱弁してAIを作るよう勧めます。
こういう言い方をすると、自分ってかなり厄介な人間だなと思います。まぁそこはいいとして。

ここ最近友達が新しい言語に挑戦し、僕の持論通りAIを作っています。じゃあその友達はM君としましょう。
まぁせっかくAIを作るわけだし、コードネームをつけようと二人で考えました。
Gmi(Growth man-made incompetence)、と名付けました。読みはグミです。本人曰く女の子です。

ちなみに、今回の記事における僕の立場はペアプログラミングの片一方....というわけでもないんです。
そりゃもちろん手伝いますし話し合いもしますが、一応僕も書いています。一応...。ですが、この記事ではお手伝い君っぽい視点から書きます。プログラムの話からは途中で逸れますが。

この記事では特に言語について詳しく触れるつもりはありませんが、C#で書いています。競プロに必要ですからね。

コードネームにある通り、Growth...成長ということで一応学習機能をつけたいみたいです。
今のところの大雑把な予定としては

  • ユーザ入力、ネットからの取得
  • 形態素分析による情報の抽出
  • 抽出した情報の蓄積
  • 蓄積したデータを相互に結びつけ、出力内容の精度を上げるネットワーク
  • ネットワークを通してテーマに沿った文の生成、出力

を考えています。何年かかるんだって感じです。
しかも開発規模はほぼ単独に近いので完成するかさえ危うい感じはします。
まぁ、先の事を考えて絶望してたら学ぶものも学べませんのでとりあえず書こうとするわけです。

コーディングにあたってプログラムの構成を考えているときでした。規模の大きなプログラムになる予定(あくまで予定)なので、土台はしっかり作ろうと考えるわけです。
C#ですから、オブジェクト指向プログラミングをするわけです。まだまだ未熟ですがそれなりに理解はあるつもりです。

以下は考えた事の羅列ですので読まなくて結構です。
Gmiそのものをオブジェクト化、単語オブジェクト、テーマごとの会話オブジェクト、テーマオブジェクト、文節オブジェクト、DBへの保存、各データを管理し適切な情報を返すネットワークオブジェクト、各情報のID・・・・

などなど挙げたらきりがないくらい構成を考えました。
聞いてみるとM君は、個性や人間味を帯びたAIにしたいんだとか。
そこで僕はAI事柄を理解し、おかしな文を出力する事もなく、型にとらわれない柔軟な対応をするにはどうすればいいかを考えました。

やっとここまで来ましたね。以上が前置きです。以下がこの記事を書くに至った理由です。

考えたところ、AIすなわちこの記事のテーマで言うところの人工無能には大きな壁があったのです。
その壁は「意味」でした。

次の章で、ようやくいろいろ掘り下げていきます。要は次が本文です。前置きが長くてごめんなさい。

僕の考え

ようやく本題です。章題にある通り一人間の一意見として読んでくださいね。

さて前章で挙げた通り人工無能には「意味」という壁がありました。これまためちゃくちゃ大きい壁なんですね。
壁といいますか、限界といいますか。簡単に言うと半導体だけではこの壁は越えられません。

結論から言わせてもらうと、真の柔軟な対応半導体のみで駆動する環境における人工無能には不可能です。
あくまで実現できるのは、人間味を帯びているかのように振る舞うことです。

ではこの結論に至った僕の考えを述べます。

あるユーザ入力に対してGmiが返答をするケースを想定しましょう。

User:おなかが空いた
Gmi:チャーハン食べたら?
User:そうする

M君が理想とする会話はこんな感じでした。アドバイザーや万能君とかではなくあくまでGmiは対等な立場、つまり友人のようなものです。
安心してください、M君はとてもユニークなので僕以外にもたくさん友達がいますよ。まぁそれはいいとして。
簡単な質問をしますので考えてみてください。

  • 上のケースにおいて、Gmiが行ったことはなんでしょう?

形態素の解析、テーマの抽出、ネットワークの参照、いろいろ行います。
では質問を変えます。

  • Gmiが意味を理解したことはなんですか?

この問いに対して、テーマが食べ物だと理解している、とか提案を求められていることを理解している、と答える人がいるかもしれません。
では、掘り下げた質問をしてみましょう。

  • おなかとはなんですか?

おなかは・・・食べ物を消化が終わるまで溜めておくところ、と答えることができるしょう。
ではもっと掘り下げましょう。

  • 食べ物とはなんですか?
  • 消化とはなんですか?
  • 溜めておくとはなんですか?
  • ところとはなんですか?

ここまで来たら大体わかりますかね?そう、このような質問にきちんと答えられるのは人間だけなんです。
?「いやいや、プログラムでも答えられるでしょう?」

  • 答えるとはなんですか?

きりがありませんね。あのまま掘り下げると生命の神秘まで教え込む必要があります。
それを世に存在するすべての単語に対して行うと・・・考えたくありませんね。

つまりどんなに人間味を帯びた出力ができても、それはただの文字列のコピペに過ぎません。
機械学習といっても出力できる事柄の幅が広がるだけで、結局根はパターンマッチングと同じです。人間味のかけらもありません。

昔、単語ひとつひとつにboolean型のパラメータをいくつも持たせて、意味として機能させようと考えた人がいるらしいです。
僕もその考えは出てきましたが、結局パラメータを判断するのはif文です。パターンマッチングと大差ありません。
活用するとしても、単語の種類わけができる程度です。

ではどうすれば人間味を帯びた柔軟な対応ができるのか。
まず、人間味について考えてみましょう。

人間味がある

これって何視点ですか?人間ですよね?
こんな質問を投げかけるのも人間だけですからね。
つまり、人間が求める人間味は人間を中心として考えているものです。

コンピュータに人間味を求める、という言い方をすると不可能なように聞こえます。
そうです不可能です。

先ほど人間を中心に考えていると述べました。当たり前ですがコンピュータと人間は違います。
そこを踏まえた上で、人間味を帯びてくれ、言い換えれば人間の立場になって出力しろ、と求めていることのおかしさがわかると思います。

先ほど、「人間の立場になって」と言いました。そうです、人間の立場になればできるんです。
ではここでいう人間の立場になって、とはどういうことかをお話しします。

それは、人間と同じ条件下におくことです。

まだわかりにくいですね。具体的な例で話しましょう。

息をする

この行為の意味は人間の皆さんなら理解しているはずです。
なぜ必要か、どういう仕組みか。

息をしない知的生命体がいたとしたら、コンピュータ同様、その意味を理解することはできません。

つまり、生命活動を前提として動く必要があるんです。脈を打つ心臓があって、血管があって血流があって、酸素を供給する肺もあってなどなど含めすべて備わっていないと動かないロボットを作る必要があります。それも初期は赤ちゃん。人間と同じような成長過程を経て、知識を得るものとします。

そしてようやく発する言葉にこそ、真の人間味や柔軟さがあると思います。

先ほど生命活動を前提としたロボットと述べましたが、おそらく不可能です。
法の適用範囲等微妙ですし、成長となるとハードウェア的な問題が多いです。なので先ほどのロボットはあくまで実現するのであればという話です。

他にも書くことはある気がしますが、さすがに長すぎるのでやめておいてまとめに移りたいと思います。

まとめ

読んでくれた方、お疲れ様でした。長くなって申し訳ないです。
この話題については、多分もう少しだけ書けると思うので気が向いたら書きます。
不可能だとかなんとか言いましたが、人工無能/知能に関する話は大好きです。SF映画とか見ると、とても夢があると思います。

そのうち、自分についての記事も書ければなと思っています。
へぇと思えるような話があるのでそこら辺を書こうかなと。

それでは今回はこの辺にしておきたいと思います。長くなって申し訳ないです。
これ以降はコンパクトに書こうと思っています。気が向いたら読んでくださいね。
それではまた。

AtCoderで解いた問題について

はじめに

本日1/18(月)は、関東を中心に大雪に見舞われ、自分の通う学校は休校になりました。

Twitterを見ると休校に関して嬉しい嬉しくない等様々な反応がありましたがバイトをしているわけでもなく休日登校も特に苦じゃない僕にとっては3連休になっただけという感想です。

休校になるのは前日から予想できていたので夜更かしをして昼頃に起きました。
やることに迷っていたところで友達とAtCoderでプログラム練習をすることに。

この記事は今回学んだことについて書こうと思います。

やったこと

今回挑戦したのは過去問の【AtCoder Regular Contest 046】です。
arc046.contest.atcoder.jp

解いたのはAとBのみですが、数弱からすれば殺しにきているような問題でした。AtCoderにおいてWebでの検索は認められいるので、遠慮なく調べました。
以下が参考にしたサイトです。

AtCoder Regular Contest 046 A,B問題 感想

AtCoder Regular Contest 046 A,B問題 感想
kyuuko.s7.valueserver.jp

A問題

A問題はゾロ目数の問題でした。参考にしたサイトによると群数列を使うんだとか。

群数列ってなんでしょうね?
知らないですがA問題についてこのサイトに記されている解き方の主要部分をJavaで以下に記します。

Scanner usrInput = new Scanner(System.in);
int n = usrInput.nextInt();
int num = (n - 1) % 9 + 1; //繰り返す数字
int loop = (n - 1) / 9 + 1; //繰り返す回数
 
for(int i = 0;i < loop;i++){
	System.out.print(num);
}

ソースコード中のコメントにあるように、数式はそれぞれ

・繰り返す数字

・繰り返す回数

を表しています。

世の数学は謎です。どうしてそうなるのか追い求める気になりません。

根本から理解するのは難しいので、「ゾロ目数といえばこれ」という形で覚えておきます。

B問題

続くB問題は高橋くんと青木くんの石とりゲームです。

最初に石の数amountが与えられ、次にそれぞれが一度に取れる石の数a, bが与えられます。

どちらも最適な数石を取っていき、最後の石を取った方の勝ちというルールでどちらが勝つかを先に判断するプログラムを書くという問題です。

勝負する前に勝敗がわかるプログラムを書くとは、なんて残酷なんでしょう。自分はこういうゲーム苦手です。負けます。

参考にしたサイトによると、これまた法則があるんだとか。

書いてある内容を以下のソースコードに起こしました。

int amount = usrInput.nextInt();
int a = usrInput.nextInt();
int b = usrInput.nextInt();
 
if(a == b){
	if(amount % (a + 1) == 0){
		System.out.println("Aoki");
	}else System.out.println("Takahashi");
}else{
	if(a > amount){
		System.out.println("Takahashi");
	}else if(a != b){
		if(a > b){
			System.out.println("Takahashi");
		}else System.out.println("Aoki");
	}
}

書き方が悪いですね。if文条件はそれぞれひとつずつしか書いていないので読みにくいですがこういうことです。
出力は勝つ方の名前を吐いています。読みにくいという人は参考にしたサイト中に文章と条件で書いてあるのでそちらをご覧ください。

今回やったことは以上です。

さいごに

初記事からいきなりカンニングコーディングでしたが自分としてはかなり勉強になったつもりです。

プログラミングを勉強することにおいて数学は欠かせない知識というかなんというか、
何かを実装する上で浮かぶアルゴリズムの数を増やしてくれる、要はボキャブラリの部分にあたるものだと思うので、
数学に対する苦手等は克服したいと考えています。

ちなみにこのブログはGoogle Adsenseでの小遣い稼ぎみたいなところもあるので、広告についてはご了承ください。
安心してください、誘導等は規約違反なので行いません。
年齢違反だろ?と思った方、自分は兄と起業した会社名義(または兄名義で業務代理)でGoogle Adsenseアカウントを取りますのでご安心ください。

また自分の会社についてや、Google Adsense等に関しても記事が書ければなと思っています。
毎年、全国高専プログラミングコンテストに参加しているのでそれに関しても書こうと思っています。
よろしければまた読んでください。記事の更新が止まったら察してください。
それでは。