2009年9月21日月曜日

ぜひ押さえておきたいコンピューターサイエンスの教科書

僕はバイオインフォマティクスという生物と情報の融合分野で研究を行っています。東大の理学部情報科学科にいた頃は同僚のマニアックな知識に驚かされたものですが、そのような計算機専門の世界から一歩外に出ると、それが非常に希有な環境だったことに気が付きました。外の世界では、メモリとディスクの違いから、オートマトン、計算量の概念など、コンピューターサイエンスの基礎知識はあまり知られていませんでした。コンピューターサイエンスを学び始めたばかりの生物系の人と話をしているうちに、僕が学部時代に受けた教育のうち、彼らに欠けている知識についても具体的にわかるようになってきました。

バイオインフォマティクスに限らず、今後コンピュータを専門としていない人がコンピューターサイエンスについて学ぶ機会はますます多くなると思われます。そこで、これからコンピューターサイエンスを学ぼうとする人の手助けとなるように、基礎となる参考書をまとめることにしました。

ここで紹介する本は主に英語のものですが、初学者でも読みやすいように配慮されているもの選びました。ただし、ここに挙げた書籍を合わせると、生物学系の定番教科書「Molecular Biology of the Cell」(1392ページ!)よりも分量がはるかに多く、ただ情報を吸収するだけではなく、自ら頭や手を動かして能動的に考えないと理解できないため壁も高めです。挫折しないためには、一度きちんと勉強した研究者のガイドを受けながら読むか、大学の情報系の講義に参加して科目の全体像、重要なポイントを知った上で読むことを「強く」お勧めします。もちろん、自力で読みこなせればそれに越したことはありませんのでぜひ頑張ってみてください。

この分野にこれから入ってこようとしている人をdiscourageさせないようにあらかじめ断っておくと、実はここに紹介してある本の内容を完全に理解していなくても実用上はさほど困らないかと思われます。東大の理学部情報科学科でも、教科書を全部読むような教え方ではなく、本の中の重要なエッセンスを取り出したレジュメをもとに講義が行われています。このように分野の雰囲気、全体像を知ることは大切です。というのも、本当に困るのは、必要なときにどこに必要な知識があるかわからなかったり、目の前の問題を解決するためにどのような考え方をすべきかを知らない場合だからです。僕自身の経験でも、大学の講義を受けているときにはちっとも身が入らずほとんど理解していなかったことが、数年後、キーワードを知っていたおかげで、本を通して読まずとも読むべき場所がわかり、内容がすいすい頭に入ってくることが多々ありました。授業のありがたみはこんなときに実感できます。

まずはOSから コンピューターサイエンスは、理論的なものから実用に近いものまでとても応用範囲の幅広い分野です。その基礎として、まず第一にデータ構造やアルゴリズムの知識をまず学ぶべきだと思っていたのですが、それよりも先に、コンピュータを動かしているOSそのものの知識が必要だったのです。情報屋さんは日頃OSに慣れ親しんでいるので、ここが情報系以外の人に理解されていないのが盲点でした。例えば、コンピューター上でプログラムがどう実行されるのか?1つしかないCPUで、複数のアプリケーションがどうして同時に動いているように見えるのか?(プロセス、スレッド、CPUスケジューリング)、データがメモリやファイルにどのように保存されているか。システムコールとは何か。オペレーティングシステムについて学ぶには、Silberschatz先生による「 Operating System Concepts」が定番で俗に恐竜本とも呼ばれています。アルゴリズムを学ぶ前に、それを動かす大前提となるシステムがどのように動き、どのような性質をもっているのか。情報科学科では、実際にプロセスやスレッドを生成してシェルを実装してみたり、ファイルの読み書きなどを演習しながら、これらの知識を身につけていきます。

