dondakeshimoの丸太

データサイエンス/Webアプリケーション/サッカー

機械学習の基礎的な知識についてざっくりとしたまとめ

メリークリスマスイブ!
dondakeサンタによる重ためのクリスマスプレゼントです!

(学術的な)機械学習の基礎

現在、深層学習について勉強中です。 読んでいる書籍は以下になります。

今回、第一部がようやく終わったということで、少し振り返ります。 第一部では下記エントリーの数学の基礎部分と数値計算の基礎、 最後に機械学習の基礎について学びました。

went-went-takkun135.hatenablog.com

機械学習の基礎についてはkaggleに代表されるような技術的なものでも、 企業で使われているような実際的なものでもなく、 あくまで理論的なものになります。 そのため確率やら統計やらの話ばかりで多少イメージしづらかったですが、 論文等を読む際のしっかりとした基本ができたかと思います。 自分のために非常にざっくりと忘備録をつけていきます。

目次

学習アルゴリズム

学習の定義

「コンピュータプログラムは、性能指標Pで測定されるタスクTにおける性能が 経験Eにより改善される場合、そのタスクTのクラスおよび性能指標Pに関して 経験Eから学習すると言われている」

Mitchell(1997)

タスク T

一般的なタスクを列挙する

  • 分類
  • 欠損値のある入力の分類
  • 回帰
  • 転写
  • 機械翻訳
  • 構造出力
  • 異常検知
  • 合成とサンプリング
  • 欠損値補完
  • ノイズ除去
  • 密度推定

性能指標 p

機械学習アルゴリズムの能力を評価するためのものが必要である。 例えば、モデルの精度や誤差率などがこれに該当する。 学習に用いた訓練集合とは別のテスト集合を用いて評価する。

経験 E

機械学習アルゴリズムは大きく 教師あり学習教師なし学習 に 分類されるが、それらの厳格な境界や定義はない。 学習アルゴリズムはデータ集合を経験することで学習する。

線形回帰

学習アルゴリズムの中でシンプルで有名な例として線形回帰を取り上げる。

 \hat{y} = \mathbf{w}^{\mathrm{T}} \mathbf{x}

 \mathbf{w} は重みと呼ばれるパラメータであり、  \mathbf{x} は特徴量である。 訓練集合において、予測と正解の 平均二乗誤差 を最小化するような重みを求めることで、 データ集合からモデルが経験するということになる。 線形の簡単なモデルを扱っているため、微分方程式が正規方程式として知られる形になり、 一意に解が求まることがわかっている。

 \hat{y} = \mathbf{w}^{\mathrm{T}} \mathbf{x} + b

上記のようにインターセプト b を加えたものを線形回帰として扱うこともある。 この場合、  b はバイアスと呼ばれる。統計のバイアスとは異なる。

容量、過剰適合、歌唱適合

この章は汎化に対する話となる。 訓練集合から訓練誤差が最小になるように学習を行うのに対し、 汎化性能を測定するためにはテスト集合から汎化誤差(テスト誤差)を計算する。 訓練集合とテスト集合についてはi.i.d.仮定をおいた上で、学習アルゴリズムが目指すことは

  1. 訓練誤差を小さくする
  2. 訓練誤差とテスト誤差の差を小さくする

この二つの要素は機械学習における二つの中心的な課題に相当し、 それぞれ 過少適合過剰適合 と呼ばれる。 これらの度合いは モデルの容量 を変化させることで制御する。 任意の高い容量という最も極端な状態に到達するには、 ノンパラメトリックモデル の概念を導入する。パラメータが存在しないため、モデルの容量を縛る要素が存在しないモデルである。

ノーフリーランチ定理

データを生成する分布全てを平均すると、 どのアルゴリズムも過去に観測されていない点を分類する際の誤差率は同じになる という定理。 全ての分布を平均した場合、他の機械学習アルゴリズムよりも普遍的に良いと言える 機械学習アルゴリズムは存在しないと主張している。

正則化

モデルの容量を変更する以外で過少適合、過剰適合を制御する方法として 正則化 があげられる。 正則化とは他の解に対して優先度を表現する方法の総称である。 一般的には正則化項と呼ばれるペナルティをコスト関数に追加することでモデルを正則化する。

ハイパーパラメータと検証集合

ほとんどの機械学習アルゴリズムにおいて、挙動を制御するための設定値が存在し、 それらは ハイパーパラメータ と呼ばれる。 最適なハイパーパラメータを選ぶために 検証集合 が必要になる。 検証集合は訓練データから構成される。

