新米Webエンジニアにオススメの基礎教材

自分も気付けば社会人のエンジニアとして2年目になったので、ここらで自分が読んでよかったWebエンジニアとしての基礎教材をまとめてみたいと思います。なお、本記事で扱う「Webエンジニア」という言葉は、具体的には「Web技術を扱うバックエンドを軸としたエンジニア」という意味を指しています。本記事で挙げる教材の多くは学生時代に読みましたが、社会人となった今でも折に触れて読む返す機会の多い、自分の基礎となっている教材です。と言っても定番の教材ばかりですが。

設計

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

メソッドの命名方針のようなソフトウェア開発におけるミクロの視点の設計指南書です。この手の書籍にはCODE COMPLETEという名著がありますが、かなり重厚(その分内容も重厚)なので、それに比べるとページ数的にもあっさりとした本書は手に取りやすくオススメです。

Rubyを題材にOOPの思想や作法について書かれた書籍。コードをリファクタリングしていく形式で説明が展開していく形式で書かれており分かりやすいです。

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

Javaを題材に書かれたOOPデザインパターンの書籍。これ以外だとGang Of FourによってC++smalltalkで記された書籍などが古典的名著として有名です。GoやRustなどが流行りつつある現代のソフトウェア開発におけるOOPデザインパターンの有用性には議論があります(以下URL参照)し、この書籍でJavaで書かれたデザインパターンRubyなどの別のOOP言語でそのまま全て書き換えられるわけでもありません。それでも、OOPの思想や作法の理解を助けてくれるという点においてデザインパターンを学ぶことは今尚価値があると個人的には思います。 一時期プログラミングのデザインパターンというものが大流行しましたが、現在ではどのように評価されているのでしょうか? - Quora

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

ソフトウェアアーキテクチャの設計指南書。前半でコンポーネントの原則などの説明がなされ、後半でやっとアーキテクチャパターンとしてのクリーンアーキテクチャが登場します。説明がくどい個所もありますが非常に良書。

データベース

Webエンジニアのための データベース技術[実践]入門 (Software Design plus)

Webエンジニアのための データベース技術[実践]入門 (Software Design plus)

Webエンジニアのためのデータベース概論といった感じの書籍。MySQLを中心にSQL、DBの冗長化、運用、パフォーマンスチューニングといったRDBに纏わる一通りのトピックを扱っています。データベース技術を俯瞰する上で良い書籍。NoSQLにも少し言及しています。

SQL 第2版 ゼロからはじめるデータベース操作 (プログラミング学習シリーズ)

SQL 第2版 ゼロからはじめるデータベース操作 (プログラミング学習シリーズ)

SQLの教材。RDBの種類の違いによる文法や機能の違いにも言及されています。

達人に学ぶDB設計 徹底指南書

達人に学ぶDB設計 徹底指南書

有名なRDBの設計指南書。説明がわかりやすいです。

SQLアンチパターン

SQLアンチパターン

実際の開発現場で出会う様々なデータのユースケースからそのためのDB設計のアンチパターンを列挙しつつ、より良い設計のための指針を解説してくれる良書です。

インフラ

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

OSについて実際のコードを使った実験やイラストを用いてわかりやすく説明した書籍。

マスタリングTCP/IP 入門編 第5版

マスタリングTCP/IP 入門編 第5版

ネットワーク関連技術に関する定番書。自分の場合大学の授業の指定教科書だったのでこれで勉強しましたが、もっと良い書籍がありそうな気もしています。

Goならわかるシステムプログラミング

Goならわかるシステムプログラミング

Goのサンプルコードを使ってOSやネットワークを学ぶ書籍です。上2冊を読んだ後に読むと更に理解が深まります。近年Goを使って低レイヤーを学べる書籍がたくさん出てきています。

はじめてUNIXで仕事をする人が読む本

はじめてUNIXで仕事をする人が読む本

実際に業務で扱うという視点でUNIXの機能と使い方について解説した書籍。

新しいシェルプログラミングの教科書

新しいシェルプログラミングの教科書

