実践 機械学習システムメモ

#### 私が書籍"実践 機械学習システム"を読み勉強した時に参考にしたサイトと第1章のメモです。
## 機械学習参考サイトURL

+ <a href="https://www.youtube.com/watch?v=1t14aa0Chqo&feature=youtu.be&t=19m20s">MPS Yokohama Deep Learning vol.01
</a>
+ <a href="http://gauc.no-ip.org/~hi_saito/MPS/mps_yokohama.html">数学的基礎から学ぶ Deep Learning</a>
+ <a href="http://www.twotoreal.com/u/wr/2/public/59/faq/">TwoToReal FAQ</a>
+ <a href="https://github.com/wrichert/BuildingMachineLearningSystemsWithPython">Github:wrichert/BuildingMachineLearningSystemsWithPython</a>
+ <a href="http://ai-programming.hatenablog.jp/entry/2016/02/19/204649">１章　Pythonで始める機械学習</a>
+ <a href="http://blog.amedama.jp/entry/2015/09/28/213745">Python: SciPy で特徴量の相関を調べる</a>
+ <a href="http://momijiame.tumblr.com/post/112131904206/python-scipy-%E3%81%AE%E3%82%AB%E3%83%BC%E3%83%96%E3%83%95%E3%82%A3%E3%83%83%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%92%E8%A9%A6%E3%81%99">Python: Scipy のカーブフィッティングを試す</a>
+ <a href="http://ktadaki.hatenablog.com/entry/2015/10/29/155340">プログラマーじゃない人が始める人工知能: ScipyとMatplotlibを使ってデータの近似モデルを構築する</a>
+ <a href="http://yubais.net/doc/matplotlib/modify.html">matplotlib入門 - グラフの体裁を整える</a>
+ <a href="http://bicycle1885.hatenablog.com/entry/2014/02/14/023734">matplotlib入門</a>
+ <a href="http://bicycle1885.hatenablog.com/entry/2014/02/14/023734">NumPy で回帰分析
</a>

## "実践 機械学習システム"メモ

```python
# Numpyとは？
# 大規模な多次元配列や行列のサポート、
# これらを操作するための大規模な高水準の数学関数ライブラリを提供する。

http://rest-term.com/archives/2999/
http://wbhappy.hatenablog.jp/entry/2015/02/06/210000
# ndarray.flags    配列データのメモリレイアウト情報
# ndarray.ndim     配列の次元数
# ndarray.size     配列の要素数
# ndarray.shape    各次元の要素数
# ndarray.itemsize 1要素のバイト数
# ndarray.strides  各次元で次の要素に移動する際に必要なバイト数
# ndarray.nbytes   配列全体のバイト数
# ndarray.dtype    配列要素のデータ型 (numpy.dtype)

>>> import numpy as np
>>> np.version.full_version
'1.8.0rc1'
>>> a = np.array([0,1,2,3,4,5])
>>> a
array([0, 1, 2, 3, 4, 5])
>>> a.ndim
1
>>> a.shape
(6,)
>>> b = a.reshape((3,2))
>>> b
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> b.ndim
2
>>> b.shape
(3, 2)
>>> b[1][0] = 77
>>> b
array([[ 0,  1],
       [77,  3],
       [ 4,  5]])
>>> a
array([ 0,  1, 77,  3,  4,  5])
>>> c = a.reshape((3,2)).copy()
>>> c
array([[ 0,  1],
       [77,  3],
       [ 4,  5]])
>>> c[0][0] = -99
>>> a
array([ 0,  1, 77,  3,  4,  5])
>>> c
array([[-99,   1],
       [ 77,   3],
       [  4,   5]])
>>> a*2
array([  0,   2, 154,   6,   8,  10])
>>> a**2
array([   0,    1, 5929,    9,   16,   25])
>>> a[np.array([2,3,4])]
array([77,  3,  4])
>>> a>4
array([False, False,  True, False, False,  True], dtype=bool)
>>> a[a>4]
array([77,  5])
>>> a[a>4]=4
>>> a
array([0, 1, 4, 3, 4, 4])
>>> a.clip(0,4)
array([0, 1, 4, 3, 4, 4])
>>> c = np.array([1,2,np.NAN, 3,4]) # テキストファイルから読み込んだと仮定
>>> c
array([  1.,   2.,  nan,   3.,   4.])
>>> np.isnan(c) # 欠損値を置き換える
array([False, False,  True, False, False], dtype=bool)
>>> c[~np.isnan(c)]
array([ 1.,  2.,  3.,  4.])
>>> np.mean(c[~np.isnan(c)])
2.5
>>> import timeit
>>> normal_py_sec = timeit.timeit('sum(x*x for x in xrange(1000))',number=10000)
>>> Naive_np_sec = timeit.timeit('sum(na*na)',setup="import numpy as np; na=np.arange(1000)", number=10000)
>>> good_np_sec = timeit.timeit('na.dot(na)',setup="import numpy as np;  na=np.arange(1000)", number=10000)
>>> print("Normal Python: %f sec"%normal_py_sec)
Normal Python: 0.836571 sec
>>> print("Naive Numpy: %f sec"%Naive_np_sec)
Naive Numpy: 4.806356 sec
>>> print("Good Numpy: %f sec"%good_np_sec)
Good Numpy: 0.039245 sec
>>> a = np.array([1,2,3])
>>> a.dtype
dtype('int64')
>>> np.array([1, "stringry"])
array(['1', 'stringry'],
      dtype='|S8')
>>> np.array([1, "stringy", set([1,2,3])])
array([1, 'stringy', set([1, 2, 3])], dtype=object)
```

