働きながらアメリカの大学院でCS修士号を取った

4年前に会社の福利厚生を使ってスタンフォードの授業を取ってみたら面白く、 働きながらでも続けられそうだなという実感を得たので、 2年後、受験を経てジョージア工科大学にリモートで通い始めた。 そして先日、ジョージア工科大学からコンピュータサイエンス修士号をいただくことができた。 画像の学位記は卒業式イベント用の非公式のもので、1~2か月すると Masterとちゃんと書いてある本物が来るらしい *1

興味あるしいつかは習得したいんだけどなかなか触る機会がない分野を勉強するついでに、アメリカでは何かと役に立つ *2 学位がもらえ、学費は会社の福利厚生でカバーされたし、 世界ランキング 45位 の良い大学を2年かからずに卒業できたので良いことづくめだったように思う。

この記事では、働きながらコンピュータサイエンスをリモートで学ぶ体験の感想や、授業の面白かった点などをまとめておく。 なお、ジョージア工科大学にも当然ながら普通にキャンパスに通う生徒がいるが、 この記事では本学のCSオンライン受講プログラムOMSCSの話だけ書く。

在学期間

2020秋入学で2022春卒業の計5学期を大学院で過ごした。 生徒だった期間は1年9か月なので、普通に2年かけて修士を取る人たちより少し短い期間で学位を取得できたことになる。

卒業には10個の授業を取る必要がある。1年に3つの学期があり、春と秋は2つ、夏は1つしか授業を取れないのだが、4つ授業を取った後に成績が良ければ各学期もう1つ授業を追加できるようになる。従って、元々の枠をフルに使い続けるとちょうど2年、6学期で卒業でき、この追加枠を使うと最短5学期で卒業することができる。 *3

最初の秋学期は子供が産まれた直後 *4 だったので様子見で1つしか取らなかったが、翌年春2つ取ってみてもそれほど大変さは変わらないなと思った *5 ので、夏に4つ目の授業を取った後は同時に3つ取る学期を2回過ごして卒業要件を満たした。

学費

各学期 $301 かかり、それに加えて各授業 $540 かかる。なので、5学期で10個授業を取ると $6905 で卒業できることになる。

これはとんでもなく安い。 スタンフォードで授業を取った 時は5単位の授業を1つ取るのに $6300 かかり、卒業にはその9倍の単位を取る必要があるが、 ジョージア工科大学はスタンフォードの授業1.1個分の額で卒業できてしまうことになる。

アメリカの無料オンライン大学 University of People という記事を年末見かけたが、これは授業料は無料だが期末試験の受講にトータル $4000 かかるというスキームらしいので、 つまりジョージア工科大学は"無料"の1.7倍しか費用がかからないことになる。 これは学士のコースの話らしい(コメントで気付いた)ので3.4倍と言う方がフェアかもしれない。

英語

僕は4年前に受けたTOEICが845点で、TOEICの点数を公言している友達が大体900点台後半なので英語のリーディングとリスニングはどちらかというと自信がない。 一方で、入学した時の記事TOEFL iBTが「102点でどの程度授業についていけているかを知りたい」というブコメがあったが、授業を聴く時も、教科書や論文を読む時も、グループ課題で他の生徒と話す時も、別にそこで苦労したことはなかった。むしろ、割とゆっくり丁寧に話してくれる先生が多いため、授業を1.2〜1.5倍速で再生していることがほとんどだった。

これは単に、コンピューターサイエンスに関する話であれば単語は大体知っていて、内容も文脈から推測しやすくなるので、日常英会話とかに比べたら簡単になるという現象な気がする。

授業の感想

CS6291 Embedded Software Optimization

組み込みシステムの最適化。コンパイラの授業と同じ先生がやっている。 僕はコンパイラの中だとバックエンドにしかほぼ興味がなく、この授業はコンパイラの授業のバックエンド特化版であるという評判を見て、コンパイラの方ではなくこっちを取ったのだった。 後に結局コンパイラの方も取ったのだが、レジスタ割付はどちらの授業でもやるものの、命令パイプライニングや分岐予測を考慮した命令のスケジューリングに関して議論されるのはこちらだけなので、その評判は間違ってはいない。ただ、僕の感覚では、コンパイラをまるごと作った方がやっぱり面白いなと感じた。この授業ではレジスタ割付の課題はどのオペランドをどのレジスタに割り当てるかを決めたら終わりだが、コード生成してベンチマークが改善するのを眺める方がよっぽど楽しめる。