シェルスクリプトに関する書籍。古い書籍では扱われていないbash連想配列なども扱っています。

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

コンテナ技術が開発現場で広く使われるようになったのはここ数年ですが間違いなくこれからますます使われていくであろう技術でありエンジニアの必須科目となりつつあります。本書はDockerとKubernetesについて実際の開発現場の視点を踏まえつつ基本から解説した書籍です。コンテナオーケストレーションとしてDocker Swarmは実際の開発の現場ではほとんど使われておらず、kubernetesデファクトスタンダードとなりつつありますが、一般的な開発現場でよく使われているMySQL、ninx、jenkinsなどの技術を使った構成のWebアプリの構築も学べるのでSwarmの章もやっておいて損はないと思います。

これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座

クラウド技術の知識は現代のエンジニアの必須項目です。Udemyの本講座はAWSの認定ソリューションアーキテクトの資格試験突破を想定した講座ですがAWSの基礎的な考え方や使い方を一通り抑えることができます。また、AWSはterraformなどのツールを使わない限り、GUI上でポチポチ操作することになりますが、その点書籍より動画の教材の方が適していると思います。

dev.classmethod.jp AWSを用いたterraformに関する貴重な書籍。技術書典で販売されたものだがBOOTH - 創作物の総合マーケットでpdf版を購入できます。 Infrastructure as Codeによる構造的な記述に加えてAWSのベストプラクティスに関する解説もついているため、AWSに関する知識の整理にもなり、非常にオススメです。

入門 監視 ―モダンなモニタリングのためのデザインパターン

入門 監視 ―モダンなモニタリングのためのデザインパターン

監視について体系的にまとめた貴重な書籍です。インフラからフロントエンドまで広くカバーされています。

Web技術

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

定番書。HTML, HTTPの仕組みやAPIの設計といったWebの基本知識を広く扱っています。

ビジュアルデザインではなくコードとしてのCSSの設計指南書。プログラミング言語同様、CSSもまたCSSなりの作法があり、それを弁えないとソフトウェア開発と同じような負債を産むことになるため、少しでもCSSを扱う場面があるのであれば読んでおいて損はないと思います。

セキュリティ

www.ipa.go.jp webセキュリティといえば徳丸本が定番ですが、いかんせん重厚で読み切るのには根気が必要です。とはいえ、事業を再起不能にさせる自体も起こしかねないセキュリティに関する基礎知識は真っ先に押さえておくべきです。徳丸本を読む前に一先ず最低限の知識を抑えたい、という人にはIPAが無料で配布している上記のURLの資料及びその別冊は必要な知識がコンパクトにまとまっているのでオススメです。

組織・チーム

DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する (DEV Engineer’s Books)

DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する (DEV Engineer’s Books)

DevOpsに関する書籍で思想だけではなく具体的にどのツールをどのように使えば実現できるのか記した数少ない書籍です。最先端とは言えませんが比較的モダンなツールで説明がなされています。

昨年話題になった書籍。開発チームのマネージャーだけではなくエンジニアにとっても良い書籍です。

アジャイルサムライ−達人開発者への道−

アジャイルサムライ−達人開発者への道−

アジャイル開発の入門書です。Web業界で自社サービスに携わる以上、アジャイルの知識は最低限押さえておきたいところです。

permutation importance 〜特徴量の重要度の測り方〜

概要

Random Forestや勾配ブースティングなどの決定木アルゴリズムのアンサンブル手法の強みは性能の高さの他に入力に用いた各特徴量の重要度を算出できることにあります。各特徴量の重要度の大きさを元に特徴量選択を見直し、モデルの性能の向上を図ることもデータサイエンスでは一般的です。 決定木アルゴリズムのアンサンブル手法では不純度(デフォルトではジニ不純度)に基づいて木を分割しています。scikit-learn, xgboost, lightGBMなどのライブラリで feature_importances_メソッドで算出する特徴量の重要度は学習時に使用した不純度に基づいたものです。この重要度は gini importancemean decrease impurityと呼ばれます。しかし、算出した各特徴量の重要度の値の比は性能にどれだけ貢献しているかとは一般的には関連がありません。そこで本記事でとりあげるのがpermutaion importanceです。

