seri::diary

日常

英語のリーディング勉強方法についての振り返り

洋書の技術書や英語の論文を読むようになって3か月ぐらいになる。

とは言え、母語が日本語なので日本語の方が圧倒的にinputは早いため、読んでる本の言語比率は日本語:英語 = 8:2といったぐらいである。全然である。「洋書を読んでいる」なんて決して人前で言える量ではない。*1

ちなみに英語で読んでいる技術書は下記。パラパラとわかるところだけ読んでいるものもあれば最初から読んでいるものもある。もともと本は5~6冊をパラレルで読んでいくタイプなので洋書もそんな感じで読んでいる。

Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems

Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems

Distributed Computing: Principles, Algorithms, and Systems

Distributed Computing: Principles, Algorithms, and Systems

Big Data: Principles and Best Practices of Scalable Real-Time Data Systems

Big Data: Principles and Best Practices of Scalable Real-Time Data Systems

Java Concurrency In Practice

Java Concurrency In Practice

なぜ英語で読むのかと言えば、技術書に関しては翻訳がなかったり日本語版が絶版になっていたりするため。論文はそもそも基本的に英語しかない。

そのため今は英語のリーディング力を高めるために主に語彙を増やす勉強を中心にしている。

英語の教材としてTOEIC対策の単語帳を使っている。*2

TOEIC(R)TEST英単語スピードマスター NEW EDITION

TOEIC(R)TEST英単語スピードマスター NEW EDITION

手順としては以下のようにしている。大体これで40分ぐらいである。

  1. 1回の学習で50単語ぐらいを目標として覚える範囲を決める
  2. 例文を読んで、意味やニュアンス、類似語、例文を丸暗記するぐらい読み込む
  3. 解説が不十分だと思えば辞書を読んでニュアンスを覚える。
  4. 一通りやったところで赤シートを使って覚えているかどうかを確認する。覚えてなければその部分を集中してやる。
  5. 覚えた単語をざっくりノートに書きだして、それを眺めて意味やニュアンスがすぐに思いつくかどうかを再度確認。

こんな感じでやっているのだが、語彙力がなかなか伸びずに苦労している。 どのように苦労しているかと言えば大きく下記の2点である。

1. 覚えたかどうか分からない

それはともかく、この手の方法で単語を勉強してきたつもりだが、何というか本当に覚えたかどうか、つまり語彙力がついたのかどうか確認する手段があまりにも乏しい。確認できるのは英文を読んでいてその単語が出てきたときに「この単語見たことあるやつだ!」と思えた時か、commit logを書いていて「この場合はあの単語が使える!!!」というひらめきを感じた時ぐらいである。

それでいて2週間ぐらいだってから単語帳で同じ単語を眺めた時に「あれ、これなんだっけな…」となるケースも結構あり、覚えている率は肌感覚で1/4ぐらいであるのだが、果たして本当にそうなのかを定量的に計測する手段がない。これって単語テスト付きの単語帳でも使えばもっと正確に計測できるのだろうか?そういう単語帳買うべき??うーむ。。

2. しんどい

単語のみを覚える努力をしたことのある人ならわかってくれると思うが、使うか使わないか分からない単語を必死に覚えるのはなかなかにしんどい。

「なるほど!こういう言い回しがあるのか!」という発見はそれなりに楽しいにせよ、普段日本語で日常生活を送り日本語で仕事をしている人間にとってはやはり普段使いようがない知識である。どうしても仕事で疲れ切った頭にムチ打って図書館で必死に単語帳とにらめっこしていると純粋にしんどいと思うことも多い。どうして俺は生涯一回使うか使わないかってぐらいめったに見ない「embrace」みたいな単語の使い方を覚えているのか。他にやるべきことがあるのではないか、という気分にもなるが、とはいえ語彙力が貧弱であることは間違いないので頑張ってやるしかない。しかしどこか非効率だなという気分は拭えない。

こんなことを今年入ってからずっと続けてるので、かれこれ半年ぐらいはやってきた計算になる。しかし、いい加減この方法は間違っている気になってきた。

最近採用したやりかた

やり方を間違っている気になってきたので、単語帳作戦は一旦やめることにした。

代わりに、TOIEC Part5-7の問題集を解きまくって、分からない単語出てくる度に調べてメモって覚える方式に切り替えた。ネットで検索するとこっちの方が語彙力上げる手段としては効率が良いという意見もあるし、自分としてもまだ印象に残りやすいと感じている。しばらくはこの方法でやってみる。