CS6200 Graduate Intro to Operating Systems

修士向けOS入門。学部の時にOSの授業を取りたいと思いつつもいろいろな事情 *6 があって取らなかったのだが、この機会にちゃんと基本を抑えておきたいと思って取った。プロセス、スケジューラ、スレッド、メモリ、IOといったそれっぽい話題に大体触れる。OMSCSにはOSの授業が2つあってこれも両方取ったのだが、もう一方はOSそのものについての授業はほとんどないので、OSについて勉強したい人はこちらを取ると良い。が、普段ある程度低レイヤープログラミングをやっている人だと、まあ大体勉強したことあるねみたいな感じの内容ではある。学部時代にOSの授業を取らなかったことから来る不安のようなものが払拭できたのはよかった。

CSE6250 Big Data for Health Informatics

ビッグデータ。授業の名前にあるようにビッグデータのヘルスケアへの活用に直接興味があるわけではないが、機械学習ビッグデータについて学べる授業なので取った。微分線形代数は久しぶりに触れて、大学数学を復習するのに丸一日使うといったことがあった。 この授業を取る前は機械学習はやったことがなかったが、かなり広範な技術を一通りカバーする内容になっていて、とても良い入門になった。具体的には、課題を通してNumPy、pandas、scikit-learn、Hive、Pig、Spark、PyTorchの全てに触れるので、機械学習ビッグデータ大体やったことあるなみたいな気分になれる。グループの自由課題では人間の睡眠データから病気になる確率を予測するモデルをPySparkで作ったりした。個人的に面白いと思ったのは生徒間で機械学習のモデルの性能をKaggleコンペする課題が2回あることで、しかも順位が成績に影響するところ。公開データセットでは1位だったが、最終順位が出る非公開データセットでは一気に29位に落ちるとかあった。

CS7643 Deep Learning

ディープラーニング。この手前に取ったCSE6250でもディープラーニングに触れはするしPyTorchの使い方くらいは学べるのだが、この分野一つをとってもたくさんの要素技術があるので、ちゃんとディープラーニングに関して理解したければこの授業を取った方がいいと思われる。人気のある授業で、割と最近追加された授業なこともあり、かなり新しい論文の内容にも触れるのが良い。バックプロパゲーションの基礎、CNN、言語のモデリング、AttentionやTransformerなどについて学ぶ。 この授業にはKaggleコンペはなかったが、現場で最先端の精度を出すのに使われているモデルはこうやって動いているんだなという意識があり、楽しんで取り組めた。グループ課題では食べ物の写真からレシピを生成するモデルを作った。 レシピのデータセットを触ってると、前職クックパッドのレシピも出てきて面白かった。

CS6250 Computer Networks

コンピュータネットワーク。インターネットを支える技術を一通り触る感じ。当然ある程度知ってる話も多かったけど、一度もTCP/IPについて体系的に学んだことがないみたいな不安がなくなって良い。 BGPとかネットワーク屋さんじゃないと普段触れることはなさそうだし。 インターネットで障害が発生した時に原因についての議論がある程度理解できるようになったり、何かをダウンロードしてくる時の速度の変化について後ろでどういうアルゴリズムが動いてそうなってるのか多少想像することができるようになって楽しい。

CS6515 Intro to Graduate Algorithms

修士向けアルゴリズム入門。卒業要件を満たすために重要になるため履修登録的な意味で人気な授業。僕の場合これが実質必修だったので取ったが、アルゴリズムの問題は純粋なパズル的面白さがあるので楽しめた。 動的計画法、分割統治法、高速フーリエ変換RSA、グラフアルゴリズム、最大フロー問題、線形計画法、P vs NPなどを扱う。学士で扱うよく聞くようなアルゴリズムAtCoderで水色を取る活動をしていた時に復習していたのだが、そこでは学べなかったアルゴリズムをここである程度知れたのはよかった。 こういう知識を活用する頻度が普段そんなに頻繁に発生するわけではないが、スケーラビリティとか計算量の複雑性とかを議論する際、ある程度複雑な理論を理解した経験があると、それより少し易しい話をしている時に確かな自信に裏付けされた議論や心の余裕ができる気がする。