permutation importance

permutation importanceはジニ不純度などの分割手法にも依存しない非常にシンプルな特徴量の算出手法です。

  • 簡単のためRandom Forestに入力するデータとして特徴Aと特徴Bの2つの特徴を持つデータを考える。
  • まず、データをtrainデータとvalidation dataに分ける。trainデータの特徴A,Bを学習させ、モデルを訓練する。
  • 訓練後validation dataを使用してモデルの性能をタスクに適切な評価手法で測定する(分類タスクであればaccuracy, 回帰タスクであればR2 scoreなど)。この時の性能値をbaselineとする。
  • 続いてtrainデータの特徴Aの値をランダムにシャッフルしてから訓練し、その性能をvalidationデータで測定する。
  • 同様に特徴Bの値をtrainデータの特徴Bの値をランダムにシャッフルしてから訓練し、その性能をvalidationデータで測定する。
  • 各特徴をランダムにシャッフルした時にbaselineに比べて性能がどの程度落ちたかを計算することで各特徴がどのくらい性能に貢献しているかを正確に算出する。

f:id:internetz:20181209220521p:plain

ポイントは特徴量をランダムにシャッフルすることで、特徴のデータ分布を変化させずに特徴の性能への貢献をゼロにしているところです。

使いどころ

permutaion imporanceを用いて各特徴の性能への寄与を正確に算出することができることがわかりましたが、ではその使いどころはどこでしょうか。ここでは一つユースケースを提案したいと思います。例えば、random forestで訓練した回帰予測モデルがある実システムで毎分1回推論し、その予測値とそのモデルの予測性能をシステムが使用しているとします。推論時にはその1分前にシステム内で生成されたログデータを特徴として入力に用いているとします。しかし、システムの仕様上ログデータの一部が欠損することもあり、入力すべき特徴が揃わないことがあります。この時に各特徴が欠損した場合どの程度予測性能が落ちるのかpermutation importanceで分かっていれば、特徴の欠損による性能の変化を考慮したシステム運用ができます。

実装

実際にrandom forestでpermutation importanceを算出してみます。上で説明した通り、permutation importanceのアルゴリズムは非常にシンプルであるため実装を簡単ですが、random forestでpermutation importanceを算出できるpythonライブラリがあるので今回はそのライブラリを使用してみます。

github.com

ライブラリのインストール

pip install rfpimp

簡単のためscikit-learnにプリセットされているデータセットであるBoston house-prices(ボストン市の住宅価格)の全てのカラムをそのまま(特徴設計せず)入力データとして使用し、Random Forestを用いた住宅価格の回帰予測モデルを構築した後permutaion importanceにより、各特徴(=データセットのカラム)が性能にどの程度貢献しているか算出し、可視化します。 ソースコードは以下。

import pandas as pd
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from rfpimp import *


#データセットを読み込み、入力データと目的変数のデータを9:1比でtrainデータとvalidationに分割
boston = load_boston()
x_data = pd.DataFrame(boston.data, columns=boston.feature_names)
y_data = boston.target
x_train, x_val, y_train, y_val = train_test_split(x_data, y_data, test_size=0.10)

# trainデータを用いてRandom Forestを訓練
forest = RandomForestRegressor()
forest.fit(x_train, y_train)

# validationデータを用いてR2-scoreによるpermutaion importanceを算出及び可視化
imp = importances(forest, x_val, y_val)
vizualization = plot_importances(imp)
vizualization.view()

以下の図が得られました。 f:id:internetz:20181209220529p:plain

書評「データサイエンティスト養成読本 ビジネス活用編」

データサイエンティスト養成読本シリーズの新刊である「データサイエンティスト養成読本 ビジネス活用編」が今週発売されたので早速kindleで購入して読んだ。せっかくなので僭越ながら書評を認めてみたいと思う。

