Deep Learning Tutorial

chainer and python

1章 Pythonで始める機械学習

まずはデータを読み込みます。
自分の場合は、'BMLS/ch01/data/web_traffic.tsv'にデータファイルを保存しています。
適宜ファイルパスは変更してください。

import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
data = sp.genfromtxt('BMLS/ch01/data/web_traffic.tsv', 
                                          delimiter='\t')
X = np.array([data[:,0]]).T
y = np.array(data[:,1])

SciPyのgenfromtxt()を使用しデータを取り込みます。
区切りには水平タブ'\t'を指定しました。
SciPyでは[:,0]とすることで、0列を指します。

「web_traffic.tsv」
 1  2272
 2  1656
 3  1386
 4  1365
 5  1488
 6  1337
 7  1883
 8  2283
 9  1335
10  1025
 ・・・

行ごとに時間のインデックスとその時間におけるアクセス数のデータです。

そして、matplotlibを使い散布図を作ります。

plt.scatter(X, y, c='black')
plt.title('Web traffic over the last month')
plt.xlabel('Time')
plt.ylabel('Hits / hour')
plt.xticks([w*7*24 for w in range(10)],
           ['week %i'%w for w in range(10)])
plt.autoscale(tight=True)
plt.grid()
plt.show()

f:id:tsuruchan_0827:20160216214424p:plain

まずは、単純な直線(次数1)で近似してみましょう。
scikit-learnのlinear_model.LinearRegression()を使います。
modelのオブジェクトを生成し、fit()で訓練データを与え分類器のパラメータを学習します。

from sklearn import linear_model

model = linear_model.LinearRegression()
model.fit(X, y)

f:id:tsuruchan_0827:20160216215938p:plain
このようになりました。
次数が1では上手な近似は難しいようです。

では、次数を増やしてみるとどうでしょうか。
次数を1,2,3,10,100にして、近似をしてみます。

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline

d = [1,2,3,10,100]

for deg in d:
    model = Pipeline([('poly', PolynomialFeatures(degree=deg)), \
                      ('linear', linear_model.LinearRegression())])
    model.fit(X, y)

    px = np.arange(X.min(), X.max(), 0.1)[:,np.newaxis]
    py = model.predict(px)
    
    plt.plot(px, py, linewidth=3, label='poly_deg %d'%deg)

PolynomialFeaturesで次元を設定し、linear_model.LinearRegression()を分類器として指定します。
次数を増やすほど、曲線が複雑になります。
100次元では謎の形をしていますね笑
f:id:tsuruchan_0827:20160216220822p:plain

pythonでトレーニングデータとテストデータを分けたいときは以下のコードで簡単にかけます。
train_sizeは全体の何割をトレーニングデータに使用するか設定できます。
全体をシャッフルする必要があるので、random_stateに乱数の種を与えるとそれに応じてランダムシャッフルしてくれます。
1行で書くことができるのでとても便利です。

from sklearn.cross_validation import train_test_split

X, X_test, y, y_test = train_test_split(X, y, train_size=0.8, random_state=0)

ここで、各次元のスコアを見てみましょう。

Error d=1   : 0.414046407906558
Error d=2   : 0.666596085641824
Error d=3   : 0.742343568730878
Error d=10  : 0.770849248135516
Error d=100 : 0.583463265773743

model.score()によって0〜1の間のスコアが取得できます。
スコアが大きい物ほどよく近似できているということになります。

10のときにはスコアもグラフもいい感じになっていますが、100の時には短い周期で振動するグラフとなっています。
このような形のことを過学習(オーバーフィッティング)と呼びます。


全体のコードです。

import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.cross_validation import train_test_split

data = sp.genfromtxt('BMLS/ch01/data/web_traffic.tsv', delimiter='\t')
X = np.array([data[:,0]]).T
y = np.array(data[:,1])
X, X_test, y, y_test = train_test_split(X, y, train_size=0.8, random_state=0)

d = [1,2,3,10,100]

for deg in d:
    model = Pipeline([('poly', PolynomialFeatures(degree=deg)), \
                      ('linear', linear_model.LinearRegression())])
    model.fit(X, y)

    px = np.arange(X.min(), X.max(), 0.1)[:,np.newaxis]
    py = model.predict(px)
    
    plt.plot(px, py, linewidth=3, label='poly_deg %d'%deg)
    print('Error d={} : {}'.format(deg, model.score(X_test, y_test)))

plt.scatter(X, y, c='black')
plt.title('Web traffic over the last month')
plt.xlabel('Time')
plt.ylabel('Hits / hour')

plt.xticks([w*7*24 for w in range(10)], ['week %i'%w for w in range(10)])
plt.autoscale(tight=True)
plt.legend(loc='upper left')
plt.grid()
plt.show()