```python
# http://rest-term.com/archives/2999/より

>>> import numpy as np
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]]) # 配列の生成
>>> a
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])
>>> a.flags     # 配列データのメモリレイアウト情報
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
>>> a.ndim      # 次元数
2
>>> a.size      # 要素数
12
>>> a.shape     # 各次元の要素数(行数,列数)
(4, 3)
>>> a.itemsize  # 1要素のバイト数
8
>>> a.strides   # 24バイトで次の行、8バイトで次の列
(24, 8)
>>> a.nbytes    # 配列全体のバイト数
96
>>> a.dtype     # 要素のデータ型
dtype('int64')

>>> np.zeros(5)
array([ 0.,  0.,  0.,  0.,  0.])
>>> np.ones(5)
array([ 1.,  1.,  1.,  1.,  1.])
>>> np.ones([2,3])
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> np.identity(3)                       # 単位行列
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> np.eye(3)                            # 列数指定ができる単位行列
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> np.arange(10)                        # range()と同じ
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.araange(1,2,0.2)                  # 始点,終点,増分
array([ 1. ,  1.2,  1.4,  1.6,  1.8])
>>> np.linspace(1,4,6)                   # 要素数を指定できるrange()
array([ 1. ,  1.6,  2.2,  2.8,  3.4,  4. ])
>>> np.logspace(2,3,4)                   # 対数
array([  100.        ,   215.443469  ,   464.15888336,  1000.        ])
>>> np.logspace(2,4,4, base=2)           # 底2
array([  4.        ,   6.34960421,  10.0793684 ,  16.        ])
>>> np.tile([0,1,2,3,4], 2)              # 生成、要素を繰り返した配列を返す
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
>>> a,b = np.meshgrid([1,2,3],[4,5,6,7]) # 縦横に等間隔な格子状配列
>>> a
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])
>>> b
array([[4, 4, 4],
       [5, 5, 5],
       [6, 6, 6],
       [7, 7, 7]])
>>> np.tri(3) # 三角行列
array([[ 1.,  0.,  0.],
       [ 1.,  1.,  0.],
       [ 1.,  1.,  1.]])
>>> a = np.array([[0,1,2],[3,4,5],[6,7,8]])
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> np.diag(a)                  # 入力配列から対角要素を抜き出した配列
array([0, 4, 8])
>>> np.empty(5)                 # 領域の確保のみで初期化はされない
array([  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
         1.48219694e-323,   1.97626258e-323])
>>> a = np.array([1,2,3])
>>> b = a.copy()
>>> b
array([1, 2, 3])
>>> np.random.randint(0,100,10) # 生成する乱数の範囲(最小値,最大値,要素数)を指定
array([67, 65, 61, 15, 48, 57, 42, 21, 49, 57])
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a = np.arange(10)
>>> b = a.reshape((2,5))        # 配列形状の変更(この場合2次元配列へ)
>>> b
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> a.resize((2,5))             # 要素数はそのままで2次元配列に変更
>>> a
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> a = np.tile(np.arange(3),3) # range(3)の3列格子
>>> a
array([0, 1, 2, 0, 1, 2, 0, 1, 2])
>>> np.argmax(a)                # 最大値要素のうちで最も小さいインデックス
2
>>> np.argmin(a)                # 最小値要素のうちで最も小さいインデックス
0
>>> a = np.eye(3)               # 3つ配列
>>> a
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> np.nonzero(a)               # 非ゼロ要素のインデックス配列を返す(この場合二次元配列なので二つ)
(array([0, 1, 2]), array([0, 1, 2]))
>>> a = np.arange(15).reshape((3,5))
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
>>> np.where(a%2==0)            # 条件に合致した要素のインデックス配列
(array([0, 0, 0, 1, 1, 2, 2, 2]), array([0, 2, 4, 1, 3, 0, 2, 4]))
>>> a = np.arange(10)
>>> np.select([a<3, a>5],[a, a**2]) # 複数条件検索 第一引数:条件の配列 第二引数:条件に合致した要素のインデックスにセットする値の配列
array([ 0,  1,  2,  0,  0,  0, 36, 49, 64, 81])
>>> a = np.arange(9).reshape((3,3))
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> b = np.arange(8,-1,-1).reshape((3,3))
>>> b
array([[8, 7, 6],
       [5, 4, 3],
       [2, 1, 0]])
>>> np.dstack((a,b))            # 二次元配列を結合して三次元配列にする
array([[[0, 8],
        [1, 7],
        [2, 6]],

       [[3, 5],
        [4, 4],
        [5, 3]],

       [[6, 2],
        [7, 1],
        [8, 0]]])
>>> np.hstack((a,b))            # 列方向に結合
array([[0, 1, 2, 8, 7, 6],
       [3, 4, 5, 5, 4, 3],
       [6, 7, 8, 2, 1, 0]])
>>> np.vstack((a,b))            # 行方向に結合
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8],
       [8, 7, 6],
       [5, 4, 3],
       [2, 1, 0]])
>>> a = np.arange(16).reshape(2,2,4)
>>> a
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
>>> np.dsplit(a,2)              # 3次元配列を分割
[array([[[ 0,  1],
        [ 4,  5]],

       [[ 8,  9],
        [12, 13]]]), array([[[ 2,  3],
        [ 6,  7]],

       [[10, 11],
        [14, 15]]])]
>>> a = np.arange(16).reshape(4,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
>>> np.hsplit(a,2)              # 列方向に分割
[array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [12, 13]]), array([[ 2,  3],
       [ 6,  7],
       [10, 11],
       [14, 15]])]
>>> np.vsplit(a,2)              # 行方向に分割
[array([[0, 1, 2, 3],
       [4, 5, 6, 7]]), array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])]
>>> a = np.array([[1,2],[3,4]])
>>> a
array([[1, 2],
       [3, 4]])
>>> np.transpose(a)             # 配列を転置
array([[1, 3],
       [2, 4]])
>>> a = np.array([[1,2,3]])
>>> np.swapaxes(a,0,1)          # 軸の交換
array([[1],
       [2],
       [3]])
>>> a = np.random.randint(0,500,20)
>>> a
array([444,  97, 324, 492, 275,  95, 157, 336,  51, 249, 363, 409, 299,
       432,  41, 469, 201, 308,  85, 455])
>>> np.amax(a)                  # 最大値
492
>>> np.amin(a)                  # 最小値
41
>>> np.ptp(a)                   # 値の範囲(最大値-最小値)
451
>>> np.mean(a)                  # 算術平均
279.10000000000002
>>> np.median(a)                # 中央値
303.5
>>> np.std(a)                   # 標準偏差
146.4031761950539
>>> np.var(a)                   # 分散
21433.889999999999
>>> b = np.random.randint(0,500,20)
>>> b
array([375, 207, 495, 320, 472, 481, 491, 133, 279, 480, 232, 261, 492,
       183, 168, 424,  95, 236, 176, 332])
>>> np.corrcoef(a,b)            # 相関係数
array([[ 1.        ,  0.12452095],
       [ 0.12452095,  1.        ]])
>>> c = np.random.randint(0,10,20)
>>> c
array([6, 5, 9, 7, 9, 6, 4, 0, 1, 4, 6, 3, 2, 7, 9, 3, 4, 9, 4, 8])
>>> np.histogram(c)             # ヒストグラム
(array([1, 1, 1, 2, 4, 1, 3, 2, 1, 4]), array([ 0. ,  0.9,  1.8,  2.7,  3.6,  4.5,  5.4,  6.3,  7.2,  8.1,  9. ]))
```