データサイエンティストに必要とされるスキルセットはデータサイエンススキル・データエンジニアリング・ビジネススキルの大きく3つである、というのはよく耳にする話だ。 前2つ(データサイエンススキル・データエンジニアリングスキル)に関して言えば、機械学習やデータサイエンティストブームにある近年、それらを学ぶための書籍は数多く発刊され、何年か前に比べれば大変勉強しやすい世の中になったといえる。しかし、3つ目のビジネススキルを取り上げた書籍はまだまだ少ないというのが現状だ。また、数少ないその類の書籍も多くの場合はビジネスでどこに応用するとどのような成果が得られるか、といったトピックが中心であり、業務プロセスやプロダクトマネージメント、組織作りといった内容を取り上げた書籍になるとさらにぐっと数が減ってしまう。(その数少ないうちの一冊が「仕事で始める機械学習」だろうか。)

そもそもAI・データサイエンティスト・データドリブンといったワードが持て囃されるようになったのはここ数年の話だ。国内の大手IT企業を見てみてもそれらを専門とする部署を立ち上げたり、人材の採用に注力し始めたのはここ5年ぐらいという印象である。(とは言え、私は新卒一年目なので当時を詳しくは知らない。だが、今の会社や学生時代にインターンをしていた数社の社員の話を聞く限りではどうやらそのようだ。) そのため、業界全体としてまだ試行錯誤を繰り返しているところも多いのか、蓄積された知見が外部に共有されるに至っていないのかもしれない。だからこそ、ビジネス活用に必要とされる業務プロセス、プロダクトマネージメント、組織論といったデータサイエンティストに必要とされるビジネススキルの側面を広く扱った本書は貴重な一冊だ。

本書はシリーズを通して章ごとに異なる著者が担当する体裁を取っている。個人的な考えとしては、技術や理論を書籍で学ぶ意義の一つはそのテーマを体系的あるいは段階的に学べることにあると思っている。ところが、著者が章ごとに異なると、書籍としての一貫性が崩れてしまい、体系的に学ぶには厳しい場合が多い。その観点から言えば、データサイエンティスト養成読本シリーズはあまり好んで読むタイプの書籍ではなかった。しかし、シリーズ新刊の本書は技術や理論ではなく、ビジネス活用に限定したものである。しかも知見があまり共有されていないトピックであるため、複数の著者によって複数の視点で語られるのはそれはそれで意義のあることだといえるだろう。

本書は全10章で構成されており、1~3章はデータサイエンス業務の進め方やプロジェクトの回し方、4~8章はデータ組織論、9~10章はPeople Analyticsとざっくり区分できる。(あくまでざっくり。)

社会人一年目の新米である私にとっては1~3章が現在の業務に通ずるところが多く、大変参考になった。データサイエンス業務や機械学習プロジェクトではどうしても不確実性がつきまとう。この非常に厄介な、しかし避けて通ることができない不確実性との向き合い方を学ぶことができるだろう。分析というよりデータエンジニア・機械学習エンジニア寄りの私からすると特に第3章は学びが多くあった。一般的なソフトウェア開発とは異なる不確実性を伴う機械学習プロジェクトをどう進めるべきか、というプロダクトマネージメントや開発プロセスの作法を学びたい人は一読することをぜひお勧めしたい。

4~8章に関しては、各社の組織事例を組織論的観点で知ることができるので大変興味深い。やはりデータを活用していくにはデータサイエンティストなどの専門職だけが理解しているだけでは限界があり、社内にデータ活用の文化を醸成させ、組織として取り組んでいく必要性を改めて感じた次第である。

9~10章はPeople Analyticsへの適用に関してである。働く側としてもより公正な人事評価のためにはまだまだ改善の余地があると感じる。データを活用したアプローチとしてぜひHR職の方々の参考にしていただければと思う。

章が違えどトピックが少し被っている部分もあり、異なる著者による類似した内容の記述が散見されるが、複数の著者によって何度も語られる事項ということはそれだけ重要である、というふうに受け止めるといいのかもしれない。 本書は全体を通して数式やソースコードは一切登場しないこともあり、データサイエンスの専門知識のない人たちも読める内容が多いので、データ活用に関心のあるビジネスサイドの人たちにもぜひお勧めしたい一冊だ。