計算の理論
計算の数学的な性質について学ぶことは、計算できるものと、できないものの違いを知るために必要です。また、どのくらいの速さ、メモリ量で計算できるか? それらがどのような計算の仕方で計算できる問題なのか?について学びます。具体的にはオートマトン、正規表現、文脈自由文法、チューリングマシン、計算の複雑さ(computational complexity, NP完全問題など)、判定可能性(アルゴリズムの限界、アルゴリズムで解けない問題というのがある)などが含まれます。MITの屈指の名講義と呼ばれるSipser先生の講義を教科書にした「Introduction to the Theory of Computation」がとても読みやすいのでお勧めです。この本に限っては、日本語訳版も対応の英語付きで丁寧に訳されているので日英での用語の違いに戸惑うこともないでしょう。(注:上記のリンクは初版の日本語訳に張ってありますが、第二版の日本語訳も内容を3冊に分けて出版されています。)計算のクラスを考える必要がある例を挙げると、例えば、正規表現の限界(参考:Leo's Chronicle 「正規表現に見切りをつけるとき」)を考える理由がよくわからなかった場合は、この本の内容が参考になります。



計算理論に関しては、Garey and Johnson本「Computers and Intractability: A Guide to the Theory of Np-Completeness (Series of Books in the Mathematical Sciences)」も定番中の定番です。読みやすく(易しいという意味ではなく、簡潔という意味です)、NP完全であることの証明パターンや、そのための巻末のNP完全問題のリストが役に立ちます。この本の「Coping with NP-Complete Problems(難しい問題といかに付き合っていくか)」という章のタイトルは非常に有名で、コンピューターサイエンスという学問を如実に表している表現です。




データ構造とアルゴリズム 離散数学とも呼ばれるこの分野。日本語で平易に書かれた教科書もあるのですが(例えば、データ構造とアルゴリズム (新・情報 通信システム工学)や、計算とアルゴリズム (新コンピュータサイエンス講座)など)、やはり、list、hash、red-black tree, ネットワークフロー、グラフ、木構造など主要なデータ構造をカバーしつつ、NP完全性や集合論などの数学的な基礎知識も巻末に儲けられている「Introduction to Algorithms, Third Edition」が便利です。今月には第3版も出るようです。ただし、内容が豊富で記述も多いため、初学者が通して読む目的には向かない本だとは思います。上に挙げたデータ構造について学んだあと、一通りの手法(Greedy(貪欲)アルゴリズム、分割統治法、Dynamic Programming(DP)、近似、Randomizedアルゴリズムなど)を身につけたい場合は、「Algorithm Design」の方が講義用に構成されている分読みやすいかと思います。

連続系アルゴリズム 工学的には、離散値だけではなく、実数データを扱ったり、固有値問題や、偏微分方程式をCG法(共役勾配法)で解く、波形データの解析のために高速フーリエ変換(FFT)を使う、統計量の計算、検定など、計算機が活躍する場面が多々存在します。これらの計算は並列化して高速に計算する需要も大きく、そのような連続系の計算を理解するのに役立つのが「Numerical Recipes 3rd Edition: The Art of Scientific Computing」です。計算を手法とソースコードの双方向から学習できるので、演習向けです。大学の線形代数の内容も、ここにあるような実際の計算までやってみるともっと楽しくなるように思います。最新版ではSVM(Support Vector Machine)やHMM(Hidden Marcov Model)まで言及されているとか。



ハードウェア レジスタとは何か知っていますか? マシン語は? 計算機の中で整数や小数点以下の数はどう表現されているの?などなど、JavaやRubyなど現代の便利なプログラミング言語しか使っていないと見えなくなってしまうハードウェアの世界を学ぶためには「コンピュータの構成と設計~ハードウエアとソフトウエアのインタフェース 第3版 (上), (下)」が良いでしょう。(注:通称パタヘネ本です。ヘネパタはまた別の本のことです)計算機科学はハードウェアとともに進化してきました。最新のCPUの内部構成を理解するには、レジスタ、計算のパイプライン化、割り込み、キャッシュなどの知識が不可欠ですし、これらを学べる本も、他には見当たらなくなってきました。同じメモリアクセスでもキャッシュに載っている場合とそうでない場合(localityの有無)で相当の性能差があるので、CPUの中身でどのように演算が行われているかを知らないと、CPUの性能を最大限引き出したプログラムは決して書けません。一度は目を通しておくべき本だと思います。

情報論理 アルゴリズムを設計したとき、それが正しい結果を出すこと(soundness)、そしてそのアルゴリズムがすべての答えを見つけ出すこと(completeness)を検証します。このようなsoundness/completenessの概念や、述語論理でロジックの等価性を証明したり、逆に背理法などで矛盾を導きだす技術もどこかで学ぶべきだと思います。萩谷先生の情報論理の講義資料が手軽に学べて良いと思っていますが、まとまった英語の教科書があればぜひ教えてください(識者の方)


プログラミング言語 といってもC++やJavaなどの言語の仕様のことではなく、λ計算、型情報などを用いてプログラムやその意味を数学的に表記する(操作的意味論を用いる)ことで、言語の仕様を正確に定義するのに使えたり、プログラムの意味を変えずに最適化(等価変換)する、また、プログラムが安全に実行されるかどうかを検証できるようにもなります。Pierce先生の書いたTypes and Programming Languages(TAPL)が非常にわかりやすく必要な知識がまとめられた本だと思います。

蛇足ですが、近年日本のインターネット界隈でSICPがプログラミング言語を理論的に学ぶ本として話題になっているのですが、コメント欄で住井先生が指摘されているように、SICPとTAPLではカバーしている世界が違います。僕自身も、この本をベースにした演習をしたり、最後の章にあるようなSchemeでSchemeコンパイラまで作った経験から、SICPだけで関数型言語の勉強をした気になってしまうと視野が狭くなるように思います。関数型言語に慣れたり内部の仕組みを知るにはSICP、操作意味論や型について学ぶにはTAPLが良いでしょう。

(注:このプログラミング言語に関する部分は僕の説明や用語の使い方が悪い書き方になっていたため、住井先生の指摘を受けて書き直しました。そのため、下の方にある住井先生のコメントが指していた内容がわからなくなってしまいました。すみません。)



コンパイラ テキストデータを解析するには書かせない技術です。字句解析、構文解析に始まり、構文木から実行したいコードを作成。コード内で変数の生存範囲を見て最適化を施すなどなど。プログラミング言語を作る以外にも、独自データを表現しやすくするためのデータフォーマットを作ったり、ミニ言語を作って日頃の作業を効率化するなり、身につけると非常に強力な武器になります。Compilers: Principles, Techniques, and Tools (2nd Edition)、通称Dragon Bookが一応教科書的なポジションを占めているのですが、最初から読むと構文解析すらできないうちに挫折する可能性が高いので注意。おすすめの読み方は、実際に使うツールに合わせて読むこと。例えば、ANTLRを使うならLL(1)文法を、Lex/Yacc(Flex/Bison)を使うならLALR(1)文法を知らないとデバッグすらままならないので、必要に迫られて本の該当箇所を読む使い方が良いように思います。てっとり早く内容を把握するには、萩谷先生のコンパイラの講義資料を参考に。簡潔にまとまっていて、本を読み解くのに役立ちます。



データベースシステム Webやユーザーからデータを集めて管理、表示するWebアプリケーションでは、データベースの存在が必要不可欠になってきました。バイオインフォマティクスでは、毎日テラバイト規模のデータを扱う技術が必要になってきています。データベースに関する教科書は、以前 Leo's Chronicle:ぜひ押さえておきたいデータベースの教科書で紹介しました。Raghu本 Database Management Systemsがお勧め。ストレージ管理、データベースの同時更新をさばくためのトランザクション管理、これらの技術は年々重要度を増してきていますし、Google File Systemに代表される分散ストレージや、SSDの登場による時代の変化などに対応していくためにも、データベースシステムの仕組みはぜひ押さえておきたい知識です。


ここに紹介した他にも、コンピューターグラフィックス、自然言語処理、機械学習、データマイニング、ウェブ情報処理、ゲノム配列用の文字列検索、索引、圧縮データ構造、Information Retrieval (IR)など、ここでは紹介しきれないほど、コンピューターサイエンスの応用は多岐に渡っています。そして、教科書にある知識を身につけることも大切ですが、より大事なのは、それらを活用して、コンピューターの力を応用できる分野を切り開いていくことだと思います。

(このエントリを書いているうちに、自分の知識の浅さや分野の広さにくらくらしてきました。他にもコンピューターサイエンスの基礎として勉強すべき分野、良い教科書があるよ、という情報を教えていただけると幸いです)

関連

7 件のコメント:

Casey Jones さんのコメント...

はじめまして.Caseyと申します.
古川享さんのtwitterからこちらのブログを知りました.
さて,本の話ですがOSについては「はじめての486」蒲池輝尚著も良い本だと思います.
ちょっと古い本ですが,分かりやすく説明されています.

hogemuta さんのコメント...

はじめまして。
計算論の基礎ですが、原書二版の翻訳版が出版されているのに初版への
リンクになっているのは何か理由があるのでしょうか?

三分冊になってしまったからとか、いろいろ問題があるとか。
教えていただければ幸いです。

pico さんのコメント...

ネットワーク・通信についてなら、タネンバウムの「コンピュータネットワーク第4版」がよいでしょう。網羅的です。

Taro L. Saito (leo) さんのコメント...

> Caseyさん
ありがとうございます。OSのキーワードからその本には辿り着けないので、よい情報です。

> hogemutaさん
特に深い理由はないのですが、強いて言えば3冊に分かれている点でしょうか。ぜひ全部目を通してほしい内容なのですが。注意を促す追記をしておきますね。

sternheller さんのコメント...

はじめまして。
ネットワークならComputer Networking: A Top-Down Approachもお勧めです。
名前の通り、OSIのプロトコルスタックを上から順に解説した本で、英語も平易なので読みやすいです。

sumii さんのコメント...

「プログラミング言語」について、(目次を見比べるとよくわかるのですが)SICPとTAPLでは守備範囲がまったく違うので、単純にどちらかがどちらかの代わりになるものではないです。端的に表現するとSICPは「(特に関数型言語の)プログラミングとプログラミング言語処理系の基礎」、TAPLは「プログラミング言語理論(特に操作的意味論と型システム)の基礎」のテキストといえるかと思います。なので、「プログラミングを理論的に学」んだり、「関数型言語の内側を学」んだりする目的には、TAPLよりSICPのほうが良いと思います。

ただ、SICPもちょっとわかりにくい部分が多いので、特に独学で「(関数型)プログラミングの基礎」を学ぶには、FelleisenらのHTDP (How to Design Programs)や、浅井さんの「プログラミングの基礎」などが良いのではないでしょうか。

kzhk さんのコメント...

Garey and Johnsonの計算量本は,情報科学科時代(院生&助手,約20年前)に読んで良い本だと思いました.1979年刊にも拘わらず,今も読み継がれているし,売られているんですね.この分野でバージョンアップなしに,30年間売られ続けているのは珍しい.そういう本が書けたら幸せだろうなと思います.

License

Creative Commons LicenseLeo's Chronicle by Taro L. Saito is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.1 Japan License.