```python
# SciPyとは?
# 多くのアルゴリズムを提供
#  cluster : 階層クラスタイング/ベクトリ量子化/K平均法
#  constants : 物理数学定数
#  fftpack : フーリエ定義
#  integrate : 積分
#  interpolate : 補間(リニア,キュービックなど)
#  io : データの入出力
#  linalg : BLASとLAPACKライブラリを用いた線形代数ルーチン
#  maxentropy : エントロピー分布
#  ndimage : n次元画像パッケージ
#  odr : 直交距離回帰
#  optimize : 最適化
#  signal : 信号処理
#  sparse : 疎行列
#  spatial : 空間データ構造とアルゴリズム
#  special : ベッセル関数、 やっこビアンなどの特殊関数
#  stats : 統計

>>> import scipy, numpy
>>> scipy.version.full_version
'0.13.0b1'
>>> scipy.dot is numpy.dot
True # 名前空間がNumpyと同じ
>>> data = sp.genfromtxt("sample/ch01/data/web_traffic.tsv", delimiter='\t')
>>> print(data.shape)
(743, 2)
>>> print(data[:10])

```

```python
>>> import scipy as sp
>>> data = sp.genfromtxt("./sample/ch01/data/web_traffic.tsv", delimiter="\t") #  データ読み込み
>>> print(data[:10])
 [  2.00000000e+00   1.65600000e+03]
 [  3.00000000e+00   1.38600000e+03]
 [  4.00000000e+00   1.36500000e+03]
 [  5.00000000e+00   1.48800000e+03]
 [  6.00000000e+00   1.33700000e+03]
 [  7.00000000e+00   1.88300000e+03]
 [  8.00000000e+00   2.28300000e+03]
 [  9.00000000e+00   1.33500000e+03]
 [  1.00000000e+01   1.02500000e+03]]
>>> print(data.shape)
(743, 2)
>>> x = data[:,0] # 経過時間(SciPy:0番目の次元を抽出しろ)
>>> y = data[:,1] # アクセス数
>>> sp.sum(sp.isnan(y)) # 不適切な値
0
>>> x = x[~sp.isnan(y)] # 不適切な値を取り除く
>>> y = y[~sp.isnan(y)] # 不適切な値を取り除く
>>> import matplotlib.pyplot as plt # 散布図
>>> plt.scatter(x,y)
<matplotlib.collections.PathCollection object at 0x11192e5d0>
>>> plt.title("Web traffic over the last month")
<matplotlib.text.Text object at 0x1118f7c90>
>>> plt.xlabel("Time")
<matplotlib.text.Text object at 0x111636090>
>>> plt.ylabel("Hits/hour")
<matplotlib.text.Text object at 0x111649fd0>
>>> plt.xticks([w*7*24 for w in range(10)], ['week %i' %w for w in range(10)])
([<matplotlib.axis.XTick object at 0x10e349710>, <matplotlib.axis.XTick object at 0x111653450>, <matplotlib.axis.XTick object at 0x11192edd0>, <matplotlib.axis.XTick object at 0x1119514d0>, <matplotlib.axis.XTick object at 0x111951c10>, <matplotlib.axis.XTick object at 0x113505390>, <matplotlib.axis.XTick object at 0x113505ad0>, <matplotlib.axis.XTick object at 0x11350e250>, <matplotlib.axis.XTick object at 0x11350e990>, <matplotlib.axis.XTick object at 0x11351a110>], <a list of 10 Text xticklabel objects>)
>>> plt.autoscale(tight=True)
>>> plt.grid()
>>> plt.show()
# カーブフィッティング
# polyfit(x,y,n) : 回帰分析に使う関数(n次式で2変数の回帰分析)
# 回帰分析...相関関係や因果関係があると思われる2つの変数のうち、一方の変数から将来的な値を予測するための予測式（回帰直線）を求めるための手法。
>>> def error(f, x, y): #モデル関数fが存在すると仮定した時の誤差
...     return sp.sum((f(x)-y)**2)
>>> fp1, residuals, rank, sv, rcond = sp.polyfit(x, y, 1, full=True) # polyfitでx,yを最小二乗的に近似となるモデルの係数を取得
>>> print("Model parameters: %s" % fp1)
Model parameters: [    2.57152281  1002.10684085]
>>> print(residuals) # 剰余
[  3.19874315e+08]
>>> print(rank) # 行列のランク
2
>>> print(rcond) # 条件数の逆数
1.64979141459e-13
参照 : http://ktadaki.hatenablog.com/entry/2015/10/29/155340
5個の変数に値を入れているが、使うのは最初のfp1のみ。fp1の中身はこんな感じ。
[   2.59619213  989.02487106]
つまり、こんな式を得たわけだ。
f(x)=2.59619213x+989.02487106
>>> f1 = sp.poly1d(fp1) # モデル関数を作成
>>> print(error(f1,x,y))
319874314.777
>>> import matplotlib.pyplot as plt # 散布図
>>> plt.scatter(x,y)
<matplotlib.collections.PathCollection object at 0x11192e5d0>
>>> plt.title("Web traffic over the last month")
<matplotlib.text.Text object at 0x1118f7c90>
>>> plt.xlabel("Time")
<matplotlib.text.Text object at 0x111636090>
>>> plt.ylabel("Hits/hour")
<matplotlib.text.Text object at 0x111649fd0>
>>> plt.xticks([w*7*24 for w in range(10)], ['week %i' %w for w in range(10)]) # x軸の目盛りを書き換える。引数には「どの位置に」「何を」表示するかをそれぞれリストで指定
([<matplotlib.axis.XTick object at 0x10e349710>, <matplotlib.axis.XTick object at 0x111653450>, <matplotlib.axis.XTick object at 0x11192edd0>, <matplotlib.axis.XTick object at 0x1119514d0>, <matplotlib.axis.XTick object at 0x111951c10>, <matplotlib.axis.XTick object at 0x113505390>, <matplotlib.axis.XTick object at 0x113505ad0>, <matplotlib.axis.XTick object at 0x11350e250>, <matplotlib.axis.XTick object at 0x11350e990>, <matplotlib.axis.XTick object at 0x11351a110>], <a list of 10 Text xticklabel objects>)
>>> plt.autoscale(tight=True)
<matplotlib.legend.Legend object at 0x10c587ad0>
>>> fx = sp.linspace(0, x[-1], 1000) # プロット用に"x値"を生成
>>> plt.plot(fx, f1(fx), linewidth=4) # リストをグラフとして描写
[<matplotlib.lines.Line2D object at 0x10c587850>]
>>> plt.legend(["d=%i" % f1.order], loc="upper left") # 凡例を表示
>>> plt.grid()
>>> plt.show()
```