データサイエンティスト養成読本 ビジネス活用編 (Software Design plusシリーズ)

データサイエンティスト養成読本 ビジネス活用編 (Software Design plusシリーズ)

Google colablatoryの無料TPU上でtensorflowのKeras APIで実装したCNNを動かしてみる。

久しぶりにDeep Learningを使いたいと思い、兼ねてより気になっていたが今まで使うタイミングがなかったGoogle colabolatoryの無料TPU(※ ただし、12h以内)の上でCNNを動かしてみる。本記事執筆の時点ではTPU対応の深層学習フレームワークはtensorflowのみのようだ。tensorflowは計算グラフがやや書きにくいのだが、近年tensorflowはkeras APIを提供し、抽象化した書き方ができるようになったり、eagar executionというモードではpytorchやchainerのようなDefine by Runの書き方も可能になり、大分扱いやすくなった。そこで本記事ではtensorflowのKeras APIを使ってTPU上でCNNを使ってMNISTの分類タスクの学習をやってみる。

実装

まずは全体のコードを眺めてみましょう。

import tensorflow as tf
from tensorflow.contrib.tpu.python.tpu import keras_support
import os
from keras.datasets import mnist
from keras.utils import np_utils

batch_size = 1024 #バッチサイズは大きくする 
num_classes = 10
epochs = 12

img_rows, img_cols = 28, 28

(x_train, y_train), (x_test, y_test) = mnist.load_data() # Kerasでデータセットの取得

x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
    
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

y_train = y_train.astype('int32')
y_test = y_test.astype('int32')
y_train = np_utils.to_categorical(y_train, num_classes)
y_test =  np_utils.to_categorical(y_test, num_classes)

# CNNのモデルを構築
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Dropout(0.25))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(num_classes, activation='softmax'))

# TPU用にモデルを変換
tpu_grpc_url = "grpc://"+os.environ["COLAB_TPU_ADDR"]
tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver(tpu_grpc_url)
strategy = keras_support.TPUDistributionStrategy(tpu_cluster_resolver)
model = tf.contrib.tpu.keras_to_tpu_model(model, strategy=strategy)

model.compile(loss=tf.keras.losses.categorical_crossentropy,
              optimizer=tf.keras.optimizers.RMSprop(),
              metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs,
          verbose=1, validation_data=(x_test, y_test))

# 性能評価
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

TPUを使用するためには

まず、TPUを使用する場合コード内で構築したモデルをTPU用に変換する必要がある。 変換のための処理は以下の4行である。

tpu_grpc_url = "grpc://"+os.environ["COLAB_TPU_ADDR"]
tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver(tpu_grpc_url)
strategy = keras_support.TPUDistributionStrategy(tpu_cluster_resolver)
model = tf.contrib.tpu.keras_to_tpu_model(model, strategy=strategy)

続いて ランタイムランタイムのタイプを変更を押す

f:id:internetz:20181102015531p:plain:w300

TPUを選択し、保存

f:id:internetz:20181102015706p:plain:w500

これだけでTPUが使用する準備が完了。 あとはコードを実行するだけである。

結果は、1分足らずでMNISTを12epoch回して精度99%を叩き出すことができた。

注意点

  • kerasはデータセットの取得と、出力のカテゴリをone-hot encodingする前処理のためのみに使用し、それ以外はtensorflowのKeras APIを用いている。tensorflowもkerasもGoogle Colaboratoryに元々インストールされているので一切のセットアップは要らない。
  • TPUを使用する場合バッチサイズは大きくするのがポイントである。実はTPUはバッチサイズが小さいとGPUよりも遅い。batch_size = 128で学習してみたところ 、TPUはGPUに比べて3倍ほど処理が遅いが、batch_size = 1024ではTPUはGPUの2倍ほどの速さとなった。
  • 当初optimizerにtensorflowのkeras APIではなく、純粋なkerasのoptimizerメソッドを使用していたら、TPU使用の時のみエラーで動かないケースがあったので注意。