ほとんどのデータ集合は訓練集合とテスト集合に分けられているが、 その中の訓練集合を訓練集合と検証集合に分割する。 訓練集合でモデルを学習、検証集合でハイパーパラメータの最適化を行い、 テスト集合でモデルの汎化性能を測定する。

定量、バイアス、バリアンス

点推定量

関心のある量について「最良の」予測を一つ提示する試みである。

バイアス

 \mathrm{bias}(\hat{\theta}_m) = \mathbf{E}(\hat{\theta}_m) - \theta

 \mathrm{bias}(\hat{\theta}_m) = 0 になるものは不偏と呼ばれ、好まれる推定量である。

分散と標準誤差

定量のバリアンスとは単に推定量の分散である。 推定量の分散や標準誤差は、潜在的なデータ生成過程からデータ集合を別々に再サンプリングする際に、 データから計算した推定量がどのように変化するかを示す尺度を提供する。

平均二乗誤差を最小化するためのバイアスとバリアンスとのトレードオフ

バイアスは関数やパラメータの真の値からの期待偏差を測定する。 バリアンスはデータのサンプル化の方法に起因すると考えられる期待推定力の偏差を測定する。 平均二乗誤差はこれら二つの誤差を組み込んだものである。

 \mathrm{MSE} = \mathbf{E} [ ( \hat{\theta}_{m} - \theta )^{2} ] = \mathrm{bias} ( \hat{ \theta }_{m}^{2} ) + \mathrm{Var} ( \hat{\theta}_{m} )

バイアスとバリアンスの関係は、モデルの容量や過少適合、過剰適合という機械学習の概念と 密接に関係している。

最尤推定

最尤推定を解釈する方法の一つとして、最尤推定は訓練集合で定義される経験分布とモデル分布の差を 最小化するとみなす方法がある。 最尤法は負の対数尤度(NLL)の最小化、交差エントロピーの最小化、KLダイバージェンスの最大化 として捉えることができる。

ベイズ統計

点推定に対し、予測を行う際に  \theta の取りうる値全てを考慮するものが考えられる。 この手法はベイズ統計の分野となる。 事前確率分布を先験的に仮定し、事例の経験によって、その分布を書き換えていくことで 値の分布を推定する。

最大事後確率(MAP)推定

パラメータの完全なベイズ事後分布を用いた推定を行うことが最も理にかなった手法ではあるが、 点推定を行うことが望ましい場合も多い。これを行う方法の一つとしてMAP推定が挙げられる。

教師あり学習アルゴリズム

確率的教師あり学習

最終的な出力を0~1の値に押し込むことで確率を予測することができる。

サポートベクトルマシン

線形回帰をベースとして、カーネルトリックと呼ばれる技法を用いることで、 非常に高い性能を発揮した手法。 データ集合が大きい場合、訓練の計算コストが高くなってしまうというデメリットがある。

その他の教師あり学習アルゴリズム

  • k近傍法
  • 決定木

教師なし学習アルゴリズム

古典的な教師なし学習はデータの、より単純な表現を探す手法ということができる。 より単純なに関する定義として

  • より低次元な表現
  • 疎な表現
  • 独立した表現

の三つが挙げられる。

主成分分析(PCA)

元の入力よりも次元が低い表現を学習し、 また成分が互いに線形な相関を持たない表現 (独立ではない)を学習する。 詳細は割愛。

k平均クラスタリング

k個のクラスタに分割し、疎な表現を実現する。 詳細は割愛。

確率的勾配降下法

1回のステップに対し、訓練集合の全てを用いては計算コストが大きくなってしまう。 したがって、アルゴリズムの各ステップにおいて、 訓練集合から一様に抽出されるサンプルのミニバッチをサンプリングし、 それら数百のデータを用いて1回の学習ステップを行うことで計算時間を軽減する。 この手法を確率的勾配降下法と呼び、 更新毎の計算量が訓練集合の大きさに依存しないというメリットを得る。

機械学習アルゴリズムの構築

  • データ集合の仕様
  • コスト関数
  • 最適化手順
  • モデル

上記4つを組み合わせることで機械学習アルゴリズムは構築される。

深層学習の発展を促す課題

次元の呪い

次元が大きくなると構成される空間が大きくなりすぎる。

局所一様と平滑化