また、技術書や論文に出てきた単語も覚えやすいということに気が付いた。 英文を読むとき、分からない単語を無視してとりあえず1センテンス読んで、それから分からない単語でどうしても類推できない単語だけ辞書を引くようにしたら「皆目分からない単語」だけをピンポイントだけで覚えられるようになってこれは効率が良いのではないかという気分になっている。「〇〇から遮断する」という動詞である「insulate」がアーキテクチャの解説でよく出てくるのだが*3、この単語は手持ちの単語帳の動詞コーナーには載ってなかった(索引がないので確定はできないが多分なかった)。そう考えるとやはり技術書に必要な英語は技術書を読みながら身に着けた方が早そうな気がする。

今のところリーディングさえできれば自分の用は事足りるので、もう何も考えずにいきなり英文を読み倒して分からない単語だけ辞書に当たる方が効率がよさそうである。

「英語学習にはまず単語帳が必要だ!」と思い込んでいたのは、大学受験時代の習慣というか思い込みみたいのが強かったからかなぁと思う。しかし、今や大学受験以上の語彙数力必要だとわかってる以上、異なるアプローチが必要なのは自明だよなぁと、自分の短絡さを反省する次第である。

*1:半々ぐらいになったら「趣味は洋書を読むことです」とか言っても差し支えないのではないだろうか。早く意識高い感じになりたい。

*2:ちなみにこの本、今amazonで調べたら結構辛辣なレビューがついていたのでTOIECの勉強にはあまり向いてないのかもしれない。。

*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のコードリーディングなど。今年はpythonscalaを今年学ぶ言語として勉強している。

健康の維持

どんなに優秀でも健康でない奴に重要な仕事は振られなくなる。残念ながらこれが人間の心理。人は細かいところをよく見ているもので、毎週月曜日に休んでたりすると必ず誰かがマークしている。コワイ。いわんや、高齢で体が弱いとか、ますます仕事が無くなりそうではないか。それをひっくり返すだけのバリューを出せればよいが、そうだとしてもやはり体調が悪いのは精神的によくないし、長期的にはモチベーションに関係してくる気がする。生涯現役目指すマンにとっては大きな壁となるであろう。

まずは体力ということで、最近忙しかった関係で通ってないけど(だめじゃん)ジムで筋トレしたり走ったりしている。むしろ走る方がメインか。なんでもいいけど運動は大事。運動と瞑想の習慣の無い者の末路はなんとやら、というのは多分正解。

瞑想も『サーチ・インサイド・ユアセルフ』を読んでからやってるが、1日の振り返りになって大変よい。1日に起きた出来事が頭に浮かばなくなるまで瞑想し続けてから寝ると変な気持ちを翌日まで持ち越さなくて済む。

あと、生えている最後の親知らずを先日抜いてきた。まだ少し痛い。だが、親知らずも放置したまま高齢になるとますます抜くのが難しくなるし、傷口が塞がるのも遅くなるし感染症にもかかりやすくなる、ということで今のうちに抜いておこうと思って抜いた。幸いにして真っ直ぐ生えていたので歯医者に着いてから10分もかからずに診察は終了した。この歳になるとこういう細かい体のメンテが大事じゃないかと思っている。

それ以外にやっていることとして、月1で温泉に行くとか。もちろんY氏直伝でN氏も絶賛していた交代浴をするのだ。

travel.spot-app.jp

千葉県野田市にある七光台温泉が好きで、自宅からだと電車と徒歩で片道2時間弱かかるのだが、その分土日に行ってもそこまで混んでなくて大変居心地がよい。都内の銭湯はいつ行っても混んでいてあまり好きではない。

nanakoudai.3riku.co.jp

今できていないこと

最近勉強会で登壇することがなくなってしまい、すっかりプレゼンスが下がっている。これはなんとかしないといけない。だが、今のところ発表できるネタと勉強会のテーマが合わなかったりして二の足を踏んでいる。なので基本的にブログやQiitaでのoutputをメインにしようと思うが、できれば今年中に最低一回はどこかで話したい。

あといい加減○○の人として認識されたいが、せいぜい「エモブログの人」とか(これは実際に言われたことがある)、「職業railsマン」程度なので(多分)、もう少し技術的なところでプレゼンスを発揮していきたい所存である。

その一環として、最近読んでいるsparkのコードリーディングの成果を一部qiitaに書き始めた。ある程度まとまったら第二弾を書く予定。

http://qiita.com/seri_k/items/363f5c1afdf63ca2f889qiita.com

*1:「そういう時に限ってcircle ciが障害起こしててビルドがコケて無念の中死ぬものである」というコメントを酒の席で頂いた