```python
>>> f2p = sp.polyfit(x, y, 2)
>>> print(f2p)
[  1.04688184e-02  -5.21727812e+00   1.96921629e+03]
>>> f2 = sp.poly1d(f2p)
>>> print(error(f2, x, y))
182006476.432
# f(x) = 0.0105322215 * x**2 - 5.26545650 * x + 1974.76802
>>> plt.plot(fx, f2(fx), linewidth=4)
# ↑先ほどのやつに組み込む
# より正確な曲線だが、関数が複雑
# 次数-3,10,100で試した→過学習
# 次数1で試した → 未学習
# 一つ目の直線を3.5週より前のデータを用いて学習, 二つ目の直線はそれ以降のデータを用いる
>>> inflection = 3.5*7*24 # 変化点の時間を計算
>>> xa = x[:inflection] # 変化点前のデータポイント
>>> ya = y[:inflection]
>>> xb = x[:inflection] # 変化点後
>>> yb = y[:inflection]
>>> fa = sp.poly1d(sp.polyfit(xa, ya, 1))
>>> fb = sp.poly1d(sp.polyfit(xb, yb, 1))
>>> fa_error = error(fa, xa, ya)
>>> fb_error = error(fb, xb, yb)
>>> print("Error inflection=%f" % (fa_error + fb_error))
Error inflection=218985429.871767
# plt.plot(fx, fa(fx), linewidth=4)
# plt.plot(fx, fb(fx), linewidth=4) で同じように図表示
# 変化点以降のデータを使用して学習したモデルに対して、テストデータを用いて誤差を計算する
>>> frac = 0.3 # テ ス ト に 用 い る デ ータ  の 割 合
>>> split_idx = int(frac * len(xb))
>>> shuffled = sp.random.permutation(list(range(len(xb)))) # 全データの30%をランダムに選び出す
>>> test = sorted(shuffled[:split_idx]) # テスト用のデータをインデックス配列
>>> train = sorted(shuffled[split_idx:]) # 訓練用のデータインデックス配列
>>> # それぞれの訓練データを用いて訓練を行う
>>> fbt1 = sp.poly1d(sp.polyfit(xb[train], yb[train], 1))
>>> fbt2 = sp.poly1d(sp.polyfit(xb[train], yb[train], 2))
>>> fbt3 = sp.poly1d(sp.polyfit(xb[train], yb[train], 3))
>>> fbt10 = sp.poly1d(sp.polyfit(xb[train], yb[train], 10))
>>> fbt100 = sp.poly1d(sp.polyfit(xb[train], yb[train], 100))
/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy/lib/polynomial.py:579: RuntimeWarning: overflow encountered in multiply
  scale = NX.sqrt((lhs*lhs).sum(axis=0))
/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy/lib/polynomial.py:587: RankWarning: Polyfit may be poorly conditioned
  warnings.warn(msg, RankWarning)
>>> # それぞれの訓練データを用いて評価を行う
>>> for f in [fbt1, fbt2, fbt3, fbt10, fbt100]:
...     print("Error d=%i: %f"  % (f.order, error(f, xb[test], yb[test])))
...
Error d=1: 33618254.181783
Error d=2: 31298428.161162
Error d=3: 30849423.817712
Error d=10: 28969336.428648
Error d=55: 28919778.656526
# 時間当たりのリクエストが100,000を超える時期を予想 - 二次方程式の解を求める
# 多項式から100,000を引き算して新しい多項式を作り、その新しい多項式に対して根を求める
>>> print(fbt2)
          2
0.004136 x - 1.662 x + 1677
>>> print(fbt2-100000)
          2
0.004136 x - 1.662 x - 9.832e+04
>>> from scipy.optimize import fsolve
>>> reached_max = fsolve(fbt2-100000, 800)/(7*24)
>>> print("100,000 hits/hour expected at week %f" % reached_max[0])
100,000 hits/hour expected at week 30.241873
```