機械学習アルゴリズムにおいて、ある正解データの近傍にあるものは その正解データと大きく変わらない値に学習されるように、 事前分布が仕込まれていることがほとんである。 その場合、正解データが多く集まっている場所に関しては極めてよく学習できても、 それ以外のデータが集まっていないだけで、同様の分布を持っている場所については 正しく予測できる保証がない。

多様体学習

多様体は連結した領域であり、各店の周りの近傍に関連づけられた点の集合である。 ある表現の整理の仕方によって次元が変わるということだと思われる。

「アルゴリズムの基本」を読んで実装して

アルゴリズムの基本

下に記す本を読んで、途中まで実装を行ないました。

本の内容

本の概要

アルゴリズムがなぜ必要か、どのように評価するのかをわかりやすく解説してくれています。 アルゴリズム系の他の書籍を読んだことがないのでわからないですが、 読者を舐めたような簡単すぎる内容ではなく、入門書として適切な難易度であったと感じています。 実際のプラグラミングの記述は一切なく、全てのアルゴリズムを言葉で説明しています。

読むと良いと思う人

  • プログラミングを始めたばかりでとりあえず知識をつけたい人
  • Python等の高レベル言語は触れているけど、低水準のアルゴリズムに興味がある人

読んでも大して意味がないと思う人

本の良かったところ

  • 具体例が必ずついてきてイメージしやすい
  • 特定の言語を用いていないので誰でも読める
  • 広く浅く取り扱ってくれているため面白く、そこまで難しくない
  • 参考文献を記述してくれている

本の良くなかったところ

  • 実装に関してのイメージはつきづらい
  • 本に書いてある入出力で関数を作れない気がする
  • 読んで何の役に立つのかは謎

書籍の実装について

下記のリポジトリに途中まで実装を行なっています。

github.com

先述のように実装についてはアルゴリズムが難しくなるにつれて、かなり不親切な記述になっていきます。 そもそも、実装を考えていない入門書という立ち位置の本なので、 そこに文句をいうのはお門違いなのですが。 そのため、後半の実装で疲れ、挫折しました。

技術書の実装について、良かったのは当然理解が深まることですが、 コスパはそれほど良いとは感じなかったので、入門書は入門書、 しゃぶり尽くすことを考えずに、次の実装まで考えられているレベルの書籍を読んだ方が 良かったなと思いました。

機械学習、深層学習に必要な数学についてざっくりしたまとめ

深層学習に必要な数学

深層学習、機械学習に必要な数学についてまとめます。 参考書籍は下に貼り付けておきます。

目次

微積

参考書籍では微積分については各自で習熟しているものとされています。 微積分について必要な知識は

ベクトルと行列の微分については知識がなかったため、下記のサイトを参考にしました。 基本公式を押さえておけば式変形にはついていけます。

線形代数

スカラー、ベクトル、行列、テンソル

  • スカラーはdouble型などの1変数
  • ベクトルは1次元配列
  • 行列は2次元配列
  • テンソルは3次元以上の多次元配列

線型従属と張る空間

ノルム

Lpノルムの定義

 |\mathbf{x}| = (\sum_i|x_i|^p)^{\frac{1}{p}}

最大値ノルム

 |\mathbf{x}|_{\infty} = \max_{i} |x_i|

フロベニウスノルム(行列のノルム)

 | \mathbf{A} |_{F} = \sqrt{ \sum_{ij} A^{2}_{ij} }

固有値分解

固有値分解

 \mathbf{Av} = \lambda\mathbf{v} \qquad (\mathbf{v} \neq \mathbf{0})
 \mathbf{v} : 固有ベクトル, \lambda : 固有値
 \mathbf{V} = [\mathbf{v^{(1)}}, \dots, \mathbf{v^{(n)}} ]
 \mathbf{\lambda} = \left[ \lambda_1, \dots, \lambda_n \right]^{\mathrm{T}}
 \mathbf{A} = \mathbf{V}\mathbf{\mathbf{diag}}(\lambda)\mathbf{V^{-1}}

実対称行列の固有値分解

 \mathbf{A} = \mathbf{Q} \mathbf{\Lambda} \mathbf{Q}
   \qquad (\mathbf{Q}は直交行列)

固有値
  • 全ての  \lambda > 0 なら正定値
  • 全ての  \lambda \ge 0 なら半正定値
  • 全ての  \lambda > 0 なら負定値
  • 全ての  \lambda \le 0 なら半負定値

特異値分解(Singular Value Decomposition, SVD)

