<   2015年 05月 ( 5 )   > この月の画像一覧

ラッセルのパラドックスの原因

しつこくラッセルのパラドックス周りをうろついているが、趣味だからご容赦願いたい。以下の記事の内容は今までの記事の繰り返しなのでスキップしても構わないが、ラッセルのパラドックスの原因はこれだと決めつける表現ができたかもしれないと思うので書いてみた。

以前から、「素朴集合論には何かおかしいことがある。だから公理的集合論が必要だ。」という表現にどうしても引っかかっていた。圏論でも「全ての集合からなる圏」というのを考えるが、「すべての集合の集合」はないのだから、「全ての集合からなる圏」にも矛盾が入ってくるのではないかと考えてしまう。しかし、端的に「素朴集合論はここがおかしいのでラッセルのパラドックスが発生してしまう。」と言われるとしっくりくるだろう。

一言で言うと、ラッセルのパラドックスの原因は、ズバリ、「集合とは物の集まりという『物』である。」という集合の定義だ。この定義の問題は、それが再帰的な定義であるということだ。つまり、物があれば、その集まりである集合という物が発生する。そうして、その新しい集合という物ともともとあった物とを集めて、また新しい集合を定義できる。このようにして、再帰的な集合の定義は次々に新しい集合を、無限に生成することができる。ラッセルのパラドックスは、この無限に集合が生成される過程に関して発生するのだ。

犬の集合のような「自分自身を要素として含まない」あきらかに普通の集合を何個か集めてみる。これに集合の定義を適用すると、それらの集合全てを集めた集合を考えることができる。その集合は、それまでの集合には存在しない新しい集合だ。また、その集合の部分集合も全て、最初の集合にはなかった新しい集合だ。おまけに、それらの集合は明らかに自分自身を要素としては含まない集合だ。

こうして、明らかに普通の集合の有限個の集まりに、「集合の定義」を適用することで、「自分自身を要素として含まない集合」の数が膨れ上がる。その膨れ上がった集合の集まりに、さらに「集合の定義」を適用することで、さらに集合の数は増す。無限にこの手続を繰り返せば、「自分自身を要素として含まない集合」の数は無限に増大するだろう。

しかし、この無限の集合を発生させる手順を途中で止めると、そこには、有限個ではあるが全て「自分自身を要素として含まない集合」の集まりが得られる。どの時点でも、集合の定義を用いて生成された集合は確定される。そうであれば、任意のレベルの「集合の定義の」適用でも「自分自身を要素として含まない集合」だけが発生するのであれば、この手続は、「全ての「自分自身を要素として含まない集合」を集めた集合を定義しているということができるのではないだろうか。ところがそううまくはいかないのだ。

この手続で発生する「自分自身を要素として含まない集合」全てを集めることができたとしよう。しかし、その集まりに「集合の定義」を適用した、「自分自身を要素として含まない集合の集合」は、その要素には存在しない新しい「自分自身を要素として含まない集合」になってしまう。つまり、「自分自身を要素として含まない集合」全てを集めたとしても、それに『集合の定義』を適用することによって、それまでの集合とは違う集合を発生させてしまうのだ。それは、自然数に最大数が存在しないという論理と似ている。自然数の再帰的定義は、最大数を元に最大数より更に大きい数を発生させてしまうからだ。

ところで、無限集合を扱うのに有限の立場をとるということはつぎのようなトリックを行っているということだ。すなわち、無限集合の全ての要素を、無限集合の「任意」の要素に置き換え、さらに、再帰的定義によって、無限集合の任意の要素を、有限の論理に帰着させるという綱渡りを行っている。

しかしながら、「自分自身を要素として含まない集合の集合」の場合、再帰的定義が、その集合の要素ではない新しい集合を定義してしまうため、「自分自身を要素として含まない集合全て」の集合は作ることができない。どのような大きな集合の集まりを持ってきても、その集合の集まりに再帰的な「集合の定義」を適用することによって、その集合の集まりには含まれない新しい集合を創りだしてしまうからだ。これを無理に「自分自身を要素として含まない集合の集合」が定義できると仮定するとラッセルのパラドックスになってしまう。

