やりたいことを最初にやる,あるいは効率の良いプログラミングの勉強法について
去年は数ⅡB辺りを勉強したので今年は線形代数を勉強している。サラスの方法や余因子展開を使って行列式を求めたり、行列をあれこれ変形してrankを求めて一次方程式の解が求まるかどうかを日々検討しているのである。
しかし、勉強を始めたもともとの動機は、別の本を読んでたら出てきた「固有値」とか「固有ベクトル」という言葉の意味ってなんだっけ?という疑問であった。だから線形代数の本を買ってきて固有ベクトルの章だけ読めばよい。最初はそう思っていた。ところが、固有ベクトルの章だけ読んでもそれ以前の前提知識(特に行列式の意味や正則な行列の性質)がなければ理解できない内容だった。なので諦めて最初から参考書籍を読み問題集を解いているのである。
ちなみに読んでる本はこれ。とても分かりやすい。
- 作者: 平岡和幸,堀玄
- 出版社/メーカー: オーム社
- 発売日: 2004/10/01
- メディア: 単行本
- 購入: 27人 クリック: 278回
- この商品を含むブログ (90件) を見る
問題集はこれ。学部生向けの模様。
- 作者: 寺田文行
- 出版社/メーカー: サイエンス社
- 発売日: 2012/07/01
- メディア: 単行本
- この商品を含むブログを見る
線形代数のように順番に勉強しないといけないということは結構ある。多分資格の勉強とかも大体そうだろうと思う。しかし、新しいITスキルを習得しようとする時はどうだろうか?なぜこんなことを突然言い出したのかと言えば、今日図書館で線形代数の勉強をしていた時にふと思いついたからである。
かつての自分がやっていた「間違ったプログラミングの勉強法」
例えば、新しい言語を勉強する時に初心者用の入門書を買ってきて、頭から最後まで全部読んでからコードを書き始めるだろうか。実際、自分は一度だけやったことがある。webサービスを作りたくて,phpの入門書を買ってきて最初のページから写経し始めたのである。
ただ今振り返れば、phpを覚えてから7年ぐらい経っても未だに一度も使ったことがない関数やクラスのsampleコードを必死に写経していたのはかなり無駄だったなと感じる。もちろん、「こういうのがあるのか」というのを知っておくことは重要である。問題なのは、肝心のウェブサービスを作る上では不必要な知識だったということである。
実際に自分がphpでwebサービスを作るために自分はどうしたか?入門書の最後の方に「応用課題」として掲載されていた掲示板だのSNSだののサンプルコードをコピペしまくって改造したのである。そうしなければwebサービスは作れなかった。その章に行き着くまでに多くのコードを書いたが、それだけでは足りなかったのである。echo "Hello, php!";
から始まり mysql_connect('localhost', 'root', 'pAssw0rd') or die('データベース接続エラー');
みたいなことをやるscriptをいくら書いてもwebサービスを作ることはできなかったのである。
何が足りなかったのか?
いや、足りなかったというよりそもそも努力の仕方が間違っていた。webサービスを作りたければ、まずコピペでもなんでもいいから完成させてみることが重要だった。そうすれば自ずと何が必要か分かってくる。実際、自分のプログラミングのスキルや技術の知見は掲示板っぽい何かの実装を通じて大きく広がった。最終的にはさくらのVPSを借りてCentOSの使い方も調べてドメインまで取って、今見たらどうしようもなく意味の分からないみたいな掲示板もどきサービスを公開するところまで行った訳だが、プログラミングは覚えたので次はLinuxについてじっくり勉強してから。。などとやっていたらおそらく一生公開できなかったと思う。
それがなぜ公開にこぎつけられたかと言えば、まずやってみて、足りないと感じるものだけを補うように途中から方向転換したからだと思っている。それが結局は効率が良かった。勉強と言えばまず基礎をガッチリ固めて次に応用問題を。。という、高校までのスタイルにどっぷり浸かっていた自分は、当初プログラミングに対しても同じスタンスで挑んだが、プログラミングは学問ではない。道具なのだ。金槌を使えるようになるためにまず金槌の歴史の勉強から始める必要があるだろうか?全くないとは言い切れないが、大抵の人は金槌をまず握ってみるだろう。何なら叩いても良さそうなものを叩いてみるはずである。
プログラミングも多分同じだと思う。まず今必要なことをその言語でやってみる。次にそれで分かった足りないことを知るために書籍に立ち返って必要な部分を集中的に勉強する。結局、これが効率がよい勉強の仕方ではないかと自分では思っている。
自分がEffective Javaを読んだのはjavaを書くようになって1年近く経った後、Effective Rubyを読んだのもrubyを書くようになって2年以上経った後だったが、逆に初心者の頃だったら、何に役に立つのか分からずに多くの学びは得られなかったと思う。
新しいアプローチによる学習例
今でも新しいことを勉強するときはこのアプローチでやっていることが多い。
今年に入ってからはデータ分析の業務でpythonを結構書くようになったが(去年もNNの実装で使ったが)、何も考えずにまず brew install pyenv
して pyenv install anaconda3
してjupyter notebookをinstallしてpandasでBigQueryのデータをいじり始めた。ハマりまくったが結局やりたいことはできた。*1
たまたま別件で調べ物をしていて見つけた某大学のシステムプログラミングの講義資料が面白くなってしまい全部写経して、まだ作ったことがなかったwebサーバーを書いた。Cを集中的に書いていた時はCがどういう風にメモリを管理するかロクに知らなかったので構造体を使ったコードを書いたら至る所でSEGVの嵐で泣きたくなったが、お陰様で低レイヤーの技術とアセンブラに興味が沸いて今では社内輪読会でパタヘネを読んでいる。
このアプローチの応用で、自分がまだやれたことがないと思うのが「自分が一番難しいと思うこと」からやってみる、というものである。これまでは「多分実現可能っぽくて(周りがやってたりするので)一番やりたいこと」から手を付ける、という感じではあったのだが、それだとどうしても自分のスキル面での成長が止まってしまうと危惧しており、逆に「実現可能か全然分からないけど自分の中で一番難しいと思うこと」から手を付けてみたいと考えるようになった。
実際には時間的な制約でできなかったり、あまりに壮大過ぎて結構本気でどこから手をつけていいか分からないというものだったりするのだが*2、少しずつ課題を切り崩して、何とかとっかかりを見つけていきたいものである。
併せて読みたい(というかこれ読めば上記の文は読まなくてよい)
英語のリーディング勉強方法についての振り返り
洋書の技術書や英語の論文を読むようになって3か月ぐらいになる。
とは言え、母語が日本語なので日本語の方が圧倒的にinputは早いため、読んでる本の言語比率は日本語:英語 = 8:2といったぐらいである。全然である。「洋書を読んでいる」なんて決して人前で言える量ではない。*1
ちなみに英語で読んでいる技術書は下記。パラパラとわかるところだけ読んでいるものもあれば最初から読んでいるものもある。もともと本は5~6冊をパラレルで読んでいくタイプなので洋書もそんな感じで読んでいる。
- 作者: Martin Kleppmann
- 出版社/メーカー: O'Reilly Media
- 発売日: 2017/03/16
- メディア: Kindle版
- この商品を含むブログを見る
Distributed Computing: Principles, Algorithms, and Systems
- 作者: Ajay D. Kshemkalyani,Mukesh Singhal
- 出版社/メーカー: Cambridge University Press
- 発売日: 2008/04/17
- メディア: Kindle版
- この商品を含むブログを見る
Big Data: Principles and Best Practices of Scalable Real-Time Data Systems
- 作者: Nathan Marz,James Warren
- 出版社/メーカー: Manning Pubns Co
- 発売日: 2015/05/10
- メディア: ペーパーバック
- この商品を含むブログを見る
- 作者: Brian F. Goetz
- 出版社/メーカー: Pearson Education India
- 発売日: 2017/01
- メディア: ペーパーバック
- この商品を含むブログを見る
なぜ英語で読むのかと言えば、技術書に関しては翻訳がなかったり日本語版が絶版になっていたりするため。論文はそもそも基本的に英語しかない。
そのため今は英語のリーディング力を高めるために主に語彙を増やす勉強を中心にしている。
TOEIC(R)TEST英単語スピードマスター NEW EDITION
- 作者: 成重寿
- 出版社/メーカー: Jリサーチ出版
- 発売日: 2013/08/26
- メディア: 単行本
- この商品を含むブログを見る
手順としては以下のようにしている。大体これで40分ぐらいである。
- 1回の学習で50単語ぐらいを目標として覚える範囲を決める
- 例文を読んで、意味やニュアンス、類似語、例文を丸暗記するぐらい読み込む
- 解説が不十分だと思えば辞書を読んでニュアンスを覚える。
- 一通りやったところで赤シートを使って覚えているかどうかを確認する。覚えてなければその部分を集中してやる。
- 覚えた単語をざっくりノートに書きだして、それを眺めて意味やニュアンスがすぐに思いつくかどうかを再度確認。
こんな感じでやっているのだが、語彙力がなかなか伸びずに苦労している。 どのように苦労しているかと言えば大きく下記の2点である。
1. 覚えたかどうか分からない
それはともかく、この手の方法で単語を勉強してきたつもりだが、何というか本当に覚えたかどうか、つまり語彙力がついたのかどうか確認する手段があまりにも乏しい。確認できるのは英文を読んでいてその単語が出てきたときに「この単語見たことあるやつだ!」と思えた時か、commit logを書いていて「この場合はあの単語が使える!!!」というひらめきを感じた時ぐらいである。
それでいて2週間ぐらいだってから単語帳で同じ単語を眺めた時に「あれ、これなんだっけな…」となるケースも結構あり、覚えている率は肌感覚で1/4ぐらいであるのだが、果たして本当にそうなのかを定量的に計測する手段がない。これって単語テスト付きの単語帳でも使えばもっと正確に計測できるのだろうか?そういう単語帳買うべき??うーむ。。
2. しんどい
単語のみを覚える努力をしたことのある人ならわかってくれると思うが、使うか使わないか分からない単語を必死に覚えるのはなかなかにしんどい。
「なるほど!こういう言い回しがあるのか!」という発見はそれなりに楽しいにせよ、普段日本語で日常生活を送り日本語で仕事をしている人間にとってはやはり普段使いようがない知識である。どうしても仕事で疲れ切った頭にムチ打って図書館で必死に単語帳とにらめっこしていると純粋にしんどいと思うことも多い。どうして俺は生涯一回使うか使わないかってぐらいめったに見ない「embrace」みたいな単語の使い方を覚えているのか。他にやるべきことがあるのではないか、という気分にもなるが、とはいえ語彙力が貧弱であることは間違いないので頑張ってやるしかない。しかしどこか非効率だなという気分は拭えない。
こんなことを今年入ってからずっと続けてるので、かれこれ半年ぐらいはやってきた計算になる。しかし、いい加減この方法は間違っている気になってきた。
最近採用したやりかた
やり方を間違っている気になってきたので、単語帳作戦は一旦やめることにした。
代わりに、TOIEC Part5-7の問題集を解きまくって、分からない単語出てくる度に調べてメモって覚える方式に切り替えた。ネットで検索するとこっちの方が語彙力上げる手段としては効率が良いという意見もあるし、自分としてもまだ印象に残りやすいと感じている。しばらくはこの方法でやってみる。
また、技術書や論文に出てきた単語も覚えやすいということに気が付いた。 英文を読むとき、分からない単語を無視してとりあえず1センテンス読んで、それから分からない単語でどうしても類推できない単語だけ辞書を引くようにしたら「皆目分からない単語」だけをピンポイントだけで覚えられるようになってこれは効率が良いのではないかという気分になっている。「〇〇から遮断する」という動詞である「insulate」がアーキテクチャの解説でよく出てくるのだが*3、この単語は手持ちの単語帳の動詞コーナーには載ってなかった(索引がないので確定はできないが多分なかった)。そう考えるとやはり技術書に必要な英語は技術書を読みながら身に着けた方が早そうな気がする。
今のところリーディングさえできれば自分の用は事足りるので、もう何も考えずにいきなり英文を読み倒して分からない単語だけ辞書に当たる方が効率がよさそうである。
「英語学習にはまず単語帳が必要だ!」と思い込んでいたのは、大学受験時代の習慣というか思い込みみたいのが強かったからかなぁと思う。しかし、今や大学受験以上の語彙数力必要だとわかってる以上、異なるアプローチが必要なのは自明だよなぁと、自分の短絡さを反省する次第である。
死ぬまでエンジニアでいたい
理想の死に方は、前夜にOSSのリポジトリにPRを出して、翌朝には机で突っ伏して死んでて、最期に出したPRのコメント欄がr.i.p.で溢れている。そんな状態。
なんて話を冗談めかして飲み会ですることがある。*1が、本人は割と本気で死ぬまでコードを書いていたいと思っている。
年金がもらえそうにないので生涯働かないといけないみたいな主張を最近各種メディア界隈でよく見る。しかし、それとは別に、体が元気なら死ぬまで働き続けていたいものである。定年で悠々自適におとなしくできる気がしないし、それに、エンジニアとしてならリモートでも働きやすいし、数十年後にはさらにそれに適した社会になっているとも思われるし。
死ぬまでエンジニアでいる。それはおそらく難しい。
40歳を超えた辺りで、現場を離れてマネージャーとかIT芸人とかCTOとか技術顧問とか、そにかく違う肩書で働くようになる人がたくさんいるを見てもわかるように、そもそもエンジニアという職業を長く続けることは難しいと思われる訳で、死ぬまでエンジニアでいるのは多分容易ではない。自分の周りでいえば、現場でコードを書いてる人で一番高齢の人でも40歳で、それ以上は見たことがない。大体それぐらいになるとマネジメントとか会社の広報活動をメインでするようになって、現場から離れてコードを書かなくなっている。
でも自分はマネジメント方面には今のところ興味がない。仕事でそういう振る舞いが必要になって、他の人を巻き込んでそれらしいことをすることはあっても、それを専門にして飯を食いたいとは思わない。
もし自分が現場を離れてプロジェクトマネージャーになったとしても、自分が担当してるプロジェクトでこっそりコードを書いてPRを出したり、開発環境を改善するツールやライブラリを作って配布したり、CI環境を整備してテストとデプロイを自動化したり、PRというPRに目を通してコメントしてまわってウザがられるであろう。そんなプロジェクトマネージャーがいたら自分だったらイヤなので、やはり自分はマネージャーになるべきでない。とにかく目についた気になる所は即座にissueを立てて時間ができた瞬間に片っ端から修正するPRを出していく、そんな人間はやはりマネジメントをするよりコード書き野郎として生きるしかない。
ではそれをどうやって実現するか。今のところ割りと真面目に考えている話として以下を考えていたりする。
コードを書き続ける
当たり前のことかもしれないが意外と難しいということに気づいた。なぜなら、仕事における課題は大体コードの外で起きている。コードの外で起きている問題に対処し始めるとあれよあれよとコードを書く時間は失われていく。だから、意識してコードを書き続け無いと1週間のスプリントで何もdeployできない、なんていうのが普通になる。それが習慣化したらエンジニアとしての自分は死ぬと思っている。*2
あと家にいても気になるコードは読む、cloneして手元で動かす、バグを見つけたらPRを出す。気になる技術はdoc読んでわかった気にならずに動くコードを写経して感覚を覚える。そういう習慣が大事。youtubeやニコ動ばかり観ててはいかんのだ(けもフレ12.1話最高でした)。
長らくdocker以外の新しい技術を学んでいなかったなと反省して、最近はelectron本の写経をするなどしている。electronの本というよりモダンなフロントエンド開発の要素をまるごと勉強できてお得な一冊。サンプルコードもES2015で書かれている。
それ以外だとsparkのコードリーディングなど。今年はpythonとscalaを今年学ぶ言語として勉強している。
健康の維持
どんなに優秀でも健康でない奴に重要な仕事は振られなくなる。残念ながらこれが人間の心理。人は細かいところをよく見ているもので、毎週月曜日に休んでたりすると必ず誰かがマークしている。コワイ。いわんや、高齢で体が弱いとか、ますます仕事が無くなりそうではないか。それをひっくり返すだけのバリューを出せればよいが、そうだとしてもやはり体調が悪いのは精神的によくないし、長期的にはモチベーションに関係してくる気がする。生涯現役目指すマンにとっては大きな壁となるであろう。
まずは体力ということで、最近忙しかった関係で通ってないけど(だめじゃん)ジムで筋トレしたり走ったりしている。むしろ走る方がメインか。なんでもいいけど運動は大事。運動と瞑想の習慣の無い者の末路はなんとやら、というのは多分正解。
瞑想も『サーチ・インサイド・ユアセルフ』を読んでからやってるが、1日の振り返りになって大変よい。1日に起きた出来事が頭に浮かばなくなるまで瞑想し続けてから寝ると変な気持ちを翌日まで持ち越さなくて済む。
サーチ・インサイド・ユアセルフ ― 仕事と人生を飛躍させるグーグルのマインドフルネス実践法
- 作者:チャディー・メン・タン,一般社団法人マインドフルリーダーシップインスティテュート
- 発売日: 2016/05/17
- メディア: Kindle版
あと、生えている最後の親知らずを先日抜いてきた。まだ少し痛い。だが、親知らずも放置したまま高齢になるとますます抜くのが難しくなるし、傷口が塞がるのも遅くなるし感染症にもかかりやすくなる、ということで今のうちに抜いておこうと思って抜いた。幸いにして真っ直ぐ生えていたので歯医者に着いてから10分もかからずに診察は終了した。この歳になるとこういう細かい体のメンテが大事じゃないかと思っている。
それ以外にやっていることとして、月1で温泉に行くとか。もちろんY氏直伝でN氏も絶賛していた交代浴をするのだ。
千葉県野田市にある七光台温泉が好きで、自宅からだと電車と徒歩で片道2時間弱かかるのだが、その分土日に行ってもそこまで混んでなくて大変居心地がよい。都内の銭湯はいつ行っても混んでいてあまり好きではない。
今できていないこと
最近勉強会で登壇することがなくなってしまい、すっかりプレゼンスが下がっている。これはなんとかしないといけない。だが、今のところ発表できるネタと勉強会のテーマが合わなかったりして二の足を踏んでいる。なので基本的にブログやQiitaでのoutputをメインにしようと思うが、できれば今年中に最低一回はどこかで話したい。
あといい加減○○の人として認識されたいが、せいぜい「エモブログの人」とか(これは実際に言われたことがある)、「職業railsマン」程度なので(多分)、もう少し技術的なところでプレゼンスを発揮していきたい所存である。
その一環として、最近読んでいるsparkのコードリーディングの成果を一部qiitaに書き始めた。ある程度まとまったら第二弾を書く予定。
自分がRubyMineでRails appを書く理由
基本、Rails appを書く時はIDE(RubyMine)を使っている(それ以外はatomかvim)。
今の職場だとIDE使ってるの自分だけで、これまでもだいたい他の人はRails appを書く場合でもemacsかvimかatom、といった具合だった。Rails appはそういうエディタで書くのが普通らしい(自分の観測範囲においては)。
しかし、自分は仕事でrailsを書くようになってから3年ぐらいになるが、ずっとRubyMineを使っている。理由は下記。
- 自分で各種プラグインを入れなくても開発に必要な機能が最初から揃っているのでインストールするだけで開発がすぐ始められる。
- リファクタ機能が強力。メソッド名をファイルをまたいで一括で変更できるのが超絶便利。
- メソッド、クラスの定義元に一発でジャンプできる。使っているgemのソースを読みたくなったときも一発で手元のrails appからgemのソースへシームレスにジャンプできる。
- typoやsyntax erorrをエディタ上で教えてくれるので実行する前にミスに気が付ける。
- classやファイルをインクリメンタルサーチで検索してファイルを開くことができる。
- クラス構造のtreeを表示できる。1classが500行超えぐらいになるとこれがないとジャンプがつらい。
これらの機能はvimでもemacsでもプラグイン入れれば実現できるのかもしれないが、やり方を調べて設定ファイルを書いて、さらにトラブルが起きたときに自分で調査する手間を考えると、インストールすればすぐ使えて、万が一なんかあってもサポートが効く有料IDEの方がいいと思っているのでRubyMineをずっと使っている。
そこまでエディタにこだわりがないというか、正直なんでもいいと思っている。ただ、web appのメンテという仕事においては、できるだけ早く目的の箇所を探し出してコードを書く必要があるため、その効率だけを考えてエディタを選んでいる。その結果としてIDEに落ち着いている、という感じだろうか。プライベートだとC++もAtomで書いてたりはするが、仕事だったらVS使ってると思う。
ちょっとだけOSSに貢献したらすごく新感覚だった話
普段は仕事でコードを書いていて、それでおちんぎんは貰えるし、こんな自分でも多少は社会の役に立っているのではないかなぁという実感がまぁ多少は持てる時もある訳で、それなりに満たされた生活をしている。サラリーマンなので、当然大人の事情でしんどい気持ちでコードを書いてる時も少なからずあるが、それでも仕事は仕事である。頑張って書くのである。そんな毎日。
そんな中、1円ももらえないし、役に立つかどうか良くわからんが、気になったのでやった、というような状況でコードを書いてみたら、不思議な事に仕事でコードを書くのとは全く異なる満足感が得られてめっちゃテンション上がったので、その辺の話をしたい。
ある日、BigQueryにアクセスしている部分で突然エラーがraiseされてトラブったので調べてみたところ、GCPのruby clientであるgcloudというgemがGoogleのaccess tokenを取得する時に Faraday::TimeoutError
をraiseしていたことが原因だった(因みにこの時のgcloudのバージョンは0.12)。
Faradayのエラークラスをそのままraiseしてくることを想定していなかったので、自前で入れていたリトライ機構をすり抜けてしまっていた。
gcloudのnamespace配下で定義された専用のエラークラスがあるにも関わらず、Faradayのエラーを生でraiseしてきたという状況が単純に気になって調べてみたところ、errorをraiseしてきたのはgcloud本体ではなく、そのgemが使っているauth用のクライアントであるgoogleauthというgemの方だった。ソースを読んだところ、確かにrequestする部分でエラーを拾ってない事がわかった。で、gcloud側もこのエラーを拾ってwarpしてない、という状況だった。
正直このエラーをどちらかにwrapしてほしい。Faradayのエラーがそのままraiseされてくるのは流石に想定しづらいし、何よりgoogleauthもgcloudも、独自のエラークラスを定義し、主要なエラーについてはそれでwrapしてraiseするように実装してるのだから統一してほしいというモンである。
しかし、今回見つけた問題に関してはどちらが面倒を見るのが良いのだろうか?個人的意見としては、auth周りで起きている問題なのでgoogleauthに面倒見てほしい。が、googleauthを使ってるgcloud側で面倒見てもまぁそこまで筋は悪くはない。
というようなことを考えていたら、gcloudのrepositoryですでに似たような問題でお悩み相談しているissueが立っていた。なんでFaradayのエラーが飛んでくんねんという話とhttp requestのエラーくらいretryするべきではという話がごっちゃになってややこしいのだが、少なくとも議論の終盤の流れとしてgcloud側が何か対応をする気はないらしかった。
ならば、googleauth側でやるべきことが大体わかってる自分がやるのが良いだろうと思い、googleauthの方にPRを出し、先日approveされた。googleの中の人(多分)のレビューともなると色々細かいツッコミが入るかなと思ったが割とあっさりとapproveされた。まぁ大した修正じゃないしな。
まだマージされていないが、このPR自体はgcloudの方で立っていた件のissueの方で紹介されて、この件はgoogleauthの方に責任を持たせてgcloud側の上記のissue自体をcloseする提案が出ている。大した修正ではないにせよ、半年ぐらい停滞していた議論を少しでもすすめるきっかけを作れたという結果には満足しているし、自分自身も困っていた問題なので、ぜひマージされてほしい。たのむ。
今回の件は多分誰でも出来たことではあったし、ブログのネタにするにはあまりにしょうもない話だったかもしれない。しかし、自分が問題だと感じていることに対して解決策を提示して、それをほかの人が(しかもgoogleの人が)認めてくれた、という結果が、とても嬉しかった。OSSにcontributeしても1円にもならない訳だが、なんというか、多くの人がOSS活動をしている理由が少しだけわかった気がした。
なお、調子にのってopenid-rubyという2年ぐらいメンテされてなかったOpenID(Connectではない方)のクライアントにもbugfixのPRを送ってみた。もうcommiterも放置しててマージしてもらえないかなと思ってたらちゃんとマージしてもらえた。こちらはたまたま壊れてたの見つけたから直したよ、という程度だったが、自分にすぐできるのはこういうことなので身の丈に合った仕事と言えるのかも知れない。
今後も何か自分にできそうなことがあれば積極的にPRを送ってみようと思えた。多分その方が仕事でコードを書くよりも下手すると楽しい。
2017年3月29日追記
- google-auth-library-ruby の方は無事0.5.2に含まれました
技術書を読む意味について考えること
先日書いた記事が妙にバズってしまった。
別段新しいことをやったつもりはなく、NNは初めて勉強したけど専門外の知らないことを突然勉強するのは今に始まったことじゃないし、みんな普通にやってるもんだと思ってた。
それでもバズってしまったのは、あの書籍が発売直後からAmazonでずっと在庫がなくなるなどして相当の注目を集めていて、 Deep Learning
というワードがバズワード的に流行っていたから、という部分が大きいだろう。そうでなければ、あんな下手な書評がこんなにバズらない。
自分は無名なエンジニアであり、「とりあえずあの人が書いているんだから流行っているのだろう」と認識されるようなインフルエンサーでもない。ついでに言えばDeep Learning自体はもっと前、それこそ数年前から聞くようになった単語であり、それを今更勉強しているのは本当に今更感がある。本当は去年Tensor Flowがリリースされてちょっといじってみた時に深く勉強すべきだったと思っている。出遅れてしまったなぁという反省がある。今からキャッチアップして、TensorFlowやChainerを使って業務に活かすにはかなり時間がかかるだろう。ただ、それでも今のところはいくつかNNで解決するのに適していそうな問題がいくつか手元にあるため、今後も継続して勉強していきたい所である。
で、話はちょっと変わるのだが、人はどうして技術書を読むのだろうか。自分は技術書をそこまで読む方ではないのだが、基本的にNNのように知らない知識を効率よく勉強するためである。
逆にES界隈など、変化が激しい(今年は落ち着きつつあるようだが)分野については、ネット上の情報と書籍の情報での鮮度に差が激しいのでネット上で鮮度の高い情報を調べる事が多い。仕事においては後者に該当する分野の技術を使ってる事が多いので、ネットで公式リソースに直接当たるケースが圧倒的に多い。
特にruby界隈は、言語自体もgemもコミュニティ内で議論されている内容まで追わないと状況が分からないことが結構ある。前に、ruby2.1.x(パッチバージョンまでは覚えてない)でバグを踏んで、その情報はbugs.ruby-lang.orgのissueにしかなかったことがある(どれかは忘れたが)。単にググって見つかる情報だけではもう足りなくなってきている。それぐらい情報の更新頻度が高い。
ではなぜ技術書も読むのかというと、ある程度枯れて体系化された知識は技術書の方がよくまとまっている事が多いからである。リアルタイムに日々更新されるコミュニティの議論やmasterブランチのcommit logと比べると、いわば綺麗に編纂され直された歴史書とでも言うのだろうか。そういう感覚が自分にはある。歴史書には瑣末なことが書かれないように、本質的な内容だけがきれいにまとめられる余地がある。自分は技術書に対してそういうものを期待しているし、そういうものが書かれている技術書を中心的に読む傾向がある。
今年読んだもので言えば、TCP/IP, HTTP1.x, HTTP2.0の歴史と昨今のN/W界隈で話題になってることまで広く説明されている「ハイパフォーマンスブラウザネットワーキング」がまさに「歴史書」といった感じの本。@kazuhoさんのhttp2に関するスライドを読んでいてTCP/IPの輻輳制御の話がよく出てくるのだが、ネットワーク全然知らないので良くわからんということで手に取ってみた。非常に広く・深くといった感じで昨今話題になっていることを理解するのに最適な一冊だった。こういう、過去の経緯から最新の事情までを広く、かつ分野も広く知りたいような時には技術書というフォーマットが強いと特に感じた一冊でもある。
ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化
- 作者: Ilya Grigorik,和田祐一郎,株式会社プログラミングシステム社
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/05/16
- メディア: 大型本
- この商品を含むブログ (3件) を見る
あと技術書というか学術書だが、統計や機械学習といったアカデミックな分野での情報発信が根強い分野は学術書にしかないネタがまだまだ多いと感じているので、この分野はまだ書籍に優位性がある。
学術書、といっても今年は統計、機械学習関係と自然言語系の本しか買ってないのだが、一冊の値段が結構お高いので買うのに気合が必要だったりするのだが、大学に行って勉強するのに比べれば低コスト勉強できるのではないかと思う。
が、逆にアカデミックな分野は専門の人とディスカッションしたり質問したりしながら勉強しないと流石に厳しいなぁと感じる分野でもある。「データ解析のための統計モデリング入門」は初学者の自分でも分かりやすい部類の統計の本だと思うのだが、「こういう場合はどうだろう?」「ここはどういう意味だろう?」というクエスチョンマークを頭に沢山浮かべながらも調べる術がないので気合でゴリ押して読む感じになってしまうので、やはり大学の教科書的な使われ方を想定してるんだろうなという気はした。実際作者の久保拓哉弥先生は北大の准教授(出版当時で今は不明)なので、いつか直接この本に関する講義を受けてみたいなぁと思った(まぁ自分が関東にいる限り無理だろうけど…)
データ解析のための統計モデリング入門――一般化線形モデル・階層ベイズモデル・MCMC (確率と情報の科学)
- 作者: 久保拓弥
- 出版社/メーカー: 岩波書店
- 発売日: 2012/05/19
- メディア: 単行本
- 購入: 16人 クリック: 163回
- この商品を含むブログ (28件) を見る
何が言いたいかというと、そろそろもう独学での勉強が限界に来ている。
こんな私でもニューラルネットワークをスクラッチで実装できました(30歳 男性)
この記事はトレタ Advent Calendar 2016の22日目です。
21日目はswdhの ActiveRecordオブジェクトを関連ごとシリアライズしてデシリアライズするでした。
スナップショット的にその時点のモデルを関連モデル含めて保存したい、っていう要望はBtoBやってると結構遭遇しますね。テーブルをちゃんと正規化すればするほど難しくなるやつなのでgem化されてるとありがたいです。
さて、この記事ではゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装を読んでpythonに入門するところから初めてニューラルネットワークを実際に実装して見た所感を記述します。平たく言えば読書感想文です。
ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
- 作者: 斎藤康毅
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/09/24
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (18件) を見る
書籍「ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装」の概要
本の内容としては
- pythonの基礎文法
- パーセプトロン
- ニューラルネットワーク
- MNISTを使った手書き文字分類器を作るサンプルの解説
- ニューラルネットワークの学習方法
- 畳み込みニューラルネットワーク
- ディープラーニング
という流れ。
なお、本文中に出てくるサンプルコードはすべてgithubで公開されているので、写経するのがだるいという人でも安心だ。
読んで実装してみた所感
前提条件として、自分は機械学習は多少かじった程度の知識しかなく、ニューラルネットワークについてはパーセプトロンとの違いとバックプロパゲーションのぼんやりとした概念、ぐらいしか知らないレベルでこの本を手に取ってみた。あともちろんpythonも書いたことがなかった。
TensorFlowやChainerのMNISTサンプルを動かしてみたりもしたのだが、フレームワークを使うといまいち抽象度が高くて具体的に何をやってるかわからないと感じていた。(余談だが結構そういう声をよくネットで見かける)
そういう状態で読んで一通り実装してみたのだが、今までふわっとしていた「ニューラルネットワークとはこういうものか」というイメージがかなり明確になった。それが何によるものかということを以下述べていきたい。
なぜこの本が良いと思ったのか
この本の最大の特徴は、機械学習系の本だと省略されがちな数学の前提知識について1つ1つ丁寧に説明されている点と、それらが全て動く「コード」を持って説明されている点にあると感じた。
文字通り「ゼロから作る」ための本である。pythonを手元で動かせる環境さえあれば数学の知識がなくても問題ない、という機械学習系の入門書にしては非常にめずらしい位置づけの本である。
どのくらい「ゼロ」でも大丈夫か?体を張って試してみた
結論から言えば、高校数学なんて忘却の彼方という人でも全然問題無いと言える。
例えば、ニューラルネットワークでは結果を求めるまでに途中で行われる計算の流れを行列を使うとスッキリ書けるのだが、いきなり行列の積だけ書いて放置するようなことはしない。 まずは行列の積の計算の仕方(行列の掛け算ではどの要素とどの要素を乗じるのかという所から)から説明してくれる。NumPy特有の話もあるが、基本的には遠い昔高校時代に習ったような説明を受けることができる。
また、勾配降下法の説明をしている章では、微分の定義から始まり数値微分の計算方法を説明している。至れり尽くせりである。
しかも、それらは数式だけでなく、すべてpythonの実装がセットになっている。例えば数値微分を行う関数もサンプルコード上で下記のように実装されている。 *1
def numerical_diff(f, x): h = 1e-4 # 0.0001 return (f(x+h) - f(x-h)) / (2*h)
そのため、説明がよく理解できずとも、pythonの実装を読んで、写経して手元で動かしていじっているうちに計算手順のイメージを掴むことができる。
数値微分の実装は、引数をあれこれ変えて近似された値を計算で求められると、解析微分の公式だけを丸暗記していただけの微分がまた違うものに見えてきて非常に面白い。
コードを書いて動かして学ぶというアプローチについて
こういうアプローチは、数式よりもコードに馴染みがあるプログラマならではの方法かも知れないが、少なくとも自分はもともとコードを書いて動かした方が理解しやすい派なのでこの本のアプローチはかなりマッチしていた。
数学が得意な人にとっては、わざわざシンプルに表現された数式をプログラムに変換して動かして理解するという面倒なことをよくやるもんだという感想を抱くかもしれない。しかし、実際に自分でコードを書いて動かした結果を確認する学習方法は、プログラマにとって一番理解し易いアプローチではないかと思う。*2
一方で、説明がかなり細かいので、既知の知識と重複するところが多い人には本書は少々冗長に感じるかも知れない。 しかし、大学時代に数学を勉強していない筆者のような人間にとってはこういう基礎知識こそがありがたい。
まとめ
- 「プログラミングは普通にできるけど機械学習とかニューラルネットワークってなんか難しそうだな~」と思ってる人にこそ読んでほしい一冊。
- まだちゃんと理解できていない部分もあるので年末年始に改めて読み直したい。
- トレタ Advent Calendar 201623日目は私とよく昼食を一緒に食べに行くサーバーサイドエンジニアの出番です。
*1:https://github.com/oreilly-japan/deep-learning-from-scratch/blob/471ff64c25d27eaad58d8b5a9e787249db974d44/ch04/gradient_1d.py#L6-L8
*2:余談だが自分も統計モデルについての本を読んでいた時はポアソン分布の定義にしたがって確率を計算するクラスを実装してみたりしていた。 bitbucket.org