*2:今の会社に入ってから初めて1sprint内で何もデプロイできない経験をして結構ショックだった

自分がRubyMineでRails appを書く理由

基本、Rails appを書く時はIDE(RubyMine)を使っている(それ以外はatomvim)。

今の職場だとIDE使ってるの自分だけで、これまでもだいたい他の人はRails appを書く場合でもemacsvimatom、といった具合だった。Rails appはそういうエディタで書くのが普通らしい(自分の観測範囲においては)。

しかし、自分は仕事でrailsを書くようになってから3年ぐらいになるが、ずっとRubyMineを使っている。理由は下記。

  1. 自分で各種プラグインを入れなくても開発に必要な機能が最初から揃っているのでインストールするだけで開発がすぐ始められる。
  2. リファクタ機能が強力。メソッド名をファイルをまたいで一括で変更できるのが超絶便利。
  3. メソッド、クラスの定義元に一発でジャンプできる。使っているgemのソースを読みたくなったときも一発で手元のrails appからgemのソースへシームレスにジャンプできる。
  4. typoやsyntax erorrをエディタ上で教えてくれるので実行する前にミスに気が付ける。
  5. classやファイルをインクリメンタルサーチで検索してファイルを開くことができる。
  6. クラス構造のtreeを表示できる。1classが500行超えぐらいになるとこれがないとジャンプがつらい。

これらの機能はvimでもemacsでもプラグイン入れれば実現できるのかもしれないが、やり方を調べて設定ファイルを書いて、さらにトラブルが起きたときに自分で調査する手間を考えると、インストールすればすぐ使えて、万が一なんかあってもサポートが効く有料IDEの方がいいと思っているのでRubyMineをずっと使っている。

そこまでエディタにこだわりがないというか、正直なんでもいいと思っている。ただ、web appのメンテという仕事においては、できるだけ早く目的の箇所を探し出してコードを書く必要があるため、その効率だけを考えてエディタを選んでいる。その結果としてIDEに落ち着いている、という感じだろうか。プライベートだとC++Atomで書いてたりはするが、仕事だったらVS使ってると思う。

ちょっとだけOSSに貢献したらすごく新感覚だった話

普段は仕事でコードを書いていて、それでおちんぎんは貰えるし、こんな自分でも多少は社会の役に立っているのではないかなぁという実感がまぁ多少は持てる時もある訳で、それなりに満たされた生活をしている。サラリーマンなので、当然大人の事情でしんどい気持ちでコードを書いてる時も少なからずあるが、それでも仕事は仕事である。頑張って書くのである。そんな毎日。

そんな中、1円ももらえないし、役に立つかどうか良くわからんが、気になったのでやった、というような状況でコードを書いてみたら、不思議な事に仕事でコードを書くのとは全く異なる満足感が得られてめっちゃテンション上がったので、その辺の話をしたい。

ある日、BigQueryにアクセスしている部分で突然エラーがraiseされてトラブったので調べてみたところ、GCPruby clientであるgcloudというgemがGoogleaccess 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日追記

技術書を読む意味について考えること

先日書いた記事が妙にバズってしまった。

別段新しいことをやったつもりはなく、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輻輳制御の話がよく出てくるのだが、ネットワーク全然知らないので良くわからんということで手に取ってみた。非常に広く・深くといった感じで昨今話題になっていることを理解するのに最適な一冊だった。こういう、過去の経緯から最新の事情までを広く、かつ分野も広く知りたいような時には技術書というフォーマットが強いと特に感じた一冊でもある。

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

あと技術書というか学術書だが、統計や機械学習といったアカデミックな分野での情報発信が根強い分野は学術書にしかないネタがまだまだ多いと感じているので、この分野はまだ書籍に優位性がある。

学術書、といっても今年は統計、機械学習関係と自然言語系の本しか買ってないのだが、一冊の値段が結構お高いので買うのに気合が必要だったりするのだが、大学に行って勉強するのに比べれば低コスト勉強できるのではないかと思う。

が、逆にアカデミックな分野は専門の人とディスカッションしたり質問したりしながら勉強しないと流石に厳しいなぁと感じる分野でもある。「データ解析のための統計モデリング入門」は初学者の自分でも分かりやすい部類の統計の本だと思うのだが、「こういう場合はどうだろう?」「ここはどういう意味だろう?」というクエスチョンマークを頭に沢山浮かべながらも調べる術がないので気合でゴリ押して読む感じになってしまうので、やはり大学の教科書的な使われ方を想定してるんだろうなという気はした。実際作者の久保拓哉弥先生は北大の准教授(出版当時で今は不明)なので、いつか直接この本に関する講義を受けてみたいなぁと思った(まぁ自分が関東にいる限り無理だろうけど…)