無限集合のすべての要素をその集合の任意の要素に置き換えて再帰的定義を適用するというトリックは、自明な論理のようにみえるが、成功する場合と矛盾を発生してしまう場合とがあることがわかる。
[PR]
by tnomura9 | 2015-05-16 15:10 | 考えるということ | Comments(0)

パターン認識読書法その2

読書にパターン認識を使う方法が面白かったのでもう一つ考えてみた。それは、キーワードの位置を意識して覚えるやり方だ。

どういうやり方かというと、普通に文書を読みながらキーワードに下線を引いていくが、1ページを読んでしまったら、どのキーワードがどの場所にあったかを目を閉じて思い出してみるのだ。内容が理解できていれば、キーワードがどのような位置で関連しているかを見て取ることができるだろうし、内容がよく理解できなかったとしても、どのキーワードがどの位置にあったのかと考えているうちにその文章の構成が見えてきたりする。

文書の内容を図解すると理解しやすくなるが、わざわざ図解しなくても、キーワードの位置に注意を払うだけで図解と似たような効果がある。順序良く読んでいた時には、曖昧だった内容が、キーワードの位置関係に注意を払っているうちに、著者の文章の構成が見えてきたりするからだ。

文章を箇条書きのノートに取ることは普通に行っている。しかし、箇条書きは要点を抜き出しているようであるが、実際は、箇条書きの項目間の差異が見えなくなってしまって、内容が却って見えなくなってしまうことが多い。本文のページでのキーワドの位置を思い出すようにすると、キーワードの位置情報がそのキーワードを他のキーワードから浮き立たせてくれるので、逆にキーワード間の関係性に気づくことが多い。

逆に、図を見るときには、図の要素について言語化してみると良く分かる。図が全体としての模様としてしか見えなかったものが、個々の部分の特徴を言語化して他の部分と際立たせると、その部分品の全体での役割が理解できて、図として観察するときの洞察も深めてくれる。食事の味を言語化して表現することで、その味の特徴が際立ってくるのと同じだ。

文章は図で、図は文章で理解するということだ。理解に関与する感覚の種類を増やすことで、媒体が運んでいる情報をよりよく理解することができる。

どの学校にも伝説の秀才がいるものだ。そういう人の逸話には、わからないことを聞いたら、なんという本の何ページの何行目辺りに書いてあるよと教えられたというようなものが面白がって語られる。天才というものは常人にはできない些細な事まで記憶できるのだという意味で話されることが多いが、ひょっとしたらそういう読み方の方が記憶に残るのかもしれない。天才でなくてもキーワードがどの位置にあるのかというような、一見文章の内容とは関係のないような情報に注意を払うことによって印象を深めることができるからだ。

管理人も教科書をこういう読み方で読んでいたら、もっとマシな人生が送れたのかもしれない。

この記事の表題を『パターン認識読書法その2』にしたのは、上の読み方がやはり、脳のパターン認識能力を活用しているのではないかと考えるからだ。動き回る動物を見て、犬がいるという判断をするときは、その作業は無意識に行われているため気付かないが、脳はパターン認識のために複雑な処理を並列的に一瞬にして行っている。意識的な学習についても、この脳のパターン認識能力の働きを利用できないかと考えたのだ。

学習の戦略としては、一般には、記憶と論理的操作に重点が置かれているが、それに加えて脳のパターン認識の能力を活用する方法というのを開発してはどうだろうか。
[PR]
by tnomura9 | 2015-05-13 07:52 | 考えるということ | Comments(0)

パターン認識読書法

最近ニューロコンピュータの本を読み始めた。ニューロコンピュータとは、一口に言うと、人間のパターン認識能力をコンピュータでシミュレーションさせようという研究だ。

ニューロコンピュータでは、コンピュータのプログラミングは、アルゴリズムのプログラム言語への翻訳ではなく、パターンを学習させるという方法が取られる。

具体的には、たくさんの画像データとその解釈を機械に与えて、手書き文字のようなパターンを判別できるようにしたり、あるいは、多量のビッグデータからそのデータに内在する傾向を読み取らせたりする。このようにニューロコンピュータでは、プログラムの動作を決めるのが、プログラミングではなくて学習であることが特徴だ。

