これまで「データサイエンス入門」シリーズとして、確率やデータの可視化、回帰分析といった数学寄りの内容を紹介してきましたが、今回からは新しいシリーズとして、「データサイエンス入門」講義の中でも、コンピュータサイエンス・情報工学寄りの回の資料をもとに整理していきます。IT エンジニアを目指す身としては、実はこちらの内容のほうが日々の実務に直結してくる部分も多いはずなので、気合を入れて取り組んでいきます。第1回のテーマは「コンピュータとデータベース」です。
なぜ「ハードウェアの話」から始まるのか
データサイエンスの入門講義というと、統計や機械学習のアルゴリズムから入るイメージがあるかもしれませんが、この講義ではあえて、コンピュータのハードウェアの仕組みから話が始まります。その理由は、「ハードの構成・性能とデータサイエンスは不可分」だからです。
データ分析をしていると、必ずと言っていいほど次のような問いにぶつかります。
どこにボトルネック(処理が遅くなる原因)が発生するか?
コストはどのくらいかかるのか?
アルゴリズムを工夫して解決するのか、それともハードウェアの性能で力技で解決するのか、どちらを取るべきか?
これらの問いに答えるには、コンピュータがそもそもどういう仕組みで動いているのかを知っておく必要がある、というわけです。
この講義全体を通してのキーワードは「スケーラビリティ(Scalability)」です。データサイエンスで扱うのは膨大な数・種類のデータであり、そのデータを実用的な時間で処理するための基盤が「データベース」、データ数に対して処理時間がどう増えるかを考えるのが「アルゴリズム」、パラメータの種類が増えるとどうなるかを考えるのが「最適化」(次回扱います)、というように、これから紹介する3つのテーマはすべて、この「規模が大きくなったときにどう対応するか」という一本の軸でつながっています。「求解のアルゴリズムが存在すること」と「実用時間で解に到達可能であること」は別問題であり、「ちゃんと解を出す」にはエンジニアリングの知識も必要になる、というのがこのシリーズ全体を貫く考え方です。
コンピュータの基本的な仕組み
コンピュータ(計算機)は、1946年に登場したENIACのような巨大な装置から始まり、パーソナルコンピュータ、スーパーコンピュータ、ラップトップ、そして今ではスマートフォンの中にまで、様々な形で私たちの生活に入り込んでいます。
形はさまざまでも、コンピュータの基本的な構造(アーキテクチャ)は共通しています。それが「フォンノイマンアーキテクチャ(von Neumann architecture)」と呼ばれる構成で、次の3つの要素からできています(ハーバードアーキテクチャなど、他の構成もあります)。
中央演算装置(CPU: Central Processing Unit):
命令の解釈やプログラムの「制御」と、実際の計算である「演算」を行う部分
記憶装置(Memory):
メインメモリや外部記憶装置のこと
入出力装置(I/O Devices):
キーボード、ディスプレイ、プリンタなど、外部とのやり取りを担当する部分
CPUは、バス(bus)と呼ばれる配線を通じて記憶装置から命令とデータを読み出し、実行します。
ここで重要なポイントが、メインメモリには「プログラム」と「データ」の両方が格納される、という点です。これを「ストアードプログラム方式」と呼びます。プログラムもデータと同じようにメモリ上に置かれ、書き換え可能であるおかげで、コンピュータは特定の用途に固定されず、様々な用途に使い回せる高い汎用性を実現しています。
記憶装置の階層 ― 容量と速度はトレードオフ
コンピュータの中の記憶装置は、実は1種類ではなく、いくつもの階層に分かれています。これは「記憶容量とアクセス速度がトレードオフの関係にある」ためです。速くアクセスできる記憶装置ほど容量が小さく高価で、容量が大きい記憶装置ほどアクセスが遅い、という関係になっています。
速い順(容量が小さい順)に並べると、次のような階層になります。
レジスタ・キャッシュ:
CPU内にある、もっとも高速にアクセスできる記憶領域(SRAMなど)
メインメモリ:
DRAMで構成される、プログラムとデータを一時的に置いておく場所
補助記憶装置(2次記憶装置、ストレージ):SSDやHDDなど
外部記憶装置:microSDやUSBメモリなどのFlashメモリ
また、記憶装置は「電源を切ったら中身が消えるかどうか」という観点でも分類できます。レジスタ・キャッシュ・メインメモリのように電源を切ると消えてしまうものを「揮発性(volatile)」、SSDやHDDのように電源を切っても中身が消えないものを「不揮発性(non-volatile)」と呼びます。近年ではこの階層に、ネットワークストレージ(クラウド上のストレージ)も加わってきています。
余談:AIブームとメモリ不足
少し脱線しますが、興味深い余談として、AI市場の拡大によってDRAMが品薄・価格高騰している、という話が紹介されていました。実際、韓国のSamsung社は営業利益が前年比8.6倍にまで急増し、時価総額が1兆ドル規模になった、というニュースもあったようです。
なぜAIブームがメモリ不足を引き起こすのかというと、AIは膨大なデータに高速にアクセスできる必要があるため、GPUと「HBM(High Bandwidth Memory) 」と呼ばれる高性能メモリを大量に使う設計になっているからです。HBMは、多数のメモリチップを積み重ね(積層し)、チップを貫通する配線でGPUと直接接続する構造を取ることで、圧倒的な帯域幅を実現しています。この結果、特に高性能なDRAMがAI向けに優先的に確保されてしまい、一般向けの製品にまで品薄・価格高騰の影響が及んでいる、というわけです。
ちなみに、メモリの性能を語るときには「帯域(Bandwidth、1秒あたり何ビット送れるか)」と「レイテンシ(latency、データが届くまでに何秒かかるか)」の両方が大事な指標になる、という点も紹介されていました。
データベースとは何か
ここからは、この回のもう一つの主題である「データベース」について見ていきます。
データベース(Database)とは、データ(情報)の集合体のことで、一般には検索などが容易にできるよう構造化された、組織的(=複数人が操作する)かつ継続的に保持するデータを指します。
そして、データの作成・更新・削除・検索などを、複数人が同時に接続しても「整合性」を保ちながら行うシステムのことを「データベースマネジメントシステム(DBMS: Database Management System)」と呼びます。ここでいう「整合性」とは、データに矛盾や無効なものがない状態のことです。DBMSには、アクセス制御などのセキュリティ機能や、障害からの復旧機能なども含まれます。
余談:記憶媒体のコストとデータベースの歴史
データベースシステムという考え方自体、実は「記憶媒体のコストが劇的に低下したことで登場した」という歴史的経緯があります。かつては記憶装置が超高価だったため、そこに大量のデータを貯め込むという発想自体が贅沢でした。講義資料では、1956年に登場したIBM 350というハードディスク装置が紹介されていましたが、その重量はなんと約1トン、記憶容量はわずか4.4MBだったそうです。今ではHDDはいくらでも買えるくらい安価になったからこそ、大量のデータを蓄積するデータベースという発想が一般化した、というわけです。
同じような「価値観の変化」は他の分野でも起きています。かつてインターネットが従量課金・低速だった時代は「無駄なデータをやりとりするな」という発想でしたが、今では「なんでもネット上に置いておけばいい」という発想に変わりました。次にどんなパラダイムシフトが起きるのか、考えてみるのも面白いポイントです。
リレーショナルデータベース(RDB)― 表形式でデータを整理する
もっとも代表的なデータベースの形式が「リレーショナルデータベース(RDB: Relational Database)」です。これは、データを表形式で保存し、表同士の関係(Relation)によって構築するデータベースのことです。
RDBでは、次の用語がよく使われます。
テーブル(table):1つの表全体のこと
カラム(column):表の列のこと(項目に相当)
レコード(record):表の行のこと(1件分のデータに相当)
ここで、RDBの設計における重要な考え方を、「よくない例」を通じて見てみます。次のような、履修科目に関するデータを1つの表にまとめてしまった例を考えます。
一見、表形式にはなっているものの、この表には「学生ごとに決まるデータ(氏名)」と「科目ごとに決まるデータ(科目名・教室・時間割)」と「学生と科目の組み合わせで決まるデータ(成績)」が、すべて混在してしまっています。学生が100万人、科目が100万個あって、各学生が1万個ほどの授業を履修している、という規模を想像すると、この形式ではデータの整合性を確認するのに非常な手間がかかってしまいます(たとえば、ある科目の教室が変更になったとき、その科目を履修している学生全員のレコードを、1件も漏らさず修正しなければなりません)。
そこで実際のRDB設計では、データを複数のテーブルに分割し、各テーブルには「キー」(そのテーブル内でレコードを一意に特定できる、不変で簡潔な情報)を定めます。先ほどの例であれば、「学生テーブル(学籍番号をキーに、氏名などを管理)」「科目テーブル(科目コードをキーに、科目名・教室・時間割などを管理)」「成績テーブル(科目コード×学籍番号の組み合わせで、成績を管理)」というように、3つのテーブルに分割します。こうすることで、科目の教室が変わっても、科目テーブルの1件だけを修正すればよくなり、データの整合性を保ちやすくなります。
データベースの操作とSQL
データベースに対して、「どういうデータが欲しいか」という指示を与えることを「クエリ(query)」と呼び、クエリを与えるための言語を「データベース言語」と呼びます。RDBMSにおける国際標準のデータベース言語が「SQL(Structured Query Language)」です。
たとえば、「データサイエンス入門履修者全員の学籍番号、氏名、成績の一覧」を取得したい場合、次のようなSQL文を書きます。
select 学籍番号, 氏名, 成績
from 成績テーブル
join 学生テーブル
on 成績テーブル.学籍番号 = 学生テーブル.学籍番号
where 科目コード = "62506"
「成績テーブルと学生テーブルを、学籍番号という共通のキーで連結(join)し、科目コードが62506のものだけに絞り込む」という指示を、このように書くわけです。SQLの詳しい文法は「データベース工学」といった、より専門的な講義で扱われる内容なので、ここでは「テーブルを分割して整理しておくと、こういう形で必要なデータだけを柔軟に取り出せるようになる」というイメージだけつかんでおければ十分です。
データウェアハウスとデータレイク
データ分析の文脈では、RDBそのものというよりも、分析目的に特化した2つの仕組みがよく登場します。
「データウェアハウス(Data Warehouse) 」は、意思決定のために、主題別に編成され、統合され、時系列で、削除や更新をしないデータの集合体です(Inmon, 1990による定義)。一般には、複数のデータから、ETL(Extract:抽出/Transform:加工/Load:ロード)という処理を行ったうえで蓄積するもので、「書き込むときにあらかじめ構造(スキーマ)を決めておく」という意味で「schema on write」と呼ばれます。
一方、「データレイク(Data Lake) 」は、どう使うかはさておき、とにかくデータを蓄積しておくための仕組みです。構造を決めずにまず貯めておき、「読むときに構造を考える」という意味で「schema on read」と呼ばれます。あまりに整理されないまま貯め込みすぎると使いにくくなり、「データの沼」と呼ばれてしまうこともあるようです。
実際の運用では、システムやセンサー、SNSなどから収集したログ・画像・データなどをまずデータレイクに集め、そこから加工・整形したものをデータウェアハウスに格納し、それぞれをデータ分析や機械学習が参照する、という関係になっているのが一般的な構成です。
分散データベースとNoSQL
データ量がさらに巨大になると、単一のストレージ(ファイルシステム)だけでは処理しきれなくなります。そこで登場するのが「分散データベース」です。ネットワーク上に分散されたストレージにデータを蓄積し、各地で分散して処理を行う「分散処理」を行うことで、多数のデータソースからの情報を蓄積するデータレイクなどで威力を発揮します。実装例としては、オープンソースのフレームワークであるApache Hadoopなどがあります。ただし、分散処理にはそのためのオーバーヘッド(余分な処理コスト)が発生するため、小規模なシステムではかえって遅くなってしまうこともある点には注意が必要です。
もう一つ、RDBとは異なるアプローチとして「NoSQL」と呼ばれる非リレーショナル型のデータベースがあります。NoSQLは、表と表の結合(JOIN)を排除することで、柔軟なデータ対応や高速なレスポンスを実現しようとするアプローチで、目的に応じてドキュメント型、キーバリュー型、グラフ型など様々な種類があります。多様な形式のデータを分析するのに向いている一方で、整合性の確保が優先される場面ではRDBのほうが優位とされています。RDBが重視する性質は「ACID特性(Atomicity, Consistency, Isolation, Durability) 」と呼ばれ、処理が中途半端に終わることも、処理でデータが崩れることも、並列処理が影響しあうことも、完了後にデータが崩れることもない、という厳格な性質を指します。用途に応じてRDBとNoSQLを使い分ける、という考え方が大切になってきます。
まとめ
今回は、データサイエンスの土台となるコンピュータの基本的な仕組み(フォンノイマンアーキテクチャ、記憶装置の階層)から、データベースの基本概念(DBMS、整合性)、リレーショナルデータベースの設計思想(テーブルの分割とキー)、そしてデータ分析に特化したデータウェアハウス・データレイク、分散データベース・NoSQLまで、駆け足で見てきました。
「データ分析の手法を学ぶ前に、そもそもそのデータがどこにどう保存され、どうやって取り出されているのか」という土台の部分を知っておくことは、地味に見えて実はとても大切なことだと感じます。特に、リレーショナルデータベースにおける「テーブルを適切に分割する」という発想は、データベース設計に限らず、情報を整理して扱うあらゆる場面で応用が効く考え方だと思います。
次回は、こうしたデータを実際にコンピュータで処理するための土台となる、プログラミングの基礎とアルゴリズムの考え方について紹介していきます。