SVDの最も有用な特徴は逆行列法を非正方行列に部分的に一般化できること

 \mathbf{A} = \mathbf{U} \mathbf{D} \mathbf{V^{\mathrm{T}}}
 \mathbf{U}, \mathbf{V} : 直交行列, \mathbf{D} : 対角行列

ムーア・ペンローズ擬似逆行列

 \mathbf{A} : m \times n行列, \quad \mathbf{U, V, D} : 特異値分解
 \mathbf{A^+} = \lim_{\alpha \rightarrow 0}
   (\mathbf{A^{\mathrm{T}}A} + \alpha\mathbf{I})^{-1} \mathbf{A^{\mathrm{T}}}
 \mathbf{A^+} = \mathbf{VD^+U^+}

  • m < n なら  \mathbf{x} = \mathbf{A^+y} は全ての解で最小の  |\mathbf{x}|_2
  • m > n なら解が存在しない可能性、  |\mathbf{Ax} - \mathbf{y}|_2 が最小

トレース演算子

 \mathrm{Tr} (\mathbf{A}) = \sum_i \mathbf{A_{i, i}}
 | \mathbf{A} |_{F} = \sqrt{ \sum_{ij} A^2_{ij} } =
   \sqrt{ \mathrm{Tr} ( \mathbf{ A^{ \mathrm{T} } A} ) }
 \mathrm{Tr}\left(\prod^n_{i=1}F^{(i)}\right) =
   \mathrm{Tr}\left(F^{(n)}\prod^{n-1}_{i=1}F^{(i)}\right)

確率

確率変数、確率分布

観測される定義域の値を確率変数、確率変数が従う分布を確率分布

周辺確率分布

 \forall x \in \mathrm{x}, \quad P(\mathrm{x} = x) =
   \sum_y P(\mathrm{x} = x, \mathrm{y} = y)
 \forall x \in \mathrm{x}, \quad p(\mathrm{x} = x) =
   \int p(x, y) \mathrm{dy}

条件付き確率

 \displaystyle P(\mathrm{y} = y | \mathrm{x} = x) =
   \frac{P(\mathrm{y} = y, \mathrm{x} = x)}{P(\mathrm{x} = x)}

条件付き確率の連鎖律

条件付き確率の定義を用いれば、同時確率が条件付き確率の積で表せる

独立と条件付き独立

条件付き確率分布が独立であることを条件付き独立分布という

期待値、分散、共分散

 E_{\mathrm{x} \sim P} [ f(x) ] = \sum_{x} P(x)f(x)
 Var( f(x) ) = E \left[ ( f(x) - E [ f(x) ] )^{2} \right]
 Cov(f(x), g(y)) = E [ ( f(x) - E[ f(x) ] )( g(y) - E[g(y)] ) ]
 Cov(\mathrm{x})_{i, j} = Cov(\mathrm{x_i}, \mathrm{x_j})
 Cov(\mathrm{x_i}, \mathrm{x_i}) = Var(\mathrm{x_i})

一般的な確率分布

一般的な関数の有用な性質

ベイズ

 \displaystyle P(\mathrm{x|y}) = \frac{P(\mathrm{x})P(\mathrm{y|x})}{\mathrm{P(y)}}
 P(\mathrm{y}) = \sum_x P(\mathrm{y|x})P(x)

連続変数の保証

  • 測度論と呼ばれる理論に裏付けされる
  • 測度零やほとんど至るところで(almost everywhere)の概念

情報理論

自己情報量

底が  e なら  ナット 、底が  2 なら  ビット

 I(x) = -\log P(x)

シャノンエントロピー

 H(x) = E_{\mathrm{x} \sim P} [ I(x) ] = -E_{ \mathrm{x} \sim P } [ \log P(x) ]

カルバックライブラーダイバージェンス

 \displaystyle D_{KL}(P | Q) = E_{ \mathrm{x} \sim P } \left[ \log \frac{P(x)}{Q(x)} \right] =
   E_{ \mathrm{x} \sim P } [ \log P(x) - \log Q(x) ]
 D_{KL}(P | Q) \ne D_{KL}(Q | P)

 P Q の並びによって意味合いが異なる

交差エントロピー

 H(P, Q) = H(P) + D_{KL}(P | Q) = -E_{\mathrm{x} \sim P} \log Q(x)

2018-19シーズン-プレミアリーグ第14節 アーセナルvsトッテナム