この学習によるパターン認識が、今までの手続き型のプログラミングをはるかに越えるパターン認識力をもたらしてくれることが注目されている。しかし、人間の脳は、すでにそのような高度なパターン認識を獲得する能力を有している。これを読書に活用できないだろうか。

パターン認識の観点から読書法を考えたとき、今までの文章を逐次的に追いかける普通の読書法とは全く異なってくる。

先ず、ページをパラパラと気ままに繰りながら、目についた所、興味のありそうな所をちょっとだけ読んでいく。スキミングと呼ばれる手法で、雑誌やグラビアを読むときに無意識にやっている方法だ。

パターン認識読書法では、このスキミングを行う際に内容をあまり詮索しない。チラチラと読みとった内容が自然にパターンを形づくるまで、ひたすら情報のインプットだけを続けるのだ。したがって、ページを開く順序はランダムでいいし、知らない用語が出てきても特に調べることもしなくて良い。意味の理解はパターンがひとりでに現れるまで待つことになる。

ただし、本に書かれていることの意味が自然に理解できるためには何回も本に目を通す必要がある。普通に読む場合より効率がいい訳ではない。脳の中でパターン認識の結合ができるためには、シナプス結合の効率がそれにあわせて変化する必要がある。ニューロコンピュータのアナロジーが脳でも働いているとすれば、刺激の提示に対して、シナプスの結合性の変化は徐々にしか起こらない。きちんとしたパターンが生成するためには、原則刺激の提示の十分な回数が必要だからだ。

それでは、なぜ、そのような効率の悪い読み方をするのかという話になるが、この方法は、あまり馴染みのない知識の本を読むときに便利なのだ。良く知らない分野の知識は、そもそもフレームワーク自体を持ち合わせていない。しかし、意味不明のまま、スキミングで眺めているうちに、何となくパターンが見えてくる。脳のパターン認識能力のおかげだ。

全てをパターン認識でやりとおすことはかえって効率が悪いだろう。ある時点で通常の読み方に切り替える必要がある。しかし、パターン認識で概要が掴めた後は、普通の読み方をする場合も随分楽に感じる。

脳のパターン認識の力は普段あまり意識することはない。パターン認識の作業が無意識に行われているからだ。しかし、ノイマン型のコンピュータが苦手なことをスイスイこなすスーパーコンピュータを自前で持っているのだから、意識的に活用することも考えて良いのではないだろうか。
[PR]
by tnomura9 | 2015-05-12 10:05 | 考えるということ | Comments(0)

System.Random (17) Random クラス

System.Random 解読シリーズ

Random 型クラスは、乱数ジェネレータを利用して、様々な型のデータを発生させるときのクラスメソッドを提供している。クラスメソッドは Int 型でも Double 型でも同様の動作を行うときに共通の名前を使うことができ、操作の抽象化ができる。クラスメソッドはこのように多相型関数だが、実装は instance 宣言の時にそれぞれの型に応じて行う必要がある。

以下に、System.Random.hs のソースファイルの Random 型クラスの class 宣言のコメントを日本語訳したものを示す。

Random クラスは、乱数ジェネレータを利用して、プログラマに様々なデータ型の乱数を発生する手段を提供する。

最小限実装を定義すべき Random クラスの関数は randomR と random だ。

class Random a where

randomR は乱数の範囲 (lo, hi) と乱数ジェネレータ g を引数に取り、範囲 [lo, hi] の間の均一に分布する乱数および新しい乱数ジェネレータを値として返す。lo > hi の時の動作については特に明示していない。連続なデータ型については、lo と hi の値についての規定はないが、それらは、実装と範囲の値による。

  randomR :: RandomGen g => (a,a) -> g -> (a,g)

random は randomR と同じように乱数を発生するが、乱数のデータ型のデフォールトの範囲を使う。

Bounded タイプ(例えば Char 型のような有界のデータで Bounded クラスのインスタンス)では範囲はそのデータ型の全体になる)

分数型のデータでは、範囲は一般に [0,1) のような半閉区間になる。

整数型のデータでは、範囲は Int 型の範囲だ。

  random  :: RandomGen g => g -> (a, g)