```python
# 2章 P27
# クラス分類/教師あり学習
# アイリスデータセット
# 特微量
# 三角:Setosa 丸:Versucikir 罰:Virginica
>>> from matplotlib import pyplot as plt
>>> from sklearn.datasets import load_iris
>>> import numpy as np
>>> data = load_iris() # sklearnからload_iris関数を用いてデータをロードする
>>> features = data['data']
>>> feature_names = data['feature_names']
>>> target = data['target']
>>> target_names = data['target_names']
>>> labels = target_names[target] # ?
>>> for t,marker,c in zip(range(3), ">ox","rgb"):
...     plt.scatter(features[target == t,0],
...                 features[target == t,1],
...                 marker = marker,
...                 c = c) # クラスごとに色の異なるマーカでプロットする
...
<matplotlib.collections.PathCollection object at 0x10a5ec668>
<matplotlib.collections.PathCollection object at 0x10a287208>
<matplotlib.collections.PathCollection object at 0x10a5fa908>
# 「花弁の長さ」は配列の3番目に格納されている。
>>> plength = features[:, 2]
>>> is_setosa = (labels == 'setosa') # setosaかどうかのboolean配列を生成
>>> max_setosa = plength[is_setosa].max()
>>> min_non_setosa = plength[~is_setosa].min()
>>> print('Maximum of setosa: {0}.'.format(max_setosa))
Maximum of setosa: 1.9. # 花弁長さの最大値->1.9
>>> print('Minimum of others: {0}.'.format(min_non_setosa))
Minimum of others: 3.0. # 花弁長さの最小値->3.0
>>> def apply_model( example ):
...     if example[2] < 2:
...         print("Iris Setosa")
...     else:
...         print("Iris Virginica or Itis Versicolor")
# 他のアイリスの違いをせ出来るだけ最善の方法で
>>> features = features[~is_setosa]
>>> labels = labels[~is_setosa]
>>> virginica = (labels == 'virginica')
>>> best_acc = -1.0
>>> best_fi = -1.0
>>> best_t = -1.0
>>> for fi in range(features.shape[1]): # 各特微量ごとに閾値の候補を生成する
...     thresh = features[:,fi].copy()
...     thresh.sort()
...     for t in thresh: # すべての閾値でテストする
...         pred = (features[:,fi] > t)
...         acc = (labels[pred] == 'virginica').mean()
...         if acc > best_acc:
...             best_acc = acc
...             best_fi  = fi
...             best_t   = t
>>> def apply_model( example ):
...     if(example[best_fi] > best_t):
...         print("virginica")
...     else:
...         print("virsicolor")
# heldout.pyを起動
# python3 ./sample/ch02/heldout.py
>>> from threshold import learn_model, apply_model, accuracy
>>> for ei in range(len(features)): # ei番目を除いたすべてのデータを用いてくれんする
...     training = np.ones(len(features), bool)
...     training[ei] = False
...     testing = ~training
...     model = learn_model(features[training], virginica[training])
...     predictions = apply_model(features[testing], virginica[testing], model)
...     error += np.sum(predictions != virginica[testing])
```