2018/12/2(日)に行われたアーセナルvsトッテナムアーセナルホームで行われたノースロンドンダービーは白熱したシーソーゲームを展開した。 試合の流れと戦略が目まぐるしく入れ替わり90分間があっという間の試合だった。 それでは、早速レビューをしていきたいと思う。

試合レビュー

序盤

キックオフからお互い縦に速いプレーを選択。 両チーム共狙いは似たようなもので、ディフェンスラインを高く設定し、 相手のビルドアップを許すことなくプレッシングを行う。 ボールを奪取したら即座に裏に抜けるオーバメヤンやケインを使いフィニッシュを目指す。 流行りに乗って言うとストーミング的な概念下でのプレー選択を行なっていたように見えた。

前半5-25分あたり

両チーム足にボールがついてきたところで、序盤の混沌とした展開が収束する。 守備のスタイルは両チームそのまま、敵陣でのボール奪取からのショートカウンター狙い。 ただし、ディフェンスライン付近でボールを奪った際のプレー選択がビルドアップに移行。 ここでフォーメーションに触れておく。

多分だいたいこんな感じだったかと思う。

ビルドアップに関しては両チーム明確に意図が分かれる。 アーセナルはCB3枚が横並びでパスを交換、DMFの2枚は中央から大きくは動かずコースの確保。 WBは両サイド大きく幅をとり、 OMFの二人はサイドバックを引きつけながら中よりのポジショニング。

トッテナムのプレッシングの意図としては中央に通させないようにしながら ボール保持者や次のパス先に強いプレッシャーを与えると言うもの。 しかし、中央のコースを消すことが徹底されていた反面、WBがどうしても空く場面が多発。

これもエメリの策なのだろう。 OMFの裏抜けを警戒するオーリエとデイビス、 縦パスのコースを切りながら中央のリスクケアをするエリクセン、シソコ、ダイアー、 必然的にどちらかのサイドのWBが浮く事になる。

アーセナルはその隙を利用し、 一度WBを経由して角度のついた楔のパスや裏へのパスを使うことで 効率的に相手プレスの回避および敵陣攻略を行なっていた。 特に、コラシナツとイウォビのユニットに対してオーリエが一人で対応するシーンが多く、 入れ替わることはないまでも最終ラインまで押し込まれる形になっていた。

対するトッテナムはビルドアップを後ろの4枚とDMF2枚、エリクセンで担当。 7枚+キーパーのユニットで第一プレッシャーラインを超えたのちに クリーンな縦パスを強力なFW陣に入れることが目的だったと推測する。 推測の域を出ないのは、トッテナムのビルドアップが ことごとくアーセナルのプレッシャーの網に引っかかったからである。

まとめると、アーセナルのペースである。

前半10分にコーナーキックからPKを獲得してアーセナルが先制点をもぎ取る。

前半25-45分

アーセナルがゲームを支配していたファーストハーフの前半に対し、 トッテナムがプレーに修正を加えた。 端的に言うとビルドアップの早い段階からのロングフィードだ。 アーセナルプレッシングの網にかかる前のフリーな状態、 あるいはキーパーからケインをターゲットにボールを放り込む。 アーセナルのディフェンスラインはプレッシングのためにかなり高く設定されており、 加えて数的同数でディフェンスラインを形成することになることもん少なくなかった。 このプレー選択の修正は功をなす。 トッテナムが相手陣地まで攻め上がれる回数が格段に増えた。

相手陣内に入ると違いを見せるのが、ケイン、ソン・フンミン、アリ、エリクセンのユニットである。 彼らの速いパス交換を前に、アーセナルDFは後手を踏まざるを得ない。 全員突破力やラストパスのセンスが光るため、強くあたりに行く必要があるが、 ダイレクトパスの交換中の相手全員に激しいタックルをお見舞いすることは不可能である。 結果的に前を向いたソン・フンミンにボールが渡りDFラインをドリブルで突破、 PKを獲得し、1-1に追いつく。

直後、同様のゲーム展開からサイドの深い位置でのFKを得たトッテナムが ニアで待ち構えつつ、ラインの駆け引きを制したダイアーに合わせ2-1と逆転。

アーセナルのビルドアップに関してはボールサイドのWBにSBが強く行くことを決めることで、 WBがフリーになることを阻害し、 これまでのようにアーセナルはクリーンに前にボールを運べなくなった。

ざっくり言うと、トッテナムのペースである。

後半