CS8803 Compilers - Theory and Practice

コンパイラコンパイラのフロント、ミドル、バックエンドの理論を全部触り、大学教育に使われるTigerというプログラミング言語MIPSコンパイルするコンパイラをスクラッチする課題がある。 正直独学でかなり手を動かしてきた分野なので最初からほとんど知っていたが、あんまりフロントエンドに興味がないのもあり、そこの基礎であるNFAやDFA、LLといったところの理論を抑えられたのはよかったと思う(多分自分では勉強しないから)。Ken Thompsonは正規表現をNFAに変換するアルゴリズムも発明していてすごいなあとか。

僕は過去にいくつか言語処理系を作っているが、大体はインタプリタでコード生成が不要か、LLVMとかを使ってコード生成をしているとかで、アセンブリを直接吐くコンパイラを一から最後まで書き上げた経験がなくて *7、それが今回できたのはよかった。レジスタ割付をやるとバックエンドやってる感が出て良い。TAや他の生徒とコンパイラの性能でランキングを競えるのが楽しかった。

CS6210 Advanced Operating Systems

OSの発展的内容を扱う授業。OSに関しての理解は前提知識とされる授業で、OSそのものに関する授業はほとんどない。 かわりに、OSを使ったシステムデザインや分散システムにひたすら触れるという感じの授業。 毎週3~4つくらいの独立したシステムやアルゴリズムに関する議論が行なわれるので、割と密度が高い。 システムデザインの議論が好きな人は楽しめそうな内容だが、扱われるシステムが結構古かったり、アカデミアの外では使われていないようなものだったりと、よく実用されているシステムの設計について議論する他のクラスに比べるとやや興奮度の低い内容だった。 ただ、分散システムの話題にもある程度触れ、後述する分散システムの授業で何度か言及される授業なので、取っておいたのはよかったと思う。

CS6460 Educational Technology

EdTech。技術の教育への応用という分野には興味はないのだが、これは普通に履修登録できるクラスの中で唯一、多少自由にテーマを選んで研究ぽいことができる授業なので、修士論文を書かずに卒業するかわりにここで多少研究の経験を積んでおくことにした。 学内の教授と知り合いになると、その先生に一筆書いてもらうことでCS8903というコースを取り普通に研究をして単位をもらうことも可能なのだが、特にそういう関係を築くチャンスもなかったので、気軽に取れる方を取った。

実際この授業では論文の見つけ方、論文の読み方などを教わった後、何度も論文ぽいものを書いて添削してもらう経験ができる。ただ、研究そのものの経験はできるものの、研究の成果物は何らかの方法でEdTechに紐付けないといけない。一方、任意のテーマについて教えるコンテンツを作る、といったものでも教育に関連してるとして許容されるため、例えばポーカーの戦略についてまとめるサイトを作っている人もいた。 僕は割と本当にEdTechぽいがちゃんと自分の興味もある課題をひねり出した。具体的には、画像やサイト内のテキストから知らない英単語を抜き出し、任意の辞書で意味を調べ、それを自動で単語帳アプリに登録するみたいなものを作った*8。 英語の語彙が弱いので、単語帳で勉強する労力を下げられるようなものを作れてよかった。

CS7210 Distributed Computing

分散システム。僕が取った奴の中では一番最近追加された授業で、入学時点ではこういう授業がなくてガッカリしていたのだが、取れてよかった。 社内の輪読で割と分散システムに関する論文を読んでいた経験から、これも知っているか業務の経験から理解しているものがちょくちょくあったが、分散システムの基礎的な範囲をいろいろ触っているので知らないものもまあまああり、結構勉強になった。 論理時計、一貫性、レプリケーション、 分散合意などに触れる。Amazon AuroraGoogle Spannerのような、流行りのクラウドが採用しているアーキテクチャに関する議論があるのもとても楽しい。