何が言いたいかというと、そろそろもう独学での勉強が限界に来ている。

こんな私でもニューラルネットワークをスクラッチで実装できました(30歳 男性)

この記事はトレタ Advent Calendar 2016の22日目です。
21日目はswdhActiveRecordオブジェクトを関連ごとシリアライズしてデシリアライズするでした。

スナップショット的にその時点のモデルを関連モデル含めて保存したい、っていう要望はBtoBやってると結構遭遇しますね。テーブルをちゃんと正規化すればするほど難しくなるやつなのでgem化されてるとありがたいです。

f:id:serihiro:20161221233653j:plain

さて、この記事ではゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装を読んでpythonに入門するところから初めてニューラルネットワークを実際に実装して見た所感を記述します。平たく言えば読書感想文です。


書籍「ゼロから作るDeep LearningPythonで学ぶディープラーニングの理論と実装」の概要

本の内容としては

という流れ。

なお、本文中に出てくるサンプルコードはすべて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

自分はストレス耐性が高い方ではなく、無駄に色んなことに気を揉んでしまう性格のせいか疲れを溜め込みやすい性格のようだ。そういうことに気づいたのはつい最近である。最近ではあるが、最近そうなったか?というとそうでもないように思う。振り返れば中学ぐらいの頃から余計なものをたくさん背負う癖があったようにも思うし、そうでなければ(全くそういうのに向いてないのに)生徒会役員とかやらなかっただろうなと思う。

心が折れるというのは面白い表現だと感じる。普段は折れていないのだろうか。まっすぐなのだろうか。それとも真っ直ぐでも折れてもない、いい塩梅に曲がっているのだろうか。そういう形状が通常時ならば、枯れ枝のようにポキっと折れていたら、それはまぁ誰が見たってまともな状態ではないという兆候なのだろう。

自分はどうか。自分のことは良くわからない。しかし、もう、特定のことしかやっていたくないと思うことが増えた。仕事に行かずにこれだけをやっていたい。それは本を読むことだったりコードを書くことだったり、或いは延々と映画を観たいとか旅行に行きたいとか、あるいは何の予定もなくサンフランシスコに行ってスタートアップ訪問したいとか、突拍子もないことだったりもするのだけれど、何かこう色々とうまく回せなくなってきていると感じる。この状況をどう捉えればいいか自分でもよう分からない。

がんばって客観的に自分の状況を鑑みるに、どうにもこうにも消化不良を起こしているような心情が占めているように思う。自分では納得してないけどやらなきゃならん、やるぜー、うぉーっ、と頑張ってきたことが、ある日突然外的要因により、それはもうどうしようもないくらいの力によって、ポシャってしまう。そういうことがなぜか自分の身にはたくさんあった。

そういうことが何度かあって、結果として、自分は何も成果を残せていない。残せていないから、何も自分で自分を褒める要素なんてない。当然誰からも評価はされない。新たに得たものは何もない。一応会社員としてはこれはまずい。種を植えることになって、自分はいつものように土を作っていたが、やーそろそろ種を植えようかね、というところで、畑は使われなくなってしまった。使われないから自分は畑をもとの状態に戻した。

気がつけば、確実に結果を残せることを自分で身つけて拾って片付けるようなことに自然と意識が傾き始めた。必然であったし無意識でもあったのだが、結果が残せるということは精神衛生上とても良いことだった。そうか、何かの本に書いてあったけど、小さな勝利を積み重ねるのは、だから大事なのか、ということに気付かされる。

プログラミングで言えば、細かいバグを直したり、リファクタリングしたり、依存しているライブラリのバージョンを(特に理由もなく)上げてみたり、テストが足りないところでテストを書いてみたりといった、まぁ概ね自分やらなきゃならないタスクではないとは思うような、間違えようのないタスクをやることが心の平穏につながる。どうやったってうまくいくし、自分の成果として形に残る。これは素晴らしいことだ。面白くはないけれど。

そうこうしているうちに、もしかしたら、少しは育つかもしれない種みたいのが何とか見つかってきている。

自分は土は作れる。だが種がなかった。だけど種さえあれば、何とかなるのではないか。そういう気持ちが、最近になって、本当に久しぶりなのだがようやく芽生えてきた。

そういうものをどうにかこうにか育てられればと願う。 願うだけでなく、芽が出るぐらいまでは、まぁ自分で面倒を見てやりたいと、そう思う。畑はいつでも移ることができるが、多分育てられる種は見つけた場所でしか育てられないと思うので。