機械学習技術 Clojure デジタルトランスフォーメーション技術 人工知能技術 セマンティックウェブ技術 オントロジー技術 確率的生成モデル サポートベクトルマシン スパースモデリング トピックモデル Python 自然言語処理技術 知識情報処理 Python 本ブログのナビ
サマリー
Pythonは、簡単に学べること、読みやすいコードを書けること、広範囲にわたるアプリケーションに使えることなどの、多くの優れた特徴を持つ汎用プログラミング言語となる。Pythonは、1991年にGuido van Rossumによって開発されている。
Pythonは、比較的新しい言語であるため、オブジェクト指向プログラミング、手続き型プログラミング、関数型プログラミング等の様々な効果的なプログラミング手法を利用することができる。また、多くのライブラリやフレームワークが用意されているため、Webアプリケーション、デスクトップアプリケーション、科学技術計算、機械学習、人工知能などの分野に広く使われている。さらに、クロスプラットフォームであり、Windows、Mac、Linuxなどの多くのオペレーティングシステムで動作するという特徴を持つ。Pythonは、インタープリタ言語であるため、コンパイルの必要がなく、REPL的な仕組みを持つため、開発サイクルが早くなる。
ここでは、「世界標準MIT教科書 Python言語によるプログラミングイントロダクション第2版:データサイエンスとアプリケーション」をベースにPyhtonに関するトピックについて述べる。
今回はPythonについて述べる前に、プログラミングとコンピューターについて述べる。
Python言語によるプログラミングイントロダクション(1)プログラミングとは
コンピューターは2つのこと(だけ)をする。一つは計算をすること、もう一つは計算結果を覚えていること(だけ)だ。ただし、コンピューターはこの2つのことを非常に上手にできる。一般的なコンピューターでさえ1秒間に10億回程度の計算を行う。(これは床から1mの高さからボールを落としてボールが床に到達する前に10億回以上の演算ができることとなる)また一般的なコンピューターが持つ数百ギガバイトの容量は、例えば1バイト1gでイメージすると数十万トン以上の重さで、アフリカ象が数万頭換算となる。
人間の歴史のほとんどでは、計算速度は人間の頭脳の速度で、計算結果の記録は人間のてによる記述能力で制限されてきた。これはごく小さな問題だけが計算により解決できていたことに相当する。現代のコンピューターを使うことで、この問題処理能力が大幅に拡張されてきたこととなる。
ここで問題を計算で解決するための「計算的な思考」について考える。
すべての知識は宣言的(declaretive)もしくは命令的(imperative)かのいずれかに分類できる。宣言的知識とは、事実の記述で構成されたものとなり、例えば「xの平方根はyxy=xを満たすyのことである」は宣言的な知識となる。これは事実の記述であり、いかにして平方根を求めるかについては何も述べていない。
これに対して命令的知識とは「ハウツー」の知識であり、情報を導き出すためのレシピとなる。アレクサンドリアのヘロンは、数の平方根を計算するための方法について以下のような方法を導き出した。
- 平方根の適当な推定値gからはじめる
- もしgxgがxに十分近ければ停止し、gを回として報告する
- そうでなければ、gとx/gの平気ん、つまり(g+x/g)/2を新しい推定値とする
- 新しい推定値をgとし、gxgがxに十分近くなるまで繰り返す
例として、25の平方根を求める。
- 推定値gを適当な数字3に設定する
- 3×3=9は25に十分近いとは言えないと判断
- g=(3+(25/3)/2=5.67に設定
- 5.67×5.67=32.15は25に十分近いとは言えないと判断
- g=(5.67+25/5.67)/2=5.04に設定
- 5.04×5.04=25.4は25に十分近いと判断し停止、5.04を25の平方根とする
この方法の記述は、単純なステップの例と、ステップをいつ実行するのかの流れの制御から構成されている。このような記述をアルゴリズム(algorithm)と呼ぶ。
このアルゴリズムは試行錯誤(quess-and-check algorithm)の一例となる。それは、推定値が良いか否かをチェックすることが容易だという事実に基づいている。もう少し正式にいうと、アルゴリズムとは(与えられた入力を明確に定義された状態へと変更し、最終的には結果を出力する)計算法(computatiom)を記述した命令の有限このリストとなる。
では、このような命令のリストをどのようにして機械的な処理に変換すればよいのか?一つの方法は、平方根を計算するための専用機械を設計することにある。実際に初期のコンピューターはプログラム固定コンピューター(fixed-program computer)であった。(1941年にAtansoffとBerryによって構築された初期のコンピューターは、線型方程式を解く事ができたが他のことはできず、第二次世界大戦中にアラン・チューリングにより開発された暗号解読器は、ドイツのエニグマ安吾秋を解読するためだけのものであった)
最初の真にモダンなコンピューターはManchester Mark 1となる。それは、以前のものと異なり、プログラム内臓コンピューター(stored-program computer)と呼ばれるもので、命令の列を保存(かつ操作)し、命令列を実行する部品を持つ。命令群の基本設計を作成し、命令の列(これがプログラムとなる)としての計算方法を詳細化することによって、高度に柔軟な機会を構築する事ができる。これらの命令群をデータのように扱うことによって、プログラム内臓型コンピューターは容易にプログラムを変更する事ができる。
コンピューターの心臓部は、正しい命令群を実行できるプログラム(プログラム解釈部:これをインタプリタ(interpreter)と呼ぶ)であり、これによって、基本命令群で記述可能なものなら、どんなものでも計算できるようになった。
プログラムもデータもメモリ上に駐在する。通常は、メモリ上の特定場所(番地)を示すプログラム内のカウンタがあり、その番地の命令を実行することによって計算を開始する。ほとんどの場合、インタープリタは単に次の命令を実行するが、いつもとは限らない。ある場合には、何らかのテストを行い、その結果に基づき命令の列の他の地点へとジャンプする。これは流れの制御(flow of control)と呼ばれ、複雑な仕事を実行するためのプログラムを描くために必須なものとなる。
良いプログラマは、良い料理人が同じ材料を組み合わせても数えきれないほどの美味しい料理を作るのと同様に、少数の基本的な要素を組み合わせて数えきれないほどの便利なプログラムを作り出す。これがプログラミングに多大な努力が必要な理由となる。
レシピ(命令の列)を作成するためには、こけらのことを記述し、コンピューターに進撃命令を伝えるためのプログラミング言語(programming language)が必要になる。
1936年に、英国の数学者アラン・チューリングは、その後の万能チューリング機械(universal Turing machine)と呼ばれるようになった火葬の計算装置を提案した。その機械は0か1を記述できるテープの形をした無限のメモリ、テープの移動と読み書きに対するいくつかの単純な基本命令から構成されていた。チャーチ-チューリングの提唱(Church-Turing thesis)は、もしある関数が計算可能なら、チューリング機械でプログラムでき、それを計算できるという主張となる。
チャーチ-チューリングの提唱における「もし」の部分は重要となる。すべての問題が計算による解を持つわけではない。例としてチューリングは、任意のプログラム(これをPとする)が与えられた時、Pが永遠に回り続ける時、またその時に限って、真と出力するプログラムを書く事が不可能であることを示した。これは停止問題(halting problem)と呼ばれるものとなる。
チャーチ-チューリングの提唱から、以下のチューリング完全性の概念が導かれる。プログラミング言語は万能チューリング機械をシミュレートする(同等の計算能力を持つ)ことができるならチューリング完全(Turing complete)と呼ばれる。すべてのモダンなプログラミング言語はチューリング完全となる。あるプログラミング言語でプログラム可能なものは、他のプログラミング言語でもプログラム可能となる。もちろん、ある問題は特定のプログラミング言語で記述しやすいという場合もあるが、すべてのプログラミング言語はその計算能力という観点からは基本的に同等となる。
幸いなことに、チューリング機械の基本命令だけでプログラミングを書く必要はなく、実際にはモダンなプログラミング言語は、より多くの便利な基本命令群を提供してくれる。どのような基本命令を持っていようが、それらを使うためのどのような方法を持っていようが、プログラミングの基本は、コンピュターは命令された通りしか動かないという点において同じとなる。
世界中で数百のプログラミング言語があるが、その中で最良のプログラミング言語というものはない。(最悪というものはいくつかはノミネートされるかもしれない)応用に応じてプログラミング言語間の優劣は変わってくる。たとえばMATLABはベクトルや行列操作のために優れた言語であり、C言語はデータネットワークを制御するブログラムには良い言語で、PHPはウェブサイトを構築するときには良い言語となる。そしてpythonは良い汎用プログミングの一つとなる。
個々のプログラミング言語は、基本構成要素、文法(syntax)、静的意味論(static semantics)、意味論(semantics)を持つ。自然言語とのアナロジーだと、基本構成要素は単語であり、文法は正しい文を構成するための単語の繋がりを指す。静的意味論はどのような文が意味をなすかを定義し、意味論は複数の文の意味を定義する。pythonにおける構成要素は、リテラル(literal)と、2項演算子(inflix operator)などがある。
言語の文法(syntax)は、文字や記号の列が正しく配置されているかを定義する。例えば、英語における文字の列”Cat dog boy”は文法的に正しくない。なぜなら、英語の文法は<名詞><名詞><名詞>という文を許容しないからである。Pythonにおいては”3.2+3.2″は文法的に正しいが、”3.2 3.2″は正しくない。
静的意味論(static semantics)は文法的に正しい文字の列が意味を持つかどうかを定義する。例えば、英語においては”I runs fast”は<主語><動詞><副詞>の型を持っているので、文法的には正しい。しかしながら、これは正しい英語ではない。なぜなら主語”I”は単数形であり、動詞”runs”は3人称単数で用いられるからである。これは静的意味論でのエラーとなる。Pythonでは”3.2/’abc'”は<リテラル><演算子><リテラル>の型を持っているので、文法的には正しい。しかし、数字を文字列で悪ことは意味をなさないので静的意味論ではエラーとなる。
言語の意味論(semantics)は、文法的に正しい文字列、かつ静的な意味論におけるエラーを含まないものを「意味」に近づける。自然言語における文の意味論は曖昧であることもある。例えば「私はこの生徒をあまりに高く評価することはできない」という文は、褒めているようにも貶めているようにもとれる。プログラミング言語においては、正しいプログラム(文)は一つの意味を持つように設計されている。
文法エラーは(初学者にとって)もっとも一般的に起こるエラーであるが、それは危険度が最も低いエラーとなる。すべての真面目なプログラミング言語は、文法エラーを発見するための機能をもっており、たった一つでも文法エラーを含むプログラムを実行することをゆるしていない。さらに、ほとんどの場合、プログラミング言語システムは、エラーを修正するためには何をしたら良いかについてわかるように、エラーのある箇所を明確に指摘してくれる。
静的意味論におけるエラーの場合はもう少し複雑になる。あるプログラミング言語(例えばJava)では、プログラムが実行される前にたくさんの静的意味論のチェックが行われる。他の言語(例えばCやPython)では、プログラムが実行される前には静的意味論のチェックはあまり行われない。そのかわりpython等では、プログラムの実行中に十分な数の静的意味論のチェックが行われる。
プログラム内に「意味論的なエラーがある」という言葉はあまり使われない。プログラムが文法エラーや静的意味論におけるエラーを含まない時には、そのプログラムは「意味」(言い換えれば意味論)を持つ。それは作成者が意図した意味を持つことを担保しない。プログラムが作成者の意図した通りに動かない場合には以下のような事が起こる。
- クラッシュする。 クラッシュした何らかの明白な兆候を生成して、プログラムが停止する
- 回り続けて、停止しない
- プログラムは終了して、何らかの結果を算出するが、それが正しいのか正しくないのかわからない
上記はすべて悪い状況であるが、最後のものが最悪となる。プログラムは正しいことをしているが、結果が正しくない場合は悪いことが起こりうる。例えば財産が失われたり、飛行機が墜落したりなどなど。プログラムがうまく動かない場合は、できる限り自明になるように記述する事が良いプログラングの一歩となる。
次回はPython言語の特徴について述べる。
コメント
[…] Python言語によるプログラミングイントロダクション(1)プログラミングとは […]
[…] プログラミング言語は無数にある。例えば前回紹介した図書「世界が変わるプログラム入門」ではマシン語、アセンブリ、BASIC、C、C++、JAVAが、「7つの言語、7つの世界」ではRuby、Io、Prolog、Scala、Erlang、Clojure、Haskellが、ネット上での調査では、前記以外の言語としてPython、Javascript、SQL、C#、VBA、PHP等が上げられている。 […]
[…] 自然言語とプログラミング […]
[…] ここで、コンピュータでシンボルを扱う事を考える。「Python言語によるプログラミングイントロダクション(1)プログラミングとは」で述べたように、コンピューターの行っていることをつきつめると「計算をすること」と「計算結果を覚えること」の2つとなる。よってシンボルをコンピューターで扱えるようにするためには、対象を定量化(数値化)して何らかの計算を行えるようにする必要がある。 […]
[…] 「世界標準MIT教科書 Python言語によるプログラミングイントロダクション 第2版:データサイエンスとアプリケーション」より。前回はプログラミングについての概要を述べた。今回はプログラミングの基本(構造化プログラミング)となる、データの型と基本演算、分岐、繰り返しについて述べる。 […]