この授業で良いのは全ての宿題を通して分散KVSを作るところ。スケーラビリティのためにシャーディングが可能で、各シャードを扱うクラスタはPAXOSで書き込みのログをレプリすることで耐故障性を実装し、そしてそのクラスタ間で2フェーズコミットを使うことで複数シャードにまたがる分散トランザクションを実装するというもの。で、これを実装する際に分散システムを作るフレームワークのようなものを使うのだが、それを使って実装すると、その実装で発生する状態遷移の組み合わせを全て検証するテスト、つまりモデル検査(TLA+みたいな奴)のようなことが可能になっていて、あらゆるコーナーケースで分散合意と進捗を保証しないとテストが落ちるようになっていて、これが難しい。分散システムの設計力が真に試される課題で、面白かった。

おすすめ

僕のお気に入りは CS7210 Distributed Computing と CS8803 Compilers。 単に僕個人の好みの分野で選んでいるという感じもあるが、上述したような課題の実装はやったことがなくてやってみたい、という人が受けたら確実に楽しめる内容だと思う。 ちなみに OMSCentral という授業レビューサイト上では、これらはそれぞれWorkload 1位の授業とDifficulty 1位の授業なので、最難関の授業でもある。楽な授業を取るより、本気で取り組んでやっと満足な成果が出る方が面白い。

成績

GPA: 3.90 / 4.00 だった。Deep Learningがあと0.55点あれば完璧な成績表 *9 になってたのが惜しい気持ちだが、もっと余裕でボーダーを超えられる実力をつけられていなかったので仕方ない。

学期 番号 名前 Grade 点数 A要件
2020 Fall CS6291 Embedded Software Optimization A 94.96 86
2021 Spring CS6200 Graduate Intro to Operating Systems A 87.2 80
CSE6250 Big Data for Health Informatics A 96.36 90
2021 Summer CS7643 Deep Learning B 88.95 89.5
2021 Fall CS6250 Computer Networks A 90.54 90
CS6515 Intro to Graduate Algorithms A 96.12 85
CS8803 Compilers - Theory and Practice A 94.23 87
2022 Spring CS6210 Advanced Operating Systems A 93.78 89.5
CS6460 Educational Technology A 96.75 90
CS7210 Distributed Computing A 89.2 84

まとめ

比較的安い授業料でいろいろ学べて楽しい。 修士を持っている人や、博士を持っていて他の大学で教師をやっている人もここで生徒をやっていたりするので、もう学位は持ってるという人も気軽に学び直しに来れる場だと思う。

*1:この部分は元々注釈で説明していたけど、読まれていなくて誤解が発生していたので、追記で本文に変更した。

*2:例えばソフトウェアエンジニアがH1Bという就労ビザを取ろうとすると、アメリカのCS修士があると2回抽選を受けられるが、学士や日本のCS修士では1度しか受けられない。また、グリーンカードを取る際も、学士ではEB-3、修士ではEB-2、博士ではEB-1という風に使える申請カテゴリが変わり、当然より良い学位を持っている方が一般には申請が早く済む。

*3:どうも基本的に皆フルタイムで働いてるからか、この枠をフルで使い続ける人は少ないようで、多くの人は3-4年かけて卒業するらしい。このプログラムのディレクターであるDavid Joynerに見せてもらったグラフの年では、最短の5学期で卒業したのはたった1%、6学期で卒業したのは5%しかいなかった。YMMV。

*4:なので、授業は子供が寝てから自分が寝るまでの時間だけ取り組んでいた。従って平日か休日かに関わらず20-24時の1日4時間が基本という感じだった。

*5:僕は締切が近付かないとあまり生産性が出ない人間なので、同時に3つ授業を取ると締切の数が3倍になり、従って生産性も3倍になるため効率がよかった。

*6:学部の4年間ずっとプログラミングのアルバイトをしていたのだが、さっさと卒業要件を満たして業務のプログラミングに専念する学期を作って社会人に備えたいという謎の危機感があり、3年前期までにほとんどの卒業要件を満たし、3年後期は実際必修を水曜朝1つ取ったらそれ以外はバイトをするという生活を始めたのだった。で、OSの授業はたまたま3年後期に予定されている授業だったため、自分個人の予定と折り合いがつかなかったという感じ。

*7:学部の授業で、先生が用意したx86アセンブリを吐く実装を少し拡張するみたいな課題はやった

*8:個人開発を黒字にする技術 https://k0kubun.hatenablog.com/entry/surplus で話していた奴はこれのこと

*9:点数は残らず、公式な記録はletter gradeしか残らないため