randomR の変種。randomR と同じように指定した範囲の乱数を発生させるが、単一の乱数ではなく、乱数の無限リストを生成する。新しいジェネレータは返さない。

  randomRs :: RandomGen g => (a,a) -> g -> [a]
  randomRs ival g = x : randomRs ival g' where (x,g') = randomR ival g

random の変種。random と同じようにデフォールトの範囲の乱数を発生させるが、単一の乱数ではなく、乱数の無限リストを生成する。新しいジェネレータは返さない。

  randoms  :: RandomGen g => g -> [a]
  randoms  g      = (\(x,g') -> x : randoms g') (random g)

randomR の変種でグローバルの乱数ジェネレータを利用する。"System.Random#globalrng" を参照。

  randomRIO :: (a,a) -> IO a
  randomRIO range  = getStdRandom (randomR range)

random の変種で、グローバルの乱数ジェネレータを利用する。"System.Random#globalrng"を参照。

  randomIO  :: IO a
  randomIO   = getStdRandom random

このように、コメントを除くと class 宣言による型クラスのプログラムは、単に多相型関数の型の宣言をしているもの (randomR, rondom) と、その型クラスの多相型関数を利用して関数を定義しているもの(rondomRs, romdoms) の2種類がある。

型クラスについては、Haskell の学習を始めた頃は説明を読んでものことかよくわからなかった。それは Int 型や String 型などの低レベルのデータ型からボトムアップ式に理解しようとしていたからだ。

しかしながら、トップダウンで型クラスを眺めるとその意味が良く分かる。初めに抽象的な関数を型クラスのクラスメソッドとして定義しておけは、パターンが同じでデータ型が違うような処理に対して、同じ意味の処理に対しては同じ関数で対応できる。

実際のプログラムでもいきなり個々のデータ型についてのプログラムを始めるよりは、最初に型クラスとそのクラスメソッドを定義しておいて、あとで実装を考えるという方向性のほうが全体的な見通しが良くなるだろう。

今回の解読では型クラスの便利さに目覚めることができた。
[PR]
by tnomura9 | 2015-05-07 18:35 | Haskell | Comments(0)

自然数の集合とラッセルのパラドックス

自然数の集合と「自分自身を要素としない集合の集合」というラッセルの集合はどちらも無限の要素を含むはずだ。しかし、自然数の集合は安定して集合として存在できるのに、ラッセルの集合はパラドックスになってしまう。一体どこが違うのだろうか。

無限集合は無限の要素を含むために、全てを列挙することはできない。無限集合の全ての要素を提示することはできないのだ。そこで、数学では無限集合を定義するのに内包公理を使う。無限集合のどの要素 x も述語 P(x) を充足していれば、述語 P(x) を充足する要素の集まりという内包的定義で集合が確定できると言ってもいいだろうということだ。問題はこの述語 P(x) をどのように定義するかということだ。

自然数は無限の要素を含んでいるが、ある数 x が自然数かどうかを判断するのにどのような述語 P(x) を定義したら良いのだろうか。どのような数を持ってきてもその数が自然数かどうかを反論しようもなく判断できる述語とはどのようなものなのだろうか。それには数学的帰納法が使われる。

たとえば、ある数が自然数かどうかを判断するには、その数を一定のルールで別の自然数に変換すればいい。その変換を有限回の手続きで繰り返していって、明らかに自然数である数に変換できれば元の数が自然数であると確定できるという考え方だ。ある数が自然数であるかどうかを判断する手続きは有限だが、どの数を持ってきても、この有限の手続きに帰着できるのなら、自然数の無限の要素を捕まえたと言っていいのではないかということだ。無限を有限の手続きで捉えるというこのトリッキーな方法はしかし、数学のあらゆる場面で活用されている。

ちなみに自然数を定義する帰納的定義は次のようになる。

1)1は自然数である。
2) n が自然数であれば n + 1 も自然数である。

このルールを使って 10 が自然数であることを確認するためには、2)のルールを使って、9 が自然数でなければならない。さらに、9 が自然数であるためには 8 が自然数でなければならない。この推論を繰り返すと 10, 9, 8, …, 2, 1 と1にたどり着く。1は明らかに自然数だから、2が自然数であることがわかる。2が自然数であれば、3も自然数だ。先ほどの推論を逆に繰り返すと最終的に 10 が自然数であることがわかる。

