覚え書きブログ

scikit-learnを用いた機械学習(教師あり学習 2/3)

<< scikit-learnを用いた機械学習(教師あり学習 1/3)

教師あり学習のフローのクラス化

f:id:hirotaka_hachiya:20190814151354p:plain

以下は、教師あり学習(回帰)の一連のフローを、クラス化したものです。

import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from sklearn import linear_model
from sklearn.model_selection import train_test_split

# Regressionクラス
class Regression:
    #---------------
    # コンストラクタ
    def __init__(self, datapath="house_prices_train.csv"):
        self.data = pd.read_csv(datapath)
        
        # 予測のフラグ
        self.isPred = False
    #---------------

    #---------------
    # 回帰用のデータを作成するメソッド
    def createRegData(self, xattriReg, yattriReg, data):
        self.xattriReg = xattriReg  # 入力xのデータ名
        self.yattriReg = yattriReg  # 出力yのデータ名
        self.X = data[xattriReg].values  # 入力xの設定
        self.y = data[yattriReg].values  # 出力xの設定
    #---------------

    #---------------
    # 標準化するメソッド
    def normalize(self):
        self.Xmean = np.mean(self.X,axis=0)  # 平均
        self.Xstd = np.std(self.X,axis=0)  # 標準偏差
        self.X = (self.X-self.Xmean)/self.Xstd  # 標準化
    #---------------
    
    #---------------
    # 訓練用と評価用とに分割するメソッド
    # trRatio:学習データの割合((0,1]の少数で指定、例:0.8)    
    def split2TrainTest(self,trRatio=0.8):
        self.Xtr, self.Xte, self.ytr, self.yte = \
            train_test_split(self.X,self.y,train_size=trRatio,test_size=1-trRatio)
    #---------------

    #---------------
    # 回帰用の関数する学習メソッド
    def trainRegression(self):
        self.f = linear_model.LinearRegression()  # 関数fの定義
        self.f.fit(self.Xtr, self.ytr)  # 関数fの学習
    #---------------

    #---------------
    # 回帰の予測
    def predict(self):
        self.isPred = True  # 予測のフラグをオン
        self.ypre = self.f.predict(self.Xte)  # 予測
    #---------------

    #---------------
    # 回帰の評価
    def evalRegression(self):

        # 予測
        if not self.isPred: self.predict()
        
        # 平均絶対差の計算
        self.absError = np.mean(np.abs(self.yte - self.ypre))
        
        print("評価データの絶対誤差=",self.absError)
    #---------------
    
    #---------------
    # 予測結果の散布図を作成するメソッド
    def plotResults(self):
        # 予測
        if not self.isPred: self.predict()
        
        # 元のスケールに戻す
        Xtmp = self.Xte*self.Xstd+self.Xmean
        
        fig = plt.figure()

        for ind in range(len(self.xattriReg)):
            ax=fig.add_subplot(len(self.xattriReg),1,ind+1)
        
            # 予測のプロット
            ax.plot(Xtmp[:,ind], self.ypre,'.',label='predict')
        
            # 真値のプロット
            ax.plot(Xtmp[:,ind], self.yte,'.',label='true')
        
            ax.set_ylim([np.min(self.yte), np.max(self.yte)])  # y軸の範囲
            ax.set_xlabel(self.xattriReg[ind]) # x軸のラベル
            ax.set_ylabel(self.yattriReg) # y軸のラベル

        plt.tight_layout()  # グラフ間に隙間をあける
        plt.show()  # グラフの表示
    #---------------

クラスRegressionを用いて、教師あり学習を実行すると以下のようになります。

myData = Regression()  # Regressionクラスのインスタンス化
myData.createRegData(['LotArea'],'SalePrice', myData.data[myData.data['MSSubClass']==20])  # 教師ありデータの作成
myData.normalize()  # 標準化
myData.split2TrainTest()  # 訓練用と評価用とに分割
myData.trainRegression()  # 関数の学習
myData.evalRegression()  # 誤差の評価

# 散布図で可視化
myData.plotResults()

f:id:hirotaka_hachiya:20190528124535p:plain

演習1

敷地面積LotAreaだけを入力として用いて、販売価格SalePriceを予測した場合、上記のように約600万円ほどの誤差がでます。
この回帰の精度を改善するために、入力に車庫の面積GarageAreaと、居住面積GrLivAreaを追加してみましょう。
具体的には、上記のRegressionクラスを利用して、以下のような、平均絶対誤差と、散布図を3つ作りましょう。

f:id:hirotaka_hachiya:20190528125954p:plain

scikit-learnを用いた機械学習(教師あり学習 3/3)>>