後半に入り、アーセナルはイウォビ、ムヒタリアンに代えラカゼット、ラムジーを投入。 アーセナルの守備、トッテナムの攻守の戦略は概ねそのままで、依然トッテナムペースが続く。

変わったのはアーセナルの攻撃である。 サイド経由でのビルドアップを行なっていたが、 後半からはサイドをちらつかせた中央狙いのビルドアップが姿を見せる。

WBが前半よりはやや低い位置にポジションを取り、相手SBではなく相手のMFのマークを引きつける。 最終ラインとの距離が近くなった結果、効率的にパスを交換することが可能になり、 単純な縦パスのコースが生まれる回数が増えた。 さらにその構造に旨味を加えるのはラカゼットとオーバメヤンラムジーのDFラインとの駆け引きである。 それぞれが互いの動きに連携して妨害困難な縦パスへのルートを作成する。

後半11分、一列落ちてきたベジェリンが、 ラカゼットがワイドに開いてSBを釣り出し SBとCBの間に門が開いたところに走り込んだラムジーへの縦パスを送る。 ラムジーは左サイドからカットインしてきたオーバメヤンにボールを流し、 オーバメヤンがスーパーシュート叩き込む。

2-2に追いつかれたトッテナムは最終ラインを強固にする目的からかダイアーを一列下げる。 結果的にこれが裏目にでることになる。 中央でのプレッシャーが弱まり、躍動し始めたのはトレイラである。 積極的にボールを受けて、これまでの縦に速い展開以外に、 遅攻を織り交ぜながらゲームを支配する。 逆にトッテナムは前線のユニット4枚のプレー強度が低下し、 これまでのロングフィードからの攻撃では相手DFを攻略することが困難な状況に。 さらに、前線の疲労からアーセナルDFはフリーな状態でボールを回せる機会が増え、 アーセナル支配のゲーム展開に拍車をかけることになる。

その後は、相手のビルドアップに対し変わらない強度でプレッシャーをかけ続けた アーセナルがフォイトからボールを奪い、ショートカウンターにより得点。

その3分後、相手陣内に押し込みDFラインの連携を崩して裏に抜け出したトレイラが得点を重ね、 4-2で試合終了。

感想まとめ

まずはトレイラがやばい。 あのレベルのハイプレッシングで穴を作らないようにDMFで暗躍を続けたかと思えば、 最後に出てきて決定的な仕事するって、かっこよすぎる。 ボールタッチも美しいし、最高のプレイヤーだと感じた。

トッテナムの前線4枚も狂ってるし、オバメもラカゼットも狂ってる。 あんなもん止めれるか!

ファイナルサード攻略時にアーセナルは長めのパス、 トッテナムは短めのパスを選択してたのが対比的には面白かった。 アーセナルは裏パスへの意欲がすごい高くて、 トッテナムはハーフスペースからドリブル攻略を狙っていたのかな?

DFに関してはデュエルの観点だとあんまり負けていない気もするんだけど、 駆け引きで負けている印象。 1vs1で攻撃側勝ってたのはソン・フンミンくらい? そもそもハイプレッシングを行なっていたら、最終ラインまで相手が迫ってきた時に まともなデュエルの形を作ることが難しいと思うけど。

緊張感がなかなか解けない見応えのある好ゲームだった。

なんかルールは平等でも貧富の差って生まれるらしいのでPythonに本当か聞いてみた

ツイートでこんなの見かけました。

ちょっと実装してみました。

コード

import numpy as np
import sys
from tqdm import tqdm


def release_coin(people):
    random = np.random.rand() * 6 + 0.5
    random = np.round(random)

    if random == 1:
        people["person1"] -= 1
    elif random == 2:
        people["person2"] -= 1
    elif random == 3:
        people["person3"] -= 1
    elif random == 4:
        people["person4"] -= 1
    elif random == 5:
        people["person5"] -= 1
    elif random == 6:
        people["person6"] -= 1
    else:
        print("error")
        print(random)

    return people


def get_coin(people):
    random = np.random.rand() * 6 + 0.5
    random = np.round(random)

    if random == 1:
        people["person1"] += 1
    elif random == 2:
        people["person2"] += 1
    elif random == 3:
        people["person3"] += 1
    elif random == 4:
        people["person4"] += 1
    elif random == 5:
        people["person5"] += 1
    elif random == 6:
        people["person6"] += 1
    else:
        print("error")
        print(random)

    return people


def validation(people):
    total = sum(people.values())

    if total == 600:
        return True
    else:
        return False