あるいは最初から 1 から始めても良い。1が自然数だから2も自然数だ。2が自然数ならば3も自然数だ。これを繰り返して 10 に到達すれば 10 が自然数であることがわかる。

数学的帰納法を使う場合、論証が有限回の推論で完了するということが大切だ。自然数は無限集合であるが。そのどの要素も有限界の推論で自然数の要素であることが論証できる。

しかし、数学的帰納法の特徴について特筆すべきはこのルールが生成的なルールであるということである。n + 1 が自然数であることを論証するためには 1 … n が自然数であることが既知である必要がある。既知の 1 … n から未知の自然数の要素である n + 1 が自然数の要素であることを論証できる。自然数の集合と「自分を要素としない集合の集合」というラッセルの集合との違いは、この再帰的定義の生成的な側面に注目するとわかる。

自然数の帰納的定義が生成的なルールであると同じように、「自分を要素として含まない集合の集合」というラッセルの集合の定義も生成的な定義である。そのことは次のように考えることでわかる。

まず、「犬の集合」は自分自身を要素として含まないから、明らかにラッセルの集合の要素である。当面このような明らかにラッセルの集合の要素である集合を集めてみる。これは有限の要素の集まりだ。この既知の要素から新しい自分自身を要素として含まない集合というラッセルの集合の要素を作り出すことができれば、これは生成的なルールである。その生成的なルールは何かと言うと、要素の集まりから集合を作ることができるという集合の定義である。

「犬の集合」のようなラッセルの集合の要素の有限個の集まりから、新しい「自分自身を要素として含まない集合」を作り出すことができる。たとえば、「犬の集合」のみを要素とする集合を考えると、これは、新しい「自分自身を要素として含まない集合」だ。同様に最初に集めた有限の要素の任意の組み合わせからなる集合も新しい「自分自身を要素として含まない集合」になる。しかし、元となる要素の個数が有限なので、新しく生成される要素の数も有限だ。

有限の要素から、新しい有限の要素を生成し、新しい要素を含む有限の要素が生成される。ラッセルの集合にはこのような生成的なルールが適用されているのがわかる。この生成ルールで作り出される集合はどれも「自分自身を要素として含まない集合」である。したがって、これらを集めた「自分自身を要素として含まない集合の集合」も存在するはずだと思える。

しかし既存の「自分自身を要素として含まない集合」の集まりから、集合とはものの集まりであるという集合の定義を使って新しい「自分自身を要素として含まない集合」を作り出すことができるというラッセルの集合の生成的ルールは、どのような「自分自身を要素として含まない集合」の集合があったとしても、生成的ルールによって、その集合の要素とは異なる「自分自身を要素として含まない集合」を作り出すことができてしまう。この性質こそがラッセルのパラドックスを生み出す原因となるのだ。

それは次のように考えるとわかる。いま、「自分自身を要素としない集合」全てを集めた集合 R を考えてみよう。ラッセルの集合の生成的ルールから、この集合 R の要素を使って R の要素には含まれない「自分自身を要素として含まない集合」を作り出すことができる。最低限 R 自身が R の要素には含まれないが、「自分自身を要素として含まない集合」だ。しかし、これは R の要素が「自分自身を要素として含まない集合」の全てであるという仮定に反する。したがって、「自分自身を要素としない集合」全てを集めた集合 R は存在できないことがわかる。

自然数の生成的定義は既知の自然数にない新しい n+1 という自然数が生成されてもそれは自然数の集合のメンバーであると考えることができた。しかし、ラッセルの集合の生成的定義は既知のラッセル集合の要素から新しい「自分自身を要素として含まない集合」を生成したときには、その集合は既知の要素の集合には含まれることがない。このことが、「自分自身を要素として含まない集合」全てを集めた集合を作れなくしてしまっている。

ものの集まりを集合というものと考えるという集合の定義は、つねに既知の要素から新しい「もの」を作り出すという生成的な性質を持っている。この生成的な集合の定義の性質こそが、ラッセルのパラドックスを発生させる原因だったのだ。
[PR]
by tnomura9 | 2015-05-03 07:26 | 考えるということ | Comments(0)