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()
まずは、単純な直線(次数1)で近似してみましょう。
scikit-learnのlinear_model.LinearRegression()を使います。
modelのオブジェクトを生成し、fit()で訓練データを与え分類器のパラメータを学習します。
from sklearn import linear_model model = linear_model.LinearRegression() model.fit(X, y)
このようになりました。
次数が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次元では謎の形をしていますね笑
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()