def main(loop_num):
    people = {"person1": 100,
              "person2": 100,
              "person3": 100,
              "person4": 100,
              "person5": 100,
              "person6": 100}

    for _ in tqdm(range(loop_num)):
        people = release_coin(people)
        people = get_coin(people)
        val = validation(people)

        if val:
            continue
        else:
            print("error")
            print(people)

    print(people)


if __name__ == "__main__":
    arg = int(sys.argv[1])
    main(arg)

辞書型にした理由は謎です。
乱数生成で +0.5をしばらく忘れていて痛い目にあった以外はすんなり行った気がします。

結果

% python static_disparity.py 1000000
100%|████████████████████████████████████████████████████| 1000000/1000000 [00:15<00:00, 64672.29it/s]
{'person1': 312, 'person2': 21, 'person3': 125, 'person4': -240, 'person5': -383, 'person6': 765}

% python static_disparity.py 1000000
100%|████████████████████████████████████████████████████| 1000000/1000000 [00:15<00:00, 64060.44it/s]
{'person1': 602, 'person2': -757, 'person3': -302, 'person4': 853, 'person5': -183, 'person6': 387}

% python static_disparity.py 1000000
100%|████████████████████████████████████████████████████| 1000000/1000000 [00:18<00:00, 53485.54it/s]
{'person1': -225, 'person2': -295, 'person3': -51, 'person4': -68, 'person5': 696, 'person6': 543}

まじで貧富の差が生まれていた。 一度きりの人生大変だと感じました。

webアプリを独力で作る体験をするのだ[vue-cliを使って敗者の環境構築]

Vue.js

React.jsと肩を並べる人気フレームワークで、 React.jsよりも学習コストが低めと聞いて使うことを決めました。

導入

公式ドキュメント

とりあえずチュートリアルでもやろうかなと思い、 公式ページを訪問したら、公式ドキュメントがめっちゃいい感じに流れに沿った解説だったので、 しばらく読み進めることにしました。 しかしながら、手を動かしながらじゃないと楽しくないし、眠くなるので、 先に環境を整えて遊びながらやっていこうと決めました。

環境構築

思ったよりも最高に大変でした。 まずは 単一コンポーネント という概念があるということから難関は始まるのですが、、、

単一コンポーネント

普通にhtmlとjsを分離して、js側にvueを使って書いていく方法と、 .vue拡張子のファイルにhtml, js, css全て詰め込んで部品を組み立てていく方法の 二種類が存在します。 単一コンポーネントの方がvueっぽいし楽しそう! しかもドキュメントが見た所多そう!!(Qiita斜め読み調べ) ということで単一コンポーネントと呼ばれる .vue拡張子を基礎とした書き方でいくことに決めました。

vue-cli

さて、環境構築に入るのですが、 まずはフレームワークのインストールですね。 なんとなくnpmでやればいいかなと思って

npm i -S vue

えい!これで入りました。あら簡単だ! ここまではよかったのですが、今回 単一コンポーネント を扱うため、 ビルドツールが必要とのことです。 Qiitaから察するに webpack が人気そう!ということでwebpackを導入。 webpackの設定をvueのsample repositoryを参照に書いていく。
...ムズイ。
今になって思うとバベルが何かあまりわかっていなかったことが敗因と思われるのですが、 結論から言うと諦めました。

CLI は Node.js および関連するビルドツールに関する事前知識を前提としています。Vue またはフロントエンドビルドツールを初めて使用している場合、CLI を使用する前に、ビルドツールなしでガイドを参照することを強くお勧めします。

公式に上記のように書かれており、 使ってはいけないと思っていた vue-cliと呼ばれるcliツールを使用することにしました。

npm i -g vue-cli
vue init webpack my-project
cd my-project
npm i
npm run dev

まぁ、便利ですよね、そりゃ、 一瞬で環境構築が終わってしまいました。 webpack.configが書けなかった時点で、 ビルド周りの理解はとりあえず後回しにすることを決め、 とりあえずはこのテンプレートのなかでできることを増やしていく方針にしました。 これにて導入は完了?

最初に入って学習すべきもの

babelとは何か

基本的には将来的に実装されることが決まっているが、 ブラウザがまだ対応していないESバージョンを書かせてくれる。 そして、ビルド時によしなに対応させてくれるっぽい。 新しいESまで勉強できて良いかもしれない。 altJSの一つとしてしか認識していなかったため、 勉強するの面倒としか思っておらず避けようとしていたのですが、 触れられてよかったと今は思っています。

webpackの簡単な使い方

vue-cliを使っていれば

# 開発用簡易サーバー起動
npm run dev
# 本番用ビルド
npm run build

さえ覚えていれば、正直大丈夫な気もします。 ただ、configディレクトリに入っている dev.env.jsなどを用いて環境変数を設定できるので、 それらの使い方だけは見ておくと便利かと思います。 自分はbackendのurlをここで分けています。

eslintとは何か

これはつい最近、タイポが多すぎて勉強していたので面くらわずにすみました。 簡単に言うと書き方が汚いと小煩く叱ってくれるソフトです。 エディタはAtomを使っているのですが、 Atomだと書きながらリアルタイムでeslintが添削を行ってくれます。 Atom使えないシェルでいちいち怒られるか、ブラウザで毎回怒られることになりそうなので、 IDE万歳と思いました。

test(まだ何も触ってない)

これからやります。 とりあえずtestは開発とともに書き溜めるものと言う認識のみあります。 認識だけで実際に書いていないので私はクソです。

まとめ

とりあえず何か作るたいならvue-cliめっちゃ便利

webアプリを独力で作る体験をするのだ[AWSを使ったSPA, API設計を考えた]

設計が完了した

つい先日、AWSのサービスをひたすら適当に列挙していきました。 さらに適当な考察の末、それっぽい設計ができたかなと思います。 これから以下の画像についてざっくりと説明していきます。 (最初画像貼り忘れてた...)

f:id:went-went-takkun135:20171108110110p:plain
SPAの設計

フロントエンド

SPA

Single Page Applicationの略です。 最近やたらとサクサク動くwebサービスが多いなと思っていました。 調べてみるとフロントでレンダリングして、非同期的にデータを取得してるとかいう、 誰が考えたんだよ、天才かよ、っていうものがあったのでそれを作りたいなとなりました。

フレームワーク

SPA作るに際してフレームワークは何にするの問題があって、 みたいな話は以前した気がしますが、Vue.js を用いて実装していっています。

S3, CloudFront

SPAはただの静的ファイルのため、S3 において置くだけで良いようです。 ただ、S3において置くだけだと、アクセスはできないですし、 アクセス許可するとそれはそれでセキュリティ的にどうなのってなるので、 S3の前に CloudFront を噛ませます。 これで安心安全Https接続ですね。あまりhttpsが何かはまだわかっていないんですが...。 以下のページを参考にさせていただきました。 皆さんありがとうございます。

AngularJSで作ったSPAをAWS上の「S3+CloudFront」でお手軽ホスティングして、クラウドサービスってやっぱ素晴らしいなと思った話 | I am mitsuruog

SPAを S3+CloudFront で表示する方法 - Carpe Diem

[CloudFront + S3]特定バケットに特定ディストリビューションのみからアクセスできるよう設定する | Developers.IO

バックエンド

Web API

SPAにはバックエンドが必要です。 いや、何にでもですね、すみません。 基本的にSPAのバックエンドはWeb APIを作れば良さそうです。 将来的にはこの構成で、ネイティブアプリにも対応できるなとか考えてはいます。

フレームワーク

ここもまた前に話した気がするのですが、 Nodehapi を使って実装していきます!

Elastic Beanstalk

Googleさんに聞いている限り、 バックエンドはAPI GatewayAWS Lambdaで実装するパターンが多い気がします。 しかしながら、結構強めのバックエンド作ってやろうと意気込んでいたので、 (あとはシンプルにいつも触っていたので) Elastic Beanstalk を使うことにしました!

データベース

PostgreSQL

今こいつで死ぬほど詰まっています。 なんでDynamoだけじゃないの?って聞かれたら データサイエンティストになるならSQLは書けなければならない。 って誰かに言われたからです。 SQLなんてちょろいやろって思ってたんですけど、 SQL書き始める前のセットアップが辛すぎて泣きそうです。

Dynamo DB

メインは楽そうなのでこの子です。 しかも無料枠の幅が広い。 太っ腹や!!!! NoSQLというのもそうですが、 こっちはAWSコンソールで操作ができるので、セットアップがある程度楽そうですね! 最初のテーブル作るのとかGUIAWS内で提供してくれてるの良いです

まとめ

こんな感じで設計がまとまりました。 ほぼ全ての設定で詰まっているのでなかなか進みませんが、 頑